C++ Essence Library 0.1.0
A Utility Library for Modern C++ Programming
Loading...
Searching...
No Matches
json.hpp
1/*
2 * Copyright (c) 2024 The RefValue Project
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23/****************************************************************************\
24 * Note on documentation: The source files contain links to the online *
25 * documentation of the public API at https://json.nlohmann.me. This URL *
26 * contains the most recent documentation and should also be applicable to *
27 * previous versions; documentation for deprecated functions is not *
28 * removed, but marked deprecated. See "Generate documentation" section in *
29 * file docs/README.md. *
30\****************************************************************************/
31
32#ifndef INCLUDE_NLOHMANN_JSON_HPP_
33#define INCLUDE_NLOHMANN_JSON_HPP_
34
35#include <algorithm> // all_of, find, for_each
36#include <cstddef> // nullptr_t, ptrdiff_t, size_t
37#include <functional> // hash, less
38#include <initializer_list> // initializer_list
39#ifndef JSON_NO_IO
40 #include <iosfwd> // istream, ostream
41#endif // JSON_NO_IO
42#include <iterator> // random_access_iterator_tag
43#include <memory> // unique_ptr
44#include <string> // string, stoi, to_string
45#include <utility> // declval, forward, move, pair, swap
46#include <vector> // vector
47
48// #include <nlohmann/adl_serializer.hpp>
49// __ _____ _____ _____
50// __| | __| | | | JSON for Modern C++
51// | | |__ | | | | | | version 3.11.3
52// |_____|_____|_____|_|___| https://github.com/nlohmann/json
53//
54// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
55// SPDX-License-Identifier: MIT
56
57
58
59#include <utility>
60
61// #include <nlohmann/detail/abi_macros.hpp>
62// __ _____ _____ _____
63// __| | __| | | | JSON for Modern C++
64// | | |__ | | | | | | version 3.11.3
65// |_____|_____|_____|_|___| https://github.com/nlohmann/json
66//
67// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
68// SPDX-License-Identifier: MIT
69
70
71
72// This file contains all macro definitions affecting or depending on the ABI
73
74#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
75 #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
76 #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
77 #warning "Already included a different version of the library!"
78 #endif
79 #endif
80#endif
81
82#define NLOHMANN_JSON_VERSION_MAJOR 3 // NOLINT(modernize-macro-to-enum)
83#define NLOHMANN_JSON_VERSION_MINOR 11 // NOLINT(modernize-macro-to-enum)
84#define NLOHMANN_JSON_VERSION_PATCH 3 // NOLINT(modernize-macro-to-enum)
85
86#ifndef JSON_DIAGNOSTICS
87 #define JSON_DIAGNOSTICS 0
88#endif
89
90#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
91 #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
92#endif
93
94#if JSON_DIAGNOSTICS
95 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
96#else
97 #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
98#endif
99
100#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
101 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
102#else
103 #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
104#endif
105
106#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
107 #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
108#endif
109
110// Construct the namespace ABI tags component
111#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
112#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
113 NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
114
115#define NLOHMANN_JSON_ABI_TAGS \
116 NLOHMANN_JSON_ABI_TAGS_CONCAT( \
117 NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS, \
118 NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
119
120// Construct the namespace version component
121#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
122 _v ## major ## _ ## minor ## _ ## patch
123#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
124 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
125
126#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
127#define NLOHMANN_JSON_NAMESPACE_VERSION
128#else
129#define NLOHMANN_JSON_NAMESPACE_VERSION \
130 NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
131 NLOHMANN_JSON_VERSION_MINOR, \
132 NLOHMANN_JSON_VERSION_PATCH)
133#endif
134
135// Combine namespace components
136#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
137#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
138 NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
139
140#ifndef NLOHMANN_JSON_NAMESPACE
141#define NLOHMANN_JSON_NAMESPACE \
142 nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
143 NLOHMANN_JSON_ABI_TAGS, \
144 NLOHMANN_JSON_NAMESPACE_VERSION)
145#endif
146
147#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
148#define NLOHMANN_JSON_NAMESPACE_BEGIN \
149 namespace nlohmann \
150 { \
151 inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
152 NLOHMANN_JSON_ABI_TAGS, \
153 NLOHMANN_JSON_NAMESPACE_VERSION) \
154 {
155#endif
156
157#ifndef NLOHMANN_JSON_NAMESPACE_END
158#define NLOHMANN_JSON_NAMESPACE_END \
159 } /* namespace (inline namespace) NOLINT(readability/namespace) */ \
160 } // namespace nlohmann
161#endif
162
163// #include <nlohmann/detail/conversions/from_json.hpp>
164// __ _____ _____ _____
165// __| | __| | | | JSON for Modern C++
166// | | |__ | | | | | | version 3.11.3
167// |_____|_____|_____|_|___| https://github.com/nlohmann/json
168//
169// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
170// SPDX-License-Identifier: MIT
171
172
173
174#include <algorithm> // transform
175#include <array> // array
176#include <forward_list> // forward_list
177#include <iterator> // inserter, front_inserter, end
178#include <map> // map
179#include <string> // string
180#include <tuple> // tuple, make_tuple
181#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
182#include <unordered_map> // unordered_map
183#include <utility> // pair, declval
184#include <valarray> // valarray
185
186// #include <nlohmann/detail/exceptions.hpp>
187// __ _____ _____ _____
188// __| | __| | | | JSON for Modern C++
189// | | |__ | | | | | | version 3.11.3
190// |_____|_____|_____|_|___| https://github.com/nlohmann/json
191//
192// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
193// SPDX-License-Identifier: MIT
194
195
196
197#include <cstddef> // nullptr_t
198#include <exception> // exception
199#if JSON_DIAGNOSTICS
200 #include <numeric> // accumulate
201#endif
202#include <stdexcept> // runtime_error
203#include <string> // to_string
204#include <vector> // vector
205
206// #include <nlohmann/detail/value_t.hpp>
207// __ _____ _____ _____
208// __| | __| | | | JSON for Modern C++
209// | | |__ | | | | | | version 3.11.3
210// |_____|_____|_____|_|___| https://github.com/nlohmann/json
211//
212// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
213// SPDX-License-Identifier: MIT
214
215
216
217#include <array> // array
218#include <cstddef> // size_t
219#include <cstdint> // uint8_t
220#include <string> // string
221
222// #include <nlohmann/detail/macro_scope.hpp>
223// __ _____ _____ _____
224// __| | __| | | | JSON for Modern C++
225// | | |__ | | | | | | version 3.11.3
226// |_____|_____|_____|_|___| https://github.com/nlohmann/json
227//
228// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
229// SPDX-License-Identifier: MIT
230
231
232
233#include <utility> // declval, pair
234// #include <nlohmann/detail/meta/detected.hpp>
235// __ _____ _____ _____
236// __| | __| | | | JSON for Modern C++
237// | | |__ | | | | | | version 3.11.3
238// |_____|_____|_____|_|___| https://github.com/nlohmann/json
239//
240// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
241// SPDX-License-Identifier: MIT
242
243
244
245#include <type_traits>
246
247// #include <nlohmann/detail/meta/void_t.hpp>
248// __ _____ _____ _____
249// __| | __| | | | JSON for Modern C++
250// | | |__ | | | | | | version 3.11.3
251// |_____|_____|_____|_|___| https://github.com/nlohmann/json
252//
253// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
254// SPDX-License-Identifier: MIT
255
256
257
258// #include <nlohmann/detail/abi_macros.hpp>
259
260
261NLOHMANN_JSON_NAMESPACE_BEGIN
262namespace detail
263{
264
265template<typename ...Ts> struct make_void
266{
267 using type = void;
268};
269template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
270
271} // namespace detail
272NLOHMANN_JSON_NAMESPACE_END
273
274
275NLOHMANN_JSON_NAMESPACE_BEGIN
276namespace detail
277{
278
279// https://en.cppreference.com/w/cpp/experimental/is_detected
281{
282 nonesuch() = delete;
283 ~nonesuch() = delete;
284 nonesuch(nonesuch const&) = delete;
285 nonesuch(nonesuch const&&) = delete;
286 void operator=(nonesuch const&) = delete;
287 void operator=(nonesuch&&) = delete;
288};
289
290template<class Default,
291 class AlwaysVoid,
292 template<class...> class Op,
293 class... Args>
295{
296 using value_t = std::false_type;
297 using type = Default;
298};
299
300template<class Default, template<class...> class Op, class... Args>
301struct detector<Default, void_t<Op<Args...>>, Op, Args...>
302{
303 using value_t = std::true_type;
304 using type = Op<Args...>;
305};
306
307template<template<class...> class Op, class... Args>
308using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
309
310template<template<class...> class Op, class... Args>
311struct is_detected_lazy : is_detected<Op, Args...> { };
312
313template<template<class...> class Op, class... Args>
314using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
315
316template<class Default, template<class...> class Op, class... Args>
317using detected_or = detector<Default, void, Op, Args...>;
318
319template<class Default, template<class...> class Op, class... Args>
320using detected_or_t = typename detected_or<Default, Op, Args...>::type;
321
322template<class Expected, template<class...> class Op, class... Args>
323using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
324
325template<class To, template<class...> class Op, class... Args>
326using is_detected_convertible =
327 std::is_convertible<detected_t<Op, Args...>, To>;
328
329} // namespace detail
330NLOHMANN_JSON_NAMESPACE_END
331
332// #include <nlohmann/thirdparty/hedley/hedley.hpp>
333
334
335// __ _____ _____ _____
336// __| | __| | | | JSON for Modern C++
337// | | |__ | | | | | | version 3.11.3
338// |_____|_____|_____|_|___| https://github.com/nlohmann/json
339//
340// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
341// SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <[email protected]>
342// SPDX-License-Identifier: MIT
343
344/* Hedley - https://nemequ.github.io/hedley
345 * Created by Evan Nemerson <[email protected]>
346 */
347
348#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
349#if defined(JSON_HEDLEY_VERSION)
350 #undef JSON_HEDLEY_VERSION
351#endif
352#define JSON_HEDLEY_VERSION 15
353
354#if defined(JSON_HEDLEY_STRINGIFY_EX)
355 #undef JSON_HEDLEY_STRINGIFY_EX
356#endif
357#define JSON_HEDLEY_STRINGIFY_EX(x) #x
358
359#if defined(JSON_HEDLEY_STRINGIFY)
360 #undef JSON_HEDLEY_STRINGIFY
361#endif
362#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
363
364#if defined(JSON_HEDLEY_CONCAT_EX)
365 #undef JSON_HEDLEY_CONCAT_EX
366#endif
367#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
368
369#if defined(JSON_HEDLEY_CONCAT)
370 #undef JSON_HEDLEY_CONCAT
371#endif
372#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
373
374#if defined(JSON_HEDLEY_CONCAT3_EX)
375 #undef JSON_HEDLEY_CONCAT3_EX
376#endif
377#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
378
379#if defined(JSON_HEDLEY_CONCAT3)
380 #undef JSON_HEDLEY_CONCAT3
381#endif
382#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
383
384#if defined(JSON_HEDLEY_VERSION_ENCODE)
385 #undef JSON_HEDLEY_VERSION_ENCODE
386#endif
387#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
388
389#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
390 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
391#endif
392#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
393
394#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
395 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
396#endif
397#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
398
399#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
400 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
401#endif
402#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
403
404#if defined(JSON_HEDLEY_GNUC_VERSION)
405 #undef JSON_HEDLEY_GNUC_VERSION
406#endif
407#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
408 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
409#elif defined(__GNUC__)
410 #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
411#endif
412
413#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
414 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
415#endif
416#if defined(JSON_HEDLEY_GNUC_VERSION)
417 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
418#else
419 #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
420#endif
421
422#if defined(JSON_HEDLEY_MSVC_VERSION)
423 #undef JSON_HEDLEY_MSVC_VERSION
424#endif
425#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
426 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
427#elif defined(_MSC_FULL_VER) && !defined(__ICL)
428 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
429#elif defined(_MSC_VER) && !defined(__ICL)
430 #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
431#endif
432
433#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
434 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
435#endif
436#if !defined(JSON_HEDLEY_MSVC_VERSION)
437 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
438#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
439 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
440#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
441 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
442#else
443 #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
444#endif
445
446#if defined(JSON_HEDLEY_INTEL_VERSION)
447 #undef JSON_HEDLEY_INTEL_VERSION
448#endif
449#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
450 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
451#elif defined(__INTEL_COMPILER) && !defined(__ICL)
452 #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
453#endif
454
455#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
456 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
457#endif
458#if defined(JSON_HEDLEY_INTEL_VERSION)
459 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
460#else
461 #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
462#endif
463
464#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
465 #undef JSON_HEDLEY_INTEL_CL_VERSION
466#endif
467#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
468 #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
469#endif
470
471#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
472 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
473#endif
474#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
475 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
476#else
477 #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
478#endif
479
480#if defined(JSON_HEDLEY_PGI_VERSION)
481 #undef JSON_HEDLEY_PGI_VERSION
482#endif
483#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
484 #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
485#endif
486
487#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
488 #undef JSON_HEDLEY_PGI_VERSION_CHECK
489#endif
490#if defined(JSON_HEDLEY_PGI_VERSION)
491 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
492#else
493 #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
494#endif
495
496#if defined(JSON_HEDLEY_SUNPRO_VERSION)
497 #undef JSON_HEDLEY_SUNPRO_VERSION
498#endif
499#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
500 #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)
501#elif defined(__SUNPRO_C)
502 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
503#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
504 #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)
505#elif defined(__SUNPRO_CC)
506 #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
507#endif
508
509#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
510 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
511#endif
512#if defined(JSON_HEDLEY_SUNPRO_VERSION)
513 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
514#else
515 #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
516#endif
517
518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
519 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
520#endif
521#if defined(__EMSCRIPTEN__)
522 #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
523#endif
524
525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
526 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
527#endif
528#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
529 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
530#else
531 #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
532#endif
533
534#if defined(JSON_HEDLEY_ARM_VERSION)
535 #undef JSON_HEDLEY_ARM_VERSION
536#endif
537#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
538 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
539#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
540 #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
541#endif
542
543#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
544 #undef JSON_HEDLEY_ARM_VERSION_CHECK
545#endif
546#if defined(JSON_HEDLEY_ARM_VERSION)
547 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
548#else
549 #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
550#endif
551
552#if defined(JSON_HEDLEY_IBM_VERSION)
553 #undef JSON_HEDLEY_IBM_VERSION
554#endif
555#if defined(__ibmxl__)
556 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
557#elif defined(__xlC__) && defined(__xlC_ver__)
558 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
559#elif defined(__xlC__)
560 #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
561#endif
562
563#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
564 #undef JSON_HEDLEY_IBM_VERSION_CHECK
565#endif
566#if defined(JSON_HEDLEY_IBM_VERSION)
567 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
568#else
569 #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
570#endif
571
572#if defined(JSON_HEDLEY_TI_VERSION)
573 #undef JSON_HEDLEY_TI_VERSION
574#endif
575#if \
576 defined(__TI_COMPILER_VERSION__) && \
577 ( \
578 defined(__TMS470__) || defined(__TI_ARM__) || \
579 defined(__MSP430__) || \
580 defined(__TMS320C2000__) \
581 )
582#if (__TI_COMPILER_VERSION__ >= 16000000)
583 #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
584#endif
585#endif
586
587#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
588 #undef JSON_HEDLEY_TI_VERSION_CHECK
589#endif
590#if defined(JSON_HEDLEY_TI_VERSION)
591 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
592#else
593 #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
594#endif
595
596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
597 #undef JSON_HEDLEY_TI_CL2000_VERSION
598#endif
599#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
600 #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
601#endif
602
603#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
604 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
605#endif
606#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
607 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
608#else
609 #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
610#endif
611
612#if defined(JSON_HEDLEY_TI_CL430_VERSION)
613 #undef JSON_HEDLEY_TI_CL430_VERSION
614#endif
615#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
616 #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
617#endif
618
619#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
620 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
621#endif
622#if defined(JSON_HEDLEY_TI_CL430_VERSION)
623 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
624#else
625 #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
626#endif
627
628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
629 #undef JSON_HEDLEY_TI_ARMCL_VERSION
630#endif
631#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
632 #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
633#endif
634
635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
636 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
637#endif
638#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
639 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
640#else
641 #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
642#endif
643
644#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
645 #undef JSON_HEDLEY_TI_CL6X_VERSION
646#endif
647#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
648 #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
649#endif
650
651#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
652 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
653#endif
654#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
655 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
656#else
657 #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
658#endif
659
660#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
661 #undef JSON_HEDLEY_TI_CL7X_VERSION
662#endif
663#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
664 #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
665#endif
666
667#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
668 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
669#endif
670#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
671 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
672#else
673 #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
674#endif
675
676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
677 #undef JSON_HEDLEY_TI_CLPRU_VERSION
678#endif
679#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
680 #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
681#endif
682
683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
684 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
685#endif
686#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
687 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
688#else
689 #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
690#endif
691
692#if defined(JSON_HEDLEY_CRAY_VERSION)
693 #undef JSON_HEDLEY_CRAY_VERSION
694#endif
695#if defined(_CRAYC)
696 #if defined(_RELEASE_PATCHLEVEL)
697 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
698 #else
699 #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
700 #endif
701#endif
702
703#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
704 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
705#endif
706#if defined(JSON_HEDLEY_CRAY_VERSION)
707 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
708#else
709 #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
710#endif
711
712#if defined(JSON_HEDLEY_IAR_VERSION)
713 #undef JSON_HEDLEY_IAR_VERSION
714#endif
715#if defined(__IAR_SYSTEMS_ICC__)
716 #if __VER__ > 1000
717 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
718 #else
719 #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
720 #endif
721#endif
722
723#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
724 #undef JSON_HEDLEY_IAR_VERSION_CHECK
725#endif
726#if defined(JSON_HEDLEY_IAR_VERSION)
727 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
728#else
729 #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
730#endif
731
732#if defined(JSON_HEDLEY_TINYC_VERSION)
733 #undef JSON_HEDLEY_TINYC_VERSION
734#endif
735#if defined(__TINYC__)
736 #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
737#endif
738
739#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
740 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
741#endif
742#if defined(JSON_HEDLEY_TINYC_VERSION)
743 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
744#else
745 #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
746#endif
747
748#if defined(JSON_HEDLEY_DMC_VERSION)
749 #undef JSON_HEDLEY_DMC_VERSION
750#endif
751#if defined(__DMC__)
752 #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
753#endif
754
755#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
756 #undef JSON_HEDLEY_DMC_VERSION_CHECK
757#endif
758#if defined(JSON_HEDLEY_DMC_VERSION)
759 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
760#else
761 #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
762#endif
763
764#if defined(JSON_HEDLEY_COMPCERT_VERSION)
765 #undef JSON_HEDLEY_COMPCERT_VERSION
766#endif
767#if defined(__COMPCERT_VERSION__)
768 #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
769#endif
770
771#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
772 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
773#endif
774#if defined(JSON_HEDLEY_COMPCERT_VERSION)
775 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
776#else
777 #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
778#endif
779
780#if defined(JSON_HEDLEY_PELLES_VERSION)
781 #undef JSON_HEDLEY_PELLES_VERSION
782#endif
783#if defined(__POCC__)
784 #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
785#endif
786
787#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
788 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
789#endif
790#if defined(JSON_HEDLEY_PELLES_VERSION)
791 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
792#else
793 #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
794#endif
795
796#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
797 #undef JSON_HEDLEY_MCST_LCC_VERSION
798#endif
799#if defined(__LCC__) && defined(__LCC_MINOR__)
800 #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
801#endif
802
803#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
804 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
805#endif
806#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
807 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
808#else
809 #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
810#endif
811
812#if defined(JSON_HEDLEY_GCC_VERSION)
813 #undef JSON_HEDLEY_GCC_VERSION
814#endif
815#if \
816 defined(JSON_HEDLEY_GNUC_VERSION) && \
817 !defined(__clang__) && \
818 !defined(JSON_HEDLEY_INTEL_VERSION) && \
819 !defined(JSON_HEDLEY_PGI_VERSION) && \
820 !defined(JSON_HEDLEY_ARM_VERSION) && \
821 !defined(JSON_HEDLEY_CRAY_VERSION) && \
822 !defined(JSON_HEDLEY_TI_VERSION) && \
823 !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
824 !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
825 !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
826 !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
827 !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
828 !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
829 !defined(__COMPCERT__) && \
830 !defined(JSON_HEDLEY_MCST_LCC_VERSION)
831 #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
832#endif
833
834#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
835 #undef JSON_HEDLEY_GCC_VERSION_CHECK
836#endif
837#if defined(JSON_HEDLEY_GCC_VERSION)
838 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
839#else
840 #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
841#endif
842
843#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
844 #undef JSON_HEDLEY_HAS_ATTRIBUTE
845#endif
846#if \
847 defined(__has_attribute) && \
848 ( \
849 (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
850 )
851# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
852#else
853# define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
854#endif
855
856#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
857 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
858#endif
859#if defined(__has_attribute)
860 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
861#else
862 #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
863#endif
864
865#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
866 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
867#endif
868#if defined(__has_attribute)
869 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
870#else
871 #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
872#endif
873
874#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
875 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
876#endif
877#if \
878 defined(__has_cpp_attribute) && \
879 defined(__cplusplus) && \
880 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
881 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
882#else
883 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
884#endif
885
886#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
887 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
888#endif
889#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
890 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
891#elif \
892 !defined(JSON_HEDLEY_PGI_VERSION) && \
893 !defined(JSON_HEDLEY_IAR_VERSION) && \
894 (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
895 (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
896 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
897#else
898 #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
899#endif
900
901#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
902 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
903#endif
904#if defined(__has_cpp_attribute) && defined(__cplusplus)
905 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
906#else
907 #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
908#endif
909
910#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
911 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
912#endif
913#if defined(__has_cpp_attribute) && defined(__cplusplus)
914 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
915#else
916 #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
917#endif
918
919#if defined(JSON_HEDLEY_HAS_BUILTIN)
920 #undef JSON_HEDLEY_HAS_BUILTIN
921#endif
922#if defined(__has_builtin)
923 #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
924#else
925 #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
926#endif
927
928#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
929 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
930#endif
931#if defined(__has_builtin)
932 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
933#else
934 #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
935#endif
936
937#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
938 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
939#endif
940#if defined(__has_builtin)
941 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
942#else
943 #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
944#endif
945
946#if defined(JSON_HEDLEY_HAS_FEATURE)
947 #undef JSON_HEDLEY_HAS_FEATURE
948#endif
949#if defined(__has_feature)
950 #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
951#else
952 #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
953#endif
954
955#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
956 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
957#endif
958#if defined(__has_feature)
959 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
960#else
961 #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
962#endif
963
964#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
965 #undef JSON_HEDLEY_GCC_HAS_FEATURE
966#endif
967#if defined(__has_feature)
968 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
969#else
970 #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
971#endif
972
973#if defined(JSON_HEDLEY_HAS_EXTENSION)
974 #undef JSON_HEDLEY_HAS_EXTENSION
975#endif
976#if defined(__has_extension)
977 #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
978#else
979 #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
980#endif
981
982#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
983 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
984#endif
985#if defined(__has_extension)
986 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
987#else
988 #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
989#endif
990
991#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
992 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
993#endif
994#if defined(__has_extension)
995 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
996#else
997 #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
998#endif
999
1000#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
1001 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
1002#endif
1003#if defined(__has_declspec_attribute)
1004 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
1005#else
1006 #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
1007#endif
1008
1009#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
1010 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
1011#endif
1012#if defined(__has_declspec_attribute)
1013 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1014#else
1015 #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1016#endif
1017
1018#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
1019 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
1020#endif
1021#if defined(__has_declspec_attribute)
1022 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
1023#else
1024 #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1025#endif
1026
1027#if defined(JSON_HEDLEY_HAS_WARNING)
1028 #undef JSON_HEDLEY_HAS_WARNING
1029#endif
1030#if defined(__has_warning)
1031 #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
1032#else
1033 #define JSON_HEDLEY_HAS_WARNING(warning) (0)
1034#endif
1035
1036#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
1037 #undef JSON_HEDLEY_GNUC_HAS_WARNING
1038#endif
1039#if defined(__has_warning)
1040 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1041#else
1042 #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
1043#endif
1044
1045#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
1046 #undef JSON_HEDLEY_GCC_HAS_WARNING
1047#endif
1048#if defined(__has_warning)
1049 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
1050#else
1051 #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
1052#endif
1053
1054#if \
1055 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1056 defined(__clang__) || \
1057 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1058 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1059 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1060 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
1061 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1062 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1063 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1064 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1065 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1066 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
1067 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1068 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1069 JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
1070 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
1071 JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
1072 (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
1073 #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
1074#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1075 #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
1076#else
1077 #define JSON_HEDLEY_PRAGMA(value)
1078#endif
1079
1080#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
1081 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
1082#endif
1083#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
1084 #undef JSON_HEDLEY_DIAGNOSTIC_POP
1085#endif
1086#if defined(__clang__)
1087 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
1088 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
1089#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1090 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1091 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1092#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1093 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
1094 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
1095#elif \
1096 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
1097 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1098 #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
1099 #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
1100#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
1101 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
1102 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
1103#elif \
1104 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1105 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1106 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
1107 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1108 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1109 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1110 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
1111 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
1112#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1113 #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
1114 #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
1115#else
1116 #define JSON_HEDLEY_DIAGNOSTIC_PUSH
1117 #define JSON_HEDLEY_DIAGNOSTIC_POP
1118#endif
1119
1120/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
1121 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
1122#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1123 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
1124#endif
1125#if defined(__cplusplus)
1126# if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
1127# if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
1128# if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
1129# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1130 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1131 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1132 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1133 _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
1134 xpr \
1135 JSON_HEDLEY_DIAGNOSTIC_POP
1136# else
1137# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1138 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1139 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1140 _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
1141 xpr \
1142 JSON_HEDLEY_DIAGNOSTIC_POP
1143# endif
1144# else
1145# define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
1146 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1147 _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
1148 xpr \
1149 JSON_HEDLEY_DIAGNOSTIC_POP
1150# endif
1151# endif
1152#endif
1153#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
1154 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
1155#endif
1156
1157#if defined(JSON_HEDLEY_CONST_CAST)
1158 #undef JSON_HEDLEY_CONST_CAST
1159#endif
1160#if defined(__cplusplus)
1161# define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
1162#elif \
1163 JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
1164 JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
1165 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1166# define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
1167 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1168 JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
1169 ((T) (expr)); \
1170 JSON_HEDLEY_DIAGNOSTIC_POP \
1171 }))
1172#else
1173# define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
1174#endif
1175
1176#if defined(JSON_HEDLEY_REINTERPRET_CAST)
1177 #undef JSON_HEDLEY_REINTERPRET_CAST
1178#endif
1179#if defined(__cplusplus)
1180 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
1181#else
1182 #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
1183#endif
1184
1185#if defined(JSON_HEDLEY_STATIC_CAST)
1186 #undef JSON_HEDLEY_STATIC_CAST
1187#endif
1188#if defined(__cplusplus)
1189 #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
1190#else
1191 #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
1192#endif
1193
1194#if defined(JSON_HEDLEY_CPP_CAST)
1195 #undef JSON_HEDLEY_CPP_CAST
1196#endif
1197#if defined(__cplusplus)
1198# if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
1199# define JSON_HEDLEY_CPP_CAST(T, expr) \
1200 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1201 _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
1202 ((T) (expr)) \
1203 JSON_HEDLEY_DIAGNOSTIC_POP
1204# elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
1205# define JSON_HEDLEY_CPP_CAST(T, expr) \
1206 JSON_HEDLEY_DIAGNOSTIC_PUSH \
1207 _Pragma("diag_suppress=Pe137") \
1208 JSON_HEDLEY_DIAGNOSTIC_POP
1209# else
1210# define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
1211# endif
1212#else
1213# define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
1214#endif
1215
1216#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
1217 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1218#endif
1219#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
1220 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
1221#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1222 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
1223#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1224 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
1225#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1226 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
1227#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1228 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1229#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1230 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1231#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1232 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
1233#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1234 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
1235#elif \
1236 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1237 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1238 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1239 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1240 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1241 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1242 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1243 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1244 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1245 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1246 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
1247 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
1248#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
1249 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
1250#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
1251 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
1252#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1253 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
1254#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
1255 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
1256#else
1257 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
1258#endif
1259
1260#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
1261 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1262#endif
1263#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
1264 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
1265#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1266 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
1267#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1268 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
1269#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1270 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
1271#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
1272 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
1273#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
1274 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
1275#elif \
1276 JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
1277 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1278 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1279 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
1280 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1281#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
1282 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
1283#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1284 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
1285#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1286 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
1287#else
1288 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
1289#endif
1290
1291#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
1292 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1293#endif
1294#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
1295 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
1296#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
1297 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
1298#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
1299 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
1300#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1301 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
1302#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
1303 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
1304#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
1305 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
1306#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
1307 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1308#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
1309 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
1310#elif \
1311 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1312 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1313 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
1314 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
1315#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1316 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
1317#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1318 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
1319#else
1320 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
1321#endif
1322
1323#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
1324 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1325#endif
1326#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
1327 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
1328#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
1329 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
1330#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
1331 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
1332#else
1333 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
1334#endif
1335
1336#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
1337 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1338#endif
1339#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
1340 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
1341#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
1342 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
1343#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
1344 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
1345#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1346 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
1347#else
1348 #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
1349#endif
1350
1351#if defined(JSON_HEDLEY_DEPRECATED)
1352 #undef JSON_HEDLEY_DEPRECATED
1353#endif
1354#if defined(JSON_HEDLEY_DEPRECATED_FOR)
1355 #undef JSON_HEDLEY_DEPRECATED_FOR
1356#endif
1357#if \
1358 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1359 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1360 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
1361 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
1362#elif \
1363 (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
1364 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1365 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1366 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1367 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
1368 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1369 JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
1370 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
1371 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
1372 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1373 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
1374 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1375 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
1376 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
1377#elif defined(__cplusplus) && (__cplusplus >= 201402L)
1378 #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
1379 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
1380#elif \
1381 JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
1382 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1383 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1384 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1385 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1386 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1387 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1388 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1389 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1390 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1391 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1392 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1393 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1394 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1395 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1396 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1397 #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
1398 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
1399#elif \
1400 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1401 JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
1402 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1403 #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
1404 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
1405#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1406 #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
1407 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
1408#else
1409 #define JSON_HEDLEY_DEPRECATED(since)
1410 #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
1411#endif
1412
1413#if defined(JSON_HEDLEY_UNAVAILABLE)
1414 #undef JSON_HEDLEY_UNAVAILABLE
1415#endif
1416#if \
1417 JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
1418 JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
1419 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1420 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1421 #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
1422#else
1423 #define JSON_HEDLEY_UNAVAILABLE(available_since)
1424#endif
1425
1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
1427 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
1428#endif
1429#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
1430 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
1431#endif
1432#if \
1433 JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
1434 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
1435 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1436 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1437 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1438 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1439 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1440 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1441 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1442 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1443 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1444 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1445 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1446 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1447 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1448 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1449 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1450 #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
1451 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
1452#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
1453 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1454 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
1455#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
1456 #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1457 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
1458#elif defined(_Check_return_) /* SAL */
1459 #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
1460 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
1461#else
1462 #define JSON_HEDLEY_WARN_UNUSED_RESULT
1463 #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
1464#endif
1465
1466#if defined(JSON_HEDLEY_SENTINEL)
1467 #undef JSON_HEDLEY_SENTINEL
1468#endif
1469#if \
1470 JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
1471 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1472 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1473 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
1474 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1475 #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
1476#else
1477 #define JSON_HEDLEY_SENTINEL(position)
1478#endif
1479
1480#if defined(JSON_HEDLEY_NO_RETURN)
1481 #undef JSON_HEDLEY_NO_RETURN
1482#endif
1483#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1484 #define JSON_HEDLEY_NO_RETURN __noreturn
1485#elif \
1486 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1487 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1488 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1489#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
1490 #define JSON_HEDLEY_NO_RETURN _Noreturn
1491#elif defined(__cplusplus) && (__cplusplus >= 201103L)
1492 #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
1493#elif \
1494 JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
1495 JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
1496 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1497 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1498 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1499 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1500 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1501 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1502 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1503 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1504 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1505 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1506 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1507 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1508 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1509 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1510 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1511 #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
1512#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1513 #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
1514#elif \
1515 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1516 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1517 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1518#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1519 #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
1520#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1521 #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
1522#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1523 #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
1524#else
1525 #define JSON_HEDLEY_NO_RETURN
1526#endif
1527
1528#if defined(JSON_HEDLEY_NO_ESCAPE)
1529 #undef JSON_HEDLEY_NO_ESCAPE
1530#endif
1531#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
1532 #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
1533#else
1534 #define JSON_HEDLEY_NO_ESCAPE
1535#endif
1536
1537#if defined(JSON_HEDLEY_UNREACHABLE)
1538 #undef JSON_HEDLEY_UNREACHABLE
1539#endif
1540#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
1541 #undef JSON_HEDLEY_UNREACHABLE_RETURN
1542#endif
1543#if defined(JSON_HEDLEY_ASSUME)
1544 #undef JSON_HEDLEY_ASSUME
1545#endif
1546#if \
1547 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1548 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1549 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1550 #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
1551#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
1552 #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
1553#elif \
1554 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1555 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1556 #if defined(__cplusplus)
1557 #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
1558 #else
1559 #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
1560 #endif
1561#endif
1562#if \
1563 (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
1564 JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
1565 JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
1566 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1567 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
1568 JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
1569 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1570 #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
1571#elif defined(JSON_HEDLEY_ASSUME)
1572 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1573#endif
1574#if !defined(JSON_HEDLEY_ASSUME)
1575 #if defined(JSON_HEDLEY_UNREACHABLE)
1576 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
1577 #else
1578 #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
1579 #endif
1580#endif
1581#if defined(JSON_HEDLEY_UNREACHABLE)
1582 #if \
1583 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1584 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
1585 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
1586 #else
1587 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
1588 #endif
1589#else
1590 #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
1591#endif
1592#if !defined(JSON_HEDLEY_UNREACHABLE)
1593 #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
1594#endif
1595
1596JSON_HEDLEY_DIAGNOSTIC_PUSH
1597#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
1598 #pragma clang diagnostic ignored "-Wpedantic"
1599#endif
1600#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
1601 #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
1602#endif
1603#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
1604 #if defined(__clang__)
1605 #pragma clang diagnostic ignored "-Wvariadic-macros"
1606 #elif defined(JSON_HEDLEY_GCC_VERSION)
1607 #pragma GCC diagnostic ignored "-Wvariadic-macros"
1608 #endif
1609#endif
1610#if defined(JSON_HEDLEY_NON_NULL)
1611 #undef JSON_HEDLEY_NON_NULL
1612#endif
1613#if \
1614 JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
1615 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1616 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1617 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
1618 #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
1619#else
1620 #define JSON_HEDLEY_NON_NULL(...)
1621#endif
1622JSON_HEDLEY_DIAGNOSTIC_POP
1623
1624#if defined(JSON_HEDLEY_PRINTF_FORMAT)
1625 #undef JSON_HEDLEY_PRINTF_FORMAT
1626#endif
1627#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
1628 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
1629#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
1630 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
1631#elif \
1632 JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
1633 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1634 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1635 JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
1636 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1637 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1638 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1639 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1640 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1641 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1642 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1643 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1644 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1645 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1646 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1647 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1648 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1649 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
1650#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
1651 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
1652#else
1653 #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
1654#endif
1655
1656#if defined(JSON_HEDLEY_CONSTEXPR)
1657 #undef JSON_HEDLEY_CONSTEXPR
1658#endif
1659#if defined(__cplusplus)
1660 #if __cplusplus >= 201103L
1661 #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
1662 #endif
1663#endif
1664#if !defined(JSON_HEDLEY_CONSTEXPR)
1665 #define JSON_HEDLEY_CONSTEXPR
1666#endif
1667
1668#if defined(JSON_HEDLEY_PREDICT)
1669 #undef JSON_HEDLEY_PREDICT
1670#endif
1671#if defined(JSON_HEDLEY_LIKELY)
1672 #undef JSON_HEDLEY_LIKELY
1673#endif
1674#if defined(JSON_HEDLEY_UNLIKELY)
1675 #undef JSON_HEDLEY_UNLIKELY
1676#endif
1677#if defined(JSON_HEDLEY_UNPREDICTABLE)
1678 #undef JSON_HEDLEY_UNPREDICTABLE
1679#endif
1680#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
1681 #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
1682#endif
1683#if \
1684 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
1685 JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
1686 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1687# define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability( (expr), (value), (probability))
1688# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) __builtin_expect_with_probability(!!(expr), 1 , (probability))
1689# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) __builtin_expect_with_probability(!!(expr), 0 , (probability))
1690# define JSON_HEDLEY_LIKELY(expr) __builtin_expect (!!(expr), 1 )
1691# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect (!!(expr), 0 )
1692#elif \
1693 (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
1694 JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
1695 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1696 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
1697 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1698 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1699 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1700 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
1701 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1702 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
1703 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1704 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1705 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1706 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
1707 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
1708 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1709# define JSON_HEDLEY_PREDICT(expr, expected, probability) \
1710 (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
1711# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
1712 (__extension__ ({ \
1713 double hedley_probability_ = (probability); \
1714 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
1715 }))
1716# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
1717 (__extension__ ({ \
1718 double hedley_probability_ = (probability); \
1719 ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
1720 }))
1721# define JSON_HEDLEY_LIKELY(expr) __builtin_expect(!!(expr), 1)
1722# define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
1723#else
1724# define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
1725# define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
1726# define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
1727# define JSON_HEDLEY_LIKELY(expr) (!!(expr))
1728# define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
1729#endif
1730#if !defined(JSON_HEDLEY_UNPREDICTABLE)
1731 #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
1732#endif
1733
1734#if defined(JSON_HEDLEY_MALLOC)
1735 #undef JSON_HEDLEY_MALLOC
1736#endif
1737#if \
1738 JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
1739 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1740 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1741 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1742 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1743 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
1744 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1745 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1746 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1747 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1748 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1749 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1750 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1751 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1752 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1753 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1754 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1755 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1756 #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
1757#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1758 #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
1759#elif \
1760 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1761 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1762 #define JSON_HEDLEY_MALLOC __declspec(restrict)
1763#else
1764 #define JSON_HEDLEY_MALLOC
1765#endif
1766
1767#if defined(JSON_HEDLEY_PURE)
1768 #undef JSON_HEDLEY_PURE
1769#endif
1770#if \
1771 JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
1772 JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
1773 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1774 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1775 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1776 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1777 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1778 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1779 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1780 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1781 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1782 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1783 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1784 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1785 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1786 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1787 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1788 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1789 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1790# define JSON_HEDLEY_PURE __attribute__((__pure__))
1791#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1792# define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
1793#elif defined(__cplusplus) && \
1794 ( \
1795 JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
1796 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
1797 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
1798 )
1799# define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
1800#else
1801# define JSON_HEDLEY_PURE
1802#endif
1803
1804#if defined(JSON_HEDLEY_CONST)
1805 #undef JSON_HEDLEY_CONST
1806#endif
1807#if \
1808 JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
1809 JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
1810 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1811 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1812 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1813 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1814 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1815 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1816 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1817 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1818 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1819 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1820 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1821 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1822 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1823 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1824 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1825 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1826 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1827 #define JSON_HEDLEY_CONST __attribute__((__const__))
1828#elif \
1829 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
1830 #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
1831#else
1832 #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
1833#endif
1834
1835#if defined(JSON_HEDLEY_RESTRICT)
1836 #undef JSON_HEDLEY_RESTRICT
1837#endif
1838#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
1839 #define JSON_HEDLEY_RESTRICT restrict
1840#elif \
1841 JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
1842 JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
1843 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1844 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1845 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1846 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1847 JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
1848 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1849 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
1850 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
1851 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1852 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
1853 JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
1854 defined(__clang__) || \
1855 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1856 #define JSON_HEDLEY_RESTRICT __restrict
1857#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
1858 #define JSON_HEDLEY_RESTRICT _Restrict
1859#else
1860 #define JSON_HEDLEY_RESTRICT
1861#endif
1862
1863#if defined(JSON_HEDLEY_INLINE)
1864 #undef JSON_HEDLEY_INLINE
1865#endif
1866#if \
1867 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
1868 (defined(__cplusplus) && (__cplusplus >= 199711L))
1869 #define JSON_HEDLEY_INLINE inline
1870#elif \
1871 defined(JSON_HEDLEY_GCC_VERSION) || \
1872 JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
1873 #define JSON_HEDLEY_INLINE __inline__
1874#elif \
1875 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1876 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
1877 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1878 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
1879 JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
1880 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
1881 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
1882 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1883 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1884 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
1885 #define JSON_HEDLEY_INLINE __inline
1886#else
1887 #define JSON_HEDLEY_INLINE
1888#endif
1889
1890#if defined(JSON_HEDLEY_ALWAYS_INLINE)
1891 #undef JSON_HEDLEY_ALWAYS_INLINE
1892#endif
1893#if \
1894 JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
1895 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1896 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1897 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1898 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1899 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1900 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1901 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1902 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1903 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1904 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1905 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1906 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1907 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1908 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1909 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1910 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1911 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1912 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1913# define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
1914#elif \
1915 JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
1916 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1917# define JSON_HEDLEY_ALWAYS_INLINE __forceinline
1918#elif defined(__cplusplus) && \
1919 ( \
1920 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1921 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1922 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1923 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
1924 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1925 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
1926 )
1927# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
1928#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1929# define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
1930#else
1931# define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
1932#endif
1933
1934#if defined(JSON_HEDLEY_NEVER_INLINE)
1935 #undef JSON_HEDLEY_NEVER_INLINE
1936#endif
1937#if \
1938 JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
1939 JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
1940 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1941 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1942 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1943 JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
1944 JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
1945 (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1946 JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
1947 (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1948 JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
1949 (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1950 JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
1951 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
1952 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
1953 JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
1954 JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
1955 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
1956 JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
1957 #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
1958#elif \
1959 JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
1960 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
1961 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1962#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
1963 #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
1964#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
1965 #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
1966#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
1967 #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
1968#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
1969 #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
1970#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
1971 #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
1972#else
1973 #define JSON_HEDLEY_NEVER_INLINE
1974#endif
1975
1976#if defined(JSON_HEDLEY_PRIVATE)
1977 #undef JSON_HEDLEY_PRIVATE
1978#endif
1979#if defined(JSON_HEDLEY_PUBLIC)
1980 #undef JSON_HEDLEY_PUBLIC
1981#endif
1982#if defined(JSON_HEDLEY_IMPORT)
1983 #undef JSON_HEDLEY_IMPORT
1984#endif
1985#if defined(_WIN32) || defined(__CYGWIN__)
1986# define JSON_HEDLEY_PRIVATE
1987# define JSON_HEDLEY_PUBLIC __declspec(dllexport)
1988# define JSON_HEDLEY_IMPORT __declspec(dllimport)
1989#else
1990# if \
1991 JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
1992 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
1993 JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
1994 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
1995 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
1996 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
1997 ( \
1998 defined(__TI_EABI__) && \
1999 ( \
2000 (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
2001 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
2002 ) \
2003 ) || \
2004 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2005# define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
2006# define JSON_HEDLEY_PUBLIC __attribute__((__visibility__("default")))
2007# else
2008# define JSON_HEDLEY_PRIVATE
2009# define JSON_HEDLEY_PUBLIC
2010# endif
2011# define JSON_HEDLEY_IMPORT extern
2012#endif
2013
2014#if defined(JSON_HEDLEY_NO_THROW)
2015 #undef JSON_HEDLEY_NO_THROW
2016#endif
2017#if \
2018 JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
2019 JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
2020 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2021 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2022 #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
2023#elif \
2024 JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
2025 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
2026 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
2027 #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
2028#else
2029 #define JSON_HEDLEY_NO_THROW
2030#endif
2031
2032#if defined(JSON_HEDLEY_FALL_THROUGH)
2033 #undef JSON_HEDLEY_FALL_THROUGH
2034#endif
2035#if \
2036 JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
2037 JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
2038 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2039 #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
2040#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
2041 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
2042#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
2043 #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
2044#elif defined(__fallthrough) /* SAL */
2045 #define JSON_HEDLEY_FALL_THROUGH __fallthrough
2046#else
2047 #define JSON_HEDLEY_FALL_THROUGH
2048#endif
2049
2050#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
2051 #undef JSON_HEDLEY_RETURNS_NON_NULL
2052#endif
2053#if \
2054 JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
2055 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2056 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2057 #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
2058#elif defined(_Ret_notnull_) /* SAL */
2059 #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
2060#else
2061 #define JSON_HEDLEY_RETURNS_NON_NULL
2062#endif
2063
2064#if defined(JSON_HEDLEY_ARRAY_PARAM)
2065 #undef JSON_HEDLEY_ARRAY_PARAM
2066#endif
2067#if \
2068 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
2069 !defined(__STDC_NO_VLA__) && \
2070 !defined(__cplusplus) && \
2071 !defined(JSON_HEDLEY_PGI_VERSION) && \
2072 !defined(JSON_HEDLEY_TINYC_VERSION)
2073 #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
2074#else
2075 #define JSON_HEDLEY_ARRAY_PARAM(name)
2076#endif
2077
2078#if defined(JSON_HEDLEY_IS_CONSTANT)
2079 #undef JSON_HEDLEY_IS_CONSTANT
2080#endif
2081#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
2082 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
2083#endif
2084/* JSON_HEDLEY_IS_CONSTEXPR_ is for
2085 HEDLEY INTERNAL USE ONLY. API subject to change without notice. */
2086#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2087 #undef JSON_HEDLEY_IS_CONSTEXPR_
2088#endif
2089#if \
2090 JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
2091 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2092 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2093 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
2094 JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
2095 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2096 JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
2097 (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
2098 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2099 JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
2100 #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
2101#endif
2102#if !defined(__cplusplus)
2103# if \
2104 JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
2105 JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
2106 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2107 JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
2108 JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
2109 JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
2110 JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
2111#if defined(__INTPTR_TYPE__)
2112 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
2113#else
2114 #include <stdint.h>
2115 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
2116#endif
2117# elif \
2118 ( \
2119 defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
2120 !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
2121 !defined(JSON_HEDLEY_PGI_VERSION) && \
2122 !defined(JSON_HEDLEY_IAR_VERSION)) || \
2123 (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
2124 JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
2125 JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
2126 JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
2127 JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
2128#if defined(__INTPTR_TYPE__)
2129 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
2130#else
2131 #include <stdint.h>
2132 #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
2133#endif
2134# elif \
2135 defined(JSON_HEDLEY_GCC_VERSION) || \
2136 defined(JSON_HEDLEY_INTEL_VERSION) || \
2137 defined(JSON_HEDLEY_TINYC_VERSION) || \
2138 defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
2139 JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
2140 defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
2141 defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
2142 defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
2143 defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
2144 defined(__clang__)
2145# define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
2146 sizeof(void) != \
2147 sizeof(*( \
2148 1 ? \
2149 ((void*) ((expr) * 0L) ) : \
2150((struct { char v[sizeof(void) * 2]; } *) 1) \
2151 ) \
2152 ) \
2153 )
2154# endif
2155#endif
2156#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
2157 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2158 #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
2159 #endif
2160 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
2161#else
2162 #if !defined(JSON_HEDLEY_IS_CONSTANT)
2163 #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
2164 #endif
2165 #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
2166#endif
2167
2168#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
2169 #undef JSON_HEDLEY_BEGIN_C_DECLS
2170#endif
2171#if defined(JSON_HEDLEY_END_C_DECLS)
2172 #undef JSON_HEDLEY_END_C_DECLS
2173#endif
2174#if defined(JSON_HEDLEY_C_DECL)
2175 #undef JSON_HEDLEY_C_DECL
2176#endif
2177#if defined(__cplusplus)
2178 #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
2179 #define JSON_HEDLEY_END_C_DECLS }
2180 #define JSON_HEDLEY_C_DECL extern "C"
2181#else
2182 #define JSON_HEDLEY_BEGIN_C_DECLS
2183 #define JSON_HEDLEY_END_C_DECLS
2184 #define JSON_HEDLEY_C_DECL
2185#endif
2186
2187#if defined(JSON_HEDLEY_STATIC_ASSERT)
2188 #undef JSON_HEDLEY_STATIC_ASSERT
2189#endif
2190#if \
2191 !defined(__cplusplus) && ( \
2192 (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
2193 (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
2194 JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
2195 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
2196 defined(_Static_assert) \
2197 )
2198# define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
2199#elif \
2200 (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
2201 JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
2202 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2203# define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
2204#else
2205# define JSON_HEDLEY_STATIC_ASSERT(expr, message)
2206#endif
2207
2208#if defined(JSON_HEDLEY_NULL)
2209 #undef JSON_HEDLEY_NULL
2210#endif
2211#if defined(__cplusplus)
2212 #if __cplusplus >= 201103L
2213 #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
2214 #elif defined(NULL)
2215 #define JSON_HEDLEY_NULL NULL
2216 #else
2217 #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
2218 #endif
2219#elif defined(NULL)
2220 #define JSON_HEDLEY_NULL NULL
2221#else
2222 #define JSON_HEDLEY_NULL ((void*) 0)
2223#endif
2224
2225#if defined(JSON_HEDLEY_MESSAGE)
2226 #undef JSON_HEDLEY_MESSAGE
2227#endif
2228#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2229# define JSON_HEDLEY_MESSAGE(msg) \
2230 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2231 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2232 JSON_HEDLEY_PRAGMA(message msg) \
2233 JSON_HEDLEY_DIAGNOSTIC_POP
2234#elif \
2235 JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
2236 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2237# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
2238#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
2239# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
2240#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
2241# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2242#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
2243# define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
2244#else
2245# define JSON_HEDLEY_MESSAGE(msg)
2246#endif
2247
2248#if defined(JSON_HEDLEY_WARNING)
2249 #undef JSON_HEDLEY_WARNING
2250#endif
2251#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
2252# define JSON_HEDLEY_WARNING(msg) \
2253 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2254 JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
2255 JSON_HEDLEY_PRAGMA(clang warning msg) \
2256 JSON_HEDLEY_DIAGNOSTIC_POP
2257#elif \
2258 JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
2259 JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
2260 JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
2261# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
2262#elif \
2263 JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
2264 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2265# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
2266#else
2267# define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
2268#endif
2269
2270#if defined(JSON_HEDLEY_REQUIRE)
2271 #undef JSON_HEDLEY_REQUIRE
2272#endif
2273#if defined(JSON_HEDLEY_REQUIRE_MSG)
2274 #undef JSON_HEDLEY_REQUIRE_MSG
2275#endif
2276#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
2277# if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
2278# define JSON_HEDLEY_REQUIRE(expr) \
2279 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2280 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2281 __attribute__((diagnose_if(!(expr), #expr, "error"))) \
2282 JSON_HEDLEY_DIAGNOSTIC_POP
2283# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
2284 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2285 _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
2286 __attribute__((diagnose_if(!(expr), msg, "error"))) \
2287 JSON_HEDLEY_DIAGNOSTIC_POP
2288# else
2289# define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
2290# define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
2291# endif
2292#else
2293# define JSON_HEDLEY_REQUIRE(expr)
2294# define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
2295#endif
2296
2297#if defined(JSON_HEDLEY_FLAGS)
2298 #undef JSON_HEDLEY_FLAGS
2299#endif
2300#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
2301 #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
2302#else
2303 #define JSON_HEDLEY_FLAGS
2304#endif
2305
2306#if defined(JSON_HEDLEY_FLAGS_CAST)
2307 #undef JSON_HEDLEY_FLAGS_CAST
2308#endif
2309#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
2310# define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
2311 JSON_HEDLEY_DIAGNOSTIC_PUSH \
2312 _Pragma("warning(disable:188)") \
2313 ((T) (expr)); \
2314 JSON_HEDLEY_DIAGNOSTIC_POP \
2315 }))
2316#else
2317# define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
2318#endif
2319
2320#if defined(JSON_HEDLEY_EMPTY_BASES)
2321 #undef JSON_HEDLEY_EMPTY_BASES
2322#endif
2323#if \
2324 (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
2325 JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
2326 #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
2327#else
2328 #define JSON_HEDLEY_EMPTY_BASES
2329#endif
2330
2331/* Remaining macros are deprecated. */
2332
2333#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
2334 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
2335#endif
2336#if defined(__clang__)
2337 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
2338#else
2339 #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
2340#endif
2341
2342#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
2343 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
2344#endif
2345#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
2346
2347#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
2348 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
2349#endif
2350#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
2351
2352#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
2353 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
2354#endif
2355#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
2356
2357#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
2358 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
2359#endif
2360#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
2361
2362#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
2363 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
2364#endif
2365#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
2366
2367#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
2368 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
2369#endif
2370#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
2371
2372#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
2373 #undef JSON_HEDLEY_CLANG_HAS_WARNING
2374#endif
2375#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
2376
2377#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
2378
2379
2380// This file contains all internal macro definitions (except those affecting ABI)
2381// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
2382
2383// #include <nlohmann/detail/abi_macros.hpp>
2384
2385
2386// exclude unsupported compilers
2387#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
2388 #if defined(__clang__)
2389 #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
2390 #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
2391 #endif
2392 #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
2393 #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
2394 #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
2395 #endif
2396 #endif
2397#endif
2398
2399// C++ language standard detection
2400// if the user manually specified the used c++ version this is skipped
2401#if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
2402 #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
2403 #define JSON_HAS_CPP_20
2404 #define JSON_HAS_CPP_17
2405 #define JSON_HAS_CPP_14
2406 #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
2407 #define JSON_HAS_CPP_17
2408 #define JSON_HAS_CPP_14
2409 #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
2410 #define JSON_HAS_CPP_14
2411 #endif
2412 // the cpp 11 flag is always specified because it is the minimal required version
2413 #define JSON_HAS_CPP_11
2414#endif
2415
2416#ifdef __has_include
2417 #if __has_include(<version>)
2418 #include <version>
2419 #endif
2420#endif
2421
2422#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
2423 #ifdef JSON_HAS_CPP_17
2424 #if defined(__cpp_lib_filesystem)
2425 #define JSON_HAS_FILESYSTEM 1
2426 #elif defined(__cpp_lib_experimental_filesystem)
2427 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2428 #elif !defined(__has_include)
2429 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2430 #elif __has_include(<filesystem>)
2431 #define JSON_HAS_FILESYSTEM 1
2432 #elif __has_include(<experimental/filesystem>)
2433 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
2434 #endif
2435
2436 // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
2437 #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
2438 #undef JSON_HAS_FILESYSTEM
2439 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2440 #endif
2441
2442 // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
2443 #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
2444 #undef JSON_HAS_FILESYSTEM
2445 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2446 #endif
2447
2448 // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
2449 #if defined(__clang_major__) && __clang_major__ < 7
2450 #undef JSON_HAS_FILESYSTEM
2451 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2452 #endif
2453
2454 // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
2455 #if defined(_MSC_VER) && _MSC_VER < 1914
2456 #undef JSON_HAS_FILESYSTEM
2457 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2458 #endif
2459
2460 // no filesystem support before iOS 13
2461 #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
2462 #undef JSON_HAS_FILESYSTEM
2463 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2464 #endif
2465
2466 // no filesystem support before macOS Catalina
2467 #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
2468 #undef JSON_HAS_FILESYSTEM
2469 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2470 #endif
2471 #endif
2472#endif
2473
2474#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
2475 #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
2476#endif
2477
2478#ifndef JSON_HAS_FILESYSTEM
2479 #define JSON_HAS_FILESYSTEM 0
2480#endif
2481
2482#ifndef JSON_HAS_THREE_WAY_COMPARISON
2483 #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
2484 && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
2485 #define JSON_HAS_THREE_WAY_COMPARISON 1
2486 #else
2487 #define JSON_HAS_THREE_WAY_COMPARISON 0
2488 #endif
2489#endif
2490
2491#ifndef JSON_HAS_RANGES
2492 // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
2493 #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
2494 #define JSON_HAS_RANGES 0
2495 #elif defined(__cpp_lib_ranges)
2496 #define JSON_HAS_RANGES 1
2497 #else
2498 #define JSON_HAS_RANGES 0
2499 #endif
2500#endif
2501
2502#ifndef JSON_HAS_STATIC_RTTI
2503 #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
2504 #define JSON_HAS_STATIC_RTTI 1
2505 #else
2506 #define JSON_HAS_STATIC_RTTI 0
2507 #endif
2508#endif
2509
2510#ifdef JSON_HAS_CPP_17
2511 #define JSON_INLINE_VARIABLE inline
2512#else
2513 #define JSON_INLINE_VARIABLE
2514#endif
2515
2516#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
2517 #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
2518#else
2519 #define JSON_NO_UNIQUE_ADDRESS
2520#endif
2521
2522// disable documentation warnings on clang
2523#if defined(__clang__)
2524 #pragma clang diagnostic push
2525 #pragma clang diagnostic ignored "-Wdocumentation"
2526 #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
2527#endif
2528
2529// allow disabling exceptions
2530#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
2531 #define JSON_THROW(exception) throw exception
2532 #define JSON_TRY try
2533 #define JSON_CATCH(exception) catch(exception)
2534 #define JSON_INTERNAL_CATCH(exception) catch(exception)
2535#else
2536 #include <cstdlib>
2537 #define JSON_THROW(exception) std::abort()
2538 #define JSON_TRY if(true)
2539 #define JSON_CATCH(exception) if(false)
2540 #define JSON_INTERNAL_CATCH(exception) if(false)
2541#endif
2542
2543// override exception macros
2544#if defined(JSON_THROW_USER)
2545 #undef JSON_THROW
2546 #define JSON_THROW JSON_THROW_USER
2547#endif
2548#if defined(JSON_TRY_USER)
2549 #undef JSON_TRY
2550 #define JSON_TRY JSON_TRY_USER
2551#endif
2552#if defined(JSON_CATCH_USER)
2553 #undef JSON_CATCH
2554 #define JSON_CATCH JSON_CATCH_USER
2555 #undef JSON_INTERNAL_CATCH
2556 #define JSON_INTERNAL_CATCH JSON_CATCH_USER
2557#endif
2558#if defined(JSON_INTERNAL_CATCH_USER)
2559 #undef JSON_INTERNAL_CATCH
2560 #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
2561#endif
2562
2563// allow overriding assert
2564#if !defined(JSON_ASSERT)
2565 #include <cassert> // assert
2566 #define JSON_ASSERT(x) assert(x)
2567#endif
2568
2569// allow to access some private functions (needed by the test suite)
2570#if defined(JSON_TESTS_PRIVATE)
2571 #define JSON_PRIVATE_UNLESS_TESTED public
2572#else
2573 #define JSON_PRIVATE_UNLESS_TESTED private
2574#endif
2575
2581#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...) \
2582 template<typename BasicJsonType> \
2583 inline void to_json(BasicJsonType& j, const ENUM_TYPE& e) \
2584 { \
2585 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2586 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2587 auto it = std::find_if(std::begin(m), std::end(m), \
2588 [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2589 { \
2590 return ej_pair.first == e; \
2591 }); \
2592 j = ((it != std::end(m)) ? it : std::begin(m))->second; \
2593 } \
2594 template<typename BasicJsonType> \
2595 inline void from_json(const BasicJsonType& j, ENUM_TYPE& e) \
2596 { \
2597 static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!"); \
2598 static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__; \
2599 auto it = std::find_if(std::begin(m), std::end(m), \
2600 [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
2601 { \
2602 return ej_pair.second == j; \
2603 }); \
2604 e = ((it != std::end(m)) ? it : std::begin(m))->first; \
2605 }
2606
2607// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
2608// may be removed in the future once the class is split.
2609
2610#define NLOHMANN_BASIC_JSON_TPL_DECLARATION \
2611 template<template<typename, typename, typename...> class ObjectType, \
2612 template<typename, typename...> class ArrayType, \
2613 class StringType, class BooleanType, class NumberIntegerType, \
2614 class NumberUnsignedType, class NumberFloatType, \
2615 template<typename> class AllocatorType, \
2616 template<typename, typename = void> class JSONSerializer, \
2617 class BinaryType, \
2618 class CustomBaseClass>
2619
2620#define NLOHMANN_BASIC_JSON_TPL \
2621 basic_json<ObjectType, ArrayType, StringType, BooleanType, \
2622 NumberIntegerType, NumberUnsignedType, NumberFloatType, \
2623 AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
2624
2625// Macros to simplify conversion from/to types
2626
2627#define NLOHMANN_JSON_EXPAND( x ) x
2628#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
2629#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
2630 NLOHMANN_JSON_PASTE64, \
2631 NLOHMANN_JSON_PASTE63, \
2632 NLOHMANN_JSON_PASTE62, \
2633 NLOHMANN_JSON_PASTE61, \
2634 NLOHMANN_JSON_PASTE60, \
2635 NLOHMANN_JSON_PASTE59, \
2636 NLOHMANN_JSON_PASTE58, \
2637 NLOHMANN_JSON_PASTE57, \
2638 NLOHMANN_JSON_PASTE56, \
2639 NLOHMANN_JSON_PASTE55, \
2640 NLOHMANN_JSON_PASTE54, \
2641 NLOHMANN_JSON_PASTE53, \
2642 NLOHMANN_JSON_PASTE52, \
2643 NLOHMANN_JSON_PASTE51, \
2644 NLOHMANN_JSON_PASTE50, \
2645 NLOHMANN_JSON_PASTE49, \
2646 NLOHMANN_JSON_PASTE48, \
2647 NLOHMANN_JSON_PASTE47, \
2648 NLOHMANN_JSON_PASTE46, \
2649 NLOHMANN_JSON_PASTE45, \
2650 NLOHMANN_JSON_PASTE44, \
2651 NLOHMANN_JSON_PASTE43, \
2652 NLOHMANN_JSON_PASTE42, \
2653 NLOHMANN_JSON_PASTE41, \
2654 NLOHMANN_JSON_PASTE40, \
2655 NLOHMANN_JSON_PASTE39, \
2656 NLOHMANN_JSON_PASTE38, \
2657 NLOHMANN_JSON_PASTE37, \
2658 NLOHMANN_JSON_PASTE36, \
2659 NLOHMANN_JSON_PASTE35, \
2660 NLOHMANN_JSON_PASTE34, \
2661 NLOHMANN_JSON_PASTE33, \
2662 NLOHMANN_JSON_PASTE32, \
2663 NLOHMANN_JSON_PASTE31, \
2664 NLOHMANN_JSON_PASTE30, \
2665 NLOHMANN_JSON_PASTE29, \
2666 NLOHMANN_JSON_PASTE28, \
2667 NLOHMANN_JSON_PASTE27, \
2668 NLOHMANN_JSON_PASTE26, \
2669 NLOHMANN_JSON_PASTE25, \
2670 NLOHMANN_JSON_PASTE24, \
2671 NLOHMANN_JSON_PASTE23, \
2672 NLOHMANN_JSON_PASTE22, \
2673 NLOHMANN_JSON_PASTE21, \
2674 NLOHMANN_JSON_PASTE20, \
2675 NLOHMANN_JSON_PASTE19, \
2676 NLOHMANN_JSON_PASTE18, \
2677 NLOHMANN_JSON_PASTE17, \
2678 NLOHMANN_JSON_PASTE16, \
2679 NLOHMANN_JSON_PASTE15, \
2680 NLOHMANN_JSON_PASTE14, \
2681 NLOHMANN_JSON_PASTE13, \
2682 NLOHMANN_JSON_PASTE12, \
2683 NLOHMANN_JSON_PASTE11, \
2684 NLOHMANN_JSON_PASTE10, \
2685 NLOHMANN_JSON_PASTE9, \
2686 NLOHMANN_JSON_PASTE8, \
2687 NLOHMANN_JSON_PASTE7, \
2688 NLOHMANN_JSON_PASTE6, \
2689 NLOHMANN_JSON_PASTE5, \
2690 NLOHMANN_JSON_PASTE4, \
2691 NLOHMANN_JSON_PASTE3, \
2692 NLOHMANN_JSON_PASTE2, \
2693 NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
2694#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
2695#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
2696#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
2697#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
2698#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
2699#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)
2700#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)
2701#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)
2702#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)
2703#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)
2704#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)
2705#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)
2706#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)
2707#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)
2708#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)
2709#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)
2710#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)
2711#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)
2712#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)
2713#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)
2714#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)
2715#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)
2716#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)
2717#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)
2718#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)
2719#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)
2720#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)
2721#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)
2722#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)
2723#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)
2724#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)
2725#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)
2726#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)
2727#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)
2728#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)
2729#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)
2730#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)
2731#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)
2732#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)
2733#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)
2734#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)
2735#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)
2736#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)
2737#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)
2738#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)
2739#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)
2740#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)
2741#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)
2742#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)
2743#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)
2744#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)
2745#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)
2746#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)
2747#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)
2748#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)
2749#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)
2750#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)
2751#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)
2752#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)
2753#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)
2754#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)
2755#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)
2756#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)
2757
2758#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
2759#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
2760#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
2761
2767#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...) \
2768 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__)) } \
2769 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__)) }
2770
2771#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2772 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__)) } \
2773 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__)) }
2774
2775#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2776 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__)) }
2777
2783#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...) \
2784 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__)) } \
2785 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__)) }
2786
2787#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...) \
2788 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__)) }
2789
2790#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...) \
2791 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__)) } \
2792 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__)) }
2793
2794// inspired from https://stackoverflow.com/a/26745591
2795// allows to call any std function as if (e.g. with begin):
2796// using std::begin; begin(x);
2797//
2798// it allows using the detected idiom to retrieve the return type
2799// of such an expression
2800#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name) \
2801 namespace detail { \
2802 using std::std_name; \
2803 \
2804 template<typename... T> \
2805 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2806 } \
2807 \
2808 namespace detail2 { \
2809 struct std_name##_tag \
2810 { \
2811 }; \
2812 \
2813 template<typename... T> \
2814 std_name##_tag std_name(T&&...); \
2815 \
2816 template<typename... T> \
2817 using result_of_##std_name = decltype(std_name(std::declval<T>()...)); \
2818 \
2819 template<typename... T> \
2820 struct would_call_std_##std_name \
2821 { \
2822 static constexpr auto const value = ::nlohmann::detail:: \
2823 is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
2824 }; \
2825 } /* namespace detail2 */ \
2826 \
2827 template<typename... T> \
2828 struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...> \
2829 { \
2830 }
2831
2832#ifndef JSON_USE_IMPLICIT_CONVERSIONS
2833 #define JSON_USE_IMPLICIT_CONVERSIONS 1
2834#endif
2835
2836#if JSON_USE_IMPLICIT_CONVERSIONS
2837 #define JSON_EXPLICIT
2838#else
2839 #define JSON_EXPLICIT explicit
2840#endif
2841
2842#ifndef JSON_DISABLE_ENUM_SERIALIZATION
2843 #define JSON_DISABLE_ENUM_SERIALIZATION 0
2844#endif
2845
2846#ifndef JSON_USE_GLOBAL_UDLS
2847 #define JSON_USE_GLOBAL_UDLS 1
2848#endif
2849
2850#if JSON_HAS_THREE_WAY_COMPARISON
2851 #include <compare> // partial_ordering
2852#endif
2853
2854NLOHMANN_JSON_NAMESPACE_BEGIN
2855namespace detail
2856{
2857
2859// JSON type enumeration //
2861
2886enum class value_t : std::uint8_t
2887{
2888 null,
2889 object,
2890 array,
2891 string,
2892 boolean,
2895 number_float,
2896 binary,
2897 discarded
2898};
2899
2913#if JSON_HAS_THREE_WAY_COMPARISON
2914 inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
2915#else
2916 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2917#endif
2918{
2919 static constexpr std::array<std::uint8_t, 9> order = {{
2920 0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
2921 1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
2922 6 /* binary */
2923 }
2924 };
2925
2926 const auto l_index = static_cast<std::size_t>(lhs);
2927 const auto r_index = static_cast<std::size_t>(rhs);
2928#if JSON_HAS_THREE_WAY_COMPARISON
2929 if (l_index < order.size() && r_index < order.size())
2930 {
2931 return order[l_index] <=> order[r_index]; // *NOPAD*
2932 }
2933 return std::partial_ordering::unordered;
2934#else
2935 return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
2936#endif
2937}
2938
2939// GCC selects the built-in operator< over an operator rewritten from
2940// a user-defined spaceship operator
2941// Clang, MSVC, and ICC select the rewritten candidate
2942// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
2943#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
2944inline bool operator<(const value_t lhs, const value_t rhs) noexcept
2945{
2946 return std::is_lt(lhs <=> rhs); // *NOPAD*
2947}
2948#endif
2949
2950} // namespace detail
2951NLOHMANN_JSON_NAMESPACE_END
2952
2953// #include <nlohmann/detail/string_escape.hpp>
2954// __ _____ _____ _____
2955// __| | __| | | | JSON for Modern C++
2956// | | |__ | | | | | | version 3.11.3
2957// |_____|_____|_____|_|___| https://github.com/nlohmann/json
2958//
2959// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
2960// SPDX-License-Identifier: MIT
2961
2962
2963
2964// #include <nlohmann/detail/abi_macros.hpp>
2965
2966
2967NLOHMANN_JSON_NAMESPACE_BEGIN
2968namespace detail
2969{
2970
2984template<typename StringType>
2985inline void replace_substring(StringType& s, const StringType& f,
2986 const StringType& t)
2987{
2988 JSON_ASSERT(!f.empty());
2989 for (auto pos = s.find(f); // find first occurrence of f
2990 pos != StringType::npos; // make sure f was found
2991 s.replace(pos, f.size(), t), // replace with t, and
2992 pos = s.find(f, pos + t.size())) // find next occurrence of f
2993 {}
2994}
2995
3003template<typename StringType>
3004inline StringType escape(StringType s)
3005{
3006 replace_substring(s, StringType{"~"}, StringType{"~0"});
3007 replace_substring(s, StringType{"/"}, StringType{"~1"});
3008 return s;
3009}
3010
3018template<typename StringType>
3019static void unescape(StringType& s)
3020{
3021 replace_substring(s, StringType{"~1"}, StringType{"/"});
3022 replace_substring(s, StringType{"~0"}, StringType{"~"});
3023}
3024
3025} // namespace detail
3026NLOHMANN_JSON_NAMESPACE_END
3027
3028// #include <nlohmann/detail/input/position_t.hpp>
3029// __ _____ _____ _____
3030// __| | __| | | | JSON for Modern C++
3031// | | |__ | | | | | | version 3.11.3
3032// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3033//
3034// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3035// SPDX-License-Identifier: MIT
3036
3037
3038
3039#include <cstddef> // size_t
3040
3041// #include <nlohmann/detail/abi_macros.hpp>
3042
3043
3044NLOHMANN_JSON_NAMESPACE_BEGIN
3045namespace detail
3046{
3047
3050{
3052 std::size_t chars_read_total = 0;
3056 std::size_t lines_read = 0;
3057
3059 constexpr operator size_t() const
3060 {
3061 return chars_read_total;
3062 }
3063};
3064
3065} // namespace detail
3066NLOHMANN_JSON_NAMESPACE_END
3067
3068// #include <nlohmann/detail/macro_scope.hpp>
3069
3070// #include <nlohmann/detail/meta/cpp_future.hpp>
3071// __ _____ _____ _____
3072// __| | __| | | | JSON for Modern C++
3073// | | |__ | | | | | | version 3.11.3
3074// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3075//
3076// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3077// SPDX-FileCopyrightText: 2018 The Abseil Authors
3078// SPDX-License-Identifier: MIT
3079
3080
3081
3082#include <array> // array
3083#include <cstddef> // size_t
3084#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
3085#include <utility> // index_sequence, make_index_sequence, index_sequence_for
3086
3087// #include <nlohmann/detail/macro_scope.hpp>
3088
3089
3090NLOHMANN_JSON_NAMESPACE_BEGIN
3091namespace detail
3092{
3093
3094template<typename T>
3095using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
3096
3097#ifdef JSON_HAS_CPP_14
3098
3099// the following utilities are natively available in C++14
3100using std::enable_if_t;
3101using std::index_sequence;
3102using std::make_index_sequence;
3103using std::index_sequence_for;
3104
3105#else
3106
3107// alias templates to reduce boilerplate
3108template<bool B, typename T = void>
3109using enable_if_t = typename std::enable_if<B, T>::type;
3110
3111// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
3112// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
3113
3115
3116// integer_sequence
3117//
3118// Class template representing a compile-time integer sequence. An instantiation
3119// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
3120// type through its template arguments (which is a common need when
3121// working with C++11 variadic templates). `absl::integer_sequence` is designed
3122// to be a drop-in replacement for C++14's `std::integer_sequence`.
3123//
3124// Example:
3125//
3126// template< class T, T... Ints >
3127// void user_function(integer_sequence<T, Ints...>);
3128//
3129// int main()
3130// {
3131// // user_function's `T` will be deduced to `int` and `Ints...`
3132// // will be deduced to `0, 1, 2, 3, 4`.
3133// user_function(make_integer_sequence<int, 5>());
3134// }
3135template <typename T, T... Ints>
3137{
3138 using value_type = T;
3139 static constexpr std::size_t size() noexcept
3140 {
3141 return sizeof...(Ints);
3142 }
3143};
3144
3145// index_sequence
3146//
3147// A helper template for an `integer_sequence` of `size_t`,
3148// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
3149// `std::index_sequence`.
3150template <size_t... Ints>
3151using index_sequence = integer_sequence<size_t, Ints...>;
3152
3153namespace utility_internal
3154{
3155
3156template <typename Seq, size_t SeqSize, size_t Rem>
3157struct Extend;
3158
3159// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
3160template <typename T, T... Ints, size_t SeqSize>
3161struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
3162{
3163 using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
3164};
3165
3166template <typename T, T... Ints, size_t SeqSize>
3167struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
3168{
3169 using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
3170};
3171
3172// Recursion helper for 'make_integer_sequence<T, N>'.
3173// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
3174template <typename T, size_t N>
3175struct Gen
3176{
3177 using type =
3178 typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
3179};
3180
3181template <typename T>
3182struct Gen<T, 0>
3183{
3184 using type = integer_sequence<T>;
3185};
3186
3187} // namespace utility_internal
3188
3189// Compile-time sequences of integers
3190
3191// make_integer_sequence
3192//
3193// This template alias is equivalent to
3194// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
3195// replacement for C++14's `std::make_integer_sequence`.
3196template <typename T, T N>
3197using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
3198
3199// make_index_sequence
3200//
3201// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
3202// and is designed to be a drop-in replacement for C++14's
3203// `std::make_index_sequence`.
3204template <size_t N>
3205using make_index_sequence = make_integer_sequence<size_t, N>;
3206
3207// index_sequence_for
3208//
3209// Converts a typename pack into an index sequence of the same length, and
3210// is designed to be a drop-in replacement for C++14's
3211// `std::index_sequence_for()`
3212template <typename... Ts>
3213using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
3214
3216
3217#endif
3218
3219// dispatch utility (taken from ranges-v3)
3220template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
3221template<> struct priority_tag<0> {};
3222
3223// taken from ranges-v3
3224template<typename T>
3226{
3227 static JSON_INLINE_VARIABLE constexpr T value{};
3228};
3229
3230#ifndef JSON_HAS_CPP_17
3231 template<typename T>
3232 constexpr T static_const<T>::value;
3233#endif
3234
3235template<typename T, typename... Args>
3236inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
3237{
3238 return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
3239}
3240
3241} // namespace detail
3242NLOHMANN_JSON_NAMESPACE_END
3243
3244// #include <nlohmann/detail/meta/type_traits.hpp>
3245// __ _____ _____ _____
3246// __| | __| | | | JSON for Modern C++
3247// | | |__ | | | | | | version 3.11.3
3248// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3249//
3250// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3251// SPDX-License-Identifier: MIT
3252
3253
3254
3255#include <limits> // numeric_limits
3256#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
3257#include <utility> // declval
3258#include <tuple> // tuple
3259#include <string> // char_traits
3260
3261// #include <nlohmann/detail/iterators/iterator_traits.hpp>
3262// __ _____ _____ _____
3263// __| | __| | | | JSON for Modern C++
3264// | | |__ | | | | | | version 3.11.3
3265// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3266//
3267// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3268// SPDX-License-Identifier: MIT
3269
3270
3271
3272#include <iterator> // random_access_iterator_tag
3273
3274// #include <nlohmann/detail/abi_macros.hpp>
3275
3276// #include <nlohmann/detail/meta/void_t.hpp>
3277
3278// #include <nlohmann/detail/meta/cpp_future.hpp>
3279
3280
3281NLOHMANN_JSON_NAMESPACE_BEGIN
3282namespace detail
3283{
3284
3285template<typename It, typename = void>
3287
3288template<typename It>
3290 It,
3291 void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
3292 typename It::reference, typename It::iterator_category >>
3293{
3294 using difference_type = typename It::difference_type;
3295 using value_type = typename It::value_type;
3296 using pointer = typename It::pointer;
3297 using reference = typename It::reference;
3298 using iterator_category = typename It::iterator_category;
3299};
3300
3301// This is required as some compilers implement std::iterator_traits in a way that
3302// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
3303template<typename T, typename = void>
3305{
3306};
3307
3308template<typename T>
3309struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
3310 : iterator_types<T>
3311{
3312};
3313
3314template<typename T>
3315struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
3316{
3317 using iterator_category = std::random_access_iterator_tag;
3318 using value_type = T;
3319 using difference_type = ptrdiff_t;
3320 using pointer = T*;
3321 using reference = T&;
3322};
3323
3324} // namespace detail
3325NLOHMANN_JSON_NAMESPACE_END
3326
3327// #include <nlohmann/detail/macro_scope.hpp>
3328
3329// #include <nlohmann/detail/meta/call_std/begin.hpp>
3330// __ _____ _____ _____
3331// __| | __| | | | JSON for Modern C++
3332// | | |__ | | | | | | version 3.11.3
3333// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3334//
3335// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3336// SPDX-License-Identifier: MIT
3337
3338
3339
3340// #include <nlohmann/detail/macro_scope.hpp>
3341
3342
3343NLOHMANN_JSON_NAMESPACE_BEGIN
3344
3345NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
3346
3347NLOHMANN_JSON_NAMESPACE_END
3348
3349// #include <nlohmann/detail/meta/call_std/end.hpp>
3350// __ _____ _____ _____
3351// __| | __| | | | JSON for Modern C++
3352// | | |__ | | | | | | version 3.11.3
3353// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3354//
3355// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3356// SPDX-License-Identifier: MIT
3357
3358
3359
3360// #include <nlohmann/detail/macro_scope.hpp>
3361
3362
3363NLOHMANN_JSON_NAMESPACE_BEGIN
3364
3365NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
3366
3367NLOHMANN_JSON_NAMESPACE_END
3368
3369// #include <nlohmann/detail/meta/cpp_future.hpp>
3370
3371// #include <nlohmann/detail/meta/detected.hpp>
3372
3373// #include <nlohmann/json_fwd.hpp>
3374// __ _____ _____ _____
3375// __| | __| | | | JSON for Modern C++
3376// | | |__ | | | | | | version 3.11.3
3377// |_____|_____|_____|_|___| https://github.com/nlohmann/json
3378//
3379// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
3380// SPDX-License-Identifier: MIT
3381
3382#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
3383 #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
3384
3385 #include <cstdint> // int64_t, uint64_t
3386 #include <map> // map
3387 #include <memory> // allocator
3388 #include <string> // string
3389 #include <vector> // vector
3390
3391 // #include <nlohmann/detail/abi_macros.hpp>
3392
3393
3399 NLOHMANN_JSON_NAMESPACE_BEGIN
3400
3408 template<typename T = void, typename SFINAE = void>
3409 struct adl_serializer;
3410
3413 template<template<typename U, typename V, typename... Args> class ObjectType =
3414 std::map,
3415 template<typename U, typename... Args> class ArrayType = std::vector,
3416 class StringType = std::string, class BooleanType = bool,
3417 class NumberIntegerType = std::int64_t,
3418 class NumberUnsignedType = std::uint64_t,
3419 class NumberFloatType = double,
3420 template<typename U> class AllocatorType = std::allocator,
3421 template<typename T, typename SFINAE = void> class JSONSerializer =
3423 class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
3424 class CustomBaseClass = void>
3425 class basic_json;
3426
3429 template<typename RefStringType>
3430 class json_pointer;
3431
3436 using json = basic_json<>;
3437
3440 template<class Key, class T, class IgnoredLess, class Allocator>
3441 struct ordered_map;
3442
3446
3447 NLOHMANN_JSON_NAMESPACE_END
3448
3449#endif // INCLUDE_NLOHMANN_JSON_FWD_HPP_
3450
3451
3452NLOHMANN_JSON_NAMESPACE_BEGIN
3461namespace detail
3462{
3463
3465// helpers //
3467
3468// Note to maintainers:
3469//
3470// Every trait in this file expects a non CV-qualified type.
3471// The only exceptions are in the 'aliases for detected' section
3472// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
3473//
3474// In this case, T has to be properly CV-qualified to constraint the function arguments
3475// (e.g. to_json(BasicJsonType&, const T&))
3476
3477template<typename> struct is_basic_json : std::false_type {};
3478
3479NLOHMANN_BASIC_JSON_TPL_DECLARATION
3480struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
3481
3482// used by exceptions create() member functions
3483// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
3484// false_type otherwise
3485template<typename BasicJsonContext>
3487 std::integral_constant < bool,
3488 is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
3489 || std::is_same<BasicJsonContext, std::nullptr_t>::value >
3490{};
3491
3493// json_ref helpers //
3495
3496template<typename>
3497class json_ref;
3498
3499template<typename>
3500struct is_json_ref : std::false_type {};
3501
3502template<typename T>
3503struct is_json_ref<json_ref<T>> : std::true_type {};
3504
3506// aliases for detected //
3508
3509template<typename T>
3510using mapped_type_t = typename T::mapped_type;
3511
3512template<typename T>
3513using key_type_t = typename T::key_type;
3514
3515template<typename T>
3516using value_type_t = typename T::value_type;
3517
3518template<typename T>
3519using difference_type_t = typename T::difference_type;
3520
3521template<typename T>
3522using pointer_t = typename T::pointer;
3523
3524template<typename T>
3525using reference_t = typename T::reference;
3526
3527template<typename T>
3528using iterator_category_t = typename T::iterator_category;
3529
3530template<typename T, typename... Args>
3531using to_json_function = decltype(T::to_json(std::declval<Args>()...));
3532
3533template<typename T, typename... Args>
3534using from_json_function = decltype(T::from_json(std::declval<Args>()...));
3535
3536template<typename T, typename U>
3537using get_template_function = decltype(std::declval<T>().template get<U>());
3538
3539// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
3540template<typename BasicJsonType, typename T, typename = void>
3541struct has_from_json : std::false_type {};
3542
3543// trait checking if j.get<T> is valid
3544// use this trait instead of std::is_constructible or std::is_convertible,
3545// both rely on, or make use of implicit conversions, and thus fail when T
3546// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
3547template <typename BasicJsonType, typename T>
3549{
3550 static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
3551};
3552
3553template<typename BasicJsonType, typename T>
3554struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3555{
3556 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3557
3558 static constexpr bool value =
3559 is_detected_exact<void, from_json_function, serializer,
3560 const BasicJsonType&, T&>::value;
3561};
3562
3563// This trait checks if JSONSerializer<T>::from_json(json const&) exists
3564// this overload is used for non-default-constructible user-defined-types
3565template<typename BasicJsonType, typename T, typename = void>
3566struct has_non_default_from_json : std::false_type {};
3567
3568template<typename BasicJsonType, typename T>
3569struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3570{
3571 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3572
3573 static constexpr bool value =
3574 is_detected_exact<T, from_json_function, serializer,
3575 const BasicJsonType&>::value;
3576};
3577
3578// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
3579// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
3580template<typename BasicJsonType, typename T, typename = void>
3581struct has_to_json : std::false_type {};
3582
3583template<typename BasicJsonType, typename T>
3584struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
3585{
3586 using serializer = typename BasicJsonType::template json_serializer<T, void>;
3587
3588 static constexpr bool value =
3589 is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
3590 T>::value;
3591};
3592
3593template<typename T>
3594using detect_key_compare = typename T::key_compare;
3595
3596template<typename T>
3597struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
3598
3599// obtains the actual object key comparator
3600template<typename BasicJsonType>
3602{
3603 using object_t = typename BasicJsonType::object_t;
3604 using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
3605 using type = typename std::conditional < has_key_compare<object_t>::value,
3606 typename object_t::key_compare, object_comparator_t>::type;
3607};
3608
3609template<typename BasicJsonType>
3610using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
3611
3613// char_traits //
3615
3616// Primary template of char_traits calls std char_traits
3617template<typename T>
3618struct char_traits : std::char_traits<T>
3619{};
3620
3621// Explicitly define char traits for unsigned char since it is not standard
3622template<>
3623struct char_traits<unsigned char> : std::char_traits<char>
3624{
3625 using char_type = unsigned char;
3626 using int_type = uint64_t;
3627
3628 // Redefine to_int_type function
3629 static int_type to_int_type(char_type c) noexcept
3630 {
3631 return static_cast<int_type>(c);
3632 }
3633
3634 static char_type to_char_type(int_type i) noexcept
3635 {
3636 return static_cast<char_type>(i);
3637 }
3638
3639 static constexpr int_type eof() noexcept
3640 {
3641 return static_cast<int_type>(EOF);
3642 }
3643};
3644
3645// Explicitly define char traits for signed char since it is not standard
3646template<>
3647struct char_traits<signed char> : std::char_traits<char>
3648{
3649 using char_type = signed char;
3650 using int_type = uint64_t;
3651
3652 // Redefine to_int_type function
3653 static int_type to_int_type(char_type c) noexcept
3654 {
3655 return static_cast<int_type>(c);
3656 }
3657
3658 static char_type to_char_type(int_type i) noexcept
3659 {
3660 return static_cast<char_type>(i);
3661 }
3662
3663 static constexpr int_type eof() noexcept
3664 {
3665 return static_cast<int_type>(EOF);
3666 }
3667};
3668
3670// is_ functions //
3672
3673// https://en.cppreference.com/w/cpp/types/conjunction
3674template<class...> struct conjunction : std::true_type { };
3675template<class B> struct conjunction<B> : B { };
3676template<class B, class... Bn>
3677struct conjunction<B, Bn...>
3678: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
3679
3680// https://en.cppreference.com/w/cpp/types/negation
3681template<class B> struct negation : std::integral_constant < bool, !B::value > { };
3682
3683// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
3684// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
3685// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
3686template <typename T>
3687struct is_default_constructible : std::is_default_constructible<T> {};
3688
3689template <typename T1, typename T2>
3690struct is_default_constructible<std::pair<T1, T2>>
3691 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3692
3693template <typename T1, typename T2>
3694struct is_default_constructible<const std::pair<T1, T2>>
3695 : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
3696
3697template <typename... Ts>
3698struct is_default_constructible<std::tuple<Ts...>>
3699 : conjunction<is_default_constructible<Ts>...> {};
3700
3701template <typename... Ts>
3702struct is_default_constructible<const std::tuple<Ts...>>
3703 : conjunction<is_default_constructible<Ts>...> {};
3704
3705template <typename T, typename... Args>
3706struct is_constructible : std::is_constructible<T, Args...> {};
3707
3708template <typename T1, typename T2>
3709struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
3710
3711template <typename T1, typename T2>
3712struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
3713
3714template <typename... Ts>
3715struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
3716
3717template <typename... Ts>
3718struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
3719
3720template<typename T, typename = void>
3721struct is_iterator_traits : std::false_type {};
3722
3723template<typename T>
3725{
3726 private:
3727 using traits = iterator_traits<T>;
3728
3729 public:
3730 static constexpr auto value =
3731 is_detected<value_type_t, traits>::value &&
3732 is_detected<difference_type_t, traits>::value &&
3733 is_detected<pointer_t, traits>::value &&
3734 is_detected<iterator_category_t, traits>::value &&
3735 is_detected<reference_t, traits>::value;
3736};
3737
3738template<typename T>
3740{
3741 private:
3742 using t_ref = typename std::add_lvalue_reference<T>::type;
3743
3744 using iterator = detected_t<result_of_begin, t_ref>;
3745 using sentinel = detected_t<result_of_end, t_ref>;
3746
3747 // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
3748 // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
3749 // but reimplementing these would be too much work, as a lot of other concepts are used underneath
3750 static constexpr auto is_iterator_begin =
3752
3753 public:
3754 static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
3755};
3756
3757template<typename R>
3758using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
3759
3760template<typename T>
3761using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
3762
3763// The following implementation of is_complete_type is taken from
3764// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
3765// and is written by Xiang Fan who agreed to using it in this library.
3766
3767template<typename T, typename = void>
3768struct is_complete_type : std::false_type {};
3769
3770template<typename T>
3771struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
3772
3773template<typename BasicJsonType, typename CompatibleObjectType,
3774 typename = void>
3775struct is_compatible_object_type_impl : std::false_type {};
3776
3777template<typename BasicJsonType, typename CompatibleObjectType>
3779 BasicJsonType, CompatibleObjectType,
3780 enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
3781 is_detected<key_type_t, CompatibleObjectType>::value >>
3782{
3783 using object_t = typename BasicJsonType::object_t;
3784
3785 // macOS's is_constructible does not play well with nonesuch...
3786 static constexpr bool value =
3787 is_constructible<typename object_t::key_type,
3788 typename CompatibleObjectType::key_type>::value &&
3789 is_constructible<typename object_t::mapped_type,
3790 typename CompatibleObjectType::mapped_type>::value;
3791};
3792
3793template<typename BasicJsonType, typename CompatibleObjectType>
3795 : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
3796
3797template<typename BasicJsonType, typename ConstructibleObjectType,
3798 typename = void>
3799struct is_constructible_object_type_impl : std::false_type {};
3800
3801template<typename BasicJsonType, typename ConstructibleObjectType>
3803 BasicJsonType, ConstructibleObjectType,
3804 enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
3805 is_detected<key_type_t, ConstructibleObjectType>::value >>
3806{
3807 using object_t = typename BasicJsonType::object_t;
3808
3809 static constexpr bool value =
3811 (std::is_move_assignable<ConstructibleObjectType>::value ||
3812 std::is_copy_assignable<ConstructibleObjectType>::value) &&
3813 (is_constructible<typename ConstructibleObjectType::key_type,
3814 typename object_t::key_type>::value &&
3815 std::is_same <
3816 typename object_t::mapped_type,
3817 typename ConstructibleObjectType::mapped_type >::value)) ||
3818 (has_from_json<BasicJsonType,
3819 typename ConstructibleObjectType::mapped_type>::value ||
3821 BasicJsonType,
3822 typename ConstructibleObjectType::mapped_type >::value);
3823};
3824
3825template<typename BasicJsonType, typename ConstructibleObjectType>
3827 : is_constructible_object_type_impl<BasicJsonType,
3828 ConstructibleObjectType> {};
3829
3830template<typename BasicJsonType, typename CompatibleStringType>
3836
3837template<typename BasicJsonType, typename ConstructibleStringType>
3839{
3840 // launder type through decltype() to fix compilation failure on ICPC
3841#ifdef __INTEL_COMPILER
3842 using laundered_type = decltype(std::declval<ConstructibleStringType>());
3843#else
3844 using laundered_type = ConstructibleStringType;
3845#endif
3846
3847 static constexpr auto value =
3848 conjunction <
3850 is_detected_exact<typename BasicJsonType::string_t::value_type,
3851 value_type_t, laundered_type >>::value;
3852};
3853
3854template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
3855struct is_compatible_array_type_impl : std::false_type {};
3856
3857template<typename BasicJsonType, typename CompatibleArrayType>
3859 BasicJsonType, CompatibleArrayType,
3860 enable_if_t <
3861 is_detected<iterator_t, CompatibleArrayType>::value&&
3862 is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
3863// special case for types like std::filesystem::path whose iterator's value_type are themselves
3864// c.f. https://github.com/nlohmann/json/pull/3073
3865 !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
3866{
3867 static constexpr bool value =
3868 is_constructible<BasicJsonType,
3869 range_value_t<CompatibleArrayType>>::value;
3870};
3871
3872template<typename BasicJsonType, typename CompatibleArrayType>
3874 : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
3875
3876template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
3877struct is_constructible_array_type_impl : std::false_type {};
3878
3879template<typename BasicJsonType, typename ConstructibleArrayType>
3881 BasicJsonType, ConstructibleArrayType,
3882 enable_if_t<std::is_same<ConstructibleArrayType,
3883 typename BasicJsonType::value_type>::value >>
3884 : std::true_type {};
3885
3886template<typename BasicJsonType, typename ConstructibleArrayType>
3888 BasicJsonType, ConstructibleArrayType,
3889 enable_if_t < !std::is_same<ConstructibleArrayType,
3890 typename BasicJsonType::value_type>::value&&
3891 !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
3892 is_default_constructible<ConstructibleArrayType>::value&&
3893(std::is_move_assignable<ConstructibleArrayType>::value ||
3894 std::is_copy_assignable<ConstructibleArrayType>::value)&&
3895is_detected<iterator_t, ConstructibleArrayType>::value&&
3896is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
3897is_detected<range_value_t, ConstructibleArrayType>::value&&
3898// special case for types like std::filesystem::path whose iterator's value_type are themselves
3899// c.f. https://github.com/nlohmann/json/pull/3073
3900!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
3902 detected_t<range_value_t, ConstructibleArrayType >>::value >>
3903{
3904 using value_type = range_value_t<ConstructibleArrayType>;
3905
3906 static constexpr bool value =
3907 std::is_same<value_type,
3908 typename BasicJsonType::array_t::value_type>::value ||
3909 has_from_json<BasicJsonType,
3910 value_type>::value ||
3912 BasicJsonType,
3913 value_type >::value;
3914};
3915
3916template<typename BasicJsonType, typename ConstructibleArrayType>
3918 : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
3919
3920template<typename RealIntegerType, typename CompatibleNumberIntegerType,
3921 typename = void>
3922struct is_compatible_integer_type_impl : std::false_type {};
3923
3924template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3926 RealIntegerType, CompatibleNumberIntegerType,
3927 enable_if_t < std::is_integral<RealIntegerType>::value&&
3928 std::is_integral<CompatibleNumberIntegerType>::value&&
3929 !std::is_same<bool, CompatibleNumberIntegerType>::value >>
3930{
3931 // is there an assert somewhere on overflows?
3932 using RealLimits = std::numeric_limits<RealIntegerType>;
3933 using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
3934
3935 static constexpr auto value =
3936 is_constructible<RealIntegerType,
3937 CompatibleNumberIntegerType>::value &&
3938 CompatibleLimits::is_integer &&
3939 RealLimits::is_signed == CompatibleLimits::is_signed;
3940};
3941
3942template<typename RealIntegerType, typename CompatibleNumberIntegerType>
3944 : is_compatible_integer_type_impl<RealIntegerType,
3945 CompatibleNumberIntegerType> {};
3946
3947template<typename BasicJsonType, typename CompatibleType, typename = void>
3948struct is_compatible_type_impl: std::false_type {};
3949
3950template<typename BasicJsonType, typename CompatibleType>
3952 BasicJsonType, CompatibleType,
3953 enable_if_t<is_complete_type<CompatibleType>::value >>
3954{
3955 static constexpr bool value =
3957};
3958
3959template<typename BasicJsonType, typename CompatibleType>
3961 : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
3962
3963template<typename T1, typename T2>
3964struct is_constructible_tuple : std::false_type {};
3965
3966template<typename T1, typename... Args>
3967struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
3968
3969template<typename BasicJsonType, typename T>
3970struct is_json_iterator_of : std::false_type {};
3971
3972template<typename BasicJsonType>
3973struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
3974
3975template<typename BasicJsonType>
3976struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
3977{};
3978
3979// checks if a given type T is a template specialization of Primary
3980template<template <typename...> class Primary, typename T>
3981struct is_specialization_of : std::false_type {};
3982
3983template<template <typename...> class Primary, typename... Args>
3984struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
3985
3986template<typename T>
3988
3989// checks if A and B are comparable using Compare functor
3990template<typename Compare, typename A, typename B, typename = void>
3991struct is_comparable : std::false_type {};
3992
3993template<typename Compare, typename A, typename B>
3994struct is_comparable<Compare, A, B, void_t<
3995decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
3996decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
3997>> : std::true_type {};
3998
3999template<typename T>
4000using detect_is_transparent = typename T::is_transparent;
4001
4002// type trait to check if KeyType can be used as object key (without a BasicJsonType)
4003// see is_usable_as_basic_json_key_type below
4004template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4005 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4006using is_usable_as_key_type = typename std::conditional <
4008 && !(ExcludeObjectKeyType && std::is_same<KeyType,
4009 ObjectKeyType>::value)
4010 && (!RequireTransparentComparator
4011 || is_detected <detect_is_transparent, Comparator>::value)
4013 std::true_type,
4014 std::false_type >::type;
4015
4016// type trait to check if KeyType can be used as object key
4017// true if:
4018// - KeyType is comparable with BasicJsonType::object_t::key_type
4019// - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
4020// - the comparator is transparent or RequireTransparentComparator is false
4021// - KeyType is not a JSON iterator or json_pointer
4022template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
4023 bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
4024using is_usable_as_basic_json_key_type = typename std::conditional <
4025 is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
4026 typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
4027 RequireTransparentComparator, ExcludeObjectKeyType>::value
4029 std::true_type,
4030 std::false_type >::type;
4031
4032template<typename ObjectType, typename KeyType>
4033using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
4034
4035// type trait to check if object_t has an erase() member functions accepting KeyType
4036template<typename BasicJsonType, typename KeyType>
4037using has_erase_with_key_type = typename std::conditional <
4038 is_detected <
4039 detect_erase_with_key_type,
4040 typename BasicJsonType::object_t, KeyType >::value,
4041 std::true_type,
4042 std::false_type >::type;
4043
4044// a naive helper to check if a type is an ordered_map (exploits the fact that
4045// ordered_map inherits capacity() from std::vector)
4046template <typename T>
4048{
4049 using one = char;
4050
4051 struct two
4052 {
4053 char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4054 };
4055
4056 template <typename C> static one test( decltype(&C::capacity) ) ;
4057 template <typename C> static two test(...);
4058
4059 enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
4060};
4061
4062// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
4063template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
4064T conditional_static_cast(U value)
4065{
4066 return static_cast<T>(value);
4067}
4068
4069template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
4070T conditional_static_cast(U value)
4071{
4072 return value;
4073}
4074
4075template<typename... Types>
4076using all_integral = conjunction<std::is_integral<Types>...>;
4077
4078template<typename... Types>
4079using all_signed = conjunction<std::is_signed<Types>...>;
4080
4081template<typename... Types>
4082using all_unsigned = conjunction<std::is_unsigned<Types>...>;
4083
4084// there's a disjunction trait in another PR; replace when merged
4085template<typename... Types>
4086using same_sign = std::integral_constant < bool,
4087 all_signed<Types...>::value || all_unsigned<Types...>::value >;
4088
4089template<typename OfType, typename T>
4090using never_out_of_range = std::integral_constant < bool,
4091 (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
4092 || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
4093
4094template<typename OfType, typename T,
4095 bool OfTypeSigned = std::is_signed<OfType>::value,
4096 bool TSigned = std::is_signed<T>::value>
4098
4099template<typename OfType, typename T>
4100struct value_in_range_of_impl2<OfType, T, false, false>
4101{
4102 static constexpr bool test(T val)
4103 {
4104 using CommonType = typename std::common_type<OfType, T>::type;
4105 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4106 }
4107};
4108
4109template<typename OfType, typename T>
4110struct value_in_range_of_impl2<OfType, T, true, false>
4111{
4112 static constexpr bool test(T val)
4113 {
4114 using CommonType = typename std::common_type<OfType, T>::type;
4115 return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4116 }
4117};
4118
4119template<typename OfType, typename T>
4120struct value_in_range_of_impl2<OfType, T, false, true>
4121{
4122 static constexpr bool test(T val)
4123 {
4124 using CommonType = typename std::common_type<OfType, T>::type;
4125 return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4126 }
4127};
4128
4129template<typename OfType, typename T>
4130struct value_in_range_of_impl2<OfType, T, true, true>
4131{
4132 static constexpr bool test(T val)
4133 {
4134 using CommonType = typename std::common_type<OfType, T>::type;
4135 return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
4136 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
4137 }
4138};
4139
4140template<typename OfType, typename T,
4141 bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
4142 typename = detail::enable_if_t<all_integral<OfType, T>::value>>
4144
4145template<typename OfType, typename T>
4146struct value_in_range_of_impl1<OfType, T, false>
4147{
4148 static constexpr bool test(T val)
4149 {
4151 }
4152};
4153
4154template<typename OfType, typename T>
4155struct value_in_range_of_impl1<OfType, T, true>
4156{
4157 static constexpr bool test(T /*val*/)
4158 {
4159 return true;
4160 }
4161};
4162
4163template<typename OfType, typename T>
4164inline constexpr bool value_in_range_of(T val)
4165{
4167}
4168
4169template<bool Value>
4170using bool_constant = std::integral_constant<bool, Value>;
4171
4173// is_c_string
4175
4176namespace impl
4177{
4178
4179template<typename T>
4180inline constexpr bool is_c_string()
4181{
4182 using TUnExt = typename std::remove_extent<T>::type;
4183 using TUnCVExt = typename std::remove_cv<TUnExt>::type;
4184 using TUnPtr = typename std::remove_pointer<T>::type;
4185 using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
4186 return
4187 (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
4188 || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
4189}
4190
4191} // namespace impl
4192
4193// checks whether T is a [cv] char */[cv] char[] C string
4194template<typename T>
4195struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
4196
4197template<typename T>
4199
4201// is_transparent
4203
4204namespace impl
4205{
4206
4207template<typename T>
4208inline constexpr bool is_transparent()
4209{
4210 return is_detected<detect_is_transparent, T>::value;
4211}
4212
4213} // namespace impl
4214
4215// checks whether T has a member named is_transparent
4216template<typename T>
4217struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
4218
4220
4221} // namespace detail
4222NLOHMANN_JSON_NAMESPACE_END
4223
4224// #include <nlohmann/detail/string_concat.hpp>
4225// __ _____ _____ _____
4226// __| | __| | | | JSON for Modern C++
4227// | | |__ | | | | | | version 3.11.3
4228// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4229//
4230// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4231// SPDX-License-Identifier: MIT
4232
4233
4234
4235#include <cstring> // strlen
4236#include <string> // string
4237#include <utility> // forward
4238
4239// #include <nlohmann/detail/meta/cpp_future.hpp>
4240
4241// #include <nlohmann/detail/meta/detected.hpp>
4242
4243
4244NLOHMANN_JSON_NAMESPACE_BEGIN
4245namespace detail
4246{
4247
4248inline std::size_t concat_length()
4249{
4250 return 0;
4251}
4252
4253template<typename... Args>
4254inline std::size_t concat_length(const char* cstr, const Args& ... rest);
4255
4256template<typename StringType, typename... Args>
4257inline std::size_t concat_length(const StringType& str, const Args& ... rest);
4258
4259template<typename... Args>
4260inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
4261{
4262 return 1 + concat_length(rest...);
4263}
4264
4265template<typename... Args>
4266inline std::size_t concat_length(const char* cstr, const Args& ... rest)
4267{
4268 // cppcheck-suppress ignoredReturnValue
4269 return ::strlen(cstr) + concat_length(rest...);
4270}
4271
4272template<typename StringType, typename... Args>
4273inline std::size_t concat_length(const StringType& str, const Args& ... rest)
4274{
4275 return str.size() + concat_length(rest...);
4276}
4277
4278template<typename OutStringType>
4279inline void concat_into(OutStringType& /*out*/)
4280{}
4281
4282template<typename StringType, typename Arg>
4283using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
4284
4285template<typename StringType, typename Arg>
4286using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
4287
4288template<typename StringType, typename Arg>
4289using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
4290
4291template<typename StringType, typename Arg>
4292using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
4293
4294template<typename StringType, typename Arg>
4295using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
4296
4297template<typename StringType, typename Arg>
4298using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
4299
4300template<typename StringType, typename Arg>
4301using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
4302
4303template<typename StringType, typename Arg>
4304using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
4305
4306template < typename OutStringType, typename Arg, typename... Args,
4307 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4308 && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
4309inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
4310
4311template < typename OutStringType, typename Arg, typename... Args,
4312 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4313 && !detect_string_can_append_op<OutStringType, Arg>::value
4314 && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
4315inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4316
4317template < typename OutStringType, typename Arg, typename... Args,
4318 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4319 && !detect_string_can_append_op<OutStringType, Arg>::value
4320 && !detect_string_can_append_iter<OutStringType, Arg>::value
4321 && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
4322inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
4323
4324template<typename OutStringType, typename Arg, typename... Args,
4325 enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
4326inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
4327{
4328 out.append(std::forward<Arg>(arg));
4329 concat_into(out, std::forward<Args>(rest)...);
4330}
4331
4332template < typename OutStringType, typename Arg, typename... Args,
4333 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4334 && detect_string_can_append_op<OutStringType, Arg>::value, int > >
4335inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
4336{
4337 out += std::forward<Arg>(arg);
4338 concat_into(out, std::forward<Args>(rest)...);
4339}
4340
4341template < typename OutStringType, typename Arg, typename... Args,
4342 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4343 && !detect_string_can_append_op<OutStringType, Arg>::value
4344 && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
4345inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4346{
4347 out.append(arg.begin(), arg.end());
4348 concat_into(out, std::forward<Args>(rest)...);
4349}
4350
4351template < typename OutStringType, typename Arg, typename... Args,
4352 enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
4353 && !detect_string_can_append_op<OutStringType, Arg>::value
4354 && !detect_string_can_append_iter<OutStringType, Arg>::value
4355 && detect_string_can_append_data<OutStringType, Arg>::value, int > >
4356inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
4357{
4358 out.append(arg.data(), arg.size());
4359 concat_into(out, std::forward<Args>(rest)...);
4360}
4361
4362template<typename OutStringType = std::string, typename... Args>
4363inline OutStringType concat(Args && ... args)
4364{
4365 OutStringType str;
4366 str.reserve(concat_length(args...));
4367 concat_into(str, std::forward<Args>(args)...);
4368 return str;
4369}
4370
4371} // namespace detail
4372NLOHMANN_JSON_NAMESPACE_END
4373
4374
4375NLOHMANN_JSON_NAMESPACE_BEGIN
4376namespace detail
4377{
4378
4380// exceptions //
4382
4385class exception : public std::exception
4386{
4387 public:
4389 const char* what() const noexcept override
4390 {
4391 return m.what();
4392 }
4393
4395 const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
4396
4397 protected:
4398 JSON_HEDLEY_NON_NULL(3)
4399 exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
4400
4401 static std::string name(const std::string& ename, int id_)
4402 {
4403 return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
4404 }
4405
4406 static std::string diagnostics(std::nullptr_t /*leaf_element*/)
4407 {
4408 return "";
4409 }
4410
4411 template<typename BasicJsonType>
4412 static std::string diagnostics(const BasicJsonType* leaf_element)
4413 {
4414#if JSON_DIAGNOSTICS
4415 std::vector<std::string> tokens;
4416 for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
4417 {
4418 switch (current->m_parent->type())
4419 {
4420 case value_t::array:
4421 {
4422 for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
4423 {
4424 if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
4425 {
4426 tokens.emplace_back(std::to_string(i));
4427 break;
4428 }
4429 }
4430 break;
4431 }
4432
4433 case value_t::object:
4434 {
4435 for (const auto& element : *current->m_parent->m_data.m_value.object)
4436 {
4437 if (&element.second == current)
4438 {
4439 tokens.emplace_back(element.first.c_str());
4440 break;
4441 }
4442 }
4443 break;
4444 }
4445
4446 case value_t::null: // LCOV_EXCL_LINE
4447 case value_t::string: // LCOV_EXCL_LINE
4448 case value_t::boolean: // LCOV_EXCL_LINE
4449 case value_t::number_integer: // LCOV_EXCL_LINE
4450 case value_t::number_unsigned: // LCOV_EXCL_LINE
4451 case value_t::number_float: // LCOV_EXCL_LINE
4452 case value_t::binary: // LCOV_EXCL_LINE
4453 case value_t::discarded: // LCOV_EXCL_LINE
4454 default: // LCOV_EXCL_LINE
4455 break; // LCOV_EXCL_LINE
4456 }
4457 }
4458
4459 if (tokens.empty())
4460 {
4461 return "";
4462 }
4463
4464 auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
4465 [](const std::string & a, const std::string & b)
4466 {
4467 return concat(a, '/', detail::escape(b));
4468 });
4469 return concat('(', str, ") ");
4470#else
4471 static_cast<void>(leaf_element);
4472 return "";
4473#endif
4474 }
4475
4476 private:
4478 std::runtime_error m;
4479};
4480
4484{
4485 public:
4495 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4496 static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
4497 {
4498 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4499 position_string(pos), ": ", exception::diagnostics(context), what_arg);
4500 return {id_, pos.chars_read_total, w.c_str()};
4501 }
4502
4503 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4504 static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
4505 {
4506 const std::string w = concat(exception::name("parse_error", id_), "parse error",
4507 (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
4508 ": ", exception::diagnostics(context), what_arg);
4509 return {id_, byte_, w.c_str()};
4510 }
4511
4521 const std::size_t byte;
4522
4523 private:
4524 parse_error(int id_, std::size_t byte_, const char* what_arg)
4525 : exception(id_, what_arg), byte(byte_) {}
4526
4527 static std::string position_string(const position_t& pos)
4528 {
4529 return concat(" at line ", std::to_string(pos.lines_read + 1),
4530 ", column ", std::to_string(pos.chars_read_current_line));
4531 }
4532};
4533
4537{
4538 public:
4539 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4540 static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
4541 {
4542 const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
4543 return {id_, w.c_str()};
4544 }
4545
4546 private:
4547 JSON_HEDLEY_NON_NULL(3)
4548 invalid_iterator(int id_, const char* what_arg)
4549 : exception(id_, what_arg) {}
4550};
4551
4554class type_error : public exception
4555{
4556 public:
4557 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4558 static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4559 {
4560 const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
4561 return {id_, w.c_str()};
4562 }
4563
4564 private:
4565 JSON_HEDLEY_NON_NULL(3)
4566 type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4567};
4568
4572{
4573 public:
4574 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4575 static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
4576 {
4577 const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
4578 return {id_, w.c_str()};
4579 }
4580
4581 private:
4582 JSON_HEDLEY_NON_NULL(3)
4583 out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
4584};
4585
4589{
4590 public:
4591 template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
4592 static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
4593 {
4594 const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
4595 return {id_, w.c_str()};
4596 }
4597
4598 private:
4599 JSON_HEDLEY_NON_NULL(3)
4600 other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
4601};
4602
4603} // namespace detail
4604NLOHMANN_JSON_NAMESPACE_END
4605
4606// #include <nlohmann/detail/macro_scope.hpp>
4607
4608// #include <nlohmann/detail/meta/cpp_future.hpp>
4609
4610// #include <nlohmann/detail/meta/identity_tag.hpp>
4611// __ _____ _____ _____
4612// __| | __| | | | JSON for Modern C++
4613// | | |__ | | | | | | version 3.11.3
4614// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4615//
4616// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4617// SPDX-License-Identifier: MIT
4618
4619
4620
4621// #include <nlohmann/detail/abi_macros.hpp>
4622
4623
4624NLOHMANN_JSON_NAMESPACE_BEGIN
4625namespace detail
4626{
4627
4628// dispatching helper struct
4629template <class T> struct identity_tag {};
4630
4631} // namespace detail
4632NLOHMANN_JSON_NAMESPACE_END
4633
4634// #include <nlohmann/detail/meta/std_fs.hpp>
4635// __ _____ _____ _____
4636// __| | __| | | | JSON for Modern C++
4637// | | |__ | | | | | | version 3.11.3
4638// |_____|_____|_____|_|___| https://github.com/nlohmann/json
4639//
4640// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
4641// SPDX-License-Identifier: MIT
4642
4643
4644
4645// #include <nlohmann/detail/macro_scope.hpp>
4646
4647
4648#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
4649#include <experimental/filesystem>
4650NLOHMANN_JSON_NAMESPACE_BEGIN
4651namespace detail
4652{
4653namespace std_fs = std::experimental::filesystem;
4654} // namespace detail
4655NLOHMANN_JSON_NAMESPACE_END
4656#elif JSON_HAS_FILESYSTEM
4657#include <filesystem>
4658NLOHMANN_JSON_NAMESPACE_BEGIN
4659namespace detail
4660{
4661namespace std_fs = std::filesystem;
4662} // namespace detail
4663NLOHMANN_JSON_NAMESPACE_END
4664#endif
4665
4666// #include <nlohmann/detail/meta/type_traits.hpp>
4667
4668// #include <nlohmann/detail/string_concat.hpp>
4669
4670// #include <nlohmann/detail/value_t.hpp>
4671
4672
4673NLOHMANN_JSON_NAMESPACE_BEGIN
4674namespace detail
4675{
4676
4677template<typename BasicJsonType>
4678inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
4679{
4680 if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
4681 {
4682 JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
4683 }
4684 n = nullptr;
4685}
4686
4687// overloads for basic_json template parameters
4688template < typename BasicJsonType, typename ArithmeticType,
4689 enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
4690 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4691 int > = 0 >
4692void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
4693{
4694 switch (static_cast<value_t>(j))
4695 {
4697 {
4698 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4699 break;
4700 }
4702 {
4703 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4704 break;
4705 }
4707 {
4708 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4709 break;
4710 }
4711
4712 case value_t::null:
4713 case value_t::object:
4714 case value_t::array:
4715 case value_t::string:
4716 case value_t::boolean:
4717 case value_t::binary:
4718 case value_t::discarded:
4719 default:
4720 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
4721 }
4722}
4723
4724template<typename BasicJsonType>
4725inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
4726{
4727 if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
4728 {
4729 JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
4730 }
4731 b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
4732}
4733
4734template<typename BasicJsonType>
4735inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
4736{
4737 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4738 {
4739 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4740 }
4741 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4742}
4743
4744template <
4745 typename BasicJsonType, typename StringType,
4746 enable_if_t <
4747 std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
4748 && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
4749 && !std::is_same<typename BasicJsonType::string_t, StringType>::value
4750 && !is_json_ref<StringType>::value, int > = 0 >
4751inline void from_json(const BasicJsonType& j, StringType& s)
4752{
4753 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
4754 {
4755 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
4756 }
4757
4758 s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
4759}
4760
4761template<typename BasicJsonType>
4762inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
4763{
4764 get_arithmetic_value(j, val);
4765}
4766
4767template<typename BasicJsonType>
4768inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
4769{
4770 get_arithmetic_value(j, val);
4771}
4772
4773template<typename BasicJsonType>
4774inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
4775{
4776 get_arithmetic_value(j, val);
4777}
4778
4779#if !JSON_DISABLE_ENUM_SERIALIZATION
4780template<typename BasicJsonType, typename EnumType,
4781 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
4782inline void from_json(const BasicJsonType& j, EnumType& e)
4783{
4784 typename std::underlying_type<EnumType>::type val;
4785 get_arithmetic_value(j, val);
4786 e = static_cast<EnumType>(val);
4787}
4788#endif // JSON_DISABLE_ENUM_SERIALIZATION
4789
4790// forward_list doesn't have an insert method
4791template<typename BasicJsonType, typename T, typename Allocator,
4792 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4793inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
4794{
4795 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4796 {
4797 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4798 }
4799 l.clear();
4800 std::transform(j.rbegin(), j.rend(),
4801 std::front_inserter(l), [](const BasicJsonType & i)
4802 {
4803 return i.template get<T>();
4804 });
4805}
4806
4807// valarray doesn't have an insert method
4808template<typename BasicJsonType, typename T,
4809 enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
4810inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
4811{
4812 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4813 {
4814 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4815 }
4816 l.resize(j.size());
4817 std::transform(j.begin(), j.end(), std::begin(l),
4818 [](const BasicJsonType & elem)
4819 {
4820 return elem.template get<T>();
4821 });
4822}
4823
4824template<typename BasicJsonType, typename T, std::size_t N>
4825auto from_json(const BasicJsonType& j, T (&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
4826-> decltype(j.template get<T>(), void())
4827{
4828 for (std::size_t i = 0; i < N; ++i)
4829 {
4830 arr[i] = j.at(i).template get<T>();
4831 }
4832}
4833
4834template<typename BasicJsonType>
4835inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
4836{
4837 arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
4838}
4839
4840template<typename BasicJsonType, typename T, std::size_t N>
4841auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
4842 priority_tag<2> /*unused*/)
4843-> decltype(j.template get<T>(), void())
4844{
4845 for (std::size_t i = 0; i < N; ++i)
4846 {
4847 arr[i] = j.at(i).template get<T>();
4848 }
4849}
4850
4851template<typename BasicJsonType, typename ConstructibleArrayType,
4852 enable_if_t<
4853 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4854 int> = 0>
4855auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
4856-> decltype(
4857 arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
4858 j.template get<typename ConstructibleArrayType::value_type>(),
4859 void())
4860{
4861 using std::end;
4862
4863 ConstructibleArrayType ret;
4864 ret.reserve(j.size());
4865 std::transform(j.begin(), j.end(),
4866 std::inserter(ret, end(ret)), [](const BasicJsonType & i)
4867 {
4868 // get<BasicJsonType>() returns *this, this won't call a from_json
4869 // method when value_type is BasicJsonType
4870 return i.template get<typename ConstructibleArrayType::value_type>();
4871 });
4872 arr = std::move(ret);
4873}
4874
4875template<typename BasicJsonType, typename ConstructibleArrayType,
4876 enable_if_t<
4877 std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
4878 int> = 0>
4879inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
4880 priority_tag<0> /*unused*/)
4881{
4882 using std::end;
4883
4884 ConstructibleArrayType ret;
4885 std::transform(
4886 j.begin(), j.end(), std::inserter(ret, end(ret)),
4887 [](const BasicJsonType & i)
4888 {
4889 // get<BasicJsonType>() returns *this, this won't call a from_json
4890 // method when value_type is BasicJsonType
4891 return i.template get<typename ConstructibleArrayType::value_type>();
4892 });
4893 arr = std::move(ret);
4894}
4895
4896template < typename BasicJsonType, typename ConstructibleArrayType,
4897 enable_if_t <
4898 is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
4899 !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
4900 !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
4901 !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
4902 !is_basic_json<ConstructibleArrayType>::value,
4903 int > = 0 >
4904auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
4905-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
4906j.template get<typename ConstructibleArrayType::value_type>(),
4907void())
4908{
4909 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4910 {
4911 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4912 }
4913
4914 from_json_array_impl(j, arr, priority_tag<3> {});
4915}
4916
4917template < typename BasicJsonType, typename T, std::size_t... Idx >
4918std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
4919 identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
4920{
4921 return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
4922}
4923
4924template < typename BasicJsonType, typename T, std::size_t N >
4925auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
4926-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
4927{
4928 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
4929 {
4930 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
4931 }
4932
4933 return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
4934}
4935
4936template<typename BasicJsonType>
4937inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
4938{
4939 if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
4940 {
4941 JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
4942 }
4943
4944 bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
4945}
4946
4947template<typename BasicJsonType, typename ConstructibleObjectType,
4948 enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
4949inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
4950{
4951 if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
4952 {
4953 JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
4954 }
4955
4956 ConstructibleObjectType ret;
4957 const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
4958 using value_type = typename ConstructibleObjectType::value_type;
4959 std::transform(
4960 inner_object->begin(), inner_object->end(),
4961 std::inserter(ret, ret.begin()),
4962 [](typename BasicJsonType::object_t::value_type const & p)
4963 {
4964 return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
4965 });
4966 obj = std::move(ret);
4967}
4968
4969// overload for arithmetic types, not chosen for basic_json template arguments
4970// (BooleanType, etc..); note: Is it really necessary to provide explicit
4971// overloads for boolean_t etc. in case of a custom BooleanType which is not
4972// an arithmetic type?
4973template < typename BasicJsonType, typename ArithmeticType,
4974 enable_if_t <
4975 std::is_arithmetic<ArithmeticType>::value&&
4976 !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
4977 !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
4978 !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
4979 !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
4980 int > = 0 >
4981inline void from_json(const BasicJsonType& j, ArithmeticType& val)
4982{
4983 switch (static_cast<value_t>(j))
4984 {
4986 {
4987 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
4988 break;
4989 }
4991 {
4992 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
4993 break;
4994 }
4996 {
4997 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
4998 break;
4999 }
5000 case value_t::boolean:
5001 {
5002 val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
5003 break;
5004 }
5005
5006 case value_t::null:
5007 case value_t::object:
5008 case value_t::array:
5009 case value_t::string:
5010 case value_t::binary:
5011 case value_t::discarded:
5012 default:
5013 JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
5014 }
5015}
5016
5017template<typename BasicJsonType, typename... Args, std::size_t... Idx>
5018std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
5019{
5020 return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
5021}
5022
5023template < typename BasicJsonType, class A1, class A2 >
5024std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
5025{
5026 return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
5027 std::forward<BasicJsonType>(j).at(1).template get<A2>()};
5028}
5029
5030template<typename BasicJsonType, typename A1, typename A2>
5031inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
5032{
5033 p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
5034}
5035
5036template<typename BasicJsonType, typename... Args>
5037std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
5038{
5039 return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5040}
5041
5042template<typename BasicJsonType, typename... Args>
5043inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
5044{
5045 t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
5046}
5047
5048template<typename BasicJsonType, typename TupleRelated>
5049auto from_json(BasicJsonType&& j, TupleRelated&& t)
5050-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
5051{
5052 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5053 {
5054 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5055 }
5056
5057 return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
5058}
5059
5060template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
5061 typename = enable_if_t < !std::is_constructible <
5062 typename BasicJsonType::string_t, Key >::value >>
5063inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
5064{
5065 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5066 {
5067 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5068 }
5069 m.clear();
5070 for (const auto& p : j)
5071 {
5072 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5073 {
5074 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5075 }
5076 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5077 }
5078}
5079
5080template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
5081 typename = enable_if_t < !std::is_constructible <
5082 typename BasicJsonType::string_t, Key >::value >>
5083inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
5084{
5085 if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
5086 {
5087 JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
5088 }
5089 m.clear();
5090 for (const auto& p : j)
5091 {
5092 if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
5093 {
5094 JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
5095 }
5096 m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
5097 }
5098}
5099
5100#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5101template<typename BasicJsonType>
5102inline void from_json(const BasicJsonType& j, std_fs::path& p)
5103{
5104 if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
5105 {
5106 JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
5107 }
5108 p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
5109}
5110#endif
5111
5113{
5114 template<typename BasicJsonType, typename T>
5115 auto operator()(const BasicJsonType& j, T&& val) const
5116 noexcept(noexcept(from_json(j, std::forward<T>(val))))
5117 -> decltype(from_json(j, std::forward<T>(val)))
5118 {
5119 return from_json(j, std::forward<T>(val));
5120 }
5121};
5122
5123} // namespace detail
5124
5125#ifndef JSON_HAS_CPP_17
5129namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5130{
5131#endif
5132JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
5134#ifndef JSON_HAS_CPP_17
5135} // namespace
5136#endif
5137
5138NLOHMANN_JSON_NAMESPACE_END
5139
5140// #include <nlohmann/detail/conversions/to_json.hpp>
5141// __ _____ _____ _____
5142// __| | __| | | | JSON for Modern C++
5143// | | |__ | | | | | | version 3.11.3
5144// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5145//
5146// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5147// SPDX-License-Identifier: MIT
5148
5149
5150
5151#include <algorithm> // copy
5152#include <iterator> // begin, end
5153#include <string> // string
5154#include <tuple> // tuple, get
5155#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
5156#include <utility> // move, forward, declval, pair
5157#include <valarray> // valarray
5158#include <vector> // vector
5159
5160// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
5161// __ _____ _____ _____
5162// __| | __| | | | JSON for Modern C++
5163// | | |__ | | | | | | version 3.11.3
5164// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5165//
5166// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5167// SPDX-License-Identifier: MIT
5168
5169
5170
5171#include <cstddef> // size_t
5172#include <iterator> // input_iterator_tag
5173#include <string> // string, to_string
5174#include <tuple> // tuple_size, get, tuple_element
5175#include <utility> // move
5176
5177#if JSON_HAS_RANGES
5178 #include <ranges> // enable_borrowed_range
5179#endif
5180
5181// #include <nlohmann/detail/abi_macros.hpp>
5182
5183// #include <nlohmann/detail/meta/type_traits.hpp>
5184
5185// #include <nlohmann/detail/value_t.hpp>
5186
5187
5188NLOHMANN_JSON_NAMESPACE_BEGIN
5189namespace detail
5190{
5191
5192template<typename string_type>
5193void int_to_string( string_type& target, std::size_t value )
5194{
5195 // For ADL
5196 using std::to_string;
5197 target = to_string(value);
5198}
5199template<typename IteratorType> class iteration_proxy_value
5200{
5201 public:
5202 using difference_type = std::ptrdiff_t;
5203 using value_type = iteration_proxy_value;
5204 using pointer = value_type *;
5205 using reference = value_type &;
5206 using iterator_category = std::input_iterator_tag;
5207 using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
5208
5209 private:
5211 IteratorType anchor{};
5213 std::size_t array_index = 0;
5215 mutable std::size_t array_index_last = 0;
5217 mutable string_type array_index_str = "0";
5219 string_type empty_str{};
5220
5221 public:
5222 explicit iteration_proxy_value() = default;
5223 explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
5224 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5225 && std::is_nothrow_default_constructible<string_type>::value)
5226 : anchor(std::move(it))
5227 , array_index(array_index_)
5228 {}
5229
5230 iteration_proxy_value(iteration_proxy_value const&) = default;
5231 iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
5232 // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
5233 iteration_proxy_value(iteration_proxy_value&&)
5234 noexcept(std::is_nothrow_move_constructible<IteratorType>::value
5235 && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5236 iteration_proxy_value& operator=(iteration_proxy_value&&)
5237 noexcept(std::is_nothrow_move_assignable<IteratorType>::value
5238 && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
5239 ~iteration_proxy_value() = default;
5240
5242 const iteration_proxy_value& operator*() const
5243 {
5244 return *this;
5245 }
5246
5249 {
5250 ++anchor;
5251 ++array_index;
5252
5253 return *this;
5254 }
5255
5256 iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
5257 {
5258 auto tmp = iteration_proxy_value(anchor, array_index);
5259 ++anchor;
5260 ++array_index;
5261 return tmp;
5262 }
5263
5266 {
5267 return anchor == o.anchor;
5268 }
5269
5272 {
5273 return anchor != o.anchor;
5274 }
5275
5277 const string_type& key() const
5278 {
5279 JSON_ASSERT(anchor.m_object != nullptr);
5280
5281 switch (anchor.m_object->type())
5282 {
5283 // use integer array index as key
5284 case value_t::array:
5285 {
5286 if (array_index != array_index_last)
5287 {
5288 int_to_string( array_index_str, array_index );
5289 array_index_last = array_index;
5290 }
5291 return array_index_str;
5292 }
5293
5294 // use key from the object
5295 case value_t::object:
5296 return anchor.key();
5297
5298 // use an empty key for all primitive types
5299 case value_t::null:
5300 case value_t::string:
5301 case value_t::boolean:
5305 case value_t::binary:
5306 case value_t::discarded:
5307 default:
5308 return empty_str;
5309 }
5310 }
5311
5313 typename IteratorType::reference value() const
5314 {
5315 return anchor.value();
5316 }
5317};
5318
5320template<typename IteratorType> class iteration_proxy
5321{
5322 private:
5324 typename IteratorType::pointer container = nullptr;
5325
5326 public:
5327 explicit iteration_proxy() = default;
5328
5330 explicit iteration_proxy(typename IteratorType::reference cont) noexcept
5331 : container(&cont) {}
5332
5333 iteration_proxy(iteration_proxy const&) = default;
5334 iteration_proxy& operator=(iteration_proxy const&) = default;
5335 iteration_proxy(iteration_proxy&&) noexcept = default;
5336 iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
5337 ~iteration_proxy() = default;
5338
5340 iteration_proxy_value<IteratorType> begin() const noexcept
5341 {
5342 return iteration_proxy_value<IteratorType>(container->begin());
5343 }
5344
5347 {
5348 return iteration_proxy_value<IteratorType>(container->end());
5349 }
5350};
5351
5352// Structured Bindings Support
5353// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5354// And see https://github.com/nlohmann/json/pull/1391
5355template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
5356auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
5357{
5358 return i.key();
5359}
5360// Structured Bindings Support
5361// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5362// And see https://github.com/nlohmann/json/pull/1391
5363template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
5364auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
5365{
5366 return i.value();
5367}
5368
5369} // namespace detail
5370NLOHMANN_JSON_NAMESPACE_END
5371
5372// The Addition to the STD Namespace is required to add
5373// Structured Bindings Support to the iteration_proxy_value class
5374// For further reference see https://blog.tartanllama.xyz/structured-bindings/
5375// And see https://github.com/nlohmann/json/pull/1391
5376namespace std
5377{
5378
5379#if defined(__clang__)
5380 // Fix: https://github.com/nlohmann/json/issues/1401
5381 #pragma clang diagnostic push
5382 #pragma clang diagnostic ignored "-Wmismatched-tags"
5383#endif
5384template<typename IteratorType>
5385class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
5386 : public std::integral_constant<std::size_t, 2> {};
5387
5388template<std::size_t N, typename IteratorType>
5389class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
5390{
5391 public:
5392 using type = decltype(
5393 get<N>(std::declval <
5394 ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
5395};
5396#if defined(__clang__)
5397 #pragma clang diagnostic pop
5398#endif
5399
5400} // namespace std
5401
5402#if JSON_HAS_RANGES
5403 template <typename IteratorType>
5404 inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
5405#endif
5406
5407// #include <nlohmann/detail/macro_scope.hpp>
5408
5409// #include <nlohmann/detail/meta/cpp_future.hpp>
5410
5411// #include <nlohmann/detail/meta/std_fs.hpp>
5412
5413// #include <nlohmann/detail/meta/type_traits.hpp>
5414
5415// #include <nlohmann/detail/value_t.hpp>
5416
5417
5418NLOHMANN_JSON_NAMESPACE_BEGIN
5419namespace detail
5420{
5421
5423// constructors //
5425
5426/*
5427 * Note all external_constructor<>::construct functions need to call
5428 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
5429 * allocated value (e.g., a string). See bug issue
5430 * https://github.com/nlohmann/json/issues/2865 for more information.
5431 */
5432
5433template<value_t> struct external_constructor;
5434
5435template<>
5437{
5438 template<typename BasicJsonType>
5439 static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
5440 {
5441 j.m_data.m_value.destroy(j.m_data.m_type);
5442 j.m_data.m_type = value_t::boolean;
5443 j.m_data.m_value = b;
5444 j.assert_invariant();
5445 }
5446};
5447
5448template<>
5450{
5451 template<typename BasicJsonType>
5452 static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
5453 {
5454 j.m_data.m_value.destroy(j.m_data.m_type);
5455 j.m_data.m_type = value_t::string;
5456 j.m_data.m_value = s;
5457 j.assert_invariant();
5458 }
5459
5460 template<typename BasicJsonType>
5461 static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5462 {
5463 j.m_data.m_value.destroy(j.m_data.m_type);
5464 j.m_data.m_type = value_t::string;
5465 j.m_data.m_value = std::move(s);
5466 j.assert_invariant();
5467 }
5468
5469 template < typename BasicJsonType, typename CompatibleStringType,
5470 enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
5471 int > = 0 >
5472 static void construct(BasicJsonType& j, const CompatibleStringType& str)
5473 {
5474 j.m_data.m_value.destroy(j.m_data.m_type);
5475 j.m_data.m_type = value_t::string;
5476 j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
5477 j.assert_invariant();
5478 }
5479};
5480
5481template<>
5483{
5484 template<typename BasicJsonType>
5485 static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
5486 {
5487 j.m_data.m_value.destroy(j.m_data.m_type);
5488 j.m_data.m_type = value_t::binary;
5489 j.m_data.m_value = typename BasicJsonType::binary_t(b);
5490 j.assert_invariant();
5491 }
5492
5493 template<typename BasicJsonType>
5494 static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
5495 {
5496 j.m_data.m_value.destroy(j.m_data.m_type);
5497 j.m_data.m_type = value_t::binary;
5498 j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
5499 j.assert_invariant();
5500 }
5501};
5502
5503template<>
5505{
5506 template<typename BasicJsonType>
5507 static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
5508 {
5509 j.m_data.m_value.destroy(j.m_data.m_type);
5510 j.m_data.m_type = value_t::number_float;
5511 j.m_data.m_value = val;
5512 j.assert_invariant();
5513 }
5514};
5515
5516template<>
5518{
5519 template<typename BasicJsonType>
5520 static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
5521 {
5522 j.m_data.m_value.destroy(j.m_data.m_type);
5523 j.m_data.m_type = value_t::number_unsigned;
5524 j.m_data.m_value = val;
5525 j.assert_invariant();
5526 }
5527};
5528
5529template<>
5531{
5532 template<typename BasicJsonType>
5533 static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
5534 {
5535 j.m_data.m_value.destroy(j.m_data.m_type);
5536 j.m_data.m_type = value_t::number_integer;
5537 j.m_data.m_value = val;
5538 j.assert_invariant();
5539 }
5540};
5541
5542template<>
5544{
5545 template<typename BasicJsonType>
5546 static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
5547 {
5548 j.m_data.m_value.destroy(j.m_data.m_type);
5549 j.m_data.m_type = value_t::array;
5550 j.m_data.m_value = arr;
5551 j.set_parents();
5552 j.assert_invariant();
5553 }
5554
5555 template<typename BasicJsonType>
5556 static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5557 {
5558 j.m_data.m_value.destroy(j.m_data.m_type);
5559 j.m_data.m_type = value_t::array;
5560 j.m_data.m_value = std::move(arr);
5561 j.set_parents();
5562 j.assert_invariant();
5563 }
5564
5565 template < typename BasicJsonType, typename CompatibleArrayType,
5566 enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
5567 int > = 0 >
5568 static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
5569 {
5570 using std::begin;
5571 using std::end;
5572
5573 j.m_data.m_value.destroy(j.m_data.m_type);
5574 j.m_data.m_type = value_t::array;
5575 j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
5576 j.set_parents();
5577 j.assert_invariant();
5578 }
5579
5580 template<typename BasicJsonType>
5581 static void construct(BasicJsonType& j, const std::vector<bool>& arr)
5582 {
5583 j.m_data.m_value.destroy(j.m_data.m_type);
5584 j.m_data.m_type = value_t::array;
5585 j.m_data.m_value = value_t::array;
5586 j.m_data.m_value.array->reserve(arr.size());
5587 for (const bool x : arr)
5588 {
5589 j.m_data.m_value.array->push_back(x);
5590 j.set_parent(j.m_data.m_value.array->back());
5591 }
5592 j.assert_invariant();
5593 }
5594
5595 template<typename BasicJsonType, typename T,
5596 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5597 static void construct(BasicJsonType& j, const std::valarray<T>& arr)
5598 {
5599 j.m_data.m_value.destroy(j.m_data.m_type);
5600 j.m_data.m_type = value_t::array;
5601 j.m_data.m_value = value_t::array;
5602 j.m_data.m_value.array->resize(arr.size());
5603 if (arr.size() > 0)
5604 {
5605 std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
5606 }
5607 j.set_parents();
5608 j.assert_invariant();
5609 }
5610};
5611
5612template<>
5614{
5615 template<typename BasicJsonType>
5616 static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
5617 {
5618 j.m_data.m_value.destroy(j.m_data.m_type);
5619 j.m_data.m_type = value_t::object;
5620 j.m_data.m_value = obj;
5621 j.set_parents();
5622 j.assert_invariant();
5623 }
5624
5625 template<typename BasicJsonType>
5626 static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5627 {
5628 j.m_data.m_value.destroy(j.m_data.m_type);
5629 j.m_data.m_type = value_t::object;
5630 j.m_data.m_value = std::move(obj);
5631 j.set_parents();
5632 j.assert_invariant();
5633 }
5634
5635 template < typename BasicJsonType, typename CompatibleObjectType,
5636 enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
5637 static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
5638 {
5639 using std::begin;
5640 using std::end;
5641
5642 j.m_data.m_value.destroy(j.m_data.m_type);
5643 j.m_data.m_type = value_t::object;
5644 j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
5645 j.set_parents();
5646 j.assert_invariant();
5647 }
5648};
5649
5651// to_json //
5653
5654template<typename BasicJsonType, typename T,
5655 enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
5656inline void to_json(BasicJsonType& j, T b) noexcept
5657{
5659}
5660
5661template < typename BasicJsonType, typename BoolRef,
5662 enable_if_t <
5663 ((std::is_same<std::vector<bool>::reference, BoolRef>::value
5664 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
5665 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
5666 && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
5667 typename BasicJsonType::boolean_t >::value))
5668 && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
5669inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
5670{
5671 external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
5672}
5673
5674template<typename BasicJsonType, typename CompatibleString,
5675 enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
5676inline void to_json(BasicJsonType& j, const CompatibleString& s)
5677{
5678 external_constructor<value_t::string>::construct(j, s);
5679}
5680
5681template<typename BasicJsonType>
5682inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
5683{
5684 external_constructor<value_t::string>::construct(j, std::move(s));
5685}
5686
5687template<typename BasicJsonType, typename FloatType,
5688 enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
5689inline void to_json(BasicJsonType& j, FloatType val) noexcept
5690{
5691 external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
5692}
5693
5694template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
5695 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
5696inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
5697{
5698 external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
5699}
5700
5701template<typename BasicJsonType, typename CompatibleNumberIntegerType,
5702 enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
5703inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
5704{
5705 external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
5706}
5707
5708#if !JSON_DISABLE_ENUM_SERIALIZATION
5709template<typename BasicJsonType, typename EnumType,
5710 enable_if_t<std::is_enum<EnumType>::value, int> = 0>
5711inline void to_json(BasicJsonType& j, EnumType e) noexcept
5712{
5713 using underlying_type = typename std::underlying_type<EnumType>::type;
5714 external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
5715}
5716#endif // JSON_DISABLE_ENUM_SERIALIZATION
5717
5718template<typename BasicJsonType>
5719inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
5720{
5721 external_constructor<value_t::array>::construct(j, e);
5722}
5723
5724template < typename BasicJsonType, typename CompatibleArrayType,
5725 enable_if_t < is_compatible_array_type<BasicJsonType,
5726 CompatibleArrayType>::value&&
5727 !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
5728 !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
5729 !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
5730 !is_basic_json<CompatibleArrayType>::value,
5731 int > = 0 >
5732inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
5733{
5734 external_constructor<value_t::array>::construct(j, arr);
5735}
5736
5737template<typename BasicJsonType>
5738inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
5739{
5740 external_constructor<value_t::binary>::construct(j, bin);
5741}
5742
5743template<typename BasicJsonType, typename T,
5744 enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
5745inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
5746{
5747 external_constructor<value_t::array>::construct(j, std::move(arr));
5748}
5749
5750template<typename BasicJsonType>
5751inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
5752{
5753 external_constructor<value_t::array>::construct(j, std::move(arr));
5754}
5755
5756template < typename BasicJsonType, typename CompatibleObjectType,
5757 enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
5758inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
5759{
5760 external_constructor<value_t::object>::construct(j, obj);
5761}
5762
5763template<typename BasicJsonType>
5764inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
5765{
5766 external_constructor<value_t::object>::construct(j, std::move(obj));
5767}
5768
5769template <
5770 typename BasicJsonType, typename T, std::size_t N,
5771 enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
5772 const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5773 int > = 0 >
5774inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
5775{
5776 external_constructor<value_t::array>::construct(j, arr);
5777}
5778
5779template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
5780inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
5781{
5782 j = { p.first, p.second };
5783}
5784
5785// for https://github.com/nlohmann/json/pull/1134
5786template<typename BasicJsonType, typename T,
5787 enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
5788inline void to_json(BasicJsonType& j, const T& b)
5789{
5790 j = { {b.key(), b.value()} };
5791}
5792
5793template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
5794inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
5795{
5796 j = { std::get<Idx>(t)... };
5797}
5798
5799template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
5800inline void to_json(BasicJsonType& j, const T& t)
5801{
5802 to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
5803}
5804
5805#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
5806template<typename BasicJsonType>
5807inline void to_json(BasicJsonType& j, const std_fs::path& p)
5808{
5809 j = p.string();
5810}
5811#endif
5812
5814{
5815 template<typename BasicJsonType, typename T>
5816 auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
5817 -> decltype(to_json(j, std::forward<T>(val)), void())
5818 {
5819 return to_json(j, std::forward<T>(val));
5820 }
5821};
5822} // namespace detail
5823
5824#ifndef JSON_HAS_CPP_17
5828namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
5829{
5830#endif
5831JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
5833#ifndef JSON_HAS_CPP_17
5834} // namespace
5835#endif
5836
5837NLOHMANN_JSON_NAMESPACE_END
5838
5839// #include <nlohmann/detail/meta/identity_tag.hpp>
5840
5841
5842NLOHMANN_JSON_NAMESPACE_BEGIN
5843
5845template<typename ValueType, typename>
5847{
5850 template<typename BasicJsonType, typename TargetType = ValueType>
5851 static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
5852 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
5853 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
5854 {
5855 ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
5856 }
5857
5860 template<typename BasicJsonType, typename TargetType = ValueType>
5861 static auto from_json(BasicJsonType && j) noexcept(
5862 noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
5863 -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
5864 {
5865 return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
5866 }
5867
5870 template<typename BasicJsonType, typename TargetType = ValueType>
5871 static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
5872 noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
5873 -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
5874 {
5875 ::nlohmann::to_json(j, std::forward<TargetType>(val));
5876 }
5877};
5878
5879NLOHMANN_JSON_NAMESPACE_END
5880
5881// #include <nlohmann/byte_container_with_subtype.hpp>
5882// __ _____ _____ _____
5883// __| | __| | | | JSON for Modern C++
5884// | | |__ | | | | | | version 3.11.3
5885// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5886//
5887// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
5888// SPDX-License-Identifier: MIT
5889
5890
5891
5892#include <cstdint> // uint8_t, uint64_t
5893#include <tuple> // tie
5894#include <utility> // move
5895
5896// #include <nlohmann/detail/abi_macros.hpp>
5897
5898
5899NLOHMANN_JSON_NAMESPACE_BEGIN
5900
5903template<typename BinaryType>
5904class byte_container_with_subtype : public BinaryType
5905{
5906 public:
5907 using container_type = BinaryType;
5908 using subtype_type = std::uint64_t;
5909
5911 byte_container_with_subtype() noexcept(noexcept(container_type()))
5912 : container_type()
5913 {}
5914
5916 byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
5917 : container_type(b)
5918 {}
5919
5921 byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
5922 : container_type(std::move(b))
5923 {}
5924
5926 byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
5927 : container_type(b)
5928 , m_subtype(subtype_)
5929 , m_has_subtype(true)
5930 {}
5931
5933 byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
5934 : container_type(std::move(b))
5935 , m_subtype(subtype_)
5936 , m_has_subtype(true)
5937 {}
5938
5939 bool operator==(const byte_container_with_subtype& rhs) const
5940 {
5941 return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
5942 std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
5943 }
5944
5945 bool operator!=(const byte_container_with_subtype& rhs) const
5946 {
5947 return !(rhs == *this);
5948 }
5949
5952 void set_subtype(subtype_type subtype_) noexcept
5953 {
5954 m_subtype = subtype_;
5955 m_has_subtype = true;
5956 }
5957
5960 constexpr subtype_type subtype() const noexcept
5961 {
5962 return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
5963 }
5964
5967 constexpr bool has_subtype() const noexcept
5968 {
5969 return m_has_subtype;
5970 }
5971
5974 void clear_subtype() noexcept
5975 {
5976 m_subtype = 0;
5977 m_has_subtype = false;
5978 }
5979
5980 private:
5981 subtype_type m_subtype = 0;
5982 bool m_has_subtype = false;
5983};
5984
5985NLOHMANN_JSON_NAMESPACE_END
5986
5987// #include <nlohmann/detail/conversions/from_json.hpp>
5988
5989// #include <nlohmann/detail/conversions/to_json.hpp>
5990
5991// #include <nlohmann/detail/exceptions.hpp>
5992
5993// #include <nlohmann/detail/hash.hpp>
5994// __ _____ _____ _____
5995// __| | __| | | | JSON for Modern C++
5996// | | |__ | | | | | | version 3.11.3
5997// |_____|_____|_____|_|___| https://github.com/nlohmann/json
5998//
5999// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6000// SPDX-License-Identifier: MIT
6001
6002
6003
6004#include <cstdint> // uint8_t
6005#include <cstddef> // size_t
6006#include <functional> // hash
6007
6008// #include <nlohmann/detail/abi_macros.hpp>
6009
6010// #include <nlohmann/detail/value_t.hpp>
6011
6012
6013NLOHMANN_JSON_NAMESPACE_BEGIN
6014namespace detail
6015{
6016
6017// boost::hash_combine
6018inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
6019{
6020 seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
6021 return seed;
6022}
6023
6035template<typename BasicJsonType>
6036std::size_t hash(const BasicJsonType& j)
6037{
6038 using string_t = typename BasicJsonType::string_t;
6039 using number_integer_t = typename BasicJsonType::number_integer_t;
6040 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6041 using number_float_t = typename BasicJsonType::number_float_t;
6042
6043 const auto type = static_cast<std::size_t>(j.type());
6044 switch (j.type())
6045 {
6046 case BasicJsonType::value_t::null:
6047 case BasicJsonType::value_t::discarded:
6048 {
6049 return combine(type, 0);
6050 }
6051
6052 case BasicJsonType::value_t::object:
6053 {
6054 auto seed = combine(type, j.size());
6055 for (const auto& element : j.items())
6056 {
6057 const auto h = std::hash<string_t> {}(element.key());
6058 seed = combine(seed, h);
6059 seed = combine(seed, hash(element.value()));
6060 }
6061 return seed;
6062 }
6063
6064 case BasicJsonType::value_t::array:
6065 {
6066 auto seed = combine(type, j.size());
6067 for (const auto& element : j)
6068 {
6069 seed = combine(seed, hash(element));
6070 }
6071 return seed;
6072 }
6073
6074 case BasicJsonType::value_t::string:
6075 {
6076 const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
6077 return combine(type, h);
6078 }
6079
6080 case BasicJsonType::value_t::boolean:
6081 {
6082 const auto h = std::hash<bool> {}(j.template get<bool>());
6083 return combine(type, h);
6084 }
6085
6086 case BasicJsonType::value_t::number_integer:
6087 {
6088 const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
6089 return combine(type, h);
6090 }
6091
6092 case BasicJsonType::value_t::number_unsigned:
6093 {
6094 const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
6095 return combine(type, h);
6096 }
6097
6098 case BasicJsonType::value_t::number_float:
6099 {
6100 const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
6101 return combine(type, h);
6102 }
6103
6104 case BasicJsonType::value_t::binary:
6105 {
6106 auto seed = combine(type, j.get_binary().size());
6107 const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
6108 seed = combine(seed, h);
6109 seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
6110 for (const auto byte : j.get_binary())
6111 {
6112 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
6113 }
6114 return seed;
6115 }
6116
6117 default: // LCOV_EXCL_LINE
6118 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
6119 return 0; // LCOV_EXCL_LINE
6120 }
6121}
6122
6123} // namespace detail
6124NLOHMANN_JSON_NAMESPACE_END
6125
6126// #include <nlohmann/detail/input/binary_reader.hpp>
6127// __ _____ _____ _____
6128// __| | __| | | | JSON for Modern C++
6129// | | |__ | | | | | | version 3.11.3
6130// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6131//
6132// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6133// SPDX-License-Identifier: MIT
6134
6135
6136
6137#include <algorithm> // generate_n
6138#include <array> // array
6139#include <cmath> // ldexp
6140#include <cstddef> // size_t
6141#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
6142#include <cstdio> // snprintf
6143#include <cstring> // memcpy
6144#include <iterator> // back_inserter
6145#include <limits> // numeric_limits
6146#include <string> // char_traits, string
6147#include <utility> // make_pair, move
6148#include <vector> // vector
6149
6150// #include <nlohmann/detail/exceptions.hpp>
6151
6152// #include <nlohmann/detail/input/input_adapters.hpp>
6153// __ _____ _____ _____
6154// __| | __| | | | JSON for Modern C++
6155// | | |__ | | | | | | version 3.11.3
6156// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6157//
6158// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6159// SPDX-License-Identifier: MIT
6160
6161
6162
6163#include <array> // array
6164#include <cstddef> // size_t
6165#include <cstring> // strlen
6166#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
6167#include <memory> // shared_ptr, make_shared, addressof
6168#include <numeric> // accumulate
6169#include <string> // string, char_traits
6170#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
6171#include <utility> // pair, declval
6172
6173#ifndef JSON_NO_IO
6174 #include <cstdio> // FILE *
6175 #include <istream> // istream
6176#endif // JSON_NO_IO
6177
6178// #include <nlohmann/detail/iterators/iterator_traits.hpp>
6179
6180// #include <nlohmann/detail/macro_scope.hpp>
6181
6182// #include <nlohmann/detail/meta/type_traits.hpp>
6183
6184
6185NLOHMANN_JSON_NAMESPACE_BEGIN
6186namespace detail
6187{
6188
6190enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
6191
6193// input adapters //
6195
6196#ifndef JSON_NO_IO
6202{
6203 public:
6204 using char_type = char;
6205
6206 JSON_HEDLEY_NON_NULL(2)
6207 explicit file_input_adapter(std::FILE* f) noexcept
6208 : m_file(f)
6209 {
6210 JSON_ASSERT(m_file != nullptr);
6211 }
6212
6213 // make class move-only
6214 file_input_adapter(const file_input_adapter&) = delete;
6215 file_input_adapter(file_input_adapter&&) noexcept = default;
6216 file_input_adapter& operator=(const file_input_adapter&) = delete;
6217 file_input_adapter& operator=(file_input_adapter&&) = delete;
6218 ~file_input_adapter() = default;
6219
6220 std::char_traits<char>::int_type get_character() noexcept
6221 {
6222 return std::fgetc(m_file);
6223 }
6224
6225 private:
6227 std::FILE* m_file;
6228};
6229
6240{
6241 public:
6242 using char_type = char;
6243
6245 {
6246 // clear stream flags; we use underlying streambuf I/O, do not
6247 // maintain ifstream flags, except eof
6248 if (is != nullptr)
6249 {
6250 is->clear(is->rdstate() & std::ios::eofbit);
6251 }
6252 }
6253
6254 explicit input_stream_adapter(std::istream& i)
6255 : is(&i), sb(i.rdbuf())
6256 {}
6257
6258 // delete because of pointer members
6260 input_stream_adapter& operator=(input_stream_adapter&) = delete;
6261 input_stream_adapter& operator=(input_stream_adapter&&) = delete;
6262
6264 : is(rhs.is), sb(rhs.sb)
6265 {
6266 rhs.is = nullptr;
6267 rhs.sb = nullptr;
6268 }
6269
6270 // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
6271 // ensure that std::char_traits<char>::eof() and the character 0xFF do not
6272 // end up as the same value, e.g. 0xFFFFFFFF.
6273 std::char_traits<char>::int_type get_character()
6274 {
6275 auto res = sb->sbumpc();
6276 // set eof manually, as we don't use the istream interface.
6277 if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
6278 {
6279 is->clear(is->rdstate() | std::ios::eofbit);
6280 }
6281 return res;
6282 }
6283
6284 private:
6286 std::istream* is = nullptr;
6287 std::streambuf* sb = nullptr;
6288};
6289#endif // JSON_NO_IO
6290
6291// General-purpose iterator-based adapter. It might not be as fast as
6292// theoretically possible for some containers, but it is extremely versatile.
6293template<typename IteratorType>
6295{
6296 public:
6297 using char_type = typename std::iterator_traits<IteratorType>::value_type;
6298
6299 iterator_input_adapter(IteratorType first, IteratorType last)
6300 : current(std::move(first)), end(std::move(last))
6301 {}
6302
6303 typename char_traits<char_type>::int_type get_character()
6304 {
6305 if (JSON_HEDLEY_LIKELY(current != end))
6306 {
6307 auto result = char_traits<char_type>::to_int_type(*current);
6308 std::advance(current, 1);
6309 return result;
6310 }
6311
6313 }
6314
6315 private:
6316 IteratorType current;
6317 IteratorType end;
6318
6319 template<typename BaseInputAdapter, size_t T>
6320 friend struct wide_string_input_helper;
6321
6322 bool empty() const
6323 {
6324 return current == end;
6325 }
6326};
6327
6328template<typename BaseInputAdapter, size_t T>
6330
6331template<typename BaseInputAdapter>
6332struct wide_string_input_helper<BaseInputAdapter, 4>
6333{
6334 // UTF-32
6335 static void fill_buffer(BaseInputAdapter& input,
6336 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6337 size_t& utf8_bytes_index,
6338 size_t& utf8_bytes_filled)
6339 {
6340 utf8_bytes_index = 0;
6341
6342 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6343 {
6344 utf8_bytes[0] = std::char_traits<char>::eof();
6345 utf8_bytes_filled = 1;
6346 }
6347 else
6348 {
6349 // get the current character
6350 const auto wc = input.get_character();
6351
6352 // UTF-32 to UTF-8 encoding
6353 if (wc < 0x80)
6354 {
6355 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6356 utf8_bytes_filled = 1;
6357 }
6358 else if (wc <= 0x7FF)
6359 {
6360 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
6361 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6362 utf8_bytes_filled = 2;
6363 }
6364 else if (wc <= 0xFFFF)
6365 {
6366 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
6367 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6368 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6369 utf8_bytes_filled = 3;
6370 }
6371 else if (wc <= 0x10FFFF)
6372 {
6373 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
6374 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
6375 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6376 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6377 utf8_bytes_filled = 4;
6378 }
6379 else
6380 {
6381 // unknown character
6382 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6383 utf8_bytes_filled = 1;
6384 }
6385 }
6386 }
6387};
6388
6389template<typename BaseInputAdapter>
6390struct wide_string_input_helper<BaseInputAdapter, 2>
6391{
6392 // UTF-16
6393 static void fill_buffer(BaseInputAdapter& input,
6394 std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
6395 size_t& utf8_bytes_index,
6396 size_t& utf8_bytes_filled)
6397 {
6398 utf8_bytes_index = 0;
6399
6400 if (JSON_HEDLEY_UNLIKELY(input.empty()))
6401 {
6402 utf8_bytes[0] = std::char_traits<char>::eof();
6403 utf8_bytes_filled = 1;
6404 }
6405 else
6406 {
6407 // get the current character
6408 const auto wc = input.get_character();
6409
6410 // UTF-16 to UTF-8 encoding
6411 if (wc < 0x80)
6412 {
6413 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6414 utf8_bytes_filled = 1;
6415 }
6416 else if (wc <= 0x7FF)
6417 {
6418 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
6419 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6420 utf8_bytes_filled = 2;
6421 }
6422 else if (0xD800 > wc || wc >= 0xE000)
6423 {
6424 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
6425 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
6426 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
6427 utf8_bytes_filled = 3;
6428 }
6429 else
6430 {
6431 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
6432 {
6433 const auto wc2 = static_cast<unsigned int>(input.get_character());
6434 const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
6435 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
6436 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
6437 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
6438 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
6439 utf8_bytes_filled = 4;
6440 }
6441 else
6442 {
6443 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
6444 utf8_bytes_filled = 1;
6445 }
6446 }
6447 }
6448 }
6449};
6450
6451// Wraps another input adapter to convert wide character types into individual bytes.
6452template<typename BaseInputAdapter, typename WideCharType>
6454{
6455 public:
6456 using char_type = char;
6457
6458 wide_string_input_adapter(BaseInputAdapter base)
6459 : base_adapter(base) {}
6460
6461 typename std::char_traits<char>::int_type get_character() noexcept
6462 {
6463 // check if buffer needs to be filled
6464 if (utf8_bytes_index == utf8_bytes_filled)
6465 {
6466 fill_buffer<sizeof(WideCharType)>();
6467
6468 JSON_ASSERT(utf8_bytes_filled > 0);
6469 JSON_ASSERT(utf8_bytes_index == 0);
6470 }
6471
6472 // use buffer
6473 JSON_ASSERT(utf8_bytes_filled > 0);
6474 JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
6475 return utf8_bytes[utf8_bytes_index++];
6476 }
6477
6478 private:
6479 BaseInputAdapter base_adapter;
6480
6481 template<size_t T>
6482 void fill_buffer()
6483 {
6484 wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
6485 }
6486
6488 std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
6489
6491 std::size_t utf8_bytes_index = 0;
6493 std::size_t utf8_bytes_filled = 0;
6494};
6495
6496template<typename IteratorType, typename Enable = void>
6498{
6499 using iterator_type = IteratorType;
6500 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6502
6503 static adapter_type create(IteratorType first, IteratorType last)
6504 {
6505 return adapter_type(std::move(first), std::move(last));
6506 }
6507};
6508
6509template<typename T>
6511{
6512 using value_type = typename std::iterator_traits<T>::value_type;
6513 enum
6514 {
6515 value = sizeof(value_type) > 1
6516 };
6517};
6518
6519template<typename IteratorType>
6520struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
6521{
6522 using iterator_type = IteratorType;
6523 using char_type = typename std::iterator_traits<iterator_type>::value_type;
6526
6527 static adapter_type create(IteratorType first, IteratorType last)
6528 {
6529 return adapter_type(base_adapter_type(std::move(first), std::move(last)));
6530 }
6531};
6532
6533// General purpose iterator-based input
6534template<typename IteratorType>
6535typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
6536{
6538 return factory_type::create(first, last);
6539}
6540
6541// Convenience shorthand from container to iterator
6542// Enables ADL on begin(container) and end(container)
6543// Encloses the using declarations in namespace for not to leak them to outside scope
6544
6545namespace container_input_adapter_factory_impl
6546{
6547
6548using std::begin;
6549using std::end;
6550
6551template<typename ContainerType, typename Enable = void>
6553
6554template<typename ContainerType>
6556 void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
6557 {
6558 using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
6559
6560 static adapter_type create(const ContainerType& container)
6561{
6562 return input_adapter(begin(container), end(container));
6563}
6564 };
6565
6566} // namespace container_input_adapter_factory_impl
6567
6568template<typename ContainerType>
6570{
6572}
6573
6574#ifndef JSON_NO_IO
6575// Special cases with fast paths
6576inline file_input_adapter input_adapter(std::FILE* file)
6577{
6578 return file_input_adapter(file);
6579}
6580
6581inline input_stream_adapter input_adapter(std::istream& stream)
6582{
6583 return input_stream_adapter(stream);
6584}
6585
6586inline input_stream_adapter input_adapter(std::istream&& stream)
6587{
6588 return input_stream_adapter(stream);
6589}
6590#endif // JSON_NO_IO
6591
6592using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
6593
6594// Null-delimited strings, and the like.
6595template < typename CharT,
6596 typename std::enable_if <
6597 std::is_pointer<CharT>::value&&
6598 !std::is_array<CharT>::value&&
6599 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6600 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6601 int >::type = 0 >
6602contiguous_bytes_input_adapter input_adapter(CharT b)
6603{
6604 auto length = std::strlen(reinterpret_cast<const char*>(b));
6605 const auto* ptr = reinterpret_cast<const char*>(b);
6606 return input_adapter(ptr, ptr + length);
6607}
6608
6609template<typename T, std::size_t N>
6610auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
6611{
6612 return input_adapter(array, array + N);
6613}
6614
6615// This class only handles inputs of input_buffer_adapter type.
6616// It's required so that expressions like {ptr, len} can be implicitly cast
6617// to the correct adapter.
6619{
6620 public:
6621 template < typename CharT,
6622 typename std::enable_if <
6623 std::is_pointer<CharT>::value&&
6624 std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
6625 sizeof(typename std::remove_pointer<CharT>::type) == 1,
6626 int >::type = 0 >
6627 span_input_adapter(CharT b, std::size_t l)
6628 : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
6629
6630 template<class IteratorType,
6631 typename std::enable_if<
6632 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
6633 int>::type = 0>
6634 span_input_adapter(IteratorType first, IteratorType last)
6635 : ia(input_adapter(first, last)) {}
6636
6637 contiguous_bytes_input_adapter&& get()
6638 {
6639 return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
6640 }
6641
6642 private:
6643 contiguous_bytes_input_adapter ia;
6644};
6645
6646} // namespace detail
6647NLOHMANN_JSON_NAMESPACE_END
6648
6649// #include <nlohmann/detail/input/json_sax.hpp>
6650// __ _____ _____ _____
6651// __| | __| | | | JSON for Modern C++
6652// | | |__ | | | | | | version 3.11.3
6653// |_____|_____|_____|_|___| https://github.com/nlohmann/json
6654//
6655// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
6656// SPDX-License-Identifier: MIT
6657
6658
6659
6660#include <cstddef>
6661#include <string> // string
6662#include <utility> // move
6663#include <vector> // vector
6664
6665// #include <nlohmann/detail/exceptions.hpp>
6666
6667// #include <nlohmann/detail/macro_scope.hpp>
6668
6669// #include <nlohmann/detail/string_concat.hpp>
6670
6671
6672NLOHMANN_JSON_NAMESPACE_BEGIN
6673
6682template<typename BasicJsonType>
6684{
6685 using number_integer_t = typename BasicJsonType::number_integer_t;
6686 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6687 using number_float_t = typename BasicJsonType::number_float_t;
6688 using string_t = typename BasicJsonType::string_t;
6689 using binary_t = typename BasicJsonType::binary_t;
6690
6695 virtual bool null() = 0;
6696
6702 virtual bool boolean(bool val) = 0;
6703
6709 virtual bool number_integer(number_integer_t val) = 0;
6710
6716 virtual bool number_unsigned(number_unsigned_t val) = 0;
6717
6724 virtual bool number_float(number_float_t val, const string_t& s) = 0;
6725
6732 virtual bool string(string_t& val) = 0;
6733
6740 virtual bool binary(binary_t& val) = 0;
6741
6748 virtual bool start_object(std::size_t elements) = 0;
6749
6756 virtual bool key(string_t& val) = 0;
6757
6762 virtual bool end_object() = 0;
6763
6770 virtual bool start_array(std::size_t elements) = 0;
6771
6776 virtual bool end_array() = 0;
6777
6785 virtual bool parse_error(std::size_t position,
6786 const std::string& last_token,
6787 const detail::exception& ex) = 0;
6788
6789 json_sax() = default;
6790 json_sax(const json_sax&) = default;
6791 json_sax(json_sax&&) noexcept = default;
6792 json_sax& operator=(const json_sax&) = default;
6793 json_sax& operator=(json_sax&&) noexcept = default;
6794 virtual ~json_sax() = default;
6795};
6796
6797namespace detail
6798{
6812template<typename BasicJsonType>
6814{
6815 public:
6816 using number_integer_t = typename BasicJsonType::number_integer_t;
6817 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
6818 using number_float_t = typename BasicJsonType::number_float_t;
6819 using string_t = typename BasicJsonType::string_t;
6820 using binary_t = typename BasicJsonType::binary_t;
6821
6827 explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
6828 : root(r), allow_exceptions(allow_exceptions_)
6829 {}
6830
6831 // make class move-only
6833 json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6834 json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
6835 json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
6836 ~json_sax_dom_parser() = default;
6837
6838 bool null()
6839 {
6840 handle_value(nullptr);
6841 return true;
6842 }
6843
6844 bool boolean(bool val)
6845 {
6846 handle_value(val);
6847 return true;
6848 }
6849
6850 bool number_integer(number_integer_t val)
6851 {
6852 handle_value(val);
6853 return true;
6854 }
6855
6856 bool number_unsigned(number_unsigned_t val)
6857 {
6858 handle_value(val);
6859 return true;
6860 }
6861
6862 bool number_float(number_float_t val, const string_t& /*unused*/)
6863 {
6864 handle_value(val);
6865 return true;
6866 }
6867
6868 bool string(string_t& val)
6869 {
6870 handle_value(val);
6871 return true;
6872 }
6873
6874 bool binary(binary_t& val)
6875 {
6876 handle_value(std::move(val));
6877 return true;
6878 }
6879
6880 bool start_object(std::size_t len)
6881 {
6882 ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
6883
6884 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6885 {
6886 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
6887 }
6888
6889 return true;
6890 }
6891
6892 bool key(string_t& val)
6893 {
6894 JSON_ASSERT(!ref_stack.empty());
6895 JSON_ASSERT(ref_stack.back()->is_object());
6896
6897 // add null at given key and store the reference for later
6898 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
6899 return true;
6900 }
6901
6902 bool end_object()
6903 {
6904 JSON_ASSERT(!ref_stack.empty());
6905 JSON_ASSERT(ref_stack.back()->is_object());
6906
6907 ref_stack.back()->set_parents();
6908 ref_stack.pop_back();
6909 return true;
6910 }
6911
6912 bool start_array(std::size_t len)
6913 {
6914 ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
6915
6916 if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
6917 {
6918 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
6919 }
6920
6921 return true;
6922 }
6923
6924 bool end_array()
6925 {
6926 JSON_ASSERT(!ref_stack.empty());
6927 JSON_ASSERT(ref_stack.back()->is_array());
6928
6929 ref_stack.back()->set_parents();
6930 ref_stack.pop_back();
6931 return true;
6932 }
6933
6934 template<class Exception>
6935 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
6936 const Exception& ex)
6937 {
6938 errored = true;
6939 static_cast<void>(ex);
6940 if (allow_exceptions)
6941 {
6942 JSON_THROW(ex);
6943 }
6944 return false;
6945 }
6946
6947 constexpr bool is_errored() const
6948 {
6949 return errored;
6950 }
6951
6952 private:
6959 template<typename Value>
6960 JSON_HEDLEY_RETURNS_NON_NULL
6961 BasicJsonType* handle_value(Value&& v)
6962 {
6963 if (ref_stack.empty())
6964 {
6965 root = BasicJsonType(std::forward<Value>(v));
6966 return &root;
6967 }
6968
6969 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
6970
6971 if (ref_stack.back()->is_array())
6972 {
6973 ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
6974 return &(ref_stack.back()->m_data.m_value.array->back());
6975 }
6976
6977 JSON_ASSERT(ref_stack.back()->is_object());
6978 JSON_ASSERT(object_element);
6979 *object_element = BasicJsonType(std::forward<Value>(v));
6980 return object_element;
6981 }
6982
6984 BasicJsonType& root;
6986 std::vector<BasicJsonType*> ref_stack {};
6988 BasicJsonType* object_element = nullptr;
6990 bool errored = false;
6992 const bool allow_exceptions = true;
6993};
6994
6995template<typename BasicJsonType>
6997{
6998 public:
6999 using number_integer_t = typename BasicJsonType::number_integer_t;
7000 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7001 using number_float_t = typename BasicJsonType::number_float_t;
7002 using string_t = typename BasicJsonType::string_t;
7003 using binary_t = typename BasicJsonType::binary_t;
7004 using parser_callback_t = typename BasicJsonType::parser_callback_t;
7005 using parse_event_t = typename BasicJsonType::parse_event_t;
7006
7007 json_sax_dom_callback_parser(BasicJsonType& r,
7008 const parser_callback_t cb,
7009 const bool allow_exceptions_ = true)
7010 : root(r), callback(cb), allow_exceptions(allow_exceptions_)
7011 {
7012 keep_stack.push_back(true);
7013 }
7014
7015 // make class move-only
7017 json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7019 json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7021
7022 bool null()
7023 {
7024 handle_value(nullptr);
7025 return true;
7026 }
7027
7028 bool boolean(bool val)
7029 {
7030 handle_value(val);
7031 return true;
7032 }
7033
7034 bool number_integer(number_integer_t val)
7035 {
7036 handle_value(val);
7037 return true;
7038 }
7039
7040 bool number_unsigned(number_unsigned_t val)
7041 {
7042 handle_value(val);
7043 return true;
7044 }
7045
7046 bool number_float(number_float_t val, const string_t& /*unused*/)
7047 {
7048 handle_value(val);
7049 return true;
7050 }
7051
7052 bool string(string_t& val)
7053 {
7054 handle_value(val);
7055 return true;
7056 }
7057
7058 bool binary(binary_t& val)
7059 {
7060 handle_value(std::move(val));
7061 return true;
7062 }
7063
7064 bool start_object(std::size_t len)
7065 {
7066 // check callback for object start
7067 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
7068 keep_stack.push_back(keep);
7069
7070 auto val = handle_value(BasicJsonType::value_t::object, true);
7071 ref_stack.push_back(val.second);
7072
7073 // check object limit
7074 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7075 {
7076 JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
7077 }
7078
7079 return true;
7080 }
7081
7082 bool key(string_t& val)
7083 {
7084 BasicJsonType k = BasicJsonType(val);
7085
7086 // check callback for key
7087 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
7088 key_keep_stack.push_back(keep);
7089
7090 // add discarded value at given key and store the reference for later
7091 if (keep && ref_stack.back())
7092 {
7093 object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
7094 }
7095
7096 return true;
7097 }
7098
7099 bool end_object()
7100 {
7101 if (ref_stack.back())
7102 {
7103 if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
7104 {
7105 // discard object
7106 *ref_stack.back() = discarded;
7107 }
7108 else
7109 {
7110 ref_stack.back()->set_parents();
7111 }
7112 }
7113
7114 JSON_ASSERT(!ref_stack.empty());
7115 JSON_ASSERT(!keep_stack.empty());
7116 ref_stack.pop_back();
7117 keep_stack.pop_back();
7118
7119 if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
7120 {
7121 // remove discarded value
7122 for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
7123 {
7124 if (it->is_discarded())
7125 {
7126 ref_stack.back()->erase(it);
7127 break;
7128 }
7129 }
7130 }
7131
7132 return true;
7133 }
7134
7135 bool start_array(std::size_t len)
7136 {
7137 const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
7138 keep_stack.push_back(keep);
7139
7140 auto val = handle_value(BasicJsonType::value_t::array, true);
7141 ref_stack.push_back(val.second);
7142
7143 // check array limit
7144 if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
7145 {
7146 JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
7147 }
7148
7149 return true;
7150 }
7151
7152 bool end_array()
7153 {
7154 bool keep = true;
7155
7156 if (ref_stack.back())
7157 {
7158 keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
7159 if (keep)
7160 {
7161 ref_stack.back()->set_parents();
7162 }
7163 else
7164 {
7165 // discard array
7166 *ref_stack.back() = discarded;
7167 }
7168 }
7169
7170 JSON_ASSERT(!ref_stack.empty());
7171 JSON_ASSERT(!keep_stack.empty());
7172 ref_stack.pop_back();
7173 keep_stack.pop_back();
7174
7175 // remove discarded value
7176 if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
7177 {
7178 ref_stack.back()->m_data.m_value.array->pop_back();
7179 }
7180
7181 return true;
7182 }
7183
7184 template<class Exception>
7185 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
7186 const Exception& ex)
7187 {
7188 errored = true;
7189 static_cast<void>(ex);
7190 if (allow_exceptions)
7191 {
7192 JSON_THROW(ex);
7193 }
7194 return false;
7195 }
7196
7197 constexpr bool is_errored() const
7198 {
7199 return errored;
7200 }
7201
7202 private:
7218 template<typename Value>
7219 std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
7220 {
7221 JSON_ASSERT(!keep_stack.empty());
7222
7223 // do not handle this value if we know it would be added to a discarded
7224 // container
7225 if (!keep_stack.back())
7226 {
7227 return {false, nullptr};
7228 }
7229
7230 // create value
7231 auto value = BasicJsonType(std::forward<Value>(v));
7232
7233 // check callback
7234 const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
7235
7236 // do not handle this value if we just learnt it shall be discarded
7237 if (!keep)
7238 {
7239 return {false, nullptr};
7240 }
7241
7242 if (ref_stack.empty())
7243 {
7244 root = std::move(value);
7245 return {true, & root};
7246 }
7247
7248 // skip this value if we already decided to skip the parent
7249 // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
7250 if (!ref_stack.back())
7251 {
7252 return {false, nullptr};
7253 }
7254
7255 // we now only expect arrays and objects
7256 JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
7257
7258 // array
7259 if (ref_stack.back()->is_array())
7260 {
7261 ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
7262 return {true, & (ref_stack.back()->m_data.m_value.array->back())};
7263 }
7264
7265 // object
7266 JSON_ASSERT(ref_stack.back()->is_object());
7267 // check if we should store an element for the current key
7268 JSON_ASSERT(!key_keep_stack.empty());
7269 const bool store_element = key_keep_stack.back();
7270 key_keep_stack.pop_back();
7271
7272 if (!store_element)
7273 {
7274 return {false, nullptr};
7275 }
7276
7277 JSON_ASSERT(object_element);
7278 *object_element = std::move(value);
7279 return {true, object_element};
7280 }
7281
7283 BasicJsonType& root;
7285 std::vector<BasicJsonType*> ref_stack {};
7287 std::vector<bool> keep_stack {};
7289 std::vector<bool> key_keep_stack {};
7291 BasicJsonType* object_element = nullptr;
7293 bool errored = false;
7295 const parser_callback_t callback = nullptr;
7297 const bool allow_exceptions = true;
7299 BasicJsonType discarded = BasicJsonType::value_t::discarded;
7300};
7301
7302template<typename BasicJsonType>
7304{
7305 public:
7306 using number_integer_t = typename BasicJsonType::number_integer_t;
7307 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7308 using number_float_t = typename BasicJsonType::number_float_t;
7309 using string_t = typename BasicJsonType::string_t;
7310 using binary_t = typename BasicJsonType::binary_t;
7311
7312 bool null()
7313 {
7314 return true;
7315 }
7316
7317 bool boolean(bool /*unused*/)
7318 {
7319 return true;
7320 }
7321
7322 bool number_integer(number_integer_t /*unused*/)
7323 {
7324 return true;
7325 }
7326
7327 bool number_unsigned(number_unsigned_t /*unused*/)
7328 {
7329 return true;
7330 }
7331
7332 bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
7333 {
7334 return true;
7335 }
7336
7337 bool string(string_t& /*unused*/)
7338 {
7339 return true;
7340 }
7341
7342 bool binary(binary_t& /*unused*/)
7343 {
7344 return true;
7345 }
7346
7347 bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7348 {
7349 return true;
7350 }
7351
7352 bool key(string_t& /*unused*/)
7353 {
7354 return true;
7355 }
7356
7357 bool end_object()
7358 {
7359 return true;
7360 }
7361
7362 bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
7363 {
7364 return true;
7365 }
7366
7367 bool end_array()
7368 {
7369 return true;
7370 }
7371
7372 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
7373 {
7374 return false;
7375 }
7376};
7377
7378} // namespace detail
7379NLOHMANN_JSON_NAMESPACE_END
7380
7381// #include <nlohmann/detail/input/lexer.hpp>
7382// __ _____ _____ _____
7383// __| | __| | | | JSON for Modern C++
7384// | | |__ | | | | | | version 3.11.3
7385// |_____|_____|_____|_|___| https://github.com/nlohmann/json
7386//
7387// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
7388// SPDX-License-Identifier: MIT
7389
7390
7391
7392#include <array> // array
7393#include <clocale> // localeconv
7394#include <cstddef> // size_t
7395#include <cstdio> // snprintf
7396#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
7397#include <initializer_list> // initializer_list
7398#include <string> // char_traits, string
7399#include <utility> // move
7400#include <vector> // vector
7401
7402// #include <nlohmann/detail/input/input_adapters.hpp>
7403
7404// #include <nlohmann/detail/input/position_t.hpp>
7405
7406// #include <nlohmann/detail/macro_scope.hpp>
7407
7408// #include <nlohmann/detail/meta/type_traits.hpp>
7409
7410
7411NLOHMANN_JSON_NAMESPACE_BEGIN
7412namespace detail
7413{
7414
7416// lexer //
7418
7419template<typename BasicJsonType>
7421{
7422 public:
7424 enum class token_type
7425 {
7426 uninitialized,
7427 literal_true,
7428 literal_false,
7429 literal_null,
7430 value_string,
7431 value_unsigned,
7432 value_integer,
7433 value_float,
7434 begin_array,
7435 begin_object,
7436 end_array,
7437 end_object,
7438 name_separator,
7439 value_separator,
7440 parse_error,
7441 end_of_input,
7442 literal_or_value
7443 };
7444
7446 JSON_HEDLEY_RETURNS_NON_NULL
7447 JSON_HEDLEY_CONST
7448 static const char* token_type_name(const token_type t) noexcept
7449 {
7450 switch (t)
7451 {
7452 case token_type::uninitialized:
7453 return "<uninitialized>";
7454 case token_type::literal_true:
7455 return "true literal";
7456 case token_type::literal_false:
7457 return "false literal";
7458 case token_type::literal_null:
7459 return "null literal";
7460 case token_type::value_string:
7461 return "string literal";
7462 case token_type::value_unsigned:
7463 case token_type::value_integer:
7464 case token_type::value_float:
7465 return "number literal";
7466 case token_type::begin_array:
7467 return "'['";
7468 case token_type::begin_object:
7469 return "'{'";
7470 case token_type::end_array:
7471 return "']'";
7472 case token_type::end_object:
7473 return "'}'";
7474 case token_type::name_separator:
7475 return "':'";
7476 case token_type::value_separator:
7477 return "','";
7478 case token_type::parse_error:
7479 return "<parse error>";
7480 case token_type::end_of_input:
7481 return "end of input";
7482 case token_type::literal_or_value:
7483 return "'[', '{', or a literal";
7484 // LCOV_EXCL_START
7485 default: // catch non-enum values
7486 return "unknown token";
7487 // LCOV_EXCL_STOP
7488 }
7489 }
7490};
7496template<typename BasicJsonType, typename InputAdapterType>
7497class lexer : public lexer_base<BasicJsonType>
7498{
7499 using number_integer_t = typename BasicJsonType::number_integer_t;
7500 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
7501 using number_float_t = typename BasicJsonType::number_float_t;
7502 using string_t = typename BasicJsonType::string_t;
7503 using char_type = typename InputAdapterType::char_type;
7504 using char_int_type = typename char_traits<char_type>::int_type;
7505
7506 public:
7507 using token_type = typename lexer_base<BasicJsonType>::token_type;
7508
7509 explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
7510 : ia(std::move(adapter))
7511 , ignore_comments(ignore_comments_)
7512 , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
7513 {}
7514
7515 // delete because of pointer members
7516 lexer(const lexer&) = delete;
7517 lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7518 lexer& operator=(lexer&) = delete;
7519 lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
7520 ~lexer() = default;
7521
7522 private:
7524 // locales
7526
7528 JSON_HEDLEY_PURE
7529 static char get_decimal_point() noexcept
7530 {
7531 const auto* loc = localeconv();
7532 JSON_ASSERT(loc != nullptr);
7533 return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
7534 }
7535
7537 // scan functions
7539
7555 int get_codepoint()
7556 {
7557 // this function only makes sense after reading `\u`
7558 JSON_ASSERT(current == 'u');
7559 int codepoint = 0;
7560
7561 const auto factors = { 12u, 8u, 4u, 0u };
7562 for (const auto factor : factors)
7563 {
7564 get();
7565
7566 if (current >= '0' && current <= '9')
7567 {
7568 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
7569 }
7570 else if (current >= 'A' && current <= 'F')
7571 {
7572 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
7573 }
7574 else if (current >= 'a' && current <= 'f')
7575 {
7576 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
7577 }
7578 else
7579 {
7580 return -1;
7581 }
7582 }
7583
7584 JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
7585 return codepoint;
7586 }
7587
7603 bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
7604 {
7605 JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
7606 add(current);
7607
7608 for (auto range = ranges.begin(); range != ranges.end(); ++range)
7609 {
7610 get();
7611 if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
7612 {
7613 add(current);
7614 }
7615 else
7616 {
7617 error_message = "invalid string: ill-formed UTF-8 byte";
7618 return false;
7619 }
7620 }
7621
7622 return true;
7623 }
7624
7640 token_type scan_string()
7641 {
7642 // reset token_buffer (ignore opening quote)
7643 reset();
7644
7645 // we entered the function by reading an open quote
7646 JSON_ASSERT(current == '\"');
7647
7648 while (true)
7649 {
7650 // get next character
7651 switch (get())
7652 {
7653 // end of file while parsing string
7655 {
7656 error_message = "invalid string: missing closing quote";
7657 return token_type::parse_error;
7658 }
7659
7660 // closing quote
7661 case '\"':
7662 {
7663 return token_type::value_string;
7664 }
7665
7666 // escapes
7667 case '\\':
7668 {
7669 switch (get())
7670 {
7671 // quotation mark
7672 case '\"':
7673 add('\"');
7674 break;
7675 // reverse solidus
7676 case '\\':
7677 add('\\');
7678 break;
7679 // solidus
7680 case '/':
7681 add('/');
7682 break;
7683 // backspace
7684 case 'b':
7685 add('\b');
7686 break;
7687 // form feed
7688 case 'f':
7689 add('\f');
7690 break;
7691 // line feed
7692 case 'n':
7693 add('\n');
7694 break;
7695 // carriage return
7696 case 'r':
7697 add('\r');
7698 break;
7699 // tab
7700 case 't':
7701 add('\t');
7702 break;
7703
7704 // unicode escapes
7705 case 'u':
7706 {
7707 const int codepoint1 = get_codepoint();
7708 int codepoint = codepoint1; // start with codepoint1
7709
7710 if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
7711 {
7712 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7713 return token_type::parse_error;
7714 }
7715
7716 // check if code point is a high surrogate
7717 if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
7718 {
7719 // expect next \uxxxx entry
7720 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
7721 {
7722 const int codepoint2 = get_codepoint();
7723
7724 if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
7725 {
7726 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
7727 return token_type::parse_error;
7728 }
7729
7730 // check if codepoint2 is a low surrogate
7731 if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
7732 {
7733 // overwrite codepoint
7734 codepoint = static_cast<int>(
7735 // high surrogate occupies the most significant 22 bits
7736 (static_cast<unsigned int>(codepoint1) << 10u)
7737 // low surrogate occupies the least significant 15 bits
7738 + static_cast<unsigned int>(codepoint2)
7739 // there is still the 0xD800, 0xDC00 and 0x10000 noise
7740 // in the result, so we have to subtract with:
7741 // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
7742 - 0x35FDC00u);
7743 }
7744 else
7745 {
7746 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7747 return token_type::parse_error;
7748 }
7749 }
7750 else
7751 {
7752 error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
7753 return token_type::parse_error;
7754 }
7755 }
7756 else
7757 {
7758 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
7759 {
7760 error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
7761 return token_type::parse_error;
7762 }
7763 }
7764
7765 // result of the above calculation yields a proper codepoint
7766 JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
7767
7768 // translate codepoint into bytes
7769 if (codepoint < 0x80)
7770 {
7771 // 1-byte characters: 0xxxxxxx (ASCII)
7772 add(static_cast<char_int_type>(codepoint));
7773 }
7774 else if (codepoint <= 0x7FF)
7775 {
7776 // 2-byte characters: 110xxxxx 10xxxxxx
7777 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
7778 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7779 }
7780 else if (codepoint <= 0xFFFF)
7781 {
7782 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
7783 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
7784 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7785 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7786 }
7787 else
7788 {
7789 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
7790 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
7791 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
7792 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
7793 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
7794 }
7795
7796 break;
7797 }
7798
7799 // other characters after escape
7800 default:
7801 error_message = "invalid string: forbidden character after backslash";
7802 return token_type::parse_error;
7803 }
7804
7805 break;
7806 }
7807
7808 // invalid control characters
7809 case 0x00:
7810 {
7811 error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
7812 return token_type::parse_error;
7813 }
7814
7815 case 0x01:
7816 {
7817 error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
7818 return token_type::parse_error;
7819 }
7820
7821 case 0x02:
7822 {
7823 error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
7824 return token_type::parse_error;
7825 }
7826
7827 case 0x03:
7828 {
7829 error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
7830 return token_type::parse_error;
7831 }
7832
7833 case 0x04:
7834 {
7835 error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
7836 return token_type::parse_error;
7837 }
7838
7839 case 0x05:
7840 {
7841 error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
7842 return token_type::parse_error;
7843 }
7844
7845 case 0x06:
7846 {
7847 error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
7848 return token_type::parse_error;
7849 }
7850
7851 case 0x07:
7852 {
7853 error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
7854 return token_type::parse_error;
7855 }
7856
7857 case 0x08:
7858 {
7859 error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
7860 return token_type::parse_error;
7861 }
7862
7863 case 0x09:
7864 {
7865 error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
7866 return token_type::parse_error;
7867 }
7868
7869 case 0x0A:
7870 {
7871 error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
7872 return token_type::parse_error;
7873 }
7874
7875 case 0x0B:
7876 {
7877 error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
7878 return token_type::parse_error;
7879 }
7880
7881 case 0x0C:
7882 {
7883 error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
7884 return token_type::parse_error;
7885 }
7886
7887 case 0x0D:
7888 {
7889 error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
7890 return token_type::parse_error;
7891 }
7892
7893 case 0x0E:
7894 {
7895 error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
7896 return token_type::parse_error;
7897 }
7898
7899 case 0x0F:
7900 {
7901 error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
7902 return token_type::parse_error;
7903 }
7904
7905 case 0x10:
7906 {
7907 error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
7908 return token_type::parse_error;
7909 }
7910
7911 case 0x11:
7912 {
7913 error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
7914 return token_type::parse_error;
7915 }
7916
7917 case 0x12:
7918 {
7919 error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
7920 return token_type::parse_error;
7921 }
7922
7923 case 0x13:
7924 {
7925 error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
7926 return token_type::parse_error;
7927 }
7928
7929 case 0x14:
7930 {
7931 error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
7932 return token_type::parse_error;
7933 }
7934
7935 case 0x15:
7936 {
7937 error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
7938 return token_type::parse_error;
7939 }
7940
7941 case 0x16:
7942 {
7943 error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
7944 return token_type::parse_error;
7945 }
7946
7947 case 0x17:
7948 {
7949 error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
7950 return token_type::parse_error;
7951 }
7952
7953 case 0x18:
7954 {
7955 error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
7956 return token_type::parse_error;
7957 }
7958
7959 case 0x19:
7960 {
7961 error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
7962 return token_type::parse_error;
7963 }
7964
7965 case 0x1A:
7966 {
7967 error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
7968 return token_type::parse_error;
7969 }
7970
7971 case 0x1B:
7972 {
7973 error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
7974 return token_type::parse_error;
7975 }
7976
7977 case 0x1C:
7978 {
7979 error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
7980 return token_type::parse_error;
7981 }
7982
7983 case 0x1D:
7984 {
7985 error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
7986 return token_type::parse_error;
7987 }
7988
7989 case 0x1E:
7990 {
7991 error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
7992 return token_type::parse_error;
7993 }
7994
7995 case 0x1F:
7996 {
7997 error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
7998 return token_type::parse_error;
7999 }
8000
8001 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
8002 case 0x20:
8003 case 0x21:
8004 case 0x23:
8005 case 0x24:
8006 case 0x25:
8007 case 0x26:
8008 case 0x27:
8009 case 0x28:
8010 case 0x29:
8011 case 0x2A:
8012 case 0x2B:
8013 case 0x2C:
8014 case 0x2D:
8015 case 0x2E:
8016 case 0x2F:
8017 case 0x30:
8018 case 0x31:
8019 case 0x32:
8020 case 0x33:
8021 case 0x34:
8022 case 0x35:
8023 case 0x36:
8024 case 0x37:
8025 case 0x38:
8026 case 0x39:
8027 case 0x3A:
8028 case 0x3B:
8029 case 0x3C:
8030 case 0x3D:
8031 case 0x3E:
8032 case 0x3F:
8033 case 0x40:
8034 case 0x41:
8035 case 0x42:
8036 case 0x43:
8037 case 0x44:
8038 case 0x45:
8039 case 0x46:
8040 case 0x47:
8041 case 0x48:
8042 case 0x49:
8043 case 0x4A:
8044 case 0x4B:
8045 case 0x4C:
8046 case 0x4D:
8047 case 0x4E:
8048 case 0x4F:
8049 case 0x50:
8050 case 0x51:
8051 case 0x52:
8052 case 0x53:
8053 case 0x54:
8054 case 0x55:
8055 case 0x56:
8056 case 0x57:
8057 case 0x58:
8058 case 0x59:
8059 case 0x5A:
8060 case 0x5B:
8061 case 0x5D:
8062 case 0x5E:
8063 case 0x5F:
8064 case 0x60:
8065 case 0x61:
8066 case 0x62:
8067 case 0x63:
8068 case 0x64:
8069 case 0x65:
8070 case 0x66:
8071 case 0x67:
8072 case 0x68:
8073 case 0x69:
8074 case 0x6A:
8075 case 0x6B:
8076 case 0x6C:
8077 case 0x6D:
8078 case 0x6E:
8079 case 0x6F:
8080 case 0x70:
8081 case 0x71:
8082 case 0x72:
8083 case 0x73:
8084 case 0x74:
8085 case 0x75:
8086 case 0x76:
8087 case 0x77:
8088 case 0x78:
8089 case 0x79:
8090 case 0x7A:
8091 case 0x7B:
8092 case 0x7C:
8093 case 0x7D:
8094 case 0x7E:
8095 case 0x7F:
8096 {
8097 add(current);
8098 break;
8099 }
8100
8101 // U+0080..U+07FF: bytes C2..DF 80..BF
8102 case 0xC2:
8103 case 0xC3:
8104 case 0xC4:
8105 case 0xC5:
8106 case 0xC6:
8107 case 0xC7:
8108 case 0xC8:
8109 case 0xC9:
8110 case 0xCA:
8111 case 0xCB:
8112 case 0xCC:
8113 case 0xCD:
8114 case 0xCE:
8115 case 0xCF:
8116 case 0xD0:
8117 case 0xD1:
8118 case 0xD2:
8119 case 0xD3:
8120 case 0xD4:
8121 case 0xD5:
8122 case 0xD6:
8123 case 0xD7:
8124 case 0xD8:
8125 case 0xD9:
8126 case 0xDA:
8127 case 0xDB:
8128 case 0xDC:
8129 case 0xDD:
8130 case 0xDE:
8131 case 0xDF:
8132 {
8133 if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
8134 {
8135 return token_type::parse_error;
8136 }
8137 break;
8138 }
8139
8140 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
8141 case 0xE0:
8142 {
8143 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
8144 {
8145 return token_type::parse_error;
8146 }
8147 break;
8148 }
8149
8150 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
8151 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
8152 case 0xE1:
8153 case 0xE2:
8154 case 0xE3:
8155 case 0xE4:
8156 case 0xE5:
8157 case 0xE6:
8158 case 0xE7:
8159 case 0xE8:
8160 case 0xE9:
8161 case 0xEA:
8162 case 0xEB:
8163 case 0xEC:
8164 case 0xEE:
8165 case 0xEF:
8166 {
8167 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
8168 {
8169 return token_type::parse_error;
8170 }
8171 break;
8172 }
8173
8174 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
8175 case 0xED:
8176 {
8177 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
8178 {
8179 return token_type::parse_error;
8180 }
8181 break;
8182 }
8183
8184 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
8185 case 0xF0:
8186 {
8187 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8188 {
8189 return token_type::parse_error;
8190 }
8191 break;
8192 }
8193
8194 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
8195 case 0xF1:
8196 case 0xF2:
8197 case 0xF3:
8198 {
8199 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
8200 {
8201 return token_type::parse_error;
8202 }
8203 break;
8204 }
8205
8206 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
8207 case 0xF4:
8208 {
8209 if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
8210 {
8211 return token_type::parse_error;
8212 }
8213 break;
8214 }
8215
8216 // remaining bytes (80..C1 and F5..FF) are ill-formed
8217 default:
8218 {
8219 error_message = "invalid string: ill-formed UTF-8 byte";
8220 return token_type::parse_error;
8221 }
8222 }
8223 }
8224 }
8225
8230 bool scan_comment()
8231 {
8232 switch (get())
8233 {
8234 // single-line comments skip input until a newline or EOF is read
8235 case '/':
8236 {
8237 while (true)
8238 {
8239 switch (get())
8240 {
8241 case '\n':
8242 case '\r':
8244 case '\0':
8245 return true;
8246
8247 default:
8248 break;
8249 }
8250 }
8251 }
8252
8253 // multi-line comments skip input until */ is read
8254 case '*':
8255 {
8256 while (true)
8257 {
8258 switch (get())
8259 {
8261 case '\0':
8262 {
8263 error_message = "invalid comment; missing closing '*/'";
8264 return false;
8265 }
8266
8267 case '*':
8268 {
8269 switch (get())
8270 {
8271 case '/':
8272 return true;
8273
8274 default:
8275 {
8276 unget();
8277 continue;
8278 }
8279 }
8280 }
8281
8282 default:
8283 continue;
8284 }
8285 }
8286 }
8287
8288 // unexpected character after reading '/'
8289 default:
8290 {
8291 error_message = "invalid comment; expecting '/' or '*' after '/'";
8292 return false;
8293 }
8294 }
8295 }
8296
8297 JSON_HEDLEY_NON_NULL(2)
8298 static void strtof(float& f, const char* str, char** endptr) noexcept
8299 {
8300 f = std::strtof(str, endptr);
8301 }
8302
8303 JSON_HEDLEY_NON_NULL(2)
8304 static void strtof(double& f, const char* str, char** endptr) noexcept
8305 {
8306 f = std::strtod(str, endptr);
8307 }
8308
8309 JSON_HEDLEY_NON_NULL(2)
8310 static void strtof(long double& f, const char* str, char** endptr) noexcept
8311 {
8312 f = std::strtold(str, endptr);
8313 }
8314
8355 token_type scan_number() // lgtm [cpp/use-of-goto]
8356 {
8357 // reset token_buffer to store the number's bytes
8358 reset();
8359
8360 // the type of the parsed number; initially set to unsigned; will be
8361 // changed if minus sign, decimal point or exponent is read
8362 token_type number_type = token_type::value_unsigned;
8363
8364 // state (init): we just found out we need to scan a number
8365 switch (current)
8366 {
8367 case '-':
8368 {
8369 add(current);
8370 goto scan_number_minus;
8371 }
8372
8373 case '0':
8374 {
8375 add(current);
8376 goto scan_number_zero;
8377 }
8378
8379 case '1':
8380 case '2':
8381 case '3':
8382 case '4':
8383 case '5':
8384 case '6':
8385 case '7':
8386 case '8':
8387 case '9':
8388 {
8389 add(current);
8390 goto scan_number_any1;
8391 }
8392
8393 // all other characters are rejected outside scan_number()
8394 default: // LCOV_EXCL_LINE
8395 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
8396 }
8397
8398scan_number_minus:
8399 // state: we just parsed a leading minus sign
8400 number_type = token_type::value_integer;
8401 switch (get())
8402 {
8403 case '0':
8404 {
8405 add(current);
8406 goto scan_number_zero;
8407 }
8408
8409 case '1':
8410 case '2':
8411 case '3':
8412 case '4':
8413 case '5':
8414 case '6':
8415 case '7':
8416 case '8':
8417 case '9':
8418 {
8419 add(current);
8420 goto scan_number_any1;
8421 }
8422
8423 default:
8424 {
8425 error_message = "invalid number; expected digit after '-'";
8426 return token_type::parse_error;
8427 }
8428 }
8429
8430scan_number_zero:
8431 // state: we just parse a zero (maybe with a leading minus sign)
8432 switch (get())
8433 {
8434 case '.':
8435 {
8436 add(decimal_point_char);
8437 goto scan_number_decimal1;
8438 }
8439
8440 case 'e':
8441 case 'E':
8442 {
8443 add(current);
8444 goto scan_number_exponent;
8445 }
8446
8447 default:
8448 goto scan_number_done;
8449 }
8450
8451scan_number_any1:
8452 // state: we just parsed a number 0-9 (maybe with a leading minus sign)
8453 switch (get())
8454 {
8455 case '0':
8456 case '1':
8457 case '2':
8458 case '3':
8459 case '4':
8460 case '5':
8461 case '6':
8462 case '7':
8463 case '8':
8464 case '9':
8465 {
8466 add(current);
8467 goto scan_number_any1;
8468 }
8469
8470 case '.':
8471 {
8472 add(decimal_point_char);
8473 goto scan_number_decimal1;
8474 }
8475
8476 case 'e':
8477 case 'E':
8478 {
8479 add(current);
8480 goto scan_number_exponent;
8481 }
8482
8483 default:
8484 goto scan_number_done;
8485 }
8486
8487scan_number_decimal1:
8488 // state: we just parsed a decimal point
8489 number_type = token_type::value_float;
8490 switch (get())
8491 {
8492 case '0':
8493 case '1':
8494 case '2':
8495 case '3':
8496 case '4':
8497 case '5':
8498 case '6':
8499 case '7':
8500 case '8':
8501 case '9':
8502 {
8503 add(current);
8504 goto scan_number_decimal2;
8505 }
8506
8507 default:
8508 {
8509 error_message = "invalid number; expected digit after '.'";
8510 return token_type::parse_error;
8511 }
8512 }
8513
8514scan_number_decimal2:
8515 // we just parsed at least one number after a decimal point
8516 switch (get())
8517 {
8518 case '0':
8519 case '1':
8520 case '2':
8521 case '3':
8522 case '4':
8523 case '5':
8524 case '6':
8525 case '7':
8526 case '8':
8527 case '9':
8528 {
8529 add(current);
8530 goto scan_number_decimal2;
8531 }
8532
8533 case 'e':
8534 case 'E':
8535 {
8536 add(current);
8537 goto scan_number_exponent;
8538 }
8539
8540 default:
8541 goto scan_number_done;
8542 }
8543
8544scan_number_exponent:
8545 // we just parsed an exponent
8546 number_type = token_type::value_float;
8547 switch (get())
8548 {
8549 case '+':
8550 case '-':
8551 {
8552 add(current);
8553 goto scan_number_sign;
8554 }
8555
8556 case '0':
8557 case '1':
8558 case '2':
8559 case '3':
8560 case '4':
8561 case '5':
8562 case '6':
8563 case '7':
8564 case '8':
8565 case '9':
8566 {
8567 add(current);
8568 goto scan_number_any2;
8569 }
8570
8571 default:
8572 {
8573 error_message =
8574 "invalid number; expected '+', '-', or digit after exponent";
8575 return token_type::parse_error;
8576 }
8577 }
8578
8579scan_number_sign:
8580 // we just parsed an exponent sign
8581 switch (get())
8582 {
8583 case '0':
8584 case '1':
8585 case '2':
8586 case '3':
8587 case '4':
8588 case '5':
8589 case '6':
8590 case '7':
8591 case '8':
8592 case '9':
8593 {
8594 add(current);
8595 goto scan_number_any2;
8596 }
8597
8598 default:
8599 {
8600 error_message = "invalid number; expected digit after exponent sign";
8601 return token_type::parse_error;
8602 }
8603 }
8604
8605scan_number_any2:
8606 // we just parsed a number after the exponent or exponent sign
8607 switch (get())
8608 {
8609 case '0':
8610 case '1':
8611 case '2':
8612 case '3':
8613 case '4':
8614 case '5':
8615 case '6':
8616 case '7':
8617 case '8':
8618 case '9':
8619 {
8620 add(current);
8621 goto scan_number_any2;
8622 }
8623
8624 default:
8625 goto scan_number_done;
8626 }
8627
8628scan_number_done:
8629 // unget the character after the number (we only read it to know that
8630 // we are done scanning a number)
8631 unget();
8632
8633 char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8634 errno = 0;
8635
8636 // try to parse integers first and fall back to floats
8637 if (number_type == token_type::value_unsigned)
8638 {
8639 const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
8640
8641 // we checked the number format before
8642 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8643
8644 if (errno == 0)
8645 {
8646 value_unsigned = static_cast<number_unsigned_t>(x);
8647 if (value_unsigned == x)
8648 {
8649 return token_type::value_unsigned;
8650 }
8651 }
8652 }
8653 else if (number_type == token_type::value_integer)
8654 {
8655 const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
8656
8657 // we checked the number format before
8658 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8659
8660 if (errno == 0)
8661 {
8662 value_integer = static_cast<number_integer_t>(x);
8663 if (value_integer == x)
8664 {
8665 return token_type::value_integer;
8666 }
8667 }
8668 }
8669
8670 // this code is reached if we parse a floating-point number or if an
8671 // integer conversion above failed
8672 strtof(value_float, token_buffer.data(), &endptr);
8673
8674 // we checked the number format before
8675 JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
8676
8677 return token_type::value_float;
8678 }
8679
8685 JSON_HEDLEY_NON_NULL(2)
8686 token_type scan_literal(const char_type* literal_text, const std::size_t length,
8687 token_type return_type)
8688 {
8689 JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
8690 for (std::size_t i = 1; i < length; ++i)
8691 {
8692 if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
8693 {
8694 error_message = "invalid literal";
8695 return token_type::parse_error;
8696 }
8697 }
8698 return return_type;
8699 }
8700
8702 // input management
8704
8706 void reset() noexcept
8707 {
8708 token_buffer.clear();
8709 token_string.clear();
8710 token_string.push_back(char_traits<char_type>::to_char_type(current));
8711 }
8712
8713 /*
8714 @brief get next character from the input
8715
8716 This function provides the interface to the used input adapter. It does
8717 not throw in case the input reached EOF, but returns a
8718 `char_traits<char>::eof()` in that case. Stores the scanned characters
8719 for use in error messages.
8720
8721 @return character read from the input
8722 */
8723 char_int_type get()
8724 {
8725 ++position.chars_read_total;
8726 ++position.chars_read_current_line;
8727
8728 if (next_unget)
8729 {
8730 // just reset the next_unget variable and work with current
8731 next_unget = false;
8732 }
8733 else
8734 {
8735 current = ia.get_character();
8736 }
8737
8738 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8739 {
8740 token_string.push_back(char_traits<char_type>::to_char_type(current));
8741 }
8742
8743 if (current == '\n')
8744 {
8745 ++position.lines_read;
8746 position.chars_read_current_line = 0;
8747 }
8748
8749 return current;
8750 }
8751
8760 void unget()
8761 {
8762 next_unget = true;
8763
8764 --position.chars_read_total;
8765
8766 // in case we "unget" a newline, we have to also decrement the lines_read
8767 if (position.chars_read_current_line == 0)
8768 {
8769 if (position.lines_read > 0)
8770 {
8771 --position.lines_read;
8772 }
8773 }
8774 else
8775 {
8776 --position.chars_read_current_line;
8777 }
8778
8779 if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
8780 {
8781 JSON_ASSERT(!token_string.empty());
8782 token_string.pop_back();
8783 }
8784 }
8785
8787 void add(char_int_type c)
8788 {
8789 token_buffer.push_back(static_cast<typename string_t::value_type>(c));
8790 }
8791
8792 public:
8794 // value getters
8796
8798 constexpr number_integer_t get_number_integer() const noexcept
8799 {
8800 return value_integer;
8801 }
8802
8804 constexpr number_unsigned_t get_number_unsigned() const noexcept
8805 {
8806 return value_unsigned;
8807 }
8808
8810 constexpr number_float_t get_number_float() const noexcept
8811 {
8812 return value_float;
8813 }
8814
8816 string_t& get_string()
8817 {
8818 return token_buffer;
8819 }
8820
8822 // diagnostics
8824
8826 constexpr position_t get_position() const noexcept
8827 {
8828 return position;
8829 }
8830
8834 std::string get_token_string() const
8835 {
8836 // escape control characters
8837 std::string result;
8838 for (const auto c : token_string)
8839 {
8840 if (static_cast<unsigned char>(c) <= '\x1F')
8841 {
8842 // escape control characters
8843 std::array<char, 9> cs{{}};
8844 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
8845 result += cs.data();
8846 }
8847 else
8848 {
8849 // add character as is
8850 result.push_back(static_cast<std::string::value_type>(c));
8851 }
8852 }
8853
8854 return result;
8855 }
8856
8858 JSON_HEDLEY_RETURNS_NON_NULL
8859 constexpr const char* get_error_message() const noexcept
8860 {
8861 return error_message;
8862 }
8863
8865 // actual scanner
8867
8873 {
8874 if (get() == 0xEF)
8875 {
8876 // check if we completely parse the BOM
8877 return get() == 0xBB && get() == 0xBF;
8878 }
8879
8880 // the first character is not the beginning of the BOM; unget it to
8881 // process is later
8882 unget();
8883 return true;
8884 }
8885
8886 void skip_whitespace()
8887 {
8888 do
8889 {
8890 get();
8891 }
8892 while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
8893 }
8894
8895 token_type scan()
8896 {
8897 // initially, skip the BOM
8898 if (position.chars_read_total == 0 && !skip_bom())
8899 {
8900 error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
8901 return token_type::parse_error;
8902 }
8903
8904 // read next character and ignore whitespace
8905 skip_whitespace();
8906
8907 // ignore comments
8908 while (ignore_comments && current == '/')
8909 {
8910 if (!scan_comment())
8911 {
8912 return token_type::parse_error;
8913 }
8914
8915 // skip following whitespace
8916 skip_whitespace();
8917 }
8918
8919 switch (current)
8920 {
8921 // structural characters
8922 case '[':
8923 return token_type::begin_array;
8924 case ']':
8925 return token_type::end_array;
8926 case '{':
8927 return token_type::begin_object;
8928 case '}':
8929 return token_type::end_object;
8930 case ':':
8931 return token_type::name_separator;
8932 case ',':
8933 return token_type::value_separator;
8934
8935 // literals
8936 case 't':
8937 {
8938 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')}};
8939 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
8940 }
8941 case 'f':
8942 {
8943 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')}};
8944 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
8945 }
8946 case 'n':
8947 {
8948 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')}};
8949 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
8950 }
8951
8952 // string
8953 case '\"':
8954 return scan_string();
8955
8956 // number
8957 case '-':
8958 case '0':
8959 case '1':
8960 case '2':
8961 case '3':
8962 case '4':
8963 case '5':
8964 case '6':
8965 case '7':
8966 case '8':
8967 case '9':
8968 return scan_number();
8969
8970 // end of input (the null byte is needed when parsing from
8971 // string literals)
8972 case '\0':
8973 case char_traits<char_type>::eof():
8974 return token_type::end_of_input;
8975
8976 // error
8977 default:
8978 error_message = "invalid literal";
8979 return token_type::parse_error;
8980 }
8981 }
8982
8983 private:
8985 InputAdapterType ia;
8986
8988 const bool ignore_comments = false;
8989
8991 char_int_type current = char_traits<char_type>::eof();
8992
8994 bool next_unget = false;
8995
8997 position_t position {};
8998
9000 std::vector<char_type> token_string {};
9001
9003 string_t token_buffer {};
9004
9006 const char* error_message = "";
9007
9008 // number values
9009 number_integer_t value_integer = 0;
9010 number_unsigned_t value_unsigned = 0;
9011 number_float_t value_float = 0;
9012
9014 const char_int_type decimal_point_char = '.';
9015};
9016
9017} // namespace detail
9018NLOHMANN_JSON_NAMESPACE_END
9019
9020// #include <nlohmann/detail/macro_scope.hpp>
9021
9022// #include <nlohmann/detail/meta/is_sax.hpp>
9023// __ _____ _____ _____
9024// __| | __| | | | JSON for Modern C++
9025// | | |__ | | | | | | version 3.11.3
9026// |_____|_____|_____|_|___| https://github.com/nlohmann/json
9027//
9028// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
9029// SPDX-License-Identifier: MIT
9030
9031
9032
9033#include <cstdint> // size_t
9034#include <utility> // declval
9035#include <string> // string
9036
9037// #include <nlohmann/detail/abi_macros.hpp>
9038
9039// #include <nlohmann/detail/meta/detected.hpp>
9040
9041// #include <nlohmann/detail/meta/type_traits.hpp>
9042
9043
9044NLOHMANN_JSON_NAMESPACE_BEGIN
9045namespace detail
9046{
9047
9048template<typename T>
9049using null_function_t = decltype(std::declval<T&>().null());
9050
9051template<typename T>
9052using boolean_function_t =
9053 decltype(std::declval<T&>().boolean(std::declval<bool>()));
9054
9055template<typename T, typename Integer>
9056using number_integer_function_t =
9057 decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
9058
9059template<typename T, typename Unsigned>
9060using number_unsigned_function_t =
9061 decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
9062
9063template<typename T, typename Float, typename String>
9064using number_float_function_t = decltype(std::declval<T&>().number_float(
9065 std::declval<Float>(), std::declval<const String&>()));
9066
9067template<typename T, typename String>
9068using string_function_t =
9069 decltype(std::declval<T&>().string(std::declval<String&>()));
9070
9071template<typename T, typename Binary>
9072using binary_function_t =
9073 decltype(std::declval<T&>().binary(std::declval<Binary&>()));
9074
9075template<typename T>
9076using start_object_function_t =
9077 decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
9078
9079template<typename T, typename String>
9080using key_function_t =
9081 decltype(std::declval<T&>().key(std::declval<String&>()));
9082
9083template<typename T>
9084using end_object_function_t = decltype(std::declval<T&>().end_object());
9085
9086template<typename T>
9087using start_array_function_t =
9088 decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
9089
9090template<typename T>
9091using end_array_function_t = decltype(std::declval<T&>().end_array());
9092
9093template<typename T, typename Exception>
9094using parse_error_function_t = decltype(std::declval<T&>().parse_error(
9095 std::declval<std::size_t>(), std::declval<const std::string&>(),
9096 std::declval<const Exception&>()));
9097
9098template<typename SAX, typename BasicJsonType>
9100{
9101 private:
9103 "BasicJsonType must be of type basic_json<...>");
9104
9105 using number_integer_t = typename BasicJsonType::number_integer_t;
9106 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9107 using number_float_t = typename BasicJsonType::number_float_t;
9108 using string_t = typename BasicJsonType::string_t;
9109 using binary_t = typename BasicJsonType::binary_t;
9110 using exception_t = typename BasicJsonType::exception;
9111
9112 public:
9113 static constexpr bool value =
9114 is_detected_exact<bool, null_function_t, SAX>::value &&
9115 is_detected_exact<bool, boolean_function_t, SAX>::value &&
9116 is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
9117 is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
9118 is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
9119 is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
9120 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
9121 is_detected_exact<bool, start_object_function_t, SAX>::value &&
9122 is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
9123 is_detected_exact<bool, end_object_function_t, SAX>::value &&
9124 is_detected_exact<bool, start_array_function_t, SAX>::value &&
9125 is_detected_exact<bool, end_array_function_t, SAX>::value &&
9126 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
9127};
9128
9129template<typename SAX, typename BasicJsonType>
9131{
9132 private:
9134 "BasicJsonType must be of type basic_json<...>");
9135
9136 using number_integer_t = typename BasicJsonType::number_integer_t;
9137 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9138 using number_float_t = typename BasicJsonType::number_float_t;
9139 using string_t = typename BasicJsonType::string_t;
9140 using binary_t = typename BasicJsonType::binary_t;
9141 using exception_t = typename BasicJsonType::exception;
9142
9143 public:
9144 static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
9145 "Missing/invalid function: bool null()");
9146 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9147 "Missing/invalid function: bool boolean(bool)");
9148 static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
9149 "Missing/invalid function: bool boolean(bool)");
9150 static_assert(
9151 is_detected_exact<bool, number_integer_function_t, SAX,
9152 number_integer_t>::value,
9153 "Missing/invalid function: bool number_integer(number_integer_t)");
9154 static_assert(
9155 is_detected_exact<bool, number_unsigned_function_t, SAX,
9156 number_unsigned_t>::value,
9157 "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
9158 static_assert(is_detected_exact<bool, number_float_function_t, SAX,
9159 number_float_t, string_t>::value,
9160 "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
9161 static_assert(
9162 is_detected_exact<bool, string_function_t, SAX, string_t>::value,
9163 "Missing/invalid function: bool string(string_t&)");
9164 static_assert(
9165 is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
9166 "Missing/invalid function: bool binary(binary_t&)");
9167 static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
9168 "Missing/invalid function: bool start_object(std::size_t)");
9169 static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
9170 "Missing/invalid function: bool key(string_t&)");
9171 static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
9172 "Missing/invalid function: bool end_object()");
9173 static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
9174 "Missing/invalid function: bool start_array(std::size_t)");
9175 static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
9176 "Missing/invalid function: bool end_array()");
9177 static_assert(
9178 is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
9179 "Missing/invalid function: bool parse_error(std::size_t, const "
9180 "std::string&, const exception&)");
9181};
9182
9183} // namespace detail
9184NLOHMANN_JSON_NAMESPACE_END
9185
9186// #include <nlohmann/detail/meta/type_traits.hpp>
9187
9188// #include <nlohmann/detail/string_concat.hpp>
9189
9190// #include <nlohmann/detail/value_t.hpp>
9191
9192
9193NLOHMANN_JSON_NAMESPACE_BEGIN
9194namespace detail
9195{
9196
9199{
9200 error,
9201 ignore,
9202 store
9203};
9204
9212static inline bool little_endianness(int num = 1) noexcept
9213{
9214 return *reinterpret_cast<char*>(&num) == 1;
9215}
9216
9218// binary reader //
9220
9224template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
9226{
9227 using number_integer_t = typename BasicJsonType::number_integer_t;
9228 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
9229 using number_float_t = typename BasicJsonType::number_float_t;
9230 using string_t = typename BasicJsonType::string_t;
9231 using binary_t = typename BasicJsonType::binary_t;
9232 using json_sax_t = SAX;
9233 using char_type = typename InputAdapterType::char_type;
9234 using char_int_type = typename char_traits<char_type>::int_type;
9235
9236 public:
9242 explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
9243 {
9245 }
9246
9247 // make class move-only
9248 binary_reader(const binary_reader&) = delete;
9249 binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9250 binary_reader& operator=(const binary_reader&) = delete;
9251 binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
9252 ~binary_reader() = default;
9253
9262 JSON_HEDLEY_NON_NULL(3)
9263 bool sax_parse(const input_format_t format,
9264 json_sax_t* sax_,
9265 const bool strict = true,
9266 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
9267 {
9268 sax = sax_;
9269 bool result = false;
9270
9271 switch (format)
9272 {
9273 case input_format_t::bson:
9274 result = parse_bson_internal();
9275 break;
9276
9277 case input_format_t::cbor:
9278 result = parse_cbor_internal(true, tag_handler);
9279 break;
9280
9281 case input_format_t::msgpack:
9282 result = parse_msgpack_internal();
9283 break;
9284
9285 case input_format_t::ubjson:
9286 case input_format_t::bjdata:
9287 result = parse_ubjson_internal();
9288 break;
9289
9290 case input_format_t::json: // LCOV_EXCL_LINE
9291 default: // LCOV_EXCL_LINE
9292 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9293 }
9294
9295 // strict mode: next byte must be EOF
9296 if (result && strict)
9297 {
9298 if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
9299 {
9300 get_ignore_noop();
9301 }
9302 else
9303 {
9304 get();
9305 }
9306
9307 if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
9308 {
9309 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
9310 exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
9311 }
9312 }
9313
9314 return result;
9315 }
9316
9317 private:
9319 // BSON //
9321
9326 bool parse_bson_internal()
9327 {
9328 std::int32_t document_size{};
9329 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9330
9331 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
9332 {
9333 return false;
9334 }
9335
9336 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
9337 {
9338 return false;
9339 }
9340
9341 return sax->end_object();
9342 }
9343
9351 bool get_bson_cstr(string_t& result)
9352 {
9353 auto out = std::back_inserter(result);
9354 while (true)
9355 {
9356 get();
9357 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
9358 {
9359 return false;
9360 }
9361 if (current == 0x00)
9362 {
9363 return true;
9364 }
9365 *out++ = static_cast<typename string_t::value_type>(current);
9366 }
9367 }
9368
9380 template<typename NumberType>
9381 bool get_bson_string(const NumberType len, string_t& result)
9382 {
9383 if (JSON_HEDLEY_UNLIKELY(len < 1))
9384 {
9385 auto last_token = get_token_string();
9386 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9387 exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
9388 }
9389
9390 return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
9391 }
9392
9402 template<typename NumberType>
9403 bool get_bson_binary(const NumberType len, binary_t& result)
9404 {
9405 if (JSON_HEDLEY_UNLIKELY(len < 0))
9406 {
9407 auto last_token = get_token_string();
9408 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9409 exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
9410 }
9411
9412 // All BSON binary values have a subtype
9413 std::uint8_t subtype{};
9414 get_number<std::uint8_t>(input_format_t::bson, subtype);
9415 result.set_subtype(subtype);
9416
9417 return get_binary(input_format_t::bson, len, result);
9418 }
9419
9430 bool parse_bson_element_internal(const char_int_type element_type,
9431 const std::size_t element_type_parse_position)
9432 {
9433 switch (element_type)
9434 {
9435 case 0x01: // double
9436 {
9437 double number{};
9438 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
9439 }
9440
9441 case 0x02: // string
9442 {
9443 std::int32_t len{};
9444 string_t value;
9445 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
9446 }
9447
9448 case 0x03: // object
9449 {
9450 return parse_bson_internal();
9451 }
9452
9453 case 0x04: // array
9454 {
9455 return parse_bson_array();
9456 }
9457
9458 case 0x05: // binary
9459 {
9460 std::int32_t len{};
9461 binary_t value;
9462 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
9463 }
9464
9465 case 0x08: // boolean
9466 {
9467 return sax->boolean(get() != 0);
9468 }
9469
9470 case 0x0A: // null
9471 {
9472 return sax->null();
9473 }
9474
9475 case 0x10: // int32
9476 {
9477 std::int32_t value{};
9478 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9479 }
9480
9481 case 0x12: // int64
9482 {
9483 std::int64_t value{};
9484 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
9485 }
9486
9487 default: // anything else not supported (yet)
9488 {
9489 std::array<char, 3> cr{{}};
9490 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
9491 const std::string cr_str{cr.data()};
9492 return sax->parse_error(element_type_parse_position, cr_str,
9493 parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
9494 }
9495 }
9496 }
9497
9510 bool parse_bson_element_list(const bool is_array)
9511 {
9512 string_t key;
9513
9514 while (auto element_type = get())
9515 {
9516 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
9517 {
9518 return false;
9519 }
9520
9521 const std::size_t element_type_parse_position = chars_read;
9522 if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
9523 {
9524 return false;
9525 }
9526
9527 if (!is_array && !sax->key(key))
9528 {
9529 return false;
9530 }
9531
9532 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
9533 {
9534 return false;
9535 }
9536
9537 // get_bson_cstr only appends
9538 key.clear();
9539 }
9540
9541 return true;
9542 }
9543
9548 bool parse_bson_array()
9549 {
9550 std::int32_t document_size{};
9551 get_number<std::int32_t, true>(input_format_t::bson, document_size);
9552
9553 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
9554 {
9555 return false;
9556 }
9557
9558 if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
9559 {
9560 return false;
9561 }
9562
9563 return sax->end_array();
9564 }
9565
9567 // CBOR //
9569
9578 bool parse_cbor_internal(const bool get_char,
9579 const cbor_tag_handler_t tag_handler)
9580 {
9581 switch (get_char ? get() : current)
9582 {
9583 // EOF
9584 case char_traits<char_type>::eof():
9585 return unexpect_eof(input_format_t::cbor, "value");
9586
9587 // Integer 0x00..0x17 (0..23)
9588 case 0x00:
9589 case 0x01:
9590 case 0x02:
9591 case 0x03:
9592 case 0x04:
9593 case 0x05:
9594 case 0x06:
9595 case 0x07:
9596 case 0x08:
9597 case 0x09:
9598 case 0x0A:
9599 case 0x0B:
9600 case 0x0C:
9601 case 0x0D:
9602 case 0x0E:
9603 case 0x0F:
9604 case 0x10:
9605 case 0x11:
9606 case 0x12:
9607 case 0x13:
9608 case 0x14:
9609 case 0x15:
9610 case 0x16:
9611 case 0x17:
9612 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
9613
9614 case 0x18: // Unsigned integer (one-byte uint8_t follows)
9615 {
9616 std::uint8_t number{};
9617 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9618 }
9619
9620 case 0x19: // Unsigned integer (two-byte uint16_t follows)
9621 {
9622 std::uint16_t number{};
9623 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9624 }
9625
9626 case 0x1A: // Unsigned integer (four-byte uint32_t follows)
9627 {
9628 std::uint32_t number{};
9629 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9630 }
9631
9632 case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
9633 {
9634 std::uint64_t number{};
9635 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
9636 }
9637
9638 // Negative integer -1-0x00..-1-0x17 (-1..-24)
9639 case 0x20:
9640 case 0x21:
9641 case 0x22:
9642 case 0x23:
9643 case 0x24:
9644 case 0x25:
9645 case 0x26:
9646 case 0x27:
9647 case 0x28:
9648 case 0x29:
9649 case 0x2A:
9650 case 0x2B:
9651 case 0x2C:
9652 case 0x2D:
9653 case 0x2E:
9654 case 0x2F:
9655 case 0x30:
9656 case 0x31:
9657 case 0x32:
9658 case 0x33:
9659 case 0x34:
9660 case 0x35:
9661 case 0x36:
9662 case 0x37:
9663 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
9664
9665 case 0x38: // Negative integer (one-byte uint8_t follows)
9666 {
9667 std::uint8_t number{};
9668 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9669 }
9670
9671 case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
9672 {
9673 std::uint16_t number{};
9674 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9675 }
9676
9677 case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
9678 {
9679 std::uint32_t number{};
9680 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
9681 }
9682
9683 case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
9684 {
9685 std::uint64_t number{};
9686 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
9687 - static_cast<number_integer_t>(number));
9688 }
9689
9690 // Binary data (0x00..0x17 bytes follow)
9691 case 0x40:
9692 case 0x41:
9693 case 0x42:
9694 case 0x43:
9695 case 0x44:
9696 case 0x45:
9697 case 0x46:
9698 case 0x47:
9699 case 0x48:
9700 case 0x49:
9701 case 0x4A:
9702 case 0x4B:
9703 case 0x4C:
9704 case 0x4D:
9705 case 0x4E:
9706 case 0x4F:
9707 case 0x50:
9708 case 0x51:
9709 case 0x52:
9710 case 0x53:
9711 case 0x54:
9712 case 0x55:
9713 case 0x56:
9714 case 0x57:
9715 case 0x58: // Binary data (one-byte uint8_t for n follows)
9716 case 0x59: // Binary data (two-byte uint16_t for n follow)
9717 case 0x5A: // Binary data (four-byte uint32_t for n follow)
9718 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
9719 case 0x5F: // Binary data (indefinite length)
9720 {
9721 binary_t b;
9722 return get_cbor_binary(b) && sax->binary(b);
9723 }
9724
9725 // UTF-8 string (0x00..0x17 bytes follow)
9726 case 0x60:
9727 case 0x61:
9728 case 0x62:
9729 case 0x63:
9730 case 0x64:
9731 case 0x65:
9732 case 0x66:
9733 case 0x67:
9734 case 0x68:
9735 case 0x69:
9736 case 0x6A:
9737 case 0x6B:
9738 case 0x6C:
9739 case 0x6D:
9740 case 0x6E:
9741 case 0x6F:
9742 case 0x70:
9743 case 0x71:
9744 case 0x72:
9745 case 0x73:
9746 case 0x74:
9747 case 0x75:
9748 case 0x76:
9749 case 0x77:
9750 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
9751 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
9752 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
9753 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
9754 case 0x7F: // UTF-8 string (indefinite length)
9755 {
9756 string_t s;
9757 return get_cbor_string(s) && sax->string(s);
9758 }
9759
9760 // array (0x00..0x17 data items follow)
9761 case 0x80:
9762 case 0x81:
9763 case 0x82:
9764 case 0x83:
9765 case 0x84:
9766 case 0x85:
9767 case 0x86:
9768 case 0x87:
9769 case 0x88:
9770 case 0x89:
9771 case 0x8A:
9772 case 0x8B:
9773 case 0x8C:
9774 case 0x8D:
9775 case 0x8E:
9776 case 0x8F:
9777 case 0x90:
9778 case 0x91:
9779 case 0x92:
9780 case 0x93:
9781 case 0x94:
9782 case 0x95:
9783 case 0x96:
9784 case 0x97:
9785 return get_cbor_array(
9786 conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9787
9788 case 0x98: // array (one-byte uint8_t for n follows)
9789 {
9790 std::uint8_t len{};
9791 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9792 }
9793
9794 case 0x99: // array (two-byte uint16_t for n follow)
9795 {
9796 std::uint16_t len{};
9797 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
9798 }
9799
9800 case 0x9A: // array (four-byte uint32_t for n follow)
9801 {
9802 std::uint32_t len{};
9803 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9804 }
9805
9806 case 0x9B: // array (eight-byte uint64_t for n follow)
9807 {
9808 std::uint64_t len{};
9809 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
9810 }
9811
9812 case 0x9F: // array (indefinite length)
9813 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
9814
9815 // map (0x00..0x17 pairs of data items follow)
9816 case 0xA0:
9817 case 0xA1:
9818 case 0xA2:
9819 case 0xA3:
9820 case 0xA4:
9821 case 0xA5:
9822 case 0xA6:
9823 case 0xA7:
9824 case 0xA8:
9825 case 0xA9:
9826 case 0xAA:
9827 case 0xAB:
9828 case 0xAC:
9829 case 0xAD:
9830 case 0xAE:
9831 case 0xAF:
9832 case 0xB0:
9833 case 0xB1:
9834 case 0xB2:
9835 case 0xB3:
9836 case 0xB4:
9837 case 0xB5:
9838 case 0xB6:
9839 case 0xB7:
9840 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
9841
9842 case 0xB8: // map (one-byte uint8_t for n follows)
9843 {
9844 std::uint8_t len{};
9845 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9846 }
9847
9848 case 0xB9: // map (two-byte uint16_t for n follow)
9849 {
9850 std::uint16_t len{};
9851 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
9852 }
9853
9854 case 0xBA: // map (four-byte uint32_t for n follow)
9855 {
9856 std::uint32_t len{};
9857 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9858 }
9859
9860 case 0xBB: // map (eight-byte uint64_t for n follow)
9861 {
9862 std::uint64_t len{};
9863 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
9864 }
9865
9866 case 0xBF: // map (indefinite length)
9867 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
9868
9869 case 0xC6: // tagged item
9870 case 0xC7:
9871 case 0xC8:
9872 case 0xC9:
9873 case 0xCA:
9874 case 0xCB:
9875 case 0xCC:
9876 case 0xCD:
9877 case 0xCE:
9878 case 0xCF:
9879 case 0xD0:
9880 case 0xD1:
9881 case 0xD2:
9882 case 0xD3:
9883 case 0xD4:
9884 case 0xD8: // tagged item (1 bytes follow)
9885 case 0xD9: // tagged item (2 bytes follow)
9886 case 0xDA: // tagged item (4 bytes follow)
9887 case 0xDB: // tagged item (8 bytes follow)
9888 {
9889 switch (tag_handler)
9890 {
9891 case cbor_tag_handler_t::error:
9892 {
9893 auto last_token = get_token_string();
9894 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
9895 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
9896 }
9897
9898 case cbor_tag_handler_t::ignore:
9899 {
9900 // ignore binary subtype
9901 switch (current)
9902 {
9903 case 0xD8:
9904 {
9905 std::uint8_t subtype_to_ignore{};
9906 get_number(input_format_t::cbor, subtype_to_ignore);
9907 break;
9908 }
9909 case 0xD9:
9910 {
9911 std::uint16_t subtype_to_ignore{};
9912 get_number(input_format_t::cbor, subtype_to_ignore);
9913 break;
9914 }
9915 case 0xDA:
9916 {
9917 std::uint32_t subtype_to_ignore{};
9918 get_number(input_format_t::cbor, subtype_to_ignore);
9919 break;
9920 }
9921 case 0xDB:
9922 {
9923 std::uint64_t subtype_to_ignore{};
9924 get_number(input_format_t::cbor, subtype_to_ignore);
9925 break;
9926 }
9927 default:
9928 break;
9929 }
9930 return parse_cbor_internal(true, tag_handler);
9931 }
9932
9933 case cbor_tag_handler_t::store:
9934 {
9935 binary_t b;
9936 // use binary subtype and store in binary container
9937 switch (current)
9938 {
9939 case 0xD8:
9940 {
9941 std::uint8_t subtype{};
9942 get_number(input_format_t::cbor, subtype);
9943 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9944 break;
9945 }
9946 case 0xD9:
9947 {
9948 std::uint16_t subtype{};
9949 get_number(input_format_t::cbor, subtype);
9950 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9951 break;
9952 }
9953 case 0xDA:
9954 {
9955 std::uint32_t subtype{};
9956 get_number(input_format_t::cbor, subtype);
9957 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9958 break;
9959 }
9960 case 0xDB:
9961 {
9962 std::uint64_t subtype{};
9963 get_number(input_format_t::cbor, subtype);
9964 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
9965 break;
9966 }
9967 default:
9968 return parse_cbor_internal(true, tag_handler);
9969 }
9970 get();
9971 return get_cbor_binary(b) && sax->binary(b);
9972 }
9973
9974 default: // LCOV_EXCL_LINE
9975 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
9976 return false; // LCOV_EXCL_LINE
9977 }
9978 }
9979
9980 case 0xF4: // false
9981 return sax->boolean(false);
9982
9983 case 0xF5: // true
9984 return sax->boolean(true);
9985
9986 case 0xF6: // null
9987 return sax->null();
9988
9989 case 0xF9: // Half-Precision Float (two-byte IEEE 754)
9990 {
9991 const auto byte1_raw = get();
9992 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9993 {
9994 return false;
9995 }
9996 const auto byte2_raw = get();
9997 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
9998 {
9999 return false;
10000 }
10001
10002 const auto byte1 = static_cast<unsigned char>(byte1_raw);
10003 const auto byte2 = static_cast<unsigned char>(byte2_raw);
10004
10005 // code from RFC 7049, Appendix D, Figure 3:
10006 // As half-precision floating-point numbers were only added
10007 // to IEEE 754 in 2008, today's programming platforms often
10008 // still only have limited support for them. It is very
10009 // easy to include at least decoding support for them even
10010 // without such support. An example of a small decoder for
10011 // half-precision floating-point numbers in the C language
10012 // is shown in Fig. 3.
10013 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10014 const double val = [&half]
10015 {
10016 const int exp = (half >> 10u) & 0x1Fu;
10017 const unsigned int mant = half & 0x3FFu;
10018 JSON_ASSERT(0 <= exp&& exp <= 32);
10019 JSON_ASSERT(mant <= 1024);
10020 switch (exp)
10021 {
10022 case 0:
10023 return std::ldexp(mant, -24);
10024 case 31:
10025 return (mant == 0)
10026 ? std::numeric_limits<double>::infinity()
10027 : std::numeric_limits<double>::quiet_NaN();
10028 default:
10029 return std::ldexp(mant + 1024, exp - 25);
10030 }
10031 }();
10032 return sax->number_float((half & 0x8000u) != 0
10033 ? static_cast<number_float_t>(-val)
10034 : static_cast<number_float_t>(val), "");
10035 }
10036
10037 case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10038 {
10039 float number{};
10040 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10041 }
10042
10043 case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10044 {
10045 double number{};
10046 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10047 }
10048
10049 default: // anything else (0xFF is handled inside the other types)
10050 {
10051 auto last_token = get_token_string();
10052 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10053 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10054 }
10055 }
10056 }
10057
10069 bool get_cbor_string(string_t& result)
10070 {
10071 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10072 {
10073 return false;
10074 }
10075
10076 switch (current)
10077 {
10078 // UTF-8 string (0x00..0x17 bytes follow)
10079 case 0x60:
10080 case 0x61:
10081 case 0x62:
10082 case 0x63:
10083 case 0x64:
10084 case 0x65:
10085 case 0x66:
10086 case 0x67:
10087 case 0x68:
10088 case 0x69:
10089 case 0x6A:
10090 case 0x6B:
10091 case 0x6C:
10092 case 0x6D:
10093 case 0x6E:
10094 case 0x6F:
10095 case 0x70:
10096 case 0x71:
10097 case 0x72:
10098 case 0x73:
10099 case 0x74:
10100 case 0x75:
10101 case 0x76:
10102 case 0x77:
10103 {
10104 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10105 }
10106
10107 case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10108 {
10109 std::uint8_t len{};
10110 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10111 }
10112
10113 case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10114 {
10115 std::uint16_t len{};
10116 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10117 }
10118
10119 case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10120 {
10121 std::uint32_t len{};
10122 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10123 }
10124
10125 case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10126 {
10127 std::uint64_t len{};
10128 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10129 }
10130
10131 case 0x7F: // UTF-8 string (indefinite length)
10132 {
10133 while (get() != 0xFF)
10134 {
10135 string_t chunk;
10136 if (!get_cbor_string(chunk))
10137 {
10138 return false;
10139 }
10140 result.append(chunk);
10141 }
10142 return true;
10143 }
10144
10145 default:
10146 {
10147 auto last_token = get_token_string();
10148 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10149 exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10150 }
10151 }
10152 }
10153
10165 bool get_cbor_binary(binary_t& result)
10166 {
10167 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10168 {
10169 return false;
10170 }
10171
10172 switch (current)
10173 {
10174 // Binary data (0x00..0x17 bytes follow)
10175 case 0x40:
10176 case 0x41:
10177 case 0x42:
10178 case 0x43:
10179 case 0x44:
10180 case 0x45:
10181 case 0x46:
10182 case 0x47:
10183 case 0x48:
10184 case 0x49:
10185 case 0x4A:
10186 case 0x4B:
10187 case 0x4C:
10188 case 0x4D:
10189 case 0x4E:
10190 case 0x4F:
10191 case 0x50:
10192 case 0x51:
10193 case 0x52:
10194 case 0x53:
10195 case 0x54:
10196 case 0x55:
10197 case 0x56:
10198 case 0x57:
10199 {
10200 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10201 }
10202
10203 case 0x58: // Binary data (one-byte uint8_t for n follows)
10204 {
10205 std::uint8_t len{};
10206 return get_number(input_format_t::cbor, len) &&
10207 get_binary(input_format_t::cbor, len, result);
10208 }
10209
10210 case 0x59: // Binary data (two-byte uint16_t for n follow)
10211 {
10212 std::uint16_t len{};
10213 return get_number(input_format_t::cbor, len) &&
10214 get_binary(input_format_t::cbor, len, result);
10215 }
10216
10217 case 0x5A: // Binary data (four-byte uint32_t for n follow)
10218 {
10219 std::uint32_t len{};
10220 return get_number(input_format_t::cbor, len) &&
10221 get_binary(input_format_t::cbor, len, result);
10222 }
10223
10224 case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10225 {
10226 std::uint64_t len{};
10227 return get_number(input_format_t::cbor, len) &&
10228 get_binary(input_format_t::cbor, len, result);
10229 }
10230
10231 case 0x5F: // Binary data (indefinite length)
10232 {
10233 while (get() != 0xFF)
10234 {
10235 binary_t chunk;
10236 if (!get_cbor_binary(chunk))
10237 {
10238 return false;
10239 }
10240 result.insert(result.end(), chunk.begin(), chunk.end());
10241 }
10242 return true;
10243 }
10244
10245 default:
10246 {
10247 auto last_token = get_token_string();
10248 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10249 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));
10250 }
10251 }
10252 }
10253
10260 bool get_cbor_array(const std::size_t len,
10261 const cbor_tag_handler_t tag_handler)
10262 {
10263 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10264 {
10265 return false;
10266 }
10267
10268 if (len != static_cast<std::size_t>(-1))
10269 {
10270 for (std::size_t i = 0; i < len; ++i)
10271 {
10272 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10273 {
10274 return false;
10275 }
10276 }
10277 }
10278 else
10279 {
10280 while (get() != 0xFF)
10281 {
10282 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10283 {
10284 return false;
10285 }
10286 }
10287 }
10288
10289 return sax->end_array();
10290 }
10291
10298 bool get_cbor_object(const std::size_t len,
10299 const cbor_tag_handler_t tag_handler)
10300 {
10301 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10302 {
10303 return false;
10304 }
10305
10306 if (len != 0)
10307 {
10308 string_t key;
10309 if (len != static_cast<std::size_t>(-1))
10310 {
10311 for (std::size_t i = 0; i < len; ++i)
10312 {
10313 get();
10314 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10315 {
10316 return false;
10317 }
10318
10319 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10320 {
10321 return false;
10322 }
10323 key.clear();
10324 }
10325 }
10326 else
10327 {
10328 while (get() != 0xFF)
10329 {
10330 if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10331 {
10332 return false;
10333 }
10334
10335 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10336 {
10337 return false;
10338 }
10339 key.clear();
10340 }
10341 }
10342 }
10343
10344 return sax->end_object();
10345 }
10346
10348 // MsgPack //
10350
10354 bool parse_msgpack_internal()
10355 {
10356 switch (get())
10357 {
10358 // EOF
10359 case char_traits<char_type>::eof():
10360 return unexpect_eof(input_format_t::msgpack, "value");
10361
10362 // positive fixint
10363 case 0x00:
10364 case 0x01:
10365 case 0x02:
10366 case 0x03:
10367 case 0x04:
10368 case 0x05:
10369 case 0x06:
10370 case 0x07:
10371 case 0x08:
10372 case 0x09:
10373 case 0x0A:
10374 case 0x0B:
10375 case 0x0C:
10376 case 0x0D:
10377 case 0x0E:
10378 case 0x0F:
10379 case 0x10:
10380 case 0x11:
10381 case 0x12:
10382 case 0x13:
10383 case 0x14:
10384 case 0x15:
10385 case 0x16:
10386 case 0x17:
10387 case 0x18:
10388 case 0x19:
10389 case 0x1A:
10390 case 0x1B:
10391 case 0x1C:
10392 case 0x1D:
10393 case 0x1E:
10394 case 0x1F:
10395 case 0x20:
10396 case 0x21:
10397 case 0x22:
10398 case 0x23:
10399 case 0x24:
10400 case 0x25:
10401 case 0x26:
10402 case 0x27:
10403 case 0x28:
10404 case 0x29:
10405 case 0x2A:
10406 case 0x2B:
10407 case 0x2C:
10408 case 0x2D:
10409 case 0x2E:
10410 case 0x2F:
10411 case 0x30:
10412 case 0x31:
10413 case 0x32:
10414 case 0x33:
10415 case 0x34:
10416 case 0x35:
10417 case 0x36:
10418 case 0x37:
10419 case 0x38:
10420 case 0x39:
10421 case 0x3A:
10422 case 0x3B:
10423 case 0x3C:
10424 case 0x3D:
10425 case 0x3E:
10426 case 0x3F:
10427 case 0x40:
10428 case 0x41:
10429 case 0x42:
10430 case 0x43:
10431 case 0x44:
10432 case 0x45:
10433 case 0x46:
10434 case 0x47:
10435 case 0x48:
10436 case 0x49:
10437 case 0x4A:
10438 case 0x4B:
10439 case 0x4C:
10440 case 0x4D:
10441 case 0x4E:
10442 case 0x4F:
10443 case 0x50:
10444 case 0x51:
10445 case 0x52:
10446 case 0x53:
10447 case 0x54:
10448 case 0x55:
10449 case 0x56:
10450 case 0x57:
10451 case 0x58:
10452 case 0x59:
10453 case 0x5A:
10454 case 0x5B:
10455 case 0x5C:
10456 case 0x5D:
10457 case 0x5E:
10458 case 0x5F:
10459 case 0x60:
10460 case 0x61:
10461 case 0x62:
10462 case 0x63:
10463 case 0x64:
10464 case 0x65:
10465 case 0x66:
10466 case 0x67:
10467 case 0x68:
10468 case 0x69:
10469 case 0x6A:
10470 case 0x6B:
10471 case 0x6C:
10472 case 0x6D:
10473 case 0x6E:
10474 case 0x6F:
10475 case 0x70:
10476 case 0x71:
10477 case 0x72:
10478 case 0x73:
10479 case 0x74:
10480 case 0x75:
10481 case 0x76:
10482 case 0x77:
10483 case 0x78:
10484 case 0x79:
10485 case 0x7A:
10486 case 0x7B:
10487 case 0x7C:
10488 case 0x7D:
10489 case 0x7E:
10490 case 0x7F:
10491 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10492
10493 // fixmap
10494 case 0x80:
10495 case 0x81:
10496 case 0x82:
10497 case 0x83:
10498 case 0x84:
10499 case 0x85:
10500 case 0x86:
10501 case 0x87:
10502 case 0x88:
10503 case 0x89:
10504 case 0x8A:
10505 case 0x8B:
10506 case 0x8C:
10507 case 0x8D:
10508 case 0x8E:
10509 case 0x8F:
10510 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10511
10512 // fixarray
10513 case 0x90:
10514 case 0x91:
10515 case 0x92:
10516 case 0x93:
10517 case 0x94:
10518 case 0x95:
10519 case 0x96:
10520 case 0x97:
10521 case 0x98:
10522 case 0x99:
10523 case 0x9A:
10524 case 0x9B:
10525 case 0x9C:
10526 case 0x9D:
10527 case 0x9E:
10528 case 0x9F:
10529 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
10530
10531 // fixstr
10532 case 0xA0:
10533 case 0xA1:
10534 case 0xA2:
10535 case 0xA3:
10536 case 0xA4:
10537 case 0xA5:
10538 case 0xA6:
10539 case 0xA7:
10540 case 0xA8:
10541 case 0xA9:
10542 case 0xAA:
10543 case 0xAB:
10544 case 0xAC:
10545 case 0xAD:
10546 case 0xAE:
10547 case 0xAF:
10548 case 0xB0:
10549 case 0xB1:
10550 case 0xB2:
10551 case 0xB3:
10552 case 0xB4:
10553 case 0xB5:
10554 case 0xB6:
10555 case 0xB7:
10556 case 0xB8:
10557 case 0xB9:
10558 case 0xBA:
10559 case 0xBB:
10560 case 0xBC:
10561 case 0xBD:
10562 case 0xBE:
10563 case 0xBF:
10564 case 0xD9: // str 8
10565 case 0xDA: // str 16
10566 case 0xDB: // str 32
10567 {
10568 string_t s;
10569 return get_msgpack_string(s) && sax->string(s);
10570 }
10571
10572 case 0xC0: // nil
10573 return sax->null();
10574
10575 case 0xC2: // false
10576 return sax->boolean(false);
10577
10578 case 0xC3: // true
10579 return sax->boolean(true);
10580
10581 case 0xC4: // bin 8
10582 case 0xC5: // bin 16
10583 case 0xC6: // bin 32
10584 case 0xC7: // ext 8
10585 case 0xC8: // ext 16
10586 case 0xC9: // ext 32
10587 case 0xD4: // fixext 1
10588 case 0xD5: // fixext 2
10589 case 0xD6: // fixext 4
10590 case 0xD7: // fixext 8
10591 case 0xD8: // fixext 16
10592 {
10593 binary_t b;
10594 return get_msgpack_binary(b) && sax->binary(b);
10595 }
10596
10597 case 0xCA: // float 32
10598 {
10599 float number{};
10600 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10601 }
10602
10603 case 0xCB: // float 64
10604 {
10605 double number{};
10606 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
10607 }
10608
10609 case 0xCC: // uint 8
10610 {
10611 std::uint8_t number{};
10612 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10613 }
10614
10615 case 0xCD: // uint 16
10616 {
10617 std::uint16_t number{};
10618 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10619 }
10620
10621 case 0xCE: // uint 32
10622 {
10623 std::uint32_t number{};
10624 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10625 }
10626
10627 case 0xCF: // uint 64
10628 {
10629 std::uint64_t number{};
10630 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
10631 }
10632
10633 case 0xD0: // int 8
10634 {
10635 std::int8_t number{};
10636 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10637 }
10638
10639 case 0xD1: // int 16
10640 {
10641 std::int16_t number{};
10642 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10643 }
10644
10645 case 0xD2: // int 32
10646 {
10647 std::int32_t number{};
10648 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10649 }
10650
10651 case 0xD3: // int 64
10652 {
10653 std::int64_t number{};
10654 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
10655 }
10656
10657 case 0xDC: // array 16
10658 {
10659 std::uint16_t len{};
10660 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
10661 }
10662
10663 case 0xDD: // array 32
10664 {
10665 std::uint32_t len{};
10666 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
10667 }
10668
10669 case 0xDE: // map 16
10670 {
10671 std::uint16_t len{};
10672 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
10673 }
10674
10675 case 0xDF: // map 32
10676 {
10677 std::uint32_t len{};
10678 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
10679 }
10680
10681 // negative fixint
10682 case 0xE0:
10683 case 0xE1:
10684 case 0xE2:
10685 case 0xE3:
10686 case 0xE4:
10687 case 0xE5:
10688 case 0xE6:
10689 case 0xE7:
10690 case 0xE8:
10691 case 0xE9:
10692 case 0xEA:
10693 case 0xEB:
10694 case 0xEC:
10695 case 0xED:
10696 case 0xEE:
10697 case 0xEF:
10698 case 0xF0:
10699 case 0xF1:
10700 case 0xF2:
10701 case 0xF3:
10702 case 0xF4:
10703 case 0xF5:
10704 case 0xF6:
10705 case 0xF7:
10706 case 0xF8:
10707 case 0xF9:
10708 case 0xFA:
10709 case 0xFB:
10710 case 0xFC:
10711 case 0xFD:
10712 case 0xFE:
10713 case 0xFF:
10714 return sax->number_integer(static_cast<std::int8_t>(current));
10715
10716 default: // anything else
10717 {
10718 auto last_token = get_token_string();
10719 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10720 exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
10721 }
10722 }
10723 }
10724
10735 bool get_msgpack_string(string_t& result)
10736 {
10737 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
10738 {
10739 return false;
10740 }
10741
10742 switch (current)
10743 {
10744 // fixstr
10745 case 0xA0:
10746 case 0xA1:
10747 case 0xA2:
10748 case 0xA3:
10749 case 0xA4:
10750 case 0xA5:
10751 case 0xA6:
10752 case 0xA7:
10753 case 0xA8:
10754 case 0xA9:
10755 case 0xAA:
10756 case 0xAB:
10757 case 0xAC:
10758 case 0xAD:
10759 case 0xAE:
10760 case 0xAF:
10761 case 0xB0:
10762 case 0xB1:
10763 case 0xB2:
10764 case 0xB3:
10765 case 0xB4:
10766 case 0xB5:
10767 case 0xB6:
10768 case 0xB7:
10769 case 0xB8:
10770 case 0xB9:
10771 case 0xBA:
10772 case 0xBB:
10773 case 0xBC:
10774 case 0xBD:
10775 case 0xBE:
10776 case 0xBF:
10777 {
10778 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
10779 }
10780
10781 case 0xD9: // str 8
10782 {
10783 std::uint8_t len{};
10784 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10785 }
10786
10787 case 0xDA: // str 16
10788 {
10789 std::uint16_t len{};
10790 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10791 }
10792
10793 case 0xDB: // str 32
10794 {
10795 std::uint32_t len{};
10796 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
10797 }
10798
10799 default:
10800 {
10801 auto last_token = get_token_string();
10802 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10803 exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
10804 }
10805 }
10806 }
10807
10818 bool get_msgpack_binary(binary_t& result)
10819 {
10820 // helper function to set the subtype
10821 auto assign_and_return_true = [&result](std::int8_t subtype)
10822 {
10823 result.set_subtype(static_cast<std::uint8_t>(subtype));
10824 return true;
10825 };
10826
10827 switch (current)
10828 {
10829 case 0xC4: // bin 8
10830 {
10831 std::uint8_t len{};
10832 return get_number(input_format_t::msgpack, len) &&
10833 get_binary(input_format_t::msgpack, len, result);
10834 }
10835
10836 case 0xC5: // bin 16
10837 {
10838 std::uint16_t len{};
10839 return get_number(input_format_t::msgpack, len) &&
10840 get_binary(input_format_t::msgpack, len, result);
10841 }
10842
10843 case 0xC6: // bin 32
10844 {
10845 std::uint32_t len{};
10846 return get_number(input_format_t::msgpack, len) &&
10847 get_binary(input_format_t::msgpack, len, result);
10848 }
10849
10850 case 0xC7: // ext 8
10851 {
10852 std::uint8_t len{};
10853 std::int8_t subtype{};
10854 return get_number(input_format_t::msgpack, len) &&
10855 get_number(input_format_t::msgpack, subtype) &&
10856 get_binary(input_format_t::msgpack, len, result) &&
10857 assign_and_return_true(subtype);
10858 }
10859
10860 case 0xC8: // ext 16
10861 {
10862 std::uint16_t len{};
10863 std::int8_t subtype{};
10864 return get_number(input_format_t::msgpack, len) &&
10865 get_number(input_format_t::msgpack, subtype) &&
10866 get_binary(input_format_t::msgpack, len, result) &&
10867 assign_and_return_true(subtype);
10868 }
10869
10870 case 0xC9: // ext 32
10871 {
10872 std::uint32_t len{};
10873 std::int8_t subtype{};
10874 return get_number(input_format_t::msgpack, len) &&
10875 get_number(input_format_t::msgpack, subtype) &&
10876 get_binary(input_format_t::msgpack, len, result) &&
10877 assign_and_return_true(subtype);
10878 }
10879
10880 case 0xD4: // fixext 1
10881 {
10882 std::int8_t subtype{};
10883 return get_number(input_format_t::msgpack, subtype) &&
10884 get_binary(input_format_t::msgpack, 1, result) &&
10885 assign_and_return_true(subtype);
10886 }
10887
10888 case 0xD5: // fixext 2
10889 {
10890 std::int8_t subtype{};
10891 return get_number(input_format_t::msgpack, subtype) &&
10892 get_binary(input_format_t::msgpack, 2, result) &&
10893 assign_and_return_true(subtype);
10894 }
10895
10896 case 0xD6: // fixext 4
10897 {
10898 std::int8_t subtype{};
10899 return get_number(input_format_t::msgpack, subtype) &&
10900 get_binary(input_format_t::msgpack, 4, result) &&
10901 assign_and_return_true(subtype);
10902 }
10903
10904 case 0xD7: // fixext 8
10905 {
10906 std::int8_t subtype{};
10907 return get_number(input_format_t::msgpack, subtype) &&
10908 get_binary(input_format_t::msgpack, 8, result) &&
10909 assign_and_return_true(subtype);
10910 }
10911
10912 case 0xD8: // fixext 16
10913 {
10914 std::int8_t subtype{};
10915 return get_number(input_format_t::msgpack, subtype) &&
10916 get_binary(input_format_t::msgpack, 16, result) &&
10917 assign_and_return_true(subtype);
10918 }
10919
10920 default: // LCOV_EXCL_LINE
10921 return false; // LCOV_EXCL_LINE
10922 }
10923 }
10924
10929 bool get_msgpack_array(const std::size_t len)
10930 {
10931 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10932 {
10933 return false;
10934 }
10935
10936 for (std::size_t i = 0; i < len; ++i)
10937 {
10938 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10939 {
10940 return false;
10941 }
10942 }
10943
10944 return sax->end_array();
10945 }
10946
10951 bool get_msgpack_object(const std::size_t len)
10952 {
10953 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10954 {
10955 return false;
10956 }
10957
10958 string_t key;
10959 for (std::size_t i = 0; i < len; ++i)
10960 {
10961 get();
10962 if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
10963 {
10964 return false;
10965 }
10966
10967 if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
10968 {
10969 return false;
10970 }
10971 key.clear();
10972 }
10973
10974 return sax->end_object();
10975 }
10976
10978 // UBJSON //
10980
10988 bool parse_ubjson_internal(const bool get_char = true)
10989 {
10990 return get_ubjson_value(get_char ? get_ignore_noop() : current);
10991 }
10992
11007 bool get_ubjson_string(string_t& result, const bool get_char = true)
11008 {
11009 if (get_char)
11010 {
11011 get(); // TODO(niels): may we ignore N here?
11012 }
11013
11014 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11015 {
11016 return false;
11017 }
11018
11019 switch (current)
11020 {
11021 case 'U':
11022 {
11023 std::uint8_t len{};
11024 return get_number(input_format, len) && get_string(input_format, len, result);
11025 }
11026
11027 case 'i':
11028 {
11029 std::int8_t len{};
11030 return get_number(input_format, len) && get_string(input_format, len, result);
11031 }
11032
11033 case 'I':
11034 {
11035 std::int16_t len{};
11036 return get_number(input_format, len) && get_string(input_format, len, result);
11037 }
11038
11039 case 'l':
11040 {
11041 std::int32_t len{};
11042 return get_number(input_format, len) && get_string(input_format, len, result);
11043 }
11044
11045 case 'L':
11046 {
11047 std::int64_t len{};
11048 return get_number(input_format, len) && get_string(input_format, len, result);
11049 }
11050
11051 case 'u':
11052 {
11053 if (input_format != input_format_t::bjdata)
11054 {
11055 break;
11056 }
11057 std::uint16_t len{};
11058 return get_number(input_format, len) && get_string(input_format, len, result);
11059 }
11060
11061 case 'm':
11062 {
11063 if (input_format != input_format_t::bjdata)
11064 {
11065 break;
11066 }
11067 std::uint32_t len{};
11068 return get_number(input_format, len) && get_string(input_format, len, result);
11069 }
11070
11071 case 'M':
11072 {
11073 if (input_format != input_format_t::bjdata)
11074 {
11075 break;
11076 }
11077 std::uint64_t len{};
11078 return get_number(input_format, len) && get_string(input_format, len, result);
11079 }
11080
11081 default:
11082 break;
11083 }
11084 auto last_token = get_token_string();
11085 std::string message;
11086
11087 if (input_format != input_format_t::bjdata)
11088 {
11089 message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11090 }
11091 else
11092 {
11093 message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11094 }
11095 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11096 }
11097
11102 bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11103 {
11104 std::pair<std::size_t, char_int_type> size_and_type;
11105 size_t dimlen = 0;
11106 bool no_ndarray = true;
11107
11108 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11109 {
11110 return false;
11111 }
11112
11113 if (size_and_type.first != npos)
11114 {
11115 if (size_and_type.second != 0)
11116 {
11117 if (size_and_type.second != 'N')
11118 {
11119 for (std::size_t i = 0; i < size_and_type.first; ++i)
11120 {
11121 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11122 {
11123 return false;
11124 }
11125 dim.push_back(dimlen);
11126 }
11127 }
11128 }
11129 else
11130 {
11131 for (std::size_t i = 0; i < size_and_type.first; ++i)
11132 {
11133 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11134 {
11135 return false;
11136 }
11137 dim.push_back(dimlen);
11138 }
11139 }
11140 }
11141 else
11142 {
11143 while (current != ']')
11144 {
11145 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11146 {
11147 return false;
11148 }
11149 dim.push_back(dimlen);
11150 get_ignore_noop();
11151 }
11152 }
11153 return true;
11154 }
11155
11167 bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11168 {
11169 if (prefix == 0)
11170 {
11171 prefix = get_ignore_noop();
11172 }
11173
11174 switch (prefix)
11175 {
11176 case 'U':
11177 {
11178 std::uint8_t number{};
11179 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11180 {
11181 return false;
11182 }
11183 result = static_cast<std::size_t>(number);
11184 return true;
11185 }
11186
11187 case 'i':
11188 {
11189 std::int8_t number{};
11190 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11191 {
11192 return false;
11193 }
11194 if (number < 0)
11195 {
11196 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11197 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11198 }
11199 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11200 return true;
11201 }
11202
11203 case 'I':
11204 {
11205 std::int16_t number{};
11206 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11207 {
11208 return false;
11209 }
11210 if (number < 0)
11211 {
11212 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11213 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11214 }
11215 result = static_cast<std::size_t>(number);
11216 return true;
11217 }
11218
11219 case 'l':
11220 {
11221 std::int32_t number{};
11222 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11223 {
11224 return false;
11225 }
11226 if (number < 0)
11227 {
11228 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11229 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11230 }
11231 result = static_cast<std::size_t>(number);
11232 return true;
11233 }
11234
11235 case 'L':
11236 {
11237 std::int64_t number{};
11238 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11239 {
11240 return false;
11241 }
11242 if (number < 0)
11243 {
11244 return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11245 exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11246 }
11247 if (!value_in_range_of<std::size_t>(number))
11248 {
11249 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11250 exception_message(input_format, "integer value overflow", "size"), nullptr));
11251 }
11252 result = static_cast<std::size_t>(number);
11253 return true;
11254 }
11255
11256 case 'u':
11257 {
11258 if (input_format != input_format_t::bjdata)
11259 {
11260 break;
11261 }
11262 std::uint16_t number{};
11263 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11264 {
11265 return false;
11266 }
11267 result = static_cast<std::size_t>(number);
11268 return true;
11269 }
11270
11271 case 'm':
11272 {
11273 if (input_format != input_format_t::bjdata)
11274 {
11275 break;
11276 }
11277 std::uint32_t number{};
11278 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11279 {
11280 return false;
11281 }
11282 result = conditional_static_cast<std::size_t>(number);
11283 return true;
11284 }
11285
11286 case 'M':
11287 {
11288 if (input_format != input_format_t::bjdata)
11289 {
11290 break;
11291 }
11292 std::uint64_t number{};
11293 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11294 {
11295 return false;
11296 }
11297 if (!value_in_range_of<std::size_t>(number))
11298 {
11299 return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11300 exception_message(input_format, "integer value overflow", "size"), nullptr));
11301 }
11302 result = detail::conditional_static_cast<std::size_t>(number);
11303 return true;
11304 }
11305
11306 case '[':
11307 {
11308 if (input_format != input_format_t::bjdata)
11309 {
11310 break;
11311 }
11312 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11313 {
11314 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));
11315 }
11316 std::vector<size_t> dim;
11317 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11318 {
11319 return false;
11320 }
11321 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11322 {
11323 result = dim.at(dim.size() - 1);
11324 return true;
11325 }
11326 if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format
11327 {
11328 for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11329 {
11330 if ( i == 0 )
11331 {
11332 result = 0;
11333 return true;
11334 }
11335 }
11336
11337 string_t key = "_ArraySize_";
11338 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11339 {
11340 return false;
11341 }
11342 result = 1;
11343 for (auto i : dim)
11344 {
11345 result *= i;
11346 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()
11347 {
11348 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));
11349 }
11350 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11351 {
11352 return false;
11353 }
11354 }
11355 is_ndarray = true;
11356 return sax->end_array();
11357 }
11358 result = 0;
11359 return true;
11360 }
11361
11362 default:
11363 break;
11364 }
11365 auto last_token = get_token_string();
11366 std::string message;
11367
11368 if (input_format != input_format_t::bjdata)
11369 {
11370 message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11371 }
11372 else
11373 {
11374 message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
11375 }
11376 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
11377 }
11378
11390 bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
11391 {
11392 result.first = npos; // size
11393 result.second = 0; // type
11394 bool is_ndarray = false;
11395
11396 get_ignore_noop();
11397
11398 if (current == '$')
11399 {
11400 result.second = get(); // must not ignore 'N', because 'N' maybe the type
11401 if (input_format == input_format_t::bjdata
11402 && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
11403 {
11404 auto last_token = get_token_string();
11405 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11406 exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
11407 }
11408
11409 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
11410 {
11411 return false;
11412 }
11413
11414 get_ignore_noop();
11415 if (JSON_HEDLEY_UNLIKELY(current != '#'))
11416 {
11417 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11418 {
11419 return false;
11420 }
11421 auto last_token = get_token_string();
11422 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11423 exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
11424 }
11425
11426 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11427 if (input_format == input_format_t::bjdata && is_ndarray)
11428 {
11429 if (inside_ndarray)
11430 {
11431 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11432 exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
11433 }
11434 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
11435 }
11436 return is_error;
11437 }
11438
11439 if (current == '#')
11440 {
11441 const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
11442 if (input_format == input_format_t::bjdata && is_ndarray)
11443 {
11444 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
11445 exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
11446 }
11447 return is_error;
11448 }
11449
11450 return true;
11451 }
11452
11457 bool get_ubjson_value(const char_int_type prefix)
11458 {
11459 switch (prefix)
11460 {
11461 case char_traits<char_type>::eof(): // EOF
11462 return unexpect_eof(input_format, "value");
11463
11464 case 'T': // true
11465 return sax->boolean(true);
11466 case 'F': // false
11467 return sax->boolean(false);
11468
11469 case 'Z': // null
11470 return sax->null();
11471
11472 case 'U':
11473 {
11474 std::uint8_t number{};
11475 return get_number(input_format, number) && sax->number_unsigned(number);
11476 }
11477
11478 case 'i':
11479 {
11480 std::int8_t number{};
11481 return get_number(input_format, number) && sax->number_integer(number);
11482 }
11483
11484 case 'I':
11485 {
11486 std::int16_t number{};
11487 return get_number(input_format, number) && sax->number_integer(number);
11488 }
11489
11490 case 'l':
11491 {
11492 std::int32_t number{};
11493 return get_number(input_format, number) && sax->number_integer(number);
11494 }
11495
11496 case 'L':
11497 {
11498 std::int64_t number{};
11499 return get_number(input_format, number) && sax->number_integer(number);
11500 }
11501
11502 case 'u':
11503 {
11504 if (input_format != input_format_t::bjdata)
11505 {
11506 break;
11507 }
11508 std::uint16_t number{};
11509 return get_number(input_format, number) && sax->number_unsigned(number);
11510 }
11511
11512 case 'm':
11513 {
11514 if (input_format != input_format_t::bjdata)
11515 {
11516 break;
11517 }
11518 std::uint32_t number{};
11519 return get_number(input_format, number) && sax->number_unsigned(number);
11520 }
11521
11522 case 'M':
11523 {
11524 if (input_format != input_format_t::bjdata)
11525 {
11526 break;
11527 }
11528 std::uint64_t number{};
11529 return get_number(input_format, number) && sax->number_unsigned(number);
11530 }
11531
11532 case 'h':
11533 {
11534 if (input_format != input_format_t::bjdata)
11535 {
11536 break;
11537 }
11538 const auto byte1_raw = get();
11539 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11540 {
11541 return false;
11542 }
11543 const auto byte2_raw = get();
11544 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11545 {
11546 return false;
11547 }
11548
11549 const auto byte1 = static_cast<unsigned char>(byte1_raw);
11550 const auto byte2 = static_cast<unsigned char>(byte2_raw);
11551
11552 // code from RFC 7049, Appendix D, Figure 3:
11553 // As half-precision floating-point numbers were only added
11554 // to IEEE 754 in 2008, today's programming platforms often
11555 // still only have limited support for them. It is very
11556 // easy to include at least decoding support for them even
11557 // without such support. An example of a small decoder for
11558 // half-precision floating-point numbers in the C language
11559 // is shown in Fig. 3.
11560 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
11561 const double val = [&half]
11562 {
11563 const int exp = (half >> 10u) & 0x1Fu;
11564 const unsigned int mant = half & 0x3FFu;
11565 JSON_ASSERT(0 <= exp&& exp <= 32);
11566 JSON_ASSERT(mant <= 1024);
11567 switch (exp)
11568 {
11569 case 0:
11570 return std::ldexp(mant, -24);
11571 case 31:
11572 return (mant == 0)
11573 ? std::numeric_limits<double>::infinity()
11574 : std::numeric_limits<double>::quiet_NaN();
11575 default:
11576 return std::ldexp(mant + 1024, exp - 25);
11577 }
11578 }();
11579 return sax->number_float((half & 0x8000u) != 0
11580 ? static_cast<number_float_t>(-val)
11581 : static_cast<number_float_t>(val), "");
11582 }
11583
11584 case 'd':
11585 {
11586 float number{};
11587 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11588 }
11589
11590 case 'D':
11591 {
11592 double number{};
11593 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
11594 }
11595
11596 case 'H':
11597 {
11598 return get_ubjson_high_precision_number();
11599 }
11600
11601 case 'C': // char
11602 {
11603 get();
11604 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
11605 {
11606 return false;
11607 }
11608 if (JSON_HEDLEY_UNLIKELY(current > 127))
11609 {
11610 auto last_token = get_token_string();
11611 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11612 exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
11613 }
11614 string_t s(1, static_cast<typename string_t::value_type>(current));
11615 return sax->string(s);
11616 }
11617
11618 case 'S': // string
11619 {
11620 string_t s;
11621 return get_ubjson_string(s) && sax->string(s);
11622 }
11623
11624 case '[': // array
11625 return get_ubjson_array();
11626
11627 case '{': // object
11628 return get_ubjson_object();
11629
11630 default: // anything else
11631 break;
11632 }
11633 auto last_token = get_token_string();
11634 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));
11635 }
11636
11640 bool get_ubjson_array()
11641 {
11642 std::pair<std::size_t, char_int_type> size_and_type;
11643 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11644 {
11645 return false;
11646 }
11647
11648 // 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):
11649 // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
11650
11651 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11652 {
11653 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
11654 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)
11655 {
11656 return p.first < t;
11657 });
11658 string_t key = "_ArrayType_";
11659 if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
11660 {
11661 auto last_token = get_token_string();
11662 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11663 exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
11664 }
11665
11666 string_t type = it->second; // sax->string() takes a reference
11667 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
11668 {
11669 return false;
11670 }
11671
11672 if (size_and_type.second == 'C')
11673 {
11674 size_and_type.second = 'U';
11675 }
11676
11677 key = "_ArrayData_";
11678 if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
11679 {
11680 return false;
11681 }
11682
11683 for (std::size_t i = 0; i < size_and_type.first; ++i)
11684 {
11685 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11686 {
11687 return false;
11688 }
11689 }
11690
11691 return (sax->end_array() && sax->end_object());
11692 }
11693
11694 if (size_and_type.first != npos)
11695 {
11696 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
11697 {
11698 return false;
11699 }
11700
11701 if (size_and_type.second != 0)
11702 {
11703 if (size_and_type.second != 'N')
11704 {
11705 for (std::size_t i = 0; i < size_and_type.first; ++i)
11706 {
11707 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11708 {
11709 return false;
11710 }
11711 }
11712 }
11713 }
11714 else
11715 {
11716 for (std::size_t i = 0; i < size_and_type.first; ++i)
11717 {
11718 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11719 {
11720 return false;
11721 }
11722 }
11723 }
11724 }
11725 else
11726 {
11727 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
11728 {
11729 return false;
11730 }
11731
11732 while (current != ']')
11733 {
11734 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
11735 {
11736 return false;
11737 }
11738 get_ignore_noop();
11739 }
11740 }
11741
11742 return sax->end_array();
11743 }
11744
11748 bool get_ubjson_object()
11749 {
11750 std::pair<std::size_t, char_int_type> size_and_type;
11751 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
11752 {
11753 return false;
11754 }
11755
11756 // do not accept ND-array size in objects in BJData
11757 if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
11758 {
11759 auto last_token = get_token_string();
11760 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11761 exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
11762 }
11763
11764 string_t key;
11765 if (size_and_type.first != npos)
11766 {
11767 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
11768 {
11769 return false;
11770 }
11771
11772 if (size_and_type.second != 0)
11773 {
11774 for (std::size_t i = 0; i < size_and_type.first; ++i)
11775 {
11776 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11777 {
11778 return false;
11779 }
11780 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
11781 {
11782 return false;
11783 }
11784 key.clear();
11785 }
11786 }
11787 else
11788 {
11789 for (std::size_t i = 0; i < size_and_type.first; ++i)
11790 {
11791 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
11792 {
11793 return false;
11794 }
11795 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11796 {
11797 return false;
11798 }
11799 key.clear();
11800 }
11801 }
11802 }
11803 else
11804 {
11805 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
11806 {
11807 return false;
11808 }
11809
11810 while (current != '}')
11811 {
11812 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
11813 {
11814 return false;
11815 }
11816 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
11817 {
11818 return false;
11819 }
11820 get_ignore_noop();
11821 key.clear();
11822 }
11823 }
11824
11825 return sax->end_object();
11826 }
11827
11828 // Note, no reader for UBJSON binary types is implemented because they do
11829 // not exist
11830
11831 bool get_ubjson_high_precision_number()
11832 {
11833 // get size of following number string
11834 std::size_t size{};
11835 bool no_ndarray = true;
11836 auto res = get_ubjson_size_value(size, no_ndarray);
11837 if (JSON_HEDLEY_UNLIKELY(!res))
11838 {
11839 return res;
11840 }
11841
11842 // get number string
11843 std::vector<char> number_vector;
11844 for (std::size_t i = 0; i < size; ++i)
11845 {
11846 get();
11847 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
11848 {
11849 return false;
11850 }
11851 number_vector.push_back(static_cast<char>(current));
11852 }
11853
11854 // parse number string
11855 using ia_type = decltype(detail::input_adapter(number_vector));
11856 auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
11857 const auto result_number = number_lexer.scan();
11858 const auto number_string = number_lexer.get_token_string();
11859 const auto result_remainder = number_lexer.scan();
11860
11861 using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
11862
11863 if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
11864 {
11865 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11866 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11867 }
11868
11869 switch (result_number)
11870 {
11871 case token_type::value_integer:
11872 return sax->number_integer(number_lexer.get_number_integer());
11873 case token_type::value_unsigned:
11874 return sax->number_unsigned(number_lexer.get_number_unsigned());
11875 case token_type::value_float:
11876 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
11877 case token_type::uninitialized:
11878 case token_type::literal_true:
11879 case token_type::literal_false:
11880 case token_type::literal_null:
11881 case token_type::value_string:
11882 case token_type::begin_array:
11883 case token_type::begin_object:
11884 case token_type::end_array:
11885 case token_type::end_object:
11886 case token_type::name_separator:
11887 case token_type::value_separator:
11888 case token_type::parse_error:
11889 case token_type::end_of_input:
11890 case token_type::literal_or_value:
11891 default:
11892 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
11893 exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
11894 }
11895 }
11896
11898 // Utility functions //
11900
11910 char_int_type get()
11911 {
11912 ++chars_read;
11913 return current = ia.get_character();
11914 }
11915
11919 char_int_type get_ignore_noop()
11920 {
11921 do
11922 {
11923 get();
11924 }
11925 while (current == 'N');
11926
11927 return current;
11928 }
11929
11930 /*
11931 @brief read a number from the input
11932
11933 @tparam NumberType the type of the number
11934 @param[in] format the current format (for diagnostics)
11935 @param[out] result number of type @a NumberType
11936
11937 @return whether conversion completed
11938
11939 @note This function needs to respect the system's endianness, because
11940 bytes in CBOR, MessagePack, and UBJSON are stored in network order
11941 (big endian) and therefore need reordering on little endian systems.
11942 On the other hand, BSON and BJData use little endian and should reorder
11943 on big endian systems.
11944 */
11945 template<typename NumberType, bool InputIsLittleEndian = false>
11946 bool get_number(const input_format_t format, NumberType& result)
11947 {
11948 // step 1: read input into array with system's byte order
11949 std::array<std::uint8_t, sizeof(NumberType)> vec{};
11950 for (std::size_t i = 0; i < sizeof(NumberType); ++i)
11951 {
11952 get();
11953 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
11954 {
11955 return false;
11956 }
11957
11958 // reverse byte order prior to conversion if necessary
11959 if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
11960 {
11961 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
11962 }
11963 else
11964 {
11965 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
11966 }
11967 }
11968
11969 // step 2: convert array into number of type T and return
11970 std::memcpy(&result, vec.data(), sizeof(NumberType));
11971 return true;
11972 }
11973
11988 template<typename NumberType>
11989 bool get_string(const input_format_t format,
11990 const NumberType len,
11991 string_t& result)
11992 {
11993 bool success = true;
11994 for (NumberType i = 0; i < len; i++)
11995 {
11996 get();
11997 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
11998 {
11999 success = false;
12000 break;
12001 }
12002 result.push_back(static_cast<typename string_t::value_type>(current));
12003 }
12004 return success;
12005 }
12006
12021 template<typename NumberType>
12022 bool get_binary(const input_format_t format,
12023 const NumberType len,
12024 binary_t& result)
12025 {
12026 bool success = true;
12027 for (NumberType i = 0; i < len; i++)
12028 {
12029 get();
12030 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12031 {
12032 success = false;
12033 break;
12034 }
12035 result.push_back(static_cast<std::uint8_t>(current));
12036 }
12037 return success;
12038 }
12039
12045 JSON_HEDLEY_NON_NULL(3)
12046 bool unexpect_eof(const input_format_t format, const char* context) const
12047 {
12048 if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12049 {
12050 return sax->parse_error(chars_read, "<end of file>",
12051 parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12052 }
12053 return true;
12054 }
12055
12059 std::string get_token_string() const
12060 {
12061 std::array<char, 3> cr{{}};
12062 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12063 return std::string{cr.data()};
12064 }
12065
12072 std::string exception_message(const input_format_t format,
12073 const std::string& detail,
12074 const std::string& context) const
12075 {
12076 std::string error_msg = "syntax error while parsing ";
12077
12078 switch (format)
12079 {
12080 case input_format_t::cbor:
12081 error_msg += "CBOR";
12082 break;
12083
12084 case input_format_t::msgpack:
12085 error_msg += "MessagePack";
12086 break;
12087
12088 case input_format_t::ubjson:
12089 error_msg += "UBJSON";
12090 break;
12091
12092 case input_format_t::bson:
12093 error_msg += "BSON";
12094 break;
12095
12096 case input_format_t::bjdata:
12097 error_msg += "BJData";
12098 break;
12099
12100 case input_format_t::json: // LCOV_EXCL_LINE
12101 default: // LCOV_EXCL_LINE
12102 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12103 }
12104
12105 return concat(error_msg, ' ', context, ": ", detail);
12106 }
12107
12108 private:
12109 static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
12110
12112 InputAdapterType ia;
12113
12115 char_int_type current = char_traits<char_type>::eof();
12116
12118 std::size_t chars_read = 0;
12119
12121 const bool is_little_endian = little_endianness();
12122
12124 const input_format_t input_format = input_format_t::json;
12125
12127 json_sax_t* sax = nullptr;
12128
12129 // excluded markers in bjdata optimized type
12130#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12131 make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12132
12133#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12134 make_array<bjd_type>( \
12135 bjd_type{'C', "char"}, \
12136 bjd_type{'D', "double"}, \
12137 bjd_type{'I', "int16"}, \
12138 bjd_type{'L', "int64"}, \
12139 bjd_type{'M', "uint64"}, \
12140 bjd_type{'U', "uint8"}, \
12141 bjd_type{'d', "single"}, \
12142 bjd_type{'i', "int8"}, \
12143 bjd_type{'l', "int32"}, \
12144 bjd_type{'m', "uint32"}, \
12145 bjd_type{'u', "uint16"})
12146
12147 JSON_PRIVATE_UNLESS_TESTED:
12148 // lookup tables
12149 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12150 const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12151 JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12152
12153 using bjd_type = std::pair<char_int_type, string_t>;
12154 // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12155 const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12156 JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12157
12158#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12159#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12160};
12161
12162#ifndef JSON_HAS_CPP_17
12163 template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12164 constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12165#endif
12166
12167} // namespace detail
12168NLOHMANN_JSON_NAMESPACE_END
12169
12170// #include <nlohmann/detail/input/input_adapters.hpp>
12171
12172// #include <nlohmann/detail/input/lexer.hpp>
12173
12174// #include <nlohmann/detail/input/parser.hpp>
12175// __ _____ _____ _____
12176// __| | __| | | | JSON for Modern C++
12177// | | |__ | | | | | | version 3.11.3
12178// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12179//
12180// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12181// SPDX-License-Identifier: MIT
12182
12183
12184
12185#include <cmath> // isfinite
12186#include <cstdint> // uint8_t
12187#include <functional> // function
12188#include <string> // string
12189#include <utility> // move
12190#include <vector> // vector
12191
12192// #include <nlohmann/detail/exceptions.hpp>
12193
12194// #include <nlohmann/detail/input/input_adapters.hpp>
12195
12196// #include <nlohmann/detail/input/json_sax.hpp>
12197
12198// #include <nlohmann/detail/input/lexer.hpp>
12199
12200// #include <nlohmann/detail/macro_scope.hpp>
12201
12202// #include <nlohmann/detail/meta/is_sax.hpp>
12203
12204// #include <nlohmann/detail/string_concat.hpp>
12205
12206// #include <nlohmann/detail/value_t.hpp>
12207
12208
12209NLOHMANN_JSON_NAMESPACE_BEGIN
12210namespace detail
12211{
12213// parser //
12215
12216enum class parse_event_t : std::uint8_t
12217{
12221 object_end,
12225 array_end,
12227 key,
12229 value
12230};
12231
12232template<typename BasicJsonType>
12233using parser_callback_t =
12234 std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12235
12241template<typename BasicJsonType, typename InputAdapterType>
12243{
12244 using number_integer_t = typename BasicJsonType::number_integer_t;
12245 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12246 using number_float_t = typename BasicJsonType::number_float_t;
12247 using string_t = typename BasicJsonType::string_t;
12249 using token_type = typename lexer_t::token_type;
12250
12251 public:
12253 explicit parser(InputAdapterType&& adapter,
12254 const parser_callback_t<BasicJsonType> cb = nullptr,
12255 const bool allow_exceptions_ = true,
12256 const bool skip_comments = false)
12257 : callback(cb)
12258 , m_lexer(std::move(adapter), skip_comments)
12259 , allow_exceptions(allow_exceptions_)
12260 {
12261 // read first token
12262 get_token();
12263 }
12264
12275 void parse(const bool strict, BasicJsonType& result)
12276 {
12277 if (callback)
12278 {
12279 json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
12280 sax_parse_internal(&sdp);
12281
12282 // in strict mode, input must be completely read
12283 if (strict && (get_token() != token_type::end_of_input))
12284 {
12285 sdp.parse_error(m_lexer.get_position(),
12286 m_lexer.get_token_string(),
12287 parse_error::create(101, m_lexer.get_position(),
12288 exception_message(token_type::end_of_input, "value"), nullptr));
12289 }
12290
12291 // in case of an error, return discarded value
12292 if (sdp.is_errored())
12293 {
12294 result = value_t::discarded;
12295 return;
12296 }
12297
12298 // set top-level value to null if it was discarded by the callback
12299 // function
12300 if (result.is_discarded())
12301 {
12302 result = nullptr;
12303 }
12304 }
12305 else
12306 {
12307 json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
12308 sax_parse_internal(&sdp);
12309
12310 // in strict mode, input must be completely read
12311 if (strict && (get_token() != token_type::end_of_input))
12312 {
12313 sdp.parse_error(m_lexer.get_position(),
12314 m_lexer.get_token_string(),
12315 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12316 }
12317
12318 // in case of an error, return discarded value
12319 if (sdp.is_errored())
12320 {
12321 result = value_t::discarded;
12322 return;
12323 }
12324 }
12325
12326 result.assert_invariant();
12327 }
12328
12335 bool accept(const bool strict = true)
12336 {
12338 return sax_parse(&sax_acceptor, strict);
12339 }
12340
12341 template<typename SAX>
12342 JSON_HEDLEY_NON_NULL(2)
12343 bool sax_parse(SAX* sax, const bool strict = true)
12344 {
12346 const bool result = sax_parse_internal(sax);
12347
12348 // strict mode: next byte must be EOF
12349 if (result && strict && (get_token() != token_type::end_of_input))
12350 {
12351 return sax->parse_error(m_lexer.get_position(),
12352 m_lexer.get_token_string(),
12353 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12354 }
12355
12356 return result;
12357 }
12358
12359 private:
12360 template<typename SAX>
12361 JSON_HEDLEY_NON_NULL(2)
12362 bool sax_parse_internal(SAX* sax)
12363 {
12364 // stack to remember the hierarchy of structured values we are parsing
12365 // true = array; false = object
12366 std::vector<bool> states;
12367 // value to avoid a goto (see comment where set to true)
12368 bool skip_to_state_evaluation = false;
12369
12370 while (true)
12371 {
12372 if (!skip_to_state_evaluation)
12373 {
12374 // invariant: get_token() was called before each iteration
12375 switch (last_token)
12376 {
12377 case token_type::begin_object:
12378 {
12379 if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
12380 {
12381 return false;
12382 }
12383
12384 // closing } -> we are done
12385 if (get_token() == token_type::end_object)
12386 {
12387 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12388 {
12389 return false;
12390 }
12391 break;
12392 }
12393
12394 // parse key
12395 if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
12396 {
12397 return sax->parse_error(m_lexer.get_position(),
12398 m_lexer.get_token_string(),
12399 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12400 }
12401 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12402 {
12403 return false;
12404 }
12405
12406 // parse separator (:)
12407 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12408 {
12409 return sax->parse_error(m_lexer.get_position(),
12410 m_lexer.get_token_string(),
12411 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12412 }
12413
12414 // remember we are now inside an object
12415 states.push_back(false);
12416
12417 // parse values
12418 get_token();
12419 continue;
12420 }
12421
12422 case token_type::begin_array:
12423 {
12424 if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
12425 {
12426 return false;
12427 }
12428
12429 // closing ] -> we are done
12430 if (get_token() == token_type::end_array)
12431 {
12432 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12433 {
12434 return false;
12435 }
12436 break;
12437 }
12438
12439 // remember we are now inside an array
12440 states.push_back(true);
12441
12442 // parse values (no need to call get_token)
12443 continue;
12444 }
12445
12446 case token_type::value_float:
12447 {
12448 const auto res = m_lexer.get_number_float();
12449
12450 if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
12451 {
12452 return sax->parse_error(m_lexer.get_position(),
12453 m_lexer.get_token_string(),
12454 out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
12455 }
12456
12457 if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
12458 {
12459 return false;
12460 }
12461
12462 break;
12463 }
12464
12465 case token_type::literal_false:
12466 {
12467 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
12468 {
12469 return false;
12470 }
12471 break;
12472 }
12473
12474 case token_type::literal_null:
12475 {
12476 if (JSON_HEDLEY_UNLIKELY(!sax->null()))
12477 {
12478 return false;
12479 }
12480 break;
12481 }
12482
12483 case token_type::literal_true:
12484 {
12485 if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
12486 {
12487 return false;
12488 }
12489 break;
12490 }
12491
12492 case token_type::value_integer:
12493 {
12494 if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
12495 {
12496 return false;
12497 }
12498 break;
12499 }
12500
12501 case token_type::value_string:
12502 {
12503 if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
12504 {
12505 return false;
12506 }
12507 break;
12508 }
12509
12510 case token_type::value_unsigned:
12511 {
12512 if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
12513 {
12514 return false;
12515 }
12516 break;
12517 }
12518
12519 case token_type::parse_error:
12520 {
12521 // using "uninitialized" to avoid "expected" message
12522 return sax->parse_error(m_lexer.get_position(),
12523 m_lexer.get_token_string(),
12524 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
12525 }
12526 case token_type::end_of_input:
12527 {
12528 if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
12529 {
12530 return sax->parse_error(m_lexer.get_position(),
12531 m_lexer.get_token_string(),
12532 parse_error::create(101, m_lexer.get_position(),
12533 "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
12534 }
12535
12536 return sax->parse_error(m_lexer.get_position(),
12537 m_lexer.get_token_string(),
12538 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12539 }
12540 case token_type::uninitialized:
12541 case token_type::end_array:
12542 case token_type::end_object:
12543 case token_type::name_separator:
12544 case token_type::value_separator:
12545 case token_type::literal_or_value:
12546 default: // the last token was unexpected
12547 {
12548 return sax->parse_error(m_lexer.get_position(),
12549 m_lexer.get_token_string(),
12550 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
12551 }
12552 }
12553 }
12554 else
12555 {
12556 skip_to_state_evaluation = false;
12557 }
12558
12559 // we reached this line after we successfully parsed a value
12560 if (states.empty())
12561 {
12562 // empty stack: we reached the end of the hierarchy: done
12563 return true;
12564 }
12565
12566 if (states.back()) // array
12567 {
12568 // comma -> next value
12569 if (get_token() == token_type::value_separator)
12570 {
12571 // parse a new value
12572 get_token();
12573 continue;
12574 }
12575
12576 // closing ]
12577 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
12578 {
12579 if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
12580 {
12581 return false;
12582 }
12583
12584 // We are done with this array. Before we can parse a
12585 // new value, we need to evaluate the new state first.
12586 // By setting skip_to_state_evaluation to false, we
12587 // are effectively jumping to the beginning of this if.
12588 JSON_ASSERT(!states.empty());
12589 states.pop_back();
12590 skip_to_state_evaluation = true;
12591 continue;
12592 }
12593
12594 return sax->parse_error(m_lexer.get_position(),
12595 m_lexer.get_token_string(),
12596 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
12597 }
12598
12599 // states.back() is false -> object
12600
12601 // comma -> next value
12602 if (get_token() == token_type::value_separator)
12603 {
12604 // parse key
12605 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
12606 {
12607 return sax->parse_error(m_lexer.get_position(),
12608 m_lexer.get_token_string(),
12609 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
12610 }
12611
12612 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
12613 {
12614 return false;
12615 }
12616
12617 // parse separator (:)
12618 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
12619 {
12620 return sax->parse_error(m_lexer.get_position(),
12621 m_lexer.get_token_string(),
12622 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
12623 }
12624
12625 // parse values
12626 get_token();
12627 continue;
12628 }
12629
12630 // closing }
12631 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
12632 {
12633 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
12634 {
12635 return false;
12636 }
12637
12638 // We are done with this object. Before we can parse a
12639 // new value, we need to evaluate the new state first.
12640 // By setting skip_to_state_evaluation to false, we
12641 // are effectively jumping to the beginning of this if.
12642 JSON_ASSERT(!states.empty());
12643 states.pop_back();
12644 skip_to_state_evaluation = true;
12645 continue;
12646 }
12647
12648 return sax->parse_error(m_lexer.get_position(),
12649 m_lexer.get_token_string(),
12650 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
12651 }
12652 }
12653
12655 token_type get_token()
12656 {
12657 return last_token = m_lexer.scan();
12658 }
12659
12660 std::string exception_message(const token_type expected, const std::string& context)
12661 {
12662 std::string error_msg = "syntax error ";
12663
12664 if (!context.empty())
12665 {
12666 error_msg += concat("while parsing ", context, ' ');
12667 }
12668
12669 error_msg += "- ";
12670
12671 if (last_token == token_type::parse_error)
12672 {
12673 error_msg += concat(m_lexer.get_error_message(), "; last read: '",
12674 m_lexer.get_token_string(), '\'');
12675 }
12676 else
12677 {
12678 error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
12679 }
12680
12681 if (expected != token_type::uninitialized)
12682 {
12683 error_msg += concat("; expected ", lexer_t::token_type_name(expected));
12684 }
12685
12686 return error_msg;
12687 }
12688
12689 private:
12691 const parser_callback_t<BasicJsonType> callback = nullptr;
12693 token_type last_token = token_type::uninitialized;
12695 lexer_t m_lexer;
12697 const bool allow_exceptions = true;
12698};
12699
12700} // namespace detail
12701NLOHMANN_JSON_NAMESPACE_END
12702
12703// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12704// __ _____ _____ _____
12705// __| | __| | | | JSON for Modern C++
12706// | | |__ | | | | | | version 3.11.3
12707// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12708//
12709// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12710// SPDX-License-Identifier: MIT
12711
12712
12713
12714// #include <nlohmann/detail/abi_macros.hpp>
12715
12716// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12717// __ _____ _____ _____
12718// __| | __| | | | JSON for Modern C++
12719// | | |__ | | | | | | version 3.11.3
12720// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12721//
12722// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12723// SPDX-License-Identifier: MIT
12724
12725
12726
12727#include <cstddef> // ptrdiff_t
12728#include <limits> // numeric_limits
12729
12730// #include <nlohmann/detail/macro_scope.hpp>
12731
12732
12733NLOHMANN_JSON_NAMESPACE_BEGIN
12734namespace detail
12735{
12736
12737/*
12738@brief an iterator for primitive JSON types
12739
12740This class models an iterator for primitive JSON types (boolean, number,
12741string). It's only purpose is to allow the iterator/const_iterator classes
12742to "iterate" over primitive values. Internally, the iterator is modeled by
12743a `difference_type` variable. Value begin_value (`0`) models the begin,
12744end_value (`1`) models past the end.
12745*/
12747{
12748 private:
12749 using difference_type = std::ptrdiff_t;
12750 static constexpr difference_type begin_value = 0;
12751 static constexpr difference_type end_value = begin_value + 1;
12752
12753 JSON_PRIVATE_UNLESS_TESTED:
12755 difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
12756
12757 public:
12758 constexpr difference_type get_value() const noexcept
12759 {
12760 return m_it;
12761 }
12762
12764 void set_begin() noexcept
12765 {
12766 m_it = begin_value;
12767 }
12768
12770 void set_end() noexcept
12771 {
12772 m_it = end_value;
12773 }
12774
12776 constexpr bool is_begin() const noexcept
12777 {
12778 return m_it == begin_value;
12779 }
12780
12782 constexpr bool is_end() const noexcept
12783 {
12784 return m_it == end_value;
12785 }
12786
12787 friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12788 {
12789 return lhs.m_it == rhs.m_it;
12790 }
12791
12792 friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12793 {
12794 return lhs.m_it < rhs.m_it;
12795 }
12796
12797 primitive_iterator_t operator+(difference_type n) noexcept
12798 {
12799 auto result = *this;
12800 result += n;
12801 return result;
12802 }
12803
12804 friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
12805 {
12806 return lhs.m_it - rhs.m_it;
12807 }
12808
12809 primitive_iterator_t& operator++() noexcept
12810 {
12811 ++m_it;
12812 return *this;
12813 }
12814
12815 primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
12816 {
12817 auto result = *this;
12818 ++m_it;
12819 return result;
12820 }
12821
12822 primitive_iterator_t& operator--() noexcept
12823 {
12824 --m_it;
12825 return *this;
12826 }
12827
12828 primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
12829 {
12830 auto result = *this;
12831 --m_it;
12832 return result;
12833 }
12834
12835 primitive_iterator_t& operator+=(difference_type n) noexcept
12836 {
12837 m_it += n;
12838 return *this;
12839 }
12840
12841 primitive_iterator_t& operator-=(difference_type n) noexcept
12842 {
12843 m_it -= n;
12844 return *this;
12845 }
12846};
12847
12848} // namespace detail
12849NLOHMANN_JSON_NAMESPACE_END
12850
12851
12852NLOHMANN_JSON_NAMESPACE_BEGIN
12853namespace detail
12854{
12855
12862template<typename BasicJsonType> struct internal_iterator
12863{
12865 typename BasicJsonType::object_t::iterator object_iterator {};
12867 typename BasicJsonType::array_t::iterator array_iterator {};
12869 primitive_iterator_t primitive_iterator {};
12870};
12871
12872} // namespace detail
12873NLOHMANN_JSON_NAMESPACE_END
12874
12875// #include <nlohmann/detail/iterators/iter_impl.hpp>
12876// __ _____ _____ _____
12877// __| | __| | | | JSON for Modern C++
12878// | | |__ | | | | | | version 3.11.3
12879// |_____|_____|_____|_|___| https://github.com/nlohmann/json
12880//
12881// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
12882// SPDX-License-Identifier: MIT
12883
12884
12885
12886#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
12887#include <type_traits> // conditional, is_const, remove_const
12888
12889// #include <nlohmann/detail/exceptions.hpp>
12890
12891// #include <nlohmann/detail/iterators/internal_iterator.hpp>
12892
12893// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
12894
12895// #include <nlohmann/detail/macro_scope.hpp>
12896
12897// #include <nlohmann/detail/meta/cpp_future.hpp>
12898
12899// #include <nlohmann/detail/meta/type_traits.hpp>
12900
12901// #include <nlohmann/detail/value_t.hpp>
12902
12903
12904NLOHMANN_JSON_NAMESPACE_BEGIN
12905namespace detail
12906{
12907
12908// forward declare, to be able to friend it later on
12909template<typename IteratorType> class iteration_proxy;
12910template<typename IteratorType> class iteration_proxy_value;
12911
12928template<typename BasicJsonType>
12929class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
12930{
12932 using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
12934 friend other_iter_impl;
12935 friend BasicJsonType;
12938
12939 using object_t = typename BasicJsonType::object_t;
12940 using array_t = typename BasicJsonType::array_t;
12941 // make sure BasicJsonType is basic_json or const basic_json
12943 "iter_impl only accepts (const) basic_json");
12944 // superficial check for the LegacyBidirectionalIterator named requirement
12945 static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
12946 && std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
12947 "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
12948
12949 public:
12955 using iterator_category = std::bidirectional_iterator_tag;
12956
12958 using value_type = typename BasicJsonType::value_type;
12960 using difference_type = typename BasicJsonType::difference_type;
12962 using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
12963 typename BasicJsonType::const_pointer,
12964 typename BasicJsonType::pointer>::type;
12967 typename std::conditional<std::is_const<BasicJsonType>::value,
12968 typename BasicJsonType::const_reference,
12969 typename BasicJsonType::reference>::type;
12970
12971 iter_impl() = default;
12972 ~iter_impl() = default;
12973 iter_impl(iter_impl&&) noexcept = default;
12974 iter_impl& operator=(iter_impl&&) noexcept = default;
12975
12982 explicit iter_impl(pointer object) noexcept : m_object(object)
12983 {
12984 JSON_ASSERT(m_object != nullptr);
12985
12986 switch (m_object->m_data.m_type)
12987 {
12988 case value_t::object:
12989 {
12990 m_it.object_iterator = typename object_t::iterator();
12991 break;
12992 }
12993
12994 case value_t::array:
12995 {
12996 m_it.array_iterator = typename array_t::iterator();
12997 break;
12998 }
12999
13000 case value_t::null:
13001 case value_t::string:
13002 case value_t::boolean:
13003 case value_t::number_integer:
13004 case value_t::number_unsigned:
13005 case value_t::number_float:
13006 case value_t::binary:
13007 case value_t::discarded:
13008 default:
13009 {
13010 m_it.primitive_iterator = primitive_iterator_t();
13011 break;
13012 }
13013 }
13014 }
13015
13033 : m_object(other.m_object), m_it(other.m_it)
13034 {}
13035
13043 {
13044 if (&other != this)
13045 {
13046 m_object = other.m_object;
13047 m_it = other.m_it;
13048 }
13049 return *this;
13050 }
13051
13057 iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13058 : m_object(other.m_object), m_it(other.m_it)
13059 {}
13060
13067 iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13068 {
13069 m_object = other.m_object;
13070 m_it = other.m_it;
13071 return *this;
13072 }
13073
13074 JSON_PRIVATE_UNLESS_TESTED:
13079 void set_begin() noexcept
13080 {
13081 JSON_ASSERT(m_object != nullptr);
13082
13083 switch (m_object->m_data.m_type)
13084 {
13085 case value_t::object:
13086 {
13087 m_it.object_iterator = m_object->m_data.m_value.object->begin();
13088 break;
13089 }
13090
13091 case value_t::array:
13092 {
13093 m_it.array_iterator = m_object->m_data.m_value.array->begin();
13094 break;
13095 }
13096
13097 case value_t::null:
13098 {
13099 // set to end so begin()==end() is true: null is empty
13100 m_it.primitive_iterator.set_end();
13101 break;
13102 }
13103
13104 case value_t::string:
13105 case value_t::boolean:
13106 case value_t::number_integer:
13107 case value_t::number_unsigned:
13108 case value_t::number_float:
13109 case value_t::binary:
13110 case value_t::discarded:
13111 default:
13112 {
13113 m_it.primitive_iterator.set_begin();
13114 break;
13115 }
13116 }
13117 }
13118
13123 void set_end() noexcept
13124 {
13125 JSON_ASSERT(m_object != nullptr);
13126
13127 switch (m_object->m_data.m_type)
13128 {
13129 case value_t::object:
13130 {
13131 m_it.object_iterator = m_object->m_data.m_value.object->end();
13132 break;
13133 }
13134
13135 case value_t::array:
13136 {
13137 m_it.array_iterator = m_object->m_data.m_value.array->end();
13138 break;
13139 }
13140
13141 case value_t::null:
13142 case value_t::string:
13143 case value_t::boolean:
13144 case value_t::number_integer:
13145 case value_t::number_unsigned:
13146 case value_t::number_float:
13147 case value_t::binary:
13148 case value_t::discarded:
13149 default:
13150 {
13151 m_it.primitive_iterator.set_end();
13152 break;
13153 }
13154 }
13155 }
13156
13157 public:
13163 {
13164 JSON_ASSERT(m_object != nullptr);
13165
13166 switch (m_object->m_data.m_type)
13167 {
13168 case value_t::object:
13169 {
13170 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13171 return m_it.object_iterator->second;
13172 }
13173
13174 case value_t::array:
13175 {
13176 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13177 return *m_it.array_iterator;
13178 }
13179
13180 case value_t::null:
13181 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13182
13183 case value_t::string:
13184 case value_t::boolean:
13185 case value_t::number_integer:
13186 case value_t::number_unsigned:
13187 case value_t::number_float:
13188 case value_t::binary:
13189 case value_t::discarded:
13190 default:
13191 {
13192 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13193 {
13194 return *m_object;
13195 }
13196
13197 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13198 }
13199 }
13200 }
13201
13207 {
13208 JSON_ASSERT(m_object != nullptr);
13209
13210 switch (m_object->m_data.m_type)
13211 {
13212 case value_t::object:
13213 {
13214 JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13215 return &(m_it.object_iterator->second);
13216 }
13217
13218 case value_t::array:
13219 {
13220 JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13221 return &*m_it.array_iterator;
13222 }
13223
13224 case value_t::null:
13225 case value_t::string:
13226 case value_t::boolean:
13227 case value_t::number_integer:
13228 case value_t::number_unsigned:
13229 case value_t::number_float:
13230 case value_t::binary:
13231 case value_t::discarded:
13232 default:
13233 {
13234 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13235 {
13236 return m_object;
13237 }
13238
13239 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13240 }
13241 }
13242 }
13243
13248 iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13249 {
13250 auto result = *this;
13251 ++(*this);
13252 return result;
13253 }
13254
13260 {
13261 JSON_ASSERT(m_object != nullptr);
13262
13263 switch (m_object->m_data.m_type)
13264 {
13265 case value_t::object:
13266 {
13267 std::advance(m_it.object_iterator, 1);
13268 break;
13269 }
13270
13271 case value_t::array:
13272 {
13273 std::advance(m_it.array_iterator, 1);
13274 break;
13275 }
13276
13277 case value_t::null:
13278 case value_t::string:
13279 case value_t::boolean:
13280 case value_t::number_integer:
13281 case value_t::number_unsigned:
13282 case value_t::number_float:
13283 case value_t::binary:
13284 case value_t::discarded:
13285 default:
13286 {
13287 ++m_it.primitive_iterator;
13288 break;
13289 }
13290 }
13291
13292 return *this;
13293 }
13294
13299 iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13300 {
13301 auto result = *this;
13302 --(*this);
13303 return result;
13304 }
13305
13311 {
13312 JSON_ASSERT(m_object != nullptr);
13313
13314 switch (m_object->m_data.m_type)
13315 {
13316 case value_t::object:
13317 {
13318 std::advance(m_it.object_iterator, -1);
13319 break;
13320 }
13321
13322 case value_t::array:
13323 {
13324 std::advance(m_it.array_iterator, -1);
13325 break;
13326 }
13327
13328 case value_t::null:
13329 case value_t::string:
13330 case value_t::boolean:
13331 case value_t::number_integer:
13332 case value_t::number_unsigned:
13333 case value_t::number_float:
13334 case value_t::binary:
13335 case value_t::discarded:
13336 default:
13337 {
13338 --m_it.primitive_iterator;
13339 break;
13340 }
13341 }
13342
13343 return *this;
13344 }
13345
13350 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 >
13351 bool operator==(const IterImpl& other) const
13352 {
13353 // if objects are not the same, the comparison is undefined
13354 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13355 {
13356 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13357 }
13358
13359 JSON_ASSERT(m_object != nullptr);
13360
13361 switch (m_object->m_data.m_type)
13362 {
13363 case value_t::object:
13364 return (m_it.object_iterator == other.m_it.object_iterator);
13365
13366 case value_t::array:
13367 return (m_it.array_iterator == other.m_it.array_iterator);
13368
13369 case value_t::null:
13370 case value_t::string:
13371 case value_t::boolean:
13372 case value_t::number_integer:
13373 case value_t::number_unsigned:
13374 case value_t::number_float:
13375 case value_t::binary:
13376 case value_t::discarded:
13377 default:
13378 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
13379 }
13380 }
13381
13386 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 >
13387 bool operator!=(const IterImpl& other) const
13388 {
13389 return !operator==(other);
13390 }
13391
13396 bool operator<(const iter_impl& other) const
13397 {
13398 // if objects are not the same, the comparison is undefined
13399 if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
13400 {
13401 JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
13402 }
13403
13404 JSON_ASSERT(m_object != nullptr);
13405
13406 switch (m_object->m_data.m_type)
13407 {
13408 case value_t::object:
13409 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
13410
13411 case value_t::array:
13412 return (m_it.array_iterator < other.m_it.array_iterator);
13413
13414 case value_t::null:
13415 case value_t::string:
13416 case value_t::boolean:
13417 case value_t::number_integer:
13418 case value_t::number_unsigned:
13419 case value_t::number_float:
13420 case value_t::binary:
13421 case value_t::discarded:
13422 default:
13423 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
13424 }
13425 }
13426
13431 bool operator<=(const iter_impl& other) const
13432 {
13433 return !other.operator < (*this);
13434 }
13435
13440 bool operator>(const iter_impl& other) const
13441 {
13442 return !operator<=(other);
13443 }
13444
13449 bool operator>=(const iter_impl& other) const
13450 {
13451 return !operator<(other);
13452 }
13453
13459 {
13460 JSON_ASSERT(m_object != nullptr);
13461
13462 switch (m_object->m_data.m_type)
13463 {
13464 case value_t::object:
13465 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13466
13467 case value_t::array:
13468 {
13469 std::advance(m_it.array_iterator, i);
13470 break;
13471 }
13472
13473 case value_t::null:
13474 case value_t::string:
13475 case value_t::boolean:
13476 case value_t::number_integer:
13477 case value_t::number_unsigned:
13478 case value_t::number_float:
13479 case value_t::binary:
13480 case value_t::discarded:
13481 default:
13482 {
13483 m_it.primitive_iterator += i;
13484 break;
13485 }
13486 }
13487
13488 return *this;
13489 }
13490
13496 {
13497 return operator+=(-i);
13498 }
13499
13505 {
13506 auto result = *this;
13507 result += i;
13508 return result;
13509 }
13510
13516 {
13517 auto result = it;
13518 result += i;
13519 return result;
13520 }
13521
13527 {
13528 auto result = *this;
13529 result -= i;
13530 return result;
13531 }
13532
13538 {
13539 JSON_ASSERT(m_object != nullptr);
13540
13541 switch (m_object->m_data.m_type)
13542 {
13543 case value_t::object:
13544 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
13545
13546 case value_t::array:
13547 return m_it.array_iterator - other.m_it.array_iterator;
13548
13549 case value_t::null:
13550 case value_t::string:
13551 case value_t::boolean:
13552 case value_t::number_integer:
13553 case value_t::number_unsigned:
13554 case value_t::number_float:
13555 case value_t::binary:
13556 case value_t::discarded:
13557 default:
13558 return m_it.primitive_iterator - other.m_it.primitive_iterator;
13559 }
13560 }
13561
13567 {
13568 JSON_ASSERT(m_object != nullptr);
13569
13570 switch (m_object->m_data.m_type)
13571 {
13572 case value_t::object:
13573 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
13574
13575 case value_t::array:
13576 return *std::next(m_it.array_iterator, n);
13577
13578 case value_t::null:
13579 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13580
13581 case value_t::string:
13582 case value_t::boolean:
13583 case value_t::number_integer:
13584 case value_t::number_unsigned:
13585 case value_t::number_float:
13586 case value_t::binary:
13587 case value_t::discarded:
13588 default:
13589 {
13590 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
13591 {
13592 return *m_object;
13593 }
13594
13595 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13596 }
13597 }
13598 }
13599
13604 const typename object_t::key_type& key() const
13605 {
13606 JSON_ASSERT(m_object != nullptr);
13607
13608 if (JSON_HEDLEY_LIKELY(m_object->is_object()))
13609 {
13610 return m_it.object_iterator->first;
13611 }
13612
13613 JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
13614 }
13615
13621 {
13622 return operator*();
13623 }
13624
13625 JSON_PRIVATE_UNLESS_TESTED:
13627 pointer m_object = nullptr;
13630};
13631
13632} // namespace detail
13633NLOHMANN_JSON_NAMESPACE_END
13634
13635// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
13636
13637// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
13638// __ _____ _____ _____
13639// __| | __| | | | JSON for Modern C++
13640// | | |__ | | | | | | version 3.11.3
13641// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13642//
13643// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13644// SPDX-License-Identifier: MIT
13645
13646
13647
13648#include <cstddef> // ptrdiff_t
13649#include <iterator> // reverse_iterator
13650#include <utility> // declval
13651
13652// #include <nlohmann/detail/abi_macros.hpp>
13653
13654
13655NLOHMANN_JSON_NAMESPACE_BEGIN
13656namespace detail
13657{
13658
13660// reverse_iterator //
13662
13681template<typename Base>
13682class json_reverse_iterator : public std::reverse_iterator<Base>
13683{
13684 public:
13685 using difference_type = std::ptrdiff_t;
13687 using base_iterator = std::reverse_iterator<Base>;
13689 using reference = typename Base::reference;
13690
13692 explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
13693 : base_iterator(it) {}
13694
13696 explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
13697
13699 json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
13700 {
13701 return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
13702 }
13703
13706 {
13707 return static_cast<json_reverse_iterator&>(base_iterator::operator++());
13708 }
13709
13711 json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
13712 {
13713 return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
13714 }
13715
13718 {
13719 return static_cast<json_reverse_iterator&>(base_iterator::operator--());
13720 }
13721
13724 {
13725 return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
13726 }
13727
13729 json_reverse_iterator operator+(difference_type i) const
13730 {
13731 return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
13732 }
13733
13735 json_reverse_iterator operator-(difference_type i) const
13736 {
13737 return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
13738 }
13739
13741 difference_type operator-(const json_reverse_iterator& other) const
13742 {
13743 return base_iterator(*this) - base_iterator(other);
13744 }
13745
13747 reference operator[](difference_type n) const
13748 {
13749 return *(this->operator+(n));
13750 }
13751
13753 auto key() const -> decltype(std::declval<Base>().key())
13754 {
13755 auto it = --this->base();
13756 return it.key();
13757 }
13758
13761 {
13762 auto it = --this->base();
13763 return it.operator * ();
13764 }
13765};
13766
13767} // namespace detail
13768NLOHMANN_JSON_NAMESPACE_END
13769
13770// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13771
13772// #include <nlohmann/detail/json_custom_base_class.hpp>
13773// __ _____ _____ _____
13774// __| | __| | | | JSON for Modern C++
13775// | | |__ | | | | | | version 3.11.3
13776// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13777//
13778// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13779// SPDX-License-Identifier: MIT
13780
13781
13782
13783#include <type_traits> // conditional, is_same
13784
13785// #include <nlohmann/detail/abi_macros.hpp>
13786
13787
13788NLOHMANN_JSON_NAMESPACE_BEGIN
13789namespace detail
13790{
13791
13803
13804template<class T>
13805using json_base_class = typename std::conditional <
13806 std::is_same<T, void>::value,
13808 T
13809 >::type;
13810
13811} // namespace detail
13812NLOHMANN_JSON_NAMESPACE_END
13813
13814// #include <nlohmann/detail/json_pointer.hpp>
13815// __ _____ _____ _____
13816// __| | __| | | | JSON for Modern C++
13817// | | |__ | | | | | | version 3.11.3
13818// |_____|_____|_____|_|___| https://github.com/nlohmann/json
13819//
13820// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
13821// SPDX-License-Identifier: MIT
13822
13823
13824
13825#include <algorithm> // all_of
13826#include <cctype> // isdigit
13827#include <cerrno> // errno, ERANGE
13828#include <cstdlib> // strtoull
13829#ifndef JSON_NO_IO
13830 #include <iosfwd> // ostream
13831#endif // JSON_NO_IO
13832#include <limits> // max
13833#include <numeric> // accumulate
13834#include <string> // string
13835#include <utility> // move
13836#include <vector> // vector
13837
13838// #include <nlohmann/detail/exceptions.hpp>
13839
13840// #include <nlohmann/detail/macro_scope.hpp>
13841
13842// #include <nlohmann/detail/string_concat.hpp>
13843
13844// #include <nlohmann/detail/string_escape.hpp>
13845
13846// #include <nlohmann/detail/value_t.hpp>
13847
13848
13849NLOHMANN_JSON_NAMESPACE_BEGIN
13850
13853template<typename RefStringType>
13855{
13856 // allow basic_json to access private members
13857 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13858 friend class basic_json;
13859
13860 template<typename>
13861 friend class json_pointer;
13862
13863 template<typename T>
13864 struct string_t_helper
13865 {
13866 using type = T;
13867 };
13868
13869 NLOHMANN_BASIC_JSON_TPL_DECLARATION
13870 struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
13871 {
13872 using type = StringType;
13873 };
13874
13875 public:
13876 // for backwards compatibility accept BasicJsonType
13877 using string_t = typename string_t_helper<RefStringType>::type;
13878
13881 explicit json_pointer(const string_t& s = "")
13882 : reference_tokens(split(s))
13883 {}
13884
13887 string_t to_string() const
13888 {
13889 return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
13890 string_t{},
13891 [](const string_t& a, const string_t& b)
13892 {
13893 return detail::concat(a, '/', detail::escape(b));
13894 });
13895 }
13896
13899 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
13900 operator string_t() const
13901 {
13902 return to_string();
13903 }
13904
13905#ifndef JSON_NO_IO
13908 friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
13909 {
13910 o << ptr.to_string();
13911 return o;
13912 }
13913#endif
13914
13918 {
13919 reference_tokens.insert(reference_tokens.end(),
13920 ptr.reference_tokens.begin(),
13921 ptr.reference_tokens.end());
13922 return *this;
13923 }
13924
13927 json_pointer& operator/=(string_t token)
13928 {
13929 push_back(std::move(token));
13930 return *this;
13931 }
13932
13935 json_pointer& operator/=(std::size_t array_idx)
13936 {
13937 return *this /= std::to_string(array_idx);
13938 }
13939
13943 const json_pointer& rhs)
13944 {
13945 return json_pointer(lhs) /= rhs;
13946 }
13947
13950 friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
13951 {
13952 return json_pointer(lhs) /= std::move(token);
13953 }
13954
13957 friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
13958 {
13959 return json_pointer(lhs) /= array_idx;
13960 }
13961
13965 {
13966 if (empty())
13967 {
13968 return *this;
13969 }
13970
13971 json_pointer res = *this;
13972 res.pop_back();
13973 return res;
13974 }
13975
13979 {
13980 if (JSON_HEDLEY_UNLIKELY(empty()))
13981 {
13982 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13983 }
13984
13985 reference_tokens.pop_back();
13986 }
13987
13990 const string_t& back() const
13991 {
13992 if (JSON_HEDLEY_UNLIKELY(empty()))
13993 {
13994 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
13995 }
13996
13997 return reference_tokens.back();
13998 }
13999
14002 void push_back(const string_t& token)
14003 {
14004 reference_tokens.push_back(token);
14005 }
14006
14009 void push_back(string_t&& token)
14010 {
14011 reference_tokens.push_back(std::move(token));
14012 }
14013
14016 bool empty() const noexcept
14017 {
14018 return reference_tokens.empty();
14019 }
14020
14021 private:
14032 template<typename BasicJsonType>
14033 static typename BasicJsonType::size_type array_index(const string_t& s)
14034 {
14035 using size_type = typename BasicJsonType::size_type;
14036
14037 // error condition (cf. RFC 6901, Sect. 4)
14038 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14039 {
14040 JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14041 }
14042
14043 // error condition (cf. RFC 6901, Sect. 4)
14044 if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14045 {
14046 JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14047 }
14048
14049 const char* p = s.c_str();
14050 char* p_end = nullptr;
14051 errno = 0; // strtoull doesn't reset errno
14052 const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14053 if (p == p_end // invalid input or empty string
14054 || errno == ERANGE // out of range
14055 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14056 {
14057 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14058 }
14059
14060 // only triggered on special platforms (like 32bit), see also
14061 // https://github.com/nlohmann/json/pull/2203
14062 if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)())) // NOLINT(runtime/int)
14063 {
14064 JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr)); // LCOV_EXCL_LINE
14065 }
14066
14067 return static_cast<size_type>(res);
14068 }
14069
14070 JSON_PRIVATE_UNLESS_TESTED:
14071 json_pointer top() const
14072 {
14073 if (JSON_HEDLEY_UNLIKELY(empty()))
14074 {
14075 JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14076 }
14077
14078 json_pointer result = *this;
14079 result.reference_tokens = {reference_tokens[0]};
14080 return result;
14081 }
14082
14083 private:
14092 template<typename BasicJsonType>
14093 BasicJsonType& get_and_create(BasicJsonType& j) const
14094 {
14095 auto* result = &j;
14096
14097 // in case no reference tokens exist, return a reference to the JSON value
14098 // j which will be overwritten by a primitive value
14099 for (const auto& reference_token : reference_tokens)
14100 {
14101 switch (result->type())
14102 {
14104 {
14105 if (reference_token == "0")
14106 {
14107 // start a new array if reference token is 0
14108 result = &result->operator[](0);
14109 }
14110 else
14111 {
14112 // start a new object otherwise
14113 result = &result->operator[](reference_token);
14114 }
14115 break;
14116 }
14117
14119 {
14120 // create an entry in the object
14121 result = &result->operator[](reference_token);
14122 break;
14123 }
14124
14126 {
14127 // create an entry in the array
14128 result = &result->operator[](array_index<BasicJsonType>(reference_token));
14129 break;
14130 }
14131
14132 /*
14133 The following code is only reached if there exists a reference
14134 token _and_ the current value is primitive. In this case, we have
14135 an error situation, because primitive values may only occur as
14136 single value; that is, with an empty list of reference tokens.
14137 */
14145 default:
14146 JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14147 }
14148 }
14149
14150 return *result;
14151 }
14152
14172 template<typename BasicJsonType>
14173 BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14174 {
14175 for (const auto& reference_token : reference_tokens)
14176 {
14177 // convert null values to arrays or objects before continuing
14178 if (ptr->is_null())
14179 {
14180 // check if reference token is a number
14181 const bool nums =
14182 std::all_of(reference_token.begin(), reference_token.end(),
14183 [](const unsigned char x)
14184 {
14185 return std::isdigit(x);
14186 });
14187
14188 // change value to array for numbers or "-" or to object otherwise
14189 *ptr = (nums || reference_token == "-")
14191 : detail::value_t::object;
14192 }
14193
14194 switch (ptr->type())
14195 {
14197 {
14198 // use unchecked object access
14199 ptr = &ptr->operator[](reference_token);
14200 break;
14201 }
14202
14204 {
14205 if (reference_token == "-")
14206 {
14207 // explicitly treat "-" as index beyond the end
14208 ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14209 }
14210 else
14211 {
14212 // convert array index to number; unchecked access
14213 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14214 }
14215 break;
14216 }
14217
14226 default:
14227 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14228 }
14229 }
14230
14231 return *ptr;
14232 }
14233
14240 template<typename BasicJsonType>
14241 BasicJsonType& get_checked(BasicJsonType* ptr) const
14242 {
14243 for (const auto& reference_token : reference_tokens)
14244 {
14245 switch (ptr->type())
14246 {
14248 {
14249 // note: at performs range check
14250 ptr = &ptr->at(reference_token);
14251 break;
14252 }
14253
14255 {
14256 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14257 {
14258 // "-" always fails the range check
14259 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14260 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14261 ") is out of range"), ptr));
14262 }
14263
14264 // note: at performs range check
14265 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14266 break;
14267 }
14268
14277 default:
14278 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14279 }
14280 }
14281
14282 return *ptr;
14283 }
14284
14298 template<typename BasicJsonType>
14299 const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14300 {
14301 for (const auto& reference_token : reference_tokens)
14302 {
14303 switch (ptr->type())
14304 {
14306 {
14307 // use unchecked object access
14308 ptr = &ptr->operator[](reference_token);
14309 break;
14310 }
14311
14313 {
14314 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14315 {
14316 // "-" cannot be used for const access
14317 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));
14318 }
14319
14320 // use unchecked array access
14321 ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14322 break;
14323 }
14324
14333 default:
14334 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14335 }
14336 }
14337
14338 return *ptr;
14339 }
14340
14347 template<typename BasicJsonType>
14348 const BasicJsonType& get_checked(const BasicJsonType* ptr) const
14349 {
14350 for (const auto& reference_token : reference_tokens)
14351 {
14352 switch (ptr->type())
14353 {
14355 {
14356 // note: at performs range check
14357 ptr = &ptr->at(reference_token);
14358 break;
14359 }
14360
14362 {
14363 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14364 {
14365 // "-" always fails the range check
14366 JSON_THROW(detail::out_of_range::create(402, detail::concat(
14367 "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14368 ") is out of range"), ptr));
14369 }
14370
14371 // note: at performs range check
14372 ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14373 break;
14374 }
14375
14384 default:
14385 JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14386 }
14387 }
14388
14389 return *ptr;
14390 }
14391
14396 template<typename BasicJsonType>
14397 bool contains(const BasicJsonType* ptr) const
14398 {
14399 for (const auto& reference_token : reference_tokens)
14400 {
14401 switch (ptr->type())
14402 {
14404 {
14405 if (!ptr->contains(reference_token))
14406 {
14407 // we did not find the key in the object
14408 return false;
14409 }
14410
14411 ptr = &ptr->operator[](reference_token);
14412 break;
14413 }
14414
14416 {
14417 if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14418 {
14419 // "-" always fails the range check
14420 return false;
14421 }
14422 if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
14423 {
14424 // invalid char
14425 return false;
14426 }
14427 if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
14428 {
14429 if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
14430 {
14431 // first char should be between '1' and '9'
14432 return false;
14433 }
14434 for (std::size_t i = 1; i < reference_token.size(); i++)
14435 {
14436 if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
14437 {
14438 // other char should be between '0' and '9'
14439 return false;
14440 }
14441 }
14442 }
14443
14444 const auto idx = array_index<BasicJsonType>(reference_token);
14445 if (idx >= ptr->size())
14446 {
14447 // index out of range
14448 return false;
14449 }
14450
14451 ptr = &ptr->operator[](idx);
14452 break;
14453 }
14454
14463 default:
14464 {
14465 // we do not expect primitive values if there is still a
14466 // reference token to process
14467 return false;
14468 }
14469 }
14470 }
14471
14472 // no reference token left means we found a primitive value
14473 return true;
14474 }
14475
14485 static std::vector<string_t> split(const string_t& reference_string)
14486 {
14487 std::vector<string_t> result;
14488
14489 // special case: empty reference string -> no reference tokens
14490 if (reference_string.empty())
14491 {
14492 return result;
14493 }
14494
14495 // check if nonempty reference string begins with slash
14496 if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
14497 {
14498 JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
14499 }
14500
14501 // extract the reference tokens:
14502 // - slash: position of the last read slash (or end of string)
14503 // - start: position after the previous slash
14504 for (
14505 // search for the first slash after the first character
14506 std::size_t slash = reference_string.find_first_of('/', 1),
14507 // set the beginning of the first reference token
14508 start = 1;
14509 // we can stop if start == 0 (if slash == string_t::npos)
14510 start != 0;
14511 // set the beginning of the next reference token
14512 // (will eventually be 0 if slash == string_t::npos)
14513 start = (slash == string_t::npos) ? 0 : slash + 1,
14514 // find next slash
14515 slash = reference_string.find_first_of('/', start))
14516 {
14517 // use the text between the beginning of the reference token
14518 // (start) and the last slash (slash).
14519 auto reference_token = reference_string.substr(start, slash - start);
14520
14521 // check reference tokens are properly escaped
14522 for (std::size_t pos = reference_token.find_first_of('~');
14523 pos != string_t::npos;
14524 pos = reference_token.find_first_of('~', pos + 1))
14525 {
14526 JSON_ASSERT(reference_token[pos] == '~');
14527
14528 // ~ must be followed by 0 or 1
14529 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
14530 (reference_token[pos + 1] != '0' &&
14531 reference_token[pos + 1] != '1')))
14532 {
14533 JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
14534 }
14535 }
14536
14537 // finally, store the reference token
14538 detail::unescape(reference_token);
14539 result.push_back(reference_token);
14540 }
14541
14542 return result;
14543 }
14544
14545 private:
14553 template<typename BasicJsonType>
14554 static void flatten(const string_t& reference_string,
14555 const BasicJsonType& value,
14556 BasicJsonType& result)
14557 {
14558 switch (value.type())
14559 {
14561 {
14562 if (value.m_data.m_value.array->empty())
14563 {
14564 // flatten empty array as null
14565 result[reference_string] = nullptr;
14566 }
14567 else
14568 {
14569 // iterate array and use index as reference string
14570 for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
14571 {
14572 flatten(detail::concat(reference_string, '/', std::to_string(i)),
14573 value.m_data.m_value.array->operator[](i), result);
14574 }
14575 }
14576 break;
14577 }
14578
14580 {
14581 if (value.m_data.m_value.object->empty())
14582 {
14583 // flatten empty object as null
14584 result[reference_string] = nullptr;
14585 }
14586 else
14587 {
14588 // iterate object and use keys as reference string
14589 for (const auto& element : *value.m_data.m_value.object)
14590 {
14591 flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
14592 }
14593 }
14594 break;
14595 }
14596
14605 default:
14606 {
14607 // add primitive value with its reference string
14608 result[reference_string] = value;
14609 break;
14610 }
14611 }
14612 }
14613
14624 template<typename BasicJsonType>
14625 static BasicJsonType
14626 unflatten(const BasicJsonType& value)
14627 {
14628 if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
14629 {
14630 JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
14631 }
14632
14633 BasicJsonType result;
14634
14635 // iterate the JSON object values
14636 for (const auto& element : *value.m_data.m_value.object)
14637 {
14638 if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
14639 {
14640 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
14641 }
14642
14643 // assign value to reference pointed to by JSON pointer; Note that if
14644 // the JSON pointer is "" (i.e., points to the whole value), function
14645 // get_and_create returns a reference to result itself. An assignment
14646 // will then create a primitive value.
14647 json_pointer(element.first).get_and_create(result) = element.second;
14648 }
14649
14650 return result;
14651 }
14652
14653 // can't use conversion operator because of ambiguity
14654 json_pointer<string_t> convert() const&
14655 {
14657 result.reference_tokens = reference_tokens;
14658 return result;
14659 }
14660
14661 json_pointer<string_t> convert()&&
14662 {
14664 result.reference_tokens = std::move(reference_tokens);
14665 return result;
14666 }
14667
14668 public:
14669#if JSON_HAS_THREE_WAY_COMPARISON
14672 template<typename RefStringTypeRhs>
14673 bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
14674 {
14675 return reference_tokens == rhs.reference_tokens;
14676 }
14677
14680 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
14681 bool operator==(const string_t& rhs) const
14682 {
14683 return *this == json_pointer(rhs);
14684 }
14685
14687 template<typename RefStringTypeRhs>
14688 std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
14689 {
14690 return reference_tokens <=> rhs.reference_tokens; // *NOPAD*
14691 }
14692#else
14695 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14696 // NOLINTNEXTLINE(readability-redundant-declaration)
14697 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14698 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14699
14702 template<typename RefStringTypeLhs, typename StringType>
14703 // NOLINTNEXTLINE(readability-redundant-declaration)
14704 friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14705 const StringType& rhs);
14706
14709 template<typename RefStringTypeRhs, typename StringType>
14710 // NOLINTNEXTLINE(readability-redundant-declaration)
14711 friend bool operator==(const StringType& lhs,
14713
14716 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14717 // NOLINTNEXTLINE(readability-redundant-declaration)
14718 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14719 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14720
14723 template<typename RefStringTypeLhs, typename StringType>
14724 // NOLINTNEXTLINE(readability-redundant-declaration)
14725 friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14726 const StringType& rhs);
14727
14730 template<typename RefStringTypeRhs, typename StringType>
14731 // NOLINTNEXTLINE(readability-redundant-declaration)
14732 friend bool operator!=(const StringType& lhs,
14734
14736 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14737 // NOLINTNEXTLINE(readability-redundant-declaration)
14738 friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14739 const json_pointer<RefStringTypeRhs>& rhs) noexcept;
14740#endif
14741
14742 private:
14744 std::vector<string_t> reference_tokens;
14745};
14746
14747#if !JSON_HAS_THREE_WAY_COMPARISON
14748// functions cannot be defined inside class due to ODR violations
14749template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14750inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14751 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14752{
14753 return lhs.reference_tokens == rhs.reference_tokens;
14754}
14755
14756template<typename RefStringTypeLhs,
14757 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14758JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14759inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
14760 const StringType& rhs)
14761{
14762 return lhs == json_pointer<RefStringTypeLhs>(rhs);
14763}
14764
14765template<typename RefStringTypeRhs,
14766 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14767JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
14768inline bool operator==(const StringType& lhs,
14769 const json_pointer<RefStringTypeRhs>& rhs)
14770{
14771 return json_pointer<RefStringTypeRhs>(lhs) == rhs;
14772}
14773
14774template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14775inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14776 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14777{
14778 return !(lhs == rhs);
14779}
14780
14781template<typename RefStringTypeLhs,
14782 typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
14783JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14784inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
14785 const StringType& rhs)
14786{
14787 return !(lhs == rhs);
14788}
14789
14790template<typename RefStringTypeRhs,
14791 typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
14792JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
14793inline bool operator!=(const StringType& lhs,
14794 const json_pointer<RefStringTypeRhs>& rhs)
14795{
14796 return !(lhs == rhs);
14797}
14798
14799template<typename RefStringTypeLhs, typename RefStringTypeRhs>
14800inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
14801 const json_pointer<RefStringTypeRhs>& rhs) noexcept
14802{
14803 return lhs.reference_tokens < rhs.reference_tokens;
14804}
14805#endif
14806
14807NLOHMANN_JSON_NAMESPACE_END
14808
14809// #include <nlohmann/detail/json_ref.hpp>
14810// __ _____ _____ _____
14811// __| | __| | | | JSON for Modern C++
14812// | | |__ | | | | | | version 3.11.3
14813// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14814//
14815// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14816// SPDX-License-Identifier: MIT
14817
14818
14819
14820#include <initializer_list>
14821#include <utility>
14822
14823// #include <nlohmann/detail/abi_macros.hpp>
14824
14825// #include <nlohmann/detail/meta/type_traits.hpp>
14826
14827
14828NLOHMANN_JSON_NAMESPACE_BEGIN
14829namespace detail
14830{
14831
14832template<typename BasicJsonType>
14834{
14835 public:
14836 using value_type = BasicJsonType;
14837
14838 json_ref(value_type&& value)
14839 : owned_value(std::move(value))
14840 {}
14841
14842 json_ref(const value_type& value)
14843 : value_ref(&value)
14844 {}
14845
14846 json_ref(std::initializer_list<json_ref> init)
14847 : owned_value(init)
14848 {}
14849
14850 template <
14851 class... Args,
14852 enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
14853 json_ref(Args && ... args)
14854 : owned_value(std::forward<Args>(args)...)
14855 {}
14856
14857 // class should be movable only
14858 json_ref(json_ref&&) noexcept = default;
14859 json_ref(const json_ref&) = delete;
14860 json_ref& operator=(const json_ref&) = delete;
14861 json_ref& operator=(json_ref&&) = delete;
14862 ~json_ref() = default;
14863
14864 value_type moved_or_copied() const
14865 {
14866 if (value_ref == nullptr)
14867 {
14868 return std::move(owned_value);
14869 }
14870 return *value_ref;
14871 }
14872
14873 value_type const& operator*() const
14874 {
14875 return value_ref ? *value_ref : owned_value;
14876 }
14877
14878 value_type const* operator->() const
14879 {
14880 return &** this;
14881 }
14882
14883 private:
14884 mutable value_type owned_value = nullptr;
14885 value_type const* value_ref = nullptr;
14886};
14887
14888} // namespace detail
14889NLOHMANN_JSON_NAMESPACE_END
14890
14891// #include <nlohmann/detail/macro_scope.hpp>
14892
14893// #include <nlohmann/detail/string_concat.hpp>
14894
14895// #include <nlohmann/detail/string_escape.hpp>
14896
14897// #include <nlohmann/detail/meta/cpp_future.hpp>
14898
14899// #include <nlohmann/detail/meta/type_traits.hpp>
14900
14901// #include <nlohmann/detail/output/binary_writer.hpp>
14902// __ _____ _____ _____
14903// __| | __| | | | JSON for Modern C++
14904// | | |__ | | | | | | version 3.11.3
14905// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14906//
14907// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14908// SPDX-License-Identifier: MIT
14909
14910
14911
14912#include <algorithm> // reverse
14913#include <array> // array
14914#include <map> // map
14915#include <cmath> // isnan, isinf
14916#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
14917#include <cstring> // memcpy
14918#include <limits> // numeric_limits
14919#include <string> // string
14920#include <utility> // move
14921#include <vector> // vector
14922
14923// #include <nlohmann/detail/input/binary_reader.hpp>
14924
14925// #include <nlohmann/detail/macro_scope.hpp>
14926
14927// #include <nlohmann/detail/output/output_adapters.hpp>
14928// __ _____ _____ _____
14929// __| | __| | | | JSON for Modern C++
14930// | | |__ | | | | | | version 3.11.3
14931// |_____|_____|_____|_|___| https://github.com/nlohmann/json
14932//
14933// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
14934// SPDX-License-Identifier: MIT
14935
14936
14937
14938#include <algorithm> // copy
14939#include <cstddef> // size_t
14940#include <iterator> // back_inserter
14941#include <memory> // shared_ptr, make_shared
14942#include <string> // basic_string
14943#include <vector> // vector
14944
14945#ifndef JSON_NO_IO
14946 #include <ios> // streamsize
14947 #include <ostream> // basic_ostream
14948#endif // JSON_NO_IO
14949
14950// #include <nlohmann/detail/macro_scope.hpp>
14951
14952
14953NLOHMANN_JSON_NAMESPACE_BEGIN
14954namespace detail
14955{
14956
14958template<typename CharType> struct output_adapter_protocol
14959{
14960 virtual void write_character(CharType c) = 0;
14961 virtual void write_characters(const CharType* s, std::size_t length) = 0;
14962 virtual ~output_adapter_protocol() = default;
14963
14964 output_adapter_protocol() = default;
14967 output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
14968 output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
14969};
14970
14972template<typename CharType>
14973using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
14974
14976template<typename CharType, typename AllocatorType = std::allocator<CharType>>
14978{
14979 public:
14980 explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
14981 : v(vec)
14982 {}
14983
14984 void write_character(CharType c) override
14985 {
14986 v.push_back(c);
14987 }
14988
14989 JSON_HEDLEY_NON_NULL(2)
14990 void write_characters(const CharType* s, std::size_t length) override
14991 {
14992 v.insert(v.end(), s, s + length);
14993 }
14994
14995 private:
14996 std::vector<CharType, AllocatorType>& v;
14997};
14998
14999#ifndef JSON_NO_IO
15001template<typename CharType>
15003{
15004 public:
15005 explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15006 : stream(s)
15007 {}
15008
15009 void write_character(CharType c) override
15010 {
15011 stream.put(c);
15012 }
15013
15014 JSON_HEDLEY_NON_NULL(2)
15015 void write_characters(const CharType* s, std::size_t length) override
15016 {
15017 stream.write(s, static_cast<std::streamsize>(length));
15018 }
15019
15020 private:
15021 std::basic_ostream<CharType>& stream;
15022};
15023#endif // JSON_NO_IO
15024
15026template<typename CharType, typename StringType = std::basic_string<CharType>>
15028{
15029 public:
15030 explicit output_string_adapter(StringType& s) noexcept
15031 : str(s)
15032 {}
15033
15034 void write_character(CharType c) override
15035 {
15036 str.push_back(c);
15037 }
15038
15039 JSON_HEDLEY_NON_NULL(2)
15040 void write_characters(const CharType* s, std::size_t length) override
15041 {
15042 str.append(s, length);
15043 }
15044
15045 private:
15046 StringType& str;
15047};
15048
15049template<typename CharType, typename StringType = std::basic_string<CharType>>
15051{
15052 public:
15053 template<typename AllocatorType = std::allocator<CharType>>
15054 output_adapter(std::vector<CharType, AllocatorType>& vec)
15055 : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15056
15057#ifndef JSON_NO_IO
15058 output_adapter(std::basic_ostream<CharType>& s)
15059 : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15060#endif // JSON_NO_IO
15061
15062 output_adapter(StringType& s)
15063 : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15064
15066 {
15067 return oa;
15068 }
15069
15070 private:
15071 output_adapter_t<CharType> oa = nullptr;
15072};
15073
15074} // namespace detail
15075NLOHMANN_JSON_NAMESPACE_END
15076
15077// #include <nlohmann/detail/string_concat.hpp>
15078
15079
15080NLOHMANN_JSON_NAMESPACE_BEGIN
15081namespace detail
15082{
15083
15085// binary writer //
15087
15091template<typename BasicJsonType, typename CharType>
15093{
15094 using string_t = typename BasicJsonType::string_t;
15095 using binary_t = typename BasicJsonType::binary_t;
15096 using number_float_t = typename BasicJsonType::number_float_t;
15097
15098 public:
15104 explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15105 {
15106 JSON_ASSERT(oa);
15107 }
15108
15113 void write_bson(const BasicJsonType& j)
15114 {
15115 switch (j.type())
15116 {
15117 case value_t::object:
15118 {
15119 write_bson_object(*j.m_data.m_value.object);
15120 break;
15121 }
15122
15123 case value_t::null:
15124 case value_t::array:
15125 case value_t::string:
15126 case value_t::boolean:
15127 case value_t::number_integer:
15128 case value_t::number_unsigned:
15129 case value_t::number_float:
15130 case value_t::binary:
15131 case value_t::discarded:
15132 default:
15133 {
15134 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15135 }
15136 }
15137 }
15138
15142 void write_cbor(const BasicJsonType& j)
15143 {
15144 switch (j.type())
15145 {
15146 case value_t::null:
15147 {
15148 oa->write_character(to_char_type(0xF6));
15149 break;
15150 }
15151
15152 case value_t::boolean:
15153 {
15154 oa->write_character(j.m_data.m_value.boolean
15155 ? to_char_type(0xF5)
15156 : to_char_type(0xF4));
15157 break;
15158 }
15159
15160 case value_t::number_integer:
15161 {
15162 if (j.m_data.m_value.number_integer >= 0)
15163 {
15164 // CBOR does not differentiate between positive signed
15165 // integers and unsigned integers. Therefore, we used the
15166 // code from the value_t::number_unsigned case here.
15167 if (j.m_data.m_value.number_integer <= 0x17)
15168 {
15169 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15170 }
15171 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15172 {
15173 oa->write_character(to_char_type(0x18));
15174 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15175 }
15176 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15177 {
15178 oa->write_character(to_char_type(0x19));
15179 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15180 }
15181 else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15182 {
15183 oa->write_character(to_char_type(0x1A));
15184 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15185 }
15186 else
15187 {
15188 oa->write_character(to_char_type(0x1B));
15189 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15190 }
15191 }
15192 else
15193 {
15194 // The conversions below encode the sign in the first
15195 // byte, and the value is converted to a positive number.
15196 const auto positive_number = -1 - j.m_data.m_value.number_integer;
15197 if (j.m_data.m_value.number_integer >= -24)
15198 {
15199 write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15200 }
15201 else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15202 {
15203 oa->write_character(to_char_type(0x38));
15204 write_number(static_cast<std::uint8_t>(positive_number));
15205 }
15206 else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15207 {
15208 oa->write_character(to_char_type(0x39));
15209 write_number(static_cast<std::uint16_t>(positive_number));
15210 }
15211 else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15212 {
15213 oa->write_character(to_char_type(0x3A));
15214 write_number(static_cast<std::uint32_t>(positive_number));
15215 }
15216 else
15217 {
15218 oa->write_character(to_char_type(0x3B));
15219 write_number(static_cast<std::uint64_t>(positive_number));
15220 }
15221 }
15222 break;
15223 }
15224
15225 case value_t::number_unsigned:
15226 {
15227 if (j.m_data.m_value.number_unsigned <= 0x17)
15228 {
15229 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15230 }
15231 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15232 {
15233 oa->write_character(to_char_type(0x18));
15234 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15235 }
15236 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15237 {
15238 oa->write_character(to_char_type(0x19));
15239 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15240 }
15241 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15242 {
15243 oa->write_character(to_char_type(0x1A));
15244 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15245 }
15246 else
15247 {
15248 oa->write_character(to_char_type(0x1B));
15249 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15250 }
15251 break;
15252 }
15253
15254 case value_t::number_float:
15255 {
15256 if (std::isnan(j.m_data.m_value.number_float))
15257 {
15258 // NaN is 0xf97e00 in CBOR
15259 oa->write_character(to_char_type(0xF9));
15260 oa->write_character(to_char_type(0x7E));
15261 oa->write_character(to_char_type(0x00));
15262 }
15263 else if (std::isinf(j.m_data.m_value.number_float))
15264 {
15265 // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15266 oa->write_character(to_char_type(0xf9));
15267 oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15268 oa->write_character(to_char_type(0x00));
15269 }
15270 else
15271 {
15272 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15273 }
15274 break;
15275 }
15276
15277 case value_t::string:
15278 {
15279 // step 1: write control byte and the string length
15280 const auto N = j.m_data.m_value.string->size();
15281 if (N <= 0x17)
15282 {
15283 write_number(static_cast<std::uint8_t>(0x60 + N));
15284 }
15285 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15286 {
15287 oa->write_character(to_char_type(0x78));
15288 write_number(static_cast<std::uint8_t>(N));
15289 }
15290 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15291 {
15292 oa->write_character(to_char_type(0x79));
15293 write_number(static_cast<std::uint16_t>(N));
15294 }
15295 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15296 {
15297 oa->write_character(to_char_type(0x7A));
15298 write_number(static_cast<std::uint32_t>(N));
15299 }
15300 // LCOV_EXCL_START
15301 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15302 {
15303 oa->write_character(to_char_type(0x7B));
15304 write_number(static_cast<std::uint64_t>(N));
15305 }
15306 // LCOV_EXCL_STOP
15307
15308 // step 2: write the string
15309 oa->write_characters(
15310 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15311 j.m_data.m_value.string->size());
15312 break;
15313 }
15314
15315 case value_t::array:
15316 {
15317 // step 1: write control byte and the array size
15318 const auto N = j.m_data.m_value.array->size();
15319 if (N <= 0x17)
15320 {
15321 write_number(static_cast<std::uint8_t>(0x80 + N));
15322 }
15323 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15324 {
15325 oa->write_character(to_char_type(0x98));
15326 write_number(static_cast<std::uint8_t>(N));
15327 }
15328 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15329 {
15330 oa->write_character(to_char_type(0x99));
15331 write_number(static_cast<std::uint16_t>(N));
15332 }
15333 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15334 {
15335 oa->write_character(to_char_type(0x9A));
15336 write_number(static_cast<std::uint32_t>(N));
15337 }
15338 // LCOV_EXCL_START
15339 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15340 {
15341 oa->write_character(to_char_type(0x9B));
15342 write_number(static_cast<std::uint64_t>(N));
15343 }
15344 // LCOV_EXCL_STOP
15345
15346 // step 2: write each element
15347 for (const auto& el : *j.m_data.m_value.array)
15348 {
15349 write_cbor(el);
15350 }
15351 break;
15352 }
15353
15354 case value_t::binary:
15355 {
15356 if (j.m_data.m_value.binary->has_subtype())
15357 {
15358 if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
15359 {
15360 write_number(static_cast<std::uint8_t>(0xd8));
15361 write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
15362 }
15363 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
15364 {
15365 write_number(static_cast<std::uint8_t>(0xd9));
15366 write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
15367 }
15368 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
15369 {
15370 write_number(static_cast<std::uint8_t>(0xda));
15371 write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
15372 }
15373 else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
15374 {
15375 write_number(static_cast<std::uint8_t>(0xdb));
15376 write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
15377 }
15378 }
15379
15380 // step 1: write control byte and the binary array size
15381 const auto N = j.m_data.m_value.binary->size();
15382 if (N <= 0x17)
15383 {
15384 write_number(static_cast<std::uint8_t>(0x40 + N));
15385 }
15386 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15387 {
15388 oa->write_character(to_char_type(0x58));
15389 write_number(static_cast<std::uint8_t>(N));
15390 }
15391 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15392 {
15393 oa->write_character(to_char_type(0x59));
15394 write_number(static_cast<std::uint16_t>(N));
15395 }
15396 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15397 {
15398 oa->write_character(to_char_type(0x5A));
15399 write_number(static_cast<std::uint32_t>(N));
15400 }
15401 // LCOV_EXCL_START
15402 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15403 {
15404 oa->write_character(to_char_type(0x5B));
15405 write_number(static_cast<std::uint64_t>(N));
15406 }
15407 // LCOV_EXCL_STOP
15408
15409 // step 2: write each element
15410 oa->write_characters(
15411 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15412 N);
15413
15414 break;
15415 }
15416
15417 case value_t::object:
15418 {
15419 // step 1: write control byte and the object size
15420 const auto N = j.m_data.m_value.object->size();
15421 if (N <= 0x17)
15422 {
15423 write_number(static_cast<std::uint8_t>(0xA0 + N));
15424 }
15425 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15426 {
15427 oa->write_character(to_char_type(0xB8));
15428 write_number(static_cast<std::uint8_t>(N));
15429 }
15430 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15431 {
15432 oa->write_character(to_char_type(0xB9));
15433 write_number(static_cast<std::uint16_t>(N));
15434 }
15435 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15436 {
15437 oa->write_character(to_char_type(0xBA));
15438 write_number(static_cast<std::uint32_t>(N));
15439 }
15440 // LCOV_EXCL_START
15441 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15442 {
15443 oa->write_character(to_char_type(0xBB));
15444 write_number(static_cast<std::uint64_t>(N));
15445 }
15446 // LCOV_EXCL_STOP
15447
15448 // step 2: write each element
15449 for (const auto& el : *j.m_data.m_value.object)
15450 {
15451 write_cbor(el.first);
15452 write_cbor(el.second);
15453 }
15454 break;
15455 }
15456
15457 case value_t::discarded:
15458 default:
15459 break;
15460 }
15461 }
15462
15466 void write_msgpack(const BasicJsonType& j)
15467 {
15468 switch (j.type())
15469 {
15470 case value_t::null: // nil
15471 {
15472 oa->write_character(to_char_type(0xC0));
15473 break;
15474 }
15475
15476 case value_t::boolean: // true and false
15477 {
15478 oa->write_character(j.m_data.m_value.boolean
15479 ? to_char_type(0xC3)
15480 : to_char_type(0xC2));
15481 break;
15482 }
15483
15484 case value_t::number_integer:
15485 {
15486 if (j.m_data.m_value.number_integer >= 0)
15487 {
15488 // MessagePack does not differentiate between positive
15489 // signed integers and unsigned integers. Therefore, we used
15490 // the code from the value_t::number_unsigned case here.
15491 if (j.m_data.m_value.number_unsigned < 128)
15492 {
15493 // positive fixnum
15494 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15495 }
15496 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15497 {
15498 // uint 8
15499 oa->write_character(to_char_type(0xCC));
15500 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15501 }
15502 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15503 {
15504 // uint 16
15505 oa->write_character(to_char_type(0xCD));
15506 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15507 }
15508 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15509 {
15510 // uint 32
15511 oa->write_character(to_char_type(0xCE));
15512 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15513 }
15514 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15515 {
15516 // uint 64
15517 oa->write_character(to_char_type(0xCF));
15518 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15519 }
15520 }
15521 else
15522 {
15523 if (j.m_data.m_value.number_integer >= -32)
15524 {
15525 // negative fixnum
15526 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15527 }
15528 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
15529 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
15530 {
15531 // int 8
15532 oa->write_character(to_char_type(0xD0));
15533 write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
15534 }
15535 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
15536 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
15537 {
15538 // int 16
15539 oa->write_character(to_char_type(0xD1));
15540 write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
15541 }
15542 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
15543 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
15544 {
15545 // int 32
15546 oa->write_character(to_char_type(0xD2));
15547 write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
15548 }
15549 else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
15550 j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
15551 {
15552 // int 64
15553 oa->write_character(to_char_type(0xD3));
15554 write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
15555 }
15556 }
15557 break;
15558 }
15559
15560 case value_t::number_unsigned:
15561 {
15562 if (j.m_data.m_value.number_unsigned < 128)
15563 {
15564 // positive fixnum
15565 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15566 }
15567 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15568 {
15569 // uint 8
15570 oa->write_character(to_char_type(0xCC));
15571 write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15572 }
15573 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15574 {
15575 // uint 16
15576 oa->write_character(to_char_type(0xCD));
15577 write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15578 }
15579 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15580 {
15581 // uint 32
15582 oa->write_character(to_char_type(0xCE));
15583 write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15584 }
15585 else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
15586 {
15587 // uint 64
15588 oa->write_character(to_char_type(0xCF));
15589 write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15590 }
15591 break;
15592 }
15593
15594 case value_t::number_float:
15595 {
15596 write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
15597 break;
15598 }
15599
15600 case value_t::string:
15601 {
15602 // step 1: write control byte and the string length
15603 const auto N = j.m_data.m_value.string->size();
15604 if (N <= 31)
15605 {
15606 // fixstr
15607 write_number(static_cast<std::uint8_t>(0xA0 | N));
15608 }
15609 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15610 {
15611 // str 8
15612 oa->write_character(to_char_type(0xD9));
15613 write_number(static_cast<std::uint8_t>(N));
15614 }
15615 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15616 {
15617 // str 16
15618 oa->write_character(to_char_type(0xDA));
15619 write_number(static_cast<std::uint16_t>(N));
15620 }
15621 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15622 {
15623 // str 32
15624 oa->write_character(to_char_type(0xDB));
15625 write_number(static_cast<std::uint32_t>(N));
15626 }
15627
15628 // step 2: write the string
15629 oa->write_characters(
15630 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15631 j.m_data.m_value.string->size());
15632 break;
15633 }
15634
15635 case value_t::array:
15636 {
15637 // step 1: write control byte and the array size
15638 const auto N = j.m_data.m_value.array->size();
15639 if (N <= 15)
15640 {
15641 // fixarray
15642 write_number(static_cast<std::uint8_t>(0x90 | N));
15643 }
15644 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15645 {
15646 // array 16
15647 oa->write_character(to_char_type(0xDC));
15648 write_number(static_cast<std::uint16_t>(N));
15649 }
15650 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15651 {
15652 // array 32
15653 oa->write_character(to_char_type(0xDD));
15654 write_number(static_cast<std::uint32_t>(N));
15655 }
15656
15657 // step 2: write each element
15658 for (const auto& el : *j.m_data.m_value.array)
15659 {
15660 write_msgpack(el);
15661 }
15662 break;
15663 }
15664
15665 case value_t::binary:
15666 {
15667 // step 0: determine if the binary type has a set subtype to
15668 // determine whether or not to use the ext or fixext types
15669 const bool use_ext = j.m_data.m_value.binary->has_subtype();
15670
15671 // step 1: write control byte and the byte string length
15672 const auto N = j.m_data.m_value.binary->size();
15673 if (N <= (std::numeric_limits<std::uint8_t>::max)())
15674 {
15675 std::uint8_t output_type{};
15676 bool fixed = true;
15677 if (use_ext)
15678 {
15679 switch (N)
15680 {
15681 case 1:
15682 output_type = 0xD4; // fixext 1
15683 break;
15684 case 2:
15685 output_type = 0xD5; // fixext 2
15686 break;
15687 case 4:
15688 output_type = 0xD6; // fixext 4
15689 break;
15690 case 8:
15691 output_type = 0xD7; // fixext 8
15692 break;
15693 case 16:
15694 output_type = 0xD8; // fixext 16
15695 break;
15696 default:
15697 output_type = 0xC7; // ext 8
15698 fixed = false;
15699 break;
15700 }
15701
15702 }
15703 else
15704 {
15705 output_type = 0xC4; // bin 8
15706 fixed = false;
15707 }
15708
15709 oa->write_character(to_char_type(output_type));
15710 if (!fixed)
15711 {
15712 write_number(static_cast<std::uint8_t>(N));
15713 }
15714 }
15715 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15716 {
15717 const std::uint8_t output_type = use_ext
15718 ? 0xC8 // ext 16
15719 : 0xC5; // bin 16
15720
15721 oa->write_character(to_char_type(output_type));
15722 write_number(static_cast<std::uint16_t>(N));
15723 }
15724 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15725 {
15726 const std::uint8_t output_type = use_ext
15727 ? 0xC9 // ext 32
15728 : 0xC6; // bin 32
15729
15730 oa->write_character(to_char_type(output_type));
15731 write_number(static_cast<std::uint32_t>(N));
15732 }
15733
15734 // step 1.5: if this is an ext type, write the subtype
15735 if (use_ext)
15736 {
15737 write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
15738 }
15739
15740 // step 2: write the byte string
15741 oa->write_characters(
15742 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15743 N);
15744
15745 break;
15746 }
15747
15748 case value_t::object:
15749 {
15750 // step 1: write control byte and the object size
15751 const auto N = j.m_data.m_value.object->size();
15752 if (N <= 15)
15753 {
15754 // fixmap
15755 write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
15756 }
15757 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15758 {
15759 // map 16
15760 oa->write_character(to_char_type(0xDE));
15761 write_number(static_cast<std::uint16_t>(N));
15762 }
15763 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15764 {
15765 // map 32
15766 oa->write_character(to_char_type(0xDF));
15767 write_number(static_cast<std::uint32_t>(N));
15768 }
15769
15770 // step 2: write each element
15771 for (const auto& el : *j.m_data.m_value.object)
15772 {
15773 write_msgpack(el.first);
15774 write_msgpack(el.second);
15775 }
15776 break;
15777 }
15778
15779 case value_t::discarded:
15780 default:
15781 break;
15782 }
15783 }
15784
15792 void write_ubjson(const BasicJsonType& j, const bool use_count,
15793 const bool use_type, const bool add_prefix = true,
15794 const bool use_bjdata = false)
15795 {
15796 switch (j.type())
15797 {
15798 case value_t::null:
15799 {
15800 if (add_prefix)
15801 {
15802 oa->write_character(to_char_type('Z'));
15803 }
15804 break;
15805 }
15806
15807 case value_t::boolean:
15808 {
15809 if (add_prefix)
15810 {
15811 oa->write_character(j.m_data.m_value.boolean
15812 ? to_char_type('T')
15813 : to_char_type('F'));
15814 }
15815 break;
15816 }
15817
15818 case value_t::number_integer:
15819 {
15820 write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
15821 break;
15822 }
15823
15824 case value_t::number_unsigned:
15825 {
15826 write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
15827 break;
15828 }
15829
15830 case value_t::number_float:
15831 {
15832 write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
15833 break;
15834 }
15835
15836 case value_t::string:
15837 {
15838 if (add_prefix)
15839 {
15840 oa->write_character(to_char_type('S'));
15841 }
15842 write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
15843 oa->write_characters(
15844 reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
15845 j.m_data.m_value.string->size());
15846 break;
15847 }
15848
15849 case value_t::array:
15850 {
15851 if (add_prefix)
15852 {
15853 oa->write_character(to_char_type('['));
15854 }
15855
15856 bool prefix_required = true;
15857 if (use_type && !j.m_data.m_value.array->empty())
15858 {
15859 JSON_ASSERT(use_count);
15860 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15861 const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
15862 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15863 {
15864 return ubjson_prefix(v, use_bjdata) == first_prefix;
15865 });
15866
15867 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15868
15869 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15870 {
15871 prefix_required = false;
15872 oa->write_character(to_char_type('$'));
15873 oa->write_character(first_prefix);
15874 }
15875 }
15876
15877 if (use_count)
15878 {
15879 oa->write_character(to_char_type('#'));
15880 write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
15881 }
15882
15883 for (const auto& el : *j.m_data.m_value.array)
15884 {
15885 write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
15886 }
15887
15888 if (!use_count)
15889 {
15890 oa->write_character(to_char_type(']'));
15891 }
15892
15893 break;
15894 }
15895
15896 case value_t::binary:
15897 {
15898 if (add_prefix)
15899 {
15900 oa->write_character(to_char_type('['));
15901 }
15902
15903 if (use_type && !j.m_data.m_value.binary->empty())
15904 {
15905 JSON_ASSERT(use_count);
15906 oa->write_character(to_char_type('$'));
15907 oa->write_character('U');
15908 }
15909
15910 if (use_count)
15911 {
15912 oa->write_character(to_char_type('#'));
15913 write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
15914 }
15915
15916 if (use_type)
15917 {
15918 oa->write_characters(
15919 reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
15920 j.m_data.m_value.binary->size());
15921 }
15922 else
15923 {
15924 for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
15925 {
15926 oa->write_character(to_char_type('U'));
15927 oa->write_character(j.m_data.m_value.binary->data()[i]);
15928 }
15929 }
15930
15931 if (!use_count)
15932 {
15933 oa->write_character(to_char_type(']'));
15934 }
15935
15936 break;
15937 }
15938
15939 case value_t::object:
15940 {
15941 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())
15942 {
15943 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)
15944 {
15945 break;
15946 }
15947 }
15948
15949 if (add_prefix)
15950 {
15951 oa->write_character(to_char_type('{'));
15952 }
15953
15954 bool prefix_required = true;
15955 if (use_type && !j.m_data.m_value.object->empty())
15956 {
15957 JSON_ASSERT(use_count);
15958 const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
15959 const bool same_prefix = std::all_of(j.begin(), j.end(),
15960 [this, first_prefix, use_bjdata](const BasicJsonType & v)
15961 {
15962 return ubjson_prefix(v, use_bjdata) == first_prefix;
15963 });
15964
15965 std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
15966
15967 if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
15968 {
15969 prefix_required = false;
15970 oa->write_character(to_char_type('$'));
15971 oa->write_character(first_prefix);
15972 }
15973 }
15974
15975 if (use_count)
15976 {
15977 oa->write_character(to_char_type('#'));
15978 write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
15979 }
15980
15981 for (const auto& el : *j.m_data.m_value.object)
15982 {
15983 write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
15984 oa->write_characters(
15985 reinterpret_cast<const CharType*>(el.first.c_str()),
15986 el.first.size());
15987 write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
15988 }
15989
15990 if (!use_count)
15991 {
15992 oa->write_character(to_char_type('}'));
15993 }
15994
15995 break;
15996 }
15997
15998 case value_t::discarded:
15999 default:
16000 break;
16001 }
16002 }
16003
16004 private:
16006 // BSON //
16008
16013 static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16014 {
16015 const auto it = name.find(static_cast<typename string_t::value_type>(0));
16016 if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16017 {
16018 JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16019 static_cast<void>(j);
16020 }
16021
16022 return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16023 }
16024
16028 void write_bson_entry_header(const string_t& name,
16029 const std::uint8_t element_type)
16030 {
16031 oa->write_character(to_char_type(element_type)); // boolean
16032 oa->write_characters(
16033 reinterpret_cast<const CharType*>(name.c_str()),
16034 name.size() + 1u);
16035 }
16036
16040 void write_bson_boolean(const string_t& name,
16041 const bool value)
16042 {
16043 write_bson_entry_header(name, 0x08);
16044 oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16045 }
16046
16050 void write_bson_double(const string_t& name,
16051 const double value)
16052 {
16053 write_bson_entry_header(name, 0x01);
16054 write_number<double>(value, true);
16055 }
16056
16060 static std::size_t calc_bson_string_size(const string_t& value)
16061 {
16062 return sizeof(std::int32_t) + value.size() + 1ul;
16063 }
16064
16068 void write_bson_string(const string_t& name,
16069 const string_t& value)
16070 {
16071 write_bson_entry_header(name, 0x02);
16072
16073 write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16074 oa->write_characters(
16075 reinterpret_cast<const CharType*>(value.c_str()),
16076 value.size() + 1);
16077 }
16078
16082 void write_bson_null(const string_t& name)
16083 {
16084 write_bson_entry_header(name, 0x0A);
16085 }
16086
16090 static std::size_t calc_bson_integer_size(const std::int64_t value)
16091 {
16092 return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16093 ? sizeof(std::int32_t)
16094 : sizeof(std::int64_t);
16095 }
16096
16100 void write_bson_integer(const string_t& name,
16101 const std::int64_t value)
16102 {
16103 if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16104 {
16105 write_bson_entry_header(name, 0x10); // int32
16106 write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16107 }
16108 else
16109 {
16110 write_bson_entry_header(name, 0x12); // int64
16111 write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16112 }
16113 }
16114
16118 static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16119 {
16120 return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16121 ? sizeof(std::int32_t)
16122 : sizeof(std::int64_t);
16123 }
16124
16128 void write_bson_unsigned(const string_t& name,
16129 const BasicJsonType& j)
16130 {
16131 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16132 {
16133 write_bson_entry_header(name, 0x10 /* int32 */);
16134 write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16135 }
16136 else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16137 {
16138 write_bson_entry_header(name, 0x12 /* int64 */);
16139 write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16140 }
16141 else
16142 {
16143 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));
16144 }
16145 }
16146
16150 void write_bson_object_entry(const string_t& name,
16151 const typename BasicJsonType::object_t& value)
16152 {
16153 write_bson_entry_header(name, 0x03); // object
16154 write_bson_object(value);
16155 }
16156
16160 static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16161 {
16162 std::size_t array_index = 0ul;
16163
16164 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)
16165 {
16166 return result + calc_bson_element_size(std::to_string(array_index++), el);
16167 });
16168
16169 return sizeof(std::int32_t) + embedded_document_size + 1ul;
16170 }
16171
16175 static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16176 {
16177 return sizeof(std::int32_t) + value.size() + 1ul;
16178 }
16179
16183 void write_bson_array(const string_t& name,
16184 const typename BasicJsonType::array_t& value)
16185 {
16186 write_bson_entry_header(name, 0x04); // array
16187 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16188
16189 std::size_t array_index = 0ul;
16190
16191 for (const auto& el : value)
16192 {
16193 write_bson_element(std::to_string(array_index++), el);
16194 }
16195
16196 oa->write_character(to_char_type(0x00));
16197 }
16198
16202 void write_bson_binary(const string_t& name,
16203 const binary_t& value)
16204 {
16205 write_bson_entry_header(name, 0x05);
16206
16207 write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16208 write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16209
16210 oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16211 }
16212
16217 static std::size_t calc_bson_element_size(const string_t& name,
16218 const BasicJsonType& j)
16219 {
16220 const auto header_size = calc_bson_entry_header_size(name, j);
16221 switch (j.type())
16222 {
16223 case value_t::object:
16224 return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16225
16226 case value_t::array:
16227 return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16228
16229 case value_t::binary:
16230 return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16231
16232 case value_t::boolean:
16233 return header_size + 1ul;
16234
16235 case value_t::number_float:
16236 return header_size + 8ul;
16237
16238 case value_t::number_integer:
16239 return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16240
16241 case value_t::number_unsigned:
16242 return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16243
16244 case value_t::string:
16245 return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16246
16247 case value_t::null:
16248 return header_size + 0ul;
16249
16250 // LCOV_EXCL_START
16251 case value_t::discarded:
16252 default:
16253 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16254 return 0ul;
16255 // LCOV_EXCL_STOP
16256 }
16257 }
16258
16265 void write_bson_element(const string_t& name,
16266 const BasicJsonType& j)
16267 {
16268 switch (j.type())
16269 {
16270 case value_t::object:
16271 return write_bson_object_entry(name, *j.m_data.m_value.object);
16272
16273 case value_t::array:
16274 return write_bson_array(name, *j.m_data.m_value.array);
16275
16276 case value_t::binary:
16277 return write_bson_binary(name, *j.m_data.m_value.binary);
16278
16279 case value_t::boolean:
16280 return write_bson_boolean(name, j.m_data.m_value.boolean);
16281
16282 case value_t::number_float:
16283 return write_bson_double(name, j.m_data.m_value.number_float);
16284
16285 case value_t::number_integer:
16286 return write_bson_integer(name, j.m_data.m_value.number_integer);
16287
16288 case value_t::number_unsigned:
16289 return write_bson_unsigned(name, j);
16290
16291 case value_t::string:
16292 return write_bson_string(name, *j.m_data.m_value.string);
16293
16294 case value_t::null:
16295 return write_bson_null(name);
16296
16297 // LCOV_EXCL_START
16298 case value_t::discarded:
16299 default:
16300 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16301 return;
16302 // LCOV_EXCL_STOP
16303 }
16304 }
16305
16312 static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
16313 {
16314 const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
16315 [](size_t result, const typename BasicJsonType::object_t::value_type & el)
16316 {
16317 return result += calc_bson_element_size(el.first, el.second);
16318 });
16319
16320 return sizeof(std::int32_t) + document_size + 1ul;
16321 }
16322
16327 void write_bson_object(const typename BasicJsonType::object_t& value)
16328 {
16329 write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
16330
16331 for (const auto& el : value)
16332 {
16333 write_bson_element(el.first, el.second);
16334 }
16335
16336 oa->write_character(to_char_type(0x00));
16337 }
16338
16340 // CBOR //
16342
16343 static constexpr CharType get_cbor_float_prefix(float /*unused*/)
16344 {
16345 return to_char_type(0xFA); // Single-Precision Float
16346 }
16347
16348 static constexpr CharType get_cbor_float_prefix(double /*unused*/)
16349 {
16350 return to_char_type(0xFB); // Double-Precision Float
16351 }
16352
16354 // MsgPack //
16356
16357 static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
16358 {
16359 return to_char_type(0xCA); // float 32
16360 }
16361
16362 static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
16363 {
16364 return to_char_type(0xCB); // float 64
16365 }
16366
16368 // UBJSON //
16370
16371 // UBJSON: write number (floating point)
16372 template<typename NumberType, typename std::enable_if<
16373 std::is_floating_point<NumberType>::value, int>::type = 0>
16374 void write_number_with_ubjson_prefix(const NumberType n,
16375 const bool add_prefix,
16376 const bool use_bjdata)
16377 {
16378 if (add_prefix)
16379 {
16380 oa->write_character(get_ubjson_float_prefix(n));
16381 }
16382 write_number(n, use_bjdata);
16383 }
16384
16385 // UBJSON: write number (unsigned integer)
16386 template<typename NumberType, typename std::enable_if<
16387 std::is_unsigned<NumberType>::value, int>::type = 0>
16388 void write_number_with_ubjson_prefix(const NumberType n,
16389 const bool add_prefix,
16390 const bool use_bjdata)
16391 {
16392 if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16393 {
16394 if (add_prefix)
16395 {
16396 oa->write_character(to_char_type('i')); // int8
16397 }
16398 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16399 }
16400 else if (n <= (std::numeric_limits<std::uint8_t>::max)())
16401 {
16402 if (add_prefix)
16403 {
16404 oa->write_character(to_char_type('U')); // uint8
16405 }
16406 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16407 }
16408 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16409 {
16410 if (add_prefix)
16411 {
16412 oa->write_character(to_char_type('I')); // int16
16413 }
16414 write_number(static_cast<std::int16_t>(n), use_bjdata);
16415 }
16416 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
16417 {
16418 if (add_prefix)
16419 {
16420 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16421 }
16422 write_number(static_cast<std::uint16_t>(n), use_bjdata);
16423 }
16424 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16425 {
16426 if (add_prefix)
16427 {
16428 oa->write_character(to_char_type('l')); // int32
16429 }
16430 write_number(static_cast<std::int32_t>(n), use_bjdata);
16431 }
16432 else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
16433 {
16434 if (add_prefix)
16435 {
16436 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16437 }
16438 write_number(static_cast<std::uint32_t>(n), use_bjdata);
16439 }
16440 else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16441 {
16442 if (add_prefix)
16443 {
16444 oa->write_character(to_char_type('L')); // int64
16445 }
16446 write_number(static_cast<std::int64_t>(n), use_bjdata);
16447 }
16448 else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
16449 {
16450 if (add_prefix)
16451 {
16452 oa->write_character(to_char_type('M')); // uint64 - bjdata only
16453 }
16454 write_number(static_cast<std::uint64_t>(n), use_bjdata);
16455 }
16456 else
16457 {
16458 if (add_prefix)
16459 {
16460 oa->write_character(to_char_type('H')); // high-precision number
16461 }
16462
16463 const auto number = BasicJsonType(n).dump();
16464 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16465 for (std::size_t i = 0; i < number.size(); ++i)
16466 {
16467 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16468 }
16469 }
16470 }
16471
16472 // UBJSON: write number (signed integer)
16473 template < typename NumberType, typename std::enable_if <
16474 std::is_signed<NumberType>::value&&
16475 !std::is_floating_point<NumberType>::value, int >::type = 0 >
16476 void write_number_with_ubjson_prefix(const NumberType n,
16477 const bool add_prefix,
16478 const bool use_bjdata)
16479 {
16480 if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
16481 {
16482 if (add_prefix)
16483 {
16484 oa->write_character(to_char_type('i')); // int8
16485 }
16486 write_number(static_cast<std::int8_t>(n), use_bjdata);
16487 }
16488 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)()))
16489 {
16490 if (add_prefix)
16491 {
16492 oa->write_character(to_char_type('U')); // uint8
16493 }
16494 write_number(static_cast<std::uint8_t>(n), use_bjdata);
16495 }
16496 else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
16497 {
16498 if (add_prefix)
16499 {
16500 oa->write_character(to_char_type('I')); // int16
16501 }
16502 write_number(static_cast<std::int16_t>(n), use_bjdata);
16503 }
16504 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)())))
16505 {
16506 if (add_prefix)
16507 {
16508 oa->write_character(to_char_type('u')); // uint16 - bjdata only
16509 }
16510 write_number(static_cast<uint16_t>(n), use_bjdata);
16511 }
16512 else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
16513 {
16514 if (add_prefix)
16515 {
16516 oa->write_character(to_char_type('l')); // int32
16517 }
16518 write_number(static_cast<std::int32_t>(n), use_bjdata);
16519 }
16520 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)())))
16521 {
16522 if (add_prefix)
16523 {
16524 oa->write_character(to_char_type('m')); // uint32 - bjdata only
16525 }
16526 write_number(static_cast<uint32_t>(n), use_bjdata);
16527 }
16528 else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
16529 {
16530 if (add_prefix)
16531 {
16532 oa->write_character(to_char_type('L')); // int64
16533 }
16534 write_number(static_cast<std::int64_t>(n), use_bjdata);
16535 }
16536 // LCOV_EXCL_START
16537 else
16538 {
16539 if (add_prefix)
16540 {
16541 oa->write_character(to_char_type('H')); // high-precision number
16542 }
16543
16544 const auto number = BasicJsonType(n).dump();
16545 write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
16546 for (std::size_t i = 0; i < number.size(); ++i)
16547 {
16548 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
16549 }
16550 }
16551 // LCOV_EXCL_STOP
16552 }
16553
16557 CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
16558 {
16559 switch (j.type())
16560 {
16561 case value_t::null:
16562 return 'Z';
16563
16564 case value_t::boolean:
16565 return j.m_data.m_value.boolean ? 'T' : 'F';
16566
16567 case value_t::number_integer:
16568 {
16569 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)())
16570 {
16571 return 'i';
16572 }
16573 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)())
16574 {
16575 return 'U';
16576 }
16577 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)())
16578 {
16579 return 'I';
16580 }
16581 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)()))
16582 {
16583 return 'u';
16584 }
16585 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)())
16586 {
16587 return 'l';
16588 }
16589 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)()))
16590 {
16591 return 'm';
16592 }
16593 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)())
16594 {
16595 return 'L';
16596 }
16597 // anything else is treated as high-precision number
16598 return 'H'; // LCOV_EXCL_LINE
16599 }
16600
16601 case value_t::number_unsigned:
16602 {
16603 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
16604 {
16605 return 'i';
16606 }
16607 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
16608 {
16609 return 'U';
16610 }
16611 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
16612 {
16613 return 'I';
16614 }
16615 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
16616 {
16617 return 'u';
16618 }
16619 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16620 {
16621 return 'l';
16622 }
16623 if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
16624 {
16625 return 'm';
16626 }
16627 if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16628 {
16629 return 'L';
16630 }
16631 if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16632 {
16633 return 'M';
16634 }
16635 // anything else is treated as high-precision number
16636 return 'H'; // LCOV_EXCL_LINE
16637 }
16638
16639 case value_t::number_float:
16640 return get_ubjson_float_prefix(j.m_data.m_value.number_float);
16641
16642 case value_t::string:
16643 return 'S';
16644
16645 case value_t::array: // fallthrough
16646 case value_t::binary:
16647 return '[';
16648
16649 case value_t::object:
16650 return '{';
16651
16652 case value_t::discarded:
16653 default: // discarded values
16654 return 'N';
16655 }
16656 }
16657
16658 static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
16659 {
16660 return 'd'; // float 32
16661 }
16662
16663 static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
16664 {
16665 return 'D'; // float 64
16666 }
16667
16671 bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
16672 {
16673 std::map<string_t, CharType> bjdtype = {{"uint8", 'U'}, {"int8", 'i'}, {"uint16", 'u'}, {"int16", 'I'},
16674 {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
16675 };
16676
16677 string_t key = "_ArrayType_";
16678 auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
16679 if (it == bjdtype.end())
16680 {
16681 return true;
16682 }
16683 CharType dtype = it->second;
16684
16685 key = "_ArraySize_";
16686 std::size_t len = (value.at(key).empty() ? 0 : 1);
16687 for (const auto& el : value.at(key))
16688 {
16689 len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
16690 }
16691
16692 key = "_ArrayData_";
16693 if (value.at(key).size() != len)
16694 {
16695 return true;
16696 }
16697
16698 oa->write_character('[');
16699 oa->write_character('$');
16700 oa->write_character(dtype);
16701 oa->write_character('#');
16702
16703 key = "_ArraySize_";
16704 write_ubjson(value.at(key), use_count, use_type, true, true);
16705
16706 key = "_ArrayData_";
16707 if (dtype == 'U' || dtype == 'C')
16708 {
16709 for (const auto& el : value.at(key))
16710 {
16711 write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
16712 }
16713 }
16714 else if (dtype == 'i')
16715 {
16716 for (const auto& el : value.at(key))
16717 {
16718 write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
16719 }
16720 }
16721 else if (dtype == 'u')
16722 {
16723 for (const auto& el : value.at(key))
16724 {
16725 write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
16726 }
16727 }
16728 else if (dtype == 'I')
16729 {
16730 for (const auto& el : value.at(key))
16731 {
16732 write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
16733 }
16734 }
16735 else if (dtype == 'm')
16736 {
16737 for (const auto& el : value.at(key))
16738 {
16739 write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
16740 }
16741 }
16742 else if (dtype == 'l')
16743 {
16744 for (const auto& el : value.at(key))
16745 {
16746 write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
16747 }
16748 }
16749 else if (dtype == 'M')
16750 {
16751 for (const auto& el : value.at(key))
16752 {
16753 write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
16754 }
16755 }
16756 else if (dtype == 'L')
16757 {
16758 for (const auto& el : value.at(key))
16759 {
16760 write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
16761 }
16762 }
16763 else if (dtype == 'd')
16764 {
16765 for (const auto& el : value.at(key))
16766 {
16767 write_number(static_cast<float>(el.m_data.m_value.number_float), true);
16768 }
16769 }
16770 else if (dtype == 'D')
16771 {
16772 for (const auto& el : value.at(key))
16773 {
16774 write_number(static_cast<double>(el.m_data.m_value.number_float), true);
16775 }
16776 }
16777 return false;
16778 }
16779
16781 // Utility functions //
16783
16784 /*
16785 @brief write a number to output input
16786 @param[in] n number of type @a NumberType
16787 @param[in] OutputIsLittleEndian Set to true if output data is
16788 required to be little endian
16789 @tparam NumberType the type of the number
16790
16791 @note This function needs to respect the system's endianness, because bytes
16792 in CBOR, MessagePack, and UBJSON are stored in network order (big
16793 endian) and therefore need reordering on little endian systems.
16794 On the other hand, BSON and BJData use little endian and should reorder
16795 on big endian systems.
16796 */
16797 template<typename NumberType>
16798 void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
16799 {
16800 // step 1: write number to array of length NumberType
16801 std::array<CharType, sizeof(NumberType)> vec{};
16802 std::memcpy(vec.data(), &n, sizeof(NumberType));
16803
16804 // step 2: write array to output (with possible reordering)
16805 if (is_little_endian != OutputIsLittleEndian)
16806 {
16807 // reverse byte order prior to conversion if necessary
16808 std::reverse(vec.begin(), vec.end());
16809 }
16810
16811 oa->write_characters(vec.data(), sizeof(NumberType));
16812 }
16813
16814 void write_compact_float(const number_float_t n, detail::input_format_t format)
16815 {
16816#ifdef __GNUC__
16817#pragma GCC diagnostic push
16818#pragma GCC diagnostic ignored "-Wfloat-equal"
16819#endif
16820 if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
16821 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
16822 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
16823 {
16824 oa->write_character(format == detail::input_format_t::cbor
16825 ? get_cbor_float_prefix(static_cast<float>(n))
16826 : get_msgpack_float_prefix(static_cast<float>(n)));
16827 write_number(static_cast<float>(n));
16828 }
16829 else
16830 {
16831 oa->write_character(format == detail::input_format_t::cbor
16832 ? get_cbor_float_prefix(n)
16833 : get_msgpack_float_prefix(n));
16834 write_number(n);
16835 }
16836#ifdef __GNUC__
16837#pragma GCC diagnostic pop
16838#endif
16839 }
16840
16841 public:
16842 // The following to_char_type functions are implement the conversion
16843 // between uint8_t and CharType. In case CharType is not unsigned,
16844 // such a conversion is required to allow values greater than 128.
16845 // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
16846 template < typename C = CharType,
16847 enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
16848 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16849 {
16850 return *reinterpret_cast<char*>(&x);
16851 }
16852
16853 template < typename C = CharType,
16854 enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
16855 static CharType to_char_type(std::uint8_t x) noexcept
16856 {
16857 static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
16858 static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
16859 CharType result;
16860 std::memcpy(&result, &x, sizeof(x));
16861 return result;
16862 }
16863
16864 template<typename C = CharType,
16865 enable_if_t<std::is_unsigned<C>::value>* = nullptr>
16866 static constexpr CharType to_char_type(std::uint8_t x) noexcept
16867 {
16868 return x;
16869 }
16870
16871 template < typename InputCharType, typename C = CharType,
16872 enable_if_t <
16873 std::is_signed<C>::value &&
16874 std::is_signed<char>::value &&
16875 std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
16876 > * = nullptr >
16877 static constexpr CharType to_char_type(InputCharType x) noexcept
16878 {
16879 return x;
16880 }
16881
16882 private:
16884 const bool is_little_endian = little_endianness();
16885
16887 output_adapter_t<CharType> oa = nullptr;
16888};
16889
16890} // namespace detail
16891NLOHMANN_JSON_NAMESPACE_END
16892
16893// #include <nlohmann/detail/output/output_adapters.hpp>
16894
16895// #include <nlohmann/detail/output/serializer.hpp>
16896// __ _____ _____ _____
16897// __| | __| | | | JSON for Modern C++
16898// | | |__ | | | | | | version 3.11.3
16899// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16900//
16901// SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <[email protected]>
16902// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16903// SPDX-License-Identifier: MIT
16904
16905
16906
16907#include <algorithm> // reverse, remove, fill, find, none_of
16908#include <array> // array
16909#include <clocale> // localeconv, lconv
16910#include <cmath> // labs, isfinite, isnan, signbit
16911#include <cstddef> // size_t, ptrdiff_t
16912#include <cstdint> // uint8_t
16913#include <cstdio> // snprintf
16914#include <limits> // numeric_limits
16915#include <string> // string, char_traits
16916#include <iomanip> // setfill, setw
16917#include <type_traits> // is_same
16918#include <utility> // move
16919
16920// #include <nlohmann/detail/conversions/to_chars.hpp>
16921// __ _____ _____ _____
16922// __| | __| | | | JSON for Modern C++
16923// | | |__ | | | | | | version 3.11.3
16924// |_____|_____|_____|_|___| https://github.com/nlohmann/json
16925//
16926// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
16927// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
16928// SPDX-License-Identifier: MIT
16929
16930
16931
16932#include <array> // array
16933#include <cmath> // signbit, isfinite
16934#include <cstdint> // intN_t, uintN_t
16935#include <cstring> // memcpy, memmove
16936#include <limits> // numeric_limits
16937#include <type_traits> // conditional
16938
16939// #include <nlohmann/detail/macro_scope.hpp>
16940
16941
16942NLOHMANN_JSON_NAMESPACE_BEGIN
16943namespace detail
16944{
16945
16965namespace dtoa_impl
16966{
16967
16968template<typename Target, typename Source>
16969Target reinterpret_bits(const Source source)
16970{
16971 static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
16972
16973 Target target;
16974 std::memcpy(&target, &source, sizeof(Source));
16975 return target;
16976}
16977
16978struct diyfp // f * 2^e
16979{
16980 static constexpr int kPrecision = 64; // = q
16981
16982 std::uint64_t f = 0;
16983 int e = 0;
16984
16985 constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
16986
16991 static diyfp sub(const diyfp& x, const diyfp& y) noexcept
16992 {
16993 JSON_ASSERT(x.e == y.e);
16994 JSON_ASSERT(x.f >= y.f);
16995
16996 return {x.f - y.f, x.e};
16997 }
16998
17003 static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17004 {
17005 static_assert(kPrecision == 64, "internal error");
17006
17007 // Computes:
17008 // f = round((x.f * y.f) / 2^q)
17009 // e = x.e + y.e + q
17010
17011 // Emulate the 64-bit * 64-bit multiplication:
17012 //
17013 // p = u * v
17014 // = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17015 // = (u_lo v_lo ) + 2^32 ((u_lo v_hi ) + (u_hi v_lo )) + 2^64 (u_hi v_hi )
17016 // = (p0 ) + 2^32 ((p1 ) + (p2 )) + 2^64 (p3 )
17017 // = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3 )
17018 // = (p0_lo ) + 2^32 (p0_hi + p1_lo + p2_lo ) + 2^64 (p1_hi + p2_hi + p3)
17019 // = (p0_lo ) + 2^32 (Q ) + 2^64 (H )
17020 // = (p0_lo ) + 2^32 (Q_lo + 2^32 Q_hi ) + 2^64 (H )
17021 //
17022 // (Since Q might be larger than 2^32 - 1)
17023 //
17024 // = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17025 //
17026 // (Q_hi + H does not overflow a 64-bit int)
17027 //
17028 // = p_lo + 2^64 p_hi
17029
17030 const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17031 const std::uint64_t u_hi = x.f >> 32u;
17032 const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17033 const std::uint64_t v_hi = y.f >> 32u;
17034
17035 const std::uint64_t p0 = u_lo * v_lo;
17036 const std::uint64_t p1 = u_lo * v_hi;
17037 const std::uint64_t p2 = u_hi * v_lo;
17038 const std::uint64_t p3 = u_hi * v_hi;
17039
17040 const std::uint64_t p0_hi = p0 >> 32u;
17041 const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17042 const std::uint64_t p1_hi = p1 >> 32u;
17043 const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17044 const std::uint64_t p2_hi = p2 >> 32u;
17045
17046 std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17047
17048 // The full product might now be computed as
17049 //
17050 // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17051 // p_lo = p0_lo + (Q << 32)
17052 //
17053 // But in this particular case here, the full p_lo is not required.
17054 // Effectively we only need to add the highest bit in p_lo to p_hi (and
17055 // Q_hi + 1 does not overflow).
17056
17057 Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17058
17059 const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17060
17061 return {h, x.e + y.e + 64};
17062 }
17063
17068 static diyfp normalize(diyfp x) noexcept
17069 {
17070 JSON_ASSERT(x.f != 0);
17071
17072 while ((x.f >> 63u) == 0)
17073 {
17074 x.f <<= 1u;
17075 x.e--;
17076 }
17077
17078 return x;
17079 }
17080
17085 static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17086 {
17087 const int delta = x.e - target_exponent;
17088
17089 JSON_ASSERT(delta >= 0);
17090 JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17091
17092 return {x.f << delta, target_exponent};
17093 }
17094};
17095
17097{
17098 diyfp w;
17099 diyfp minus;
17100 diyfp plus;
17101};
17102
17109template<typename FloatType>
17111{
17112 JSON_ASSERT(std::isfinite(value));
17113 JSON_ASSERT(value > 0);
17114
17115 // Convert the IEEE representation into a diyfp.
17116 //
17117 // If v is denormal:
17118 // value = 0.F * 2^(1 - bias) = ( F) * 2^(1 - bias - (p-1))
17119 // If v is normalized:
17120 // value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17121
17122 static_assert(std::numeric_limits<FloatType>::is_iec559,
17123 "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17124
17125 constexpr int kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17126 constexpr int kBias = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17127 constexpr int kMinExp = 1 - kBias;
17128 constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17129
17130 using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17131
17132 const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17133 const std::uint64_t E = bits >> (kPrecision - 1);
17134 const std::uint64_t F = bits & (kHiddenBit - 1);
17135
17136 const bool is_denormal = E == 0;
17137 const diyfp v = is_denormal
17138 ? diyfp(F, kMinExp)
17139 : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17140
17141 // Compute the boundaries m- and m+ of the floating-point value
17142 // v = f * 2^e.
17143 //
17144 // Determine v- and v+, the floating-point predecessor and successor if v,
17145 // respectively.
17146 //
17147 // v- = v - 2^e if f != 2^(p-1) or e == e_min (A)
17148 // = v - 2^(e-1) if f == 2^(p-1) and e > e_min (B)
17149 //
17150 // v+ = v + 2^e
17151 //
17152 // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17153 // between m- and m+ round to v, regardless of how the input rounding
17154 // algorithm breaks ties.
17155 //
17156 // ---+-------------+-------------+-------------+-------------+--- (A)
17157 // v- m- v m+ v+
17158 //
17159 // -----------------+------+------+-------------+-------------+--- (B)
17160 // v- m- v m+ v+
17161
17162 const bool lower_boundary_is_closer = F == 0 && E > 1;
17163 const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
17164 const diyfp m_minus = lower_boundary_is_closer
17165 ? diyfp(4 * v.f - 1, v.e - 2) // (B)
17166 : diyfp(2 * v.f - 1, v.e - 1); // (A)
17167
17168 // Determine the normalized w+ = m+.
17169 const diyfp w_plus = diyfp::normalize(m_plus);
17170
17171 // Determine w- = m- such that e_(w-) = e_(w+).
17172 const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17173
17174 return {diyfp::normalize(v), w_minus, w_plus};
17175}
17176
17177// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17178// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17179// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17180//
17181// alpha <= e = e_c + e_w + q <= gamma
17182//
17183// or
17184//
17185// f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17186// <= f_c * f_w * 2^gamma
17187//
17188// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17189//
17190// 2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17191//
17192// or
17193//
17194// 2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17195//
17196// The choice of (alpha,gamma) determines the size of the table and the form of
17197// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17198// in practice:
17199//
17200// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17201// processed independently: An integral part p1, and a fractional part p2:
17202//
17203// f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17204// = (f div 2^-e) + (f mod 2^-e) * 2^e
17205// = p1 + p2 * 2^e
17206//
17207// The conversion of p1 into decimal form requires a series of divisions and
17208// modulos by (a power of) 10. These operations are faster for 32-bit than for
17209// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17210// achieved by choosing
17211//
17212// -e >= 32 or e <= -32 := gamma
17213//
17214// In order to convert the fractional part
17215//
17216// p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17217//
17218// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17219// d[-i] are extracted in order:
17220//
17221// (10 * p2) div 2^-e = d[-1]
17222// (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17223//
17224// The multiplication by 10 must not overflow. It is sufficient to choose
17225//
17226// 10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17227//
17228// Since p2 = f mod 2^-e < 2^-e,
17229//
17230// -e <= 60 or e >= -60 := alpha
17231
17232constexpr int kAlpha = -60;
17233constexpr int kGamma = -32;
17234
17235struct cached_power // c = f * 2^e ~= 10^k
17236{
17237 std::uint64_t f;
17238 int e;
17239 int k;
17240};
17241
17250{
17251 // Now
17252 //
17253 // alpha <= e_c + e + q <= gamma (1)
17254 // ==> f_c * 2^alpha <= c * 2^e * 2^q
17255 //
17256 // and since the c's are normalized, 2^(q-1) <= f_c,
17257 //
17258 // ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17259 // ==> 2^(alpha - e - 1) <= c
17260 //
17261 // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17262 //
17263 // k = ceil( log_10( 2^(alpha - e - 1) ) )
17264 // = ceil( (alpha - e - 1) * log_10(2) )
17265 //
17266 // From the paper:
17267 // "In theory the result of the procedure could be wrong since c is rounded,
17268 // and the computation itself is approximated [...]. In practice, however,
17269 // this simple function is sufficient."
17270 //
17271 // For IEEE double precision floating-point numbers converted into
17272 // normalized diyfp's w = f * 2^e, with q = 64,
17273 //
17274 // e >= -1022 (min IEEE exponent)
17275 // -52 (p - 1)
17276 // -52 (p - 1, possibly normalize denormal IEEE numbers)
17277 // -11 (normalize the diyfp)
17278 // = -1137
17279 //
17280 // and
17281 //
17282 // e <= +1023 (max IEEE exponent)
17283 // -52 (p - 1)
17284 // -11 (normalize the diyfp)
17285 // = 960
17286 //
17287 // This binary exponent range [-1137,960] results in a decimal exponent
17288 // range [-307,324]. One does not need to store a cached power for each
17289 // k in this range. For each such k it suffices to find a cached power
17290 // such that the exponent of the product lies in [alpha,gamma].
17291 // This implies that the difference of the decimal exponents of adjacent
17292 // table entries must be less than or equal to
17293 //
17294 // floor( (gamma - alpha) * log_10(2) ) = 8.
17295 //
17296 // (A smaller distance gamma-alpha would require a larger table.)
17297
17298 // NB:
17299 // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17300
17301 constexpr int kCachedPowersMinDecExp = -300;
17302 constexpr int kCachedPowersDecStep = 8;
17303
17304 static constexpr std::array<cached_power, 79> kCachedPowers =
17305 {
17306 {
17307 { 0xAB70FE17C79AC6CA, -1060, -300 },
17308 { 0xFF77B1FCBEBCDC4F, -1034, -292 },
17309 { 0xBE5691EF416BD60C, -1007, -284 },
17310 { 0x8DD01FAD907FFC3C, -980, -276 },
17311 { 0xD3515C2831559A83, -954, -268 },
17312 { 0x9D71AC8FADA6C9B5, -927, -260 },
17313 { 0xEA9C227723EE8BCB, -901, -252 },
17314 { 0xAECC49914078536D, -874, -244 },
17315 { 0x823C12795DB6CE57, -847, -236 },
17316 { 0xC21094364DFB5637, -821, -228 },
17317 { 0x9096EA6F3848984F, -794, -220 },
17318 { 0xD77485CB25823AC7, -768, -212 },
17319 { 0xA086CFCD97BF97F4, -741, -204 },
17320 { 0xEF340A98172AACE5, -715, -196 },
17321 { 0xB23867FB2A35B28E, -688, -188 },
17322 { 0x84C8D4DFD2C63F3B, -661, -180 },
17323 { 0xC5DD44271AD3CDBA, -635, -172 },
17324 { 0x936B9FCEBB25C996, -608, -164 },
17325 { 0xDBAC6C247D62A584, -582, -156 },
17326 { 0xA3AB66580D5FDAF6, -555, -148 },
17327 { 0xF3E2F893DEC3F126, -529, -140 },
17328 { 0xB5B5ADA8AAFF80B8, -502, -132 },
17329 { 0x87625F056C7C4A8B, -475, -124 },
17330 { 0xC9BCFF6034C13053, -449, -116 },
17331 { 0x964E858C91BA2655, -422, -108 },
17332 { 0xDFF9772470297EBD, -396, -100 },
17333 { 0xA6DFBD9FB8E5B88F, -369, -92 },
17334 { 0xF8A95FCF88747D94, -343, -84 },
17335 { 0xB94470938FA89BCF, -316, -76 },
17336 { 0x8A08F0F8BF0F156B, -289, -68 },
17337 { 0xCDB02555653131B6, -263, -60 },
17338 { 0x993FE2C6D07B7FAC, -236, -52 },
17339 { 0xE45C10C42A2B3B06, -210, -44 },
17340 { 0xAA242499697392D3, -183, -36 },
17341 { 0xFD87B5F28300CA0E, -157, -28 },
17342 { 0xBCE5086492111AEB, -130, -20 },
17343 { 0x8CBCCC096F5088CC, -103, -12 },
17344 { 0xD1B71758E219652C, -77, -4 },
17345 { 0x9C40000000000000, -50, 4 },
17346 { 0xE8D4A51000000000, -24, 12 },
17347 { 0xAD78EBC5AC620000, 3, 20 },
17348 { 0x813F3978F8940984, 30, 28 },
17349 { 0xC097CE7BC90715B3, 56, 36 },
17350 { 0x8F7E32CE7BEA5C70, 83, 44 },
17351 { 0xD5D238A4ABE98068, 109, 52 },
17352 { 0x9F4F2726179A2245, 136, 60 },
17353 { 0xED63A231D4C4FB27, 162, 68 },
17354 { 0xB0DE65388CC8ADA8, 189, 76 },
17355 { 0x83C7088E1AAB65DB, 216, 84 },
17356 { 0xC45D1DF942711D9A, 242, 92 },
17357 { 0x924D692CA61BE758, 269, 100 },
17358 { 0xDA01EE641A708DEA, 295, 108 },
17359 { 0xA26DA3999AEF774A, 322, 116 },
17360 { 0xF209787BB47D6B85, 348, 124 },
17361 { 0xB454E4A179DD1877, 375, 132 },
17362 { 0x865B86925B9BC5C2, 402, 140 },
17363 { 0xC83553C5C8965D3D, 428, 148 },
17364 { 0x952AB45CFA97A0B3, 455, 156 },
17365 { 0xDE469FBD99A05FE3, 481, 164 },
17366 { 0xA59BC234DB398C25, 508, 172 },
17367 { 0xF6C69A72A3989F5C, 534, 180 },
17368 { 0xB7DCBF5354E9BECE, 561, 188 },
17369 { 0x88FCF317F22241E2, 588, 196 },
17370 { 0xCC20CE9BD35C78A5, 614, 204 },
17371 { 0x98165AF37B2153DF, 641, 212 },
17372 { 0xE2A0B5DC971F303A, 667, 220 },
17373 { 0xA8D9D1535CE3B396, 694, 228 },
17374 { 0xFB9B7CD9A4A7443C, 720, 236 },
17375 { 0xBB764C4CA7A44410, 747, 244 },
17376 { 0x8BAB8EEFB6409C1A, 774, 252 },
17377 { 0xD01FEF10A657842C, 800, 260 },
17378 { 0x9B10A4E5E9913129, 827, 268 },
17379 { 0xE7109BFBA19C0C9D, 853, 276 },
17380 { 0xAC2820D9623BF429, 880, 284 },
17381 { 0x80444B5E7AA7CF85, 907, 292 },
17382 { 0xBF21E44003ACDD2D, 933, 300 },
17383 { 0x8E679C2F5E44FF8F, 960, 308 },
17384 { 0xD433179D9C8CB841, 986, 316 },
17385 { 0x9E19DB92B4E31BA9, 1013, 324 },
17386 }
17387 };
17388
17389 // This computation gives exactly the same results for k as
17390 // k = ceil((kAlpha - e - 1) * 0.30102999566398114)
17391 // for |e| <= 1500, but doesn't require floating-point operations.
17392 // NB: log_10(2) ~= 78913 / 2^18
17393 JSON_ASSERT(e >= -1500);
17394 JSON_ASSERT(e <= 1500);
17395 const int f = kAlpha - e - 1;
17396 const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
17397
17398 const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
17399 JSON_ASSERT(index >= 0);
17400 JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
17401
17402 const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
17403 JSON_ASSERT(kAlpha <= cached.e + e + 64);
17404 JSON_ASSERT(kGamma >= cached.e + e + 64);
17405
17406 return cached;
17407}
17408
17413inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
17414{
17415 // LCOV_EXCL_START
17416 if (n >= 1000000000)
17417 {
17418 pow10 = 1000000000;
17419 return 10;
17420 }
17421 // LCOV_EXCL_STOP
17422 if (n >= 100000000)
17423 {
17424 pow10 = 100000000;
17425 return 9;
17426 }
17427 if (n >= 10000000)
17428 {
17429 pow10 = 10000000;
17430 return 8;
17431 }
17432 if (n >= 1000000)
17433 {
17434 pow10 = 1000000;
17435 return 7;
17436 }
17437 if (n >= 100000)
17438 {
17439 pow10 = 100000;
17440 return 6;
17441 }
17442 if (n >= 10000)
17443 {
17444 pow10 = 10000;
17445 return 5;
17446 }
17447 if (n >= 1000)
17448 {
17449 pow10 = 1000;
17450 return 4;
17451 }
17452 if (n >= 100)
17453 {
17454 pow10 = 100;
17455 return 3;
17456 }
17457 if (n >= 10)
17458 {
17459 pow10 = 10;
17460 return 2;
17461 }
17462
17463 pow10 = 1;
17464 return 1;
17465}
17466
17467inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
17468 std::uint64_t rest, std::uint64_t ten_k)
17469{
17470 JSON_ASSERT(len >= 1);
17471 JSON_ASSERT(dist <= delta);
17472 JSON_ASSERT(rest <= delta);
17473 JSON_ASSERT(ten_k > 0);
17474
17475 // <--------------------------- delta ---->
17476 // <---- dist --------->
17477 // --------------[------------------+-------------------]--------------
17478 // M- w M+
17479 //
17480 // ten_k
17481 // <------>
17482 // <---- rest ---->
17483 // --------------[------------------+----+--------------]--------------
17484 // w V
17485 // = buf * 10^k
17486 //
17487 // ten_k represents a unit-in-the-last-place in the decimal representation
17488 // stored in buf.
17489 // Decrement buf by ten_k while this takes buf closer to w.
17490
17491 // The tests are written in this order to avoid overflow in unsigned
17492 // integer arithmetic.
17493
17494 while (rest < dist
17495 && delta - rest >= ten_k
17496 && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
17497 {
17498 JSON_ASSERT(buf[len - 1] != '0');
17499 buf[len - 1]--;
17500 rest += ten_k;
17501 }
17502}
17503
17508inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
17509 diyfp M_minus, diyfp w, diyfp M_plus)
17510{
17511 static_assert(kAlpha >= -60, "internal error");
17512 static_assert(kGamma <= -32, "internal error");
17513
17514 // Generates the digits (and the exponent) of a decimal floating-point
17515 // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
17516 // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
17517 //
17518 // <--------------------------- delta ---->
17519 // <---- dist --------->
17520 // --------------[------------------+-------------------]--------------
17521 // M- w M+
17522 //
17523 // Grisu2 generates the digits of M+ from left to right and stops as soon as
17524 // V is in [M-,M+].
17525
17526 JSON_ASSERT(M_plus.e >= kAlpha);
17527 JSON_ASSERT(M_plus.e <= kGamma);
17528
17529 std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
17530 std::uint64_t dist = diyfp::sub(M_plus, w ).f; // (significand of (M+ - w ), implicit exponent is e)
17531
17532 // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
17533 //
17534 // M+ = f * 2^e
17535 // = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
17536 // = ((p1 ) * 2^-e + (p2 )) * 2^e
17537 // = p1 + p2 * 2^e
17538
17539 const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
17540
17541 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.)
17542 std::uint64_t p2 = M_plus.f & (one.f - 1); // p2 = f mod 2^-e
17543
17544 // 1)
17545 //
17546 // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
17547
17548 JSON_ASSERT(p1 > 0);
17549
17550 std::uint32_t pow10{};
17551 const int k = find_largest_pow10(p1, pow10);
17552
17553 // 10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
17554 //
17555 // p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
17556 // = (d[k-1] ) * 10^(k-1) + (p1 mod 10^(k-1))
17557 //
17558 // M+ = p1 + p2 * 2^e
17559 // = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1)) + p2 * 2^e
17560 // = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
17561 // = d[k-1] * 10^(k-1) + ( rest) * 2^e
17562 //
17563 // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
17564 //
17565 // p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
17566 //
17567 // but stop as soon as
17568 //
17569 // rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
17570
17571 int n = k;
17572 while (n > 0)
17573 {
17574 // Invariants:
17575 // M+ = buffer * 10^n + (p1 + p2 * 2^e) (buffer = 0 for n = k)
17576 // pow10 = 10^(n-1) <= p1 < 10^n
17577 //
17578 const std::uint32_t d = p1 / pow10; // d = p1 div 10^(n-1)
17579 const std::uint32_t r = p1 % pow10; // r = p1 mod 10^(n-1)
17580 //
17581 // M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
17582 // = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
17583 //
17584 JSON_ASSERT(d <= 9);
17585 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17586 //
17587 // M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
17588 //
17589 p1 = r;
17590 n--;
17591 //
17592 // M+ = buffer * 10^n + (p1 + p2 * 2^e)
17593 // pow10 = 10^n
17594 //
17595
17596 // Now check if enough digits have been generated.
17597 // Compute
17598 //
17599 // p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
17600 //
17601 // Note:
17602 // Since rest and delta share the same exponent e, it suffices to
17603 // compare the significands.
17604 const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
17605 if (rest <= delta)
17606 {
17607 // V = buffer * 10^n, with M- <= V <= M+.
17608
17609 decimal_exponent += n;
17610
17611 // We may now just stop. But instead look if the buffer could be
17612 // decremented to bring V closer to w.
17613 //
17614 // pow10 = 10^n is now 1 ulp in the decimal representation V.
17615 // The rounding procedure works with diyfp's with an implicit
17616 // exponent of e.
17617 //
17618 // 10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
17619 //
17620 const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
17621 grisu2_round(buffer, length, dist, delta, rest, ten_n);
17622
17623 return;
17624 }
17625
17626 pow10 /= 10;
17627 //
17628 // pow10 = 10^(n-1) <= p1 < 10^n
17629 // Invariants restored.
17630 }
17631
17632 // 2)
17633 //
17634 // The digits of the integral part have been generated:
17635 //
17636 // M+ = d[k-1]...d[1]d[0] + p2 * 2^e
17637 // = buffer + p2 * 2^e
17638 //
17639 // Now generate the digits of the fractional part p2 * 2^e.
17640 //
17641 // Note:
17642 // No decimal point is generated: the exponent is adjusted instead.
17643 //
17644 // p2 actually represents the fraction
17645 //
17646 // p2 * 2^e
17647 // = p2 / 2^-e
17648 // = d[-1] / 10^1 + d[-2] / 10^2 + ...
17649 //
17650 // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
17651 //
17652 // p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
17653 // + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
17654 //
17655 // using
17656 //
17657 // 10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
17658 // = ( d) * 2^-e + ( r)
17659 //
17660 // or
17661 // 10^m * p2 * 2^e = d + r * 2^e
17662 //
17663 // i.e.
17664 //
17665 // M+ = buffer + p2 * 2^e
17666 // = buffer + 10^-m * (d + r * 2^e)
17667 // = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
17668 //
17669 // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
17670
17671 JSON_ASSERT(p2 > delta);
17672
17673 int m = 0;
17674 for (;;)
17675 {
17676 // Invariant:
17677 // M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
17678 // = buffer * 10^-m + 10^-m * (p2 ) * 2^e
17679 // = buffer * 10^-m + 10^-m * (1/10 * (10 * p2) ) * 2^e
17680 // = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
17681 //
17682 JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
17683 p2 *= 10;
17684 const std::uint64_t d = p2 >> -one.e; // d = (10 * p2) div 2^-e
17685 const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
17686 //
17687 // M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
17688 // = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
17689 // = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
17690 //
17691 JSON_ASSERT(d <= 9);
17692 buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
17693 //
17694 // M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
17695 //
17696 p2 = r;
17697 m++;
17698 //
17699 // M+ = buffer * 10^-m + 10^-m * p2 * 2^e
17700 // Invariant restored.
17701
17702 // Check if enough digits have been generated.
17703 //
17704 // 10^-m * p2 * 2^e <= delta * 2^e
17705 // p2 * 2^e <= 10^m * delta * 2^e
17706 // p2 <= 10^m * delta
17707 delta *= 10;
17708 dist *= 10;
17709 if (p2 <= delta)
17710 {
17711 break;
17712 }
17713 }
17714
17715 // V = buffer * 10^-m, with M- <= V <= M+.
17716
17717 decimal_exponent -= m;
17718
17719 // 1 ulp in the decimal representation is now 10^-m.
17720 // Since delta and dist are now scaled by 10^m, we need to do the
17721 // same with ulp in order to keep the units in sync.
17722 //
17723 // 10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
17724 //
17725 const std::uint64_t ten_m = one.f;
17726 grisu2_round(buffer, length, dist, delta, p2, ten_m);
17727
17728 // By construction this algorithm generates the shortest possible decimal
17729 // number (Loitsch, Theorem 6.2) which rounds back to w.
17730 // For an input number of precision p, at least
17731 //
17732 // N = 1 + ceil(p * log_10(2))
17733 //
17734 // decimal digits are sufficient to identify all binary floating-point
17735 // numbers (Matula, "In-and-Out conversions").
17736 // This implies that the algorithm does not produce more than N decimal
17737 // digits.
17738 //
17739 // N = 17 for p = 53 (IEEE double precision)
17740 // N = 9 for p = 24 (IEEE single precision)
17741}
17742
17748JSON_HEDLEY_NON_NULL(1)
17749inline void grisu2(char* buf, int& len, int& decimal_exponent,
17750 diyfp m_minus, diyfp v, diyfp m_plus)
17751{
17752 JSON_ASSERT(m_plus.e == m_minus.e);
17753 JSON_ASSERT(m_plus.e == v.e);
17754
17755 // --------(-----------------------+-----------------------)-------- (A)
17756 // m- v m+
17757 //
17758 // --------------------(-----------+-----------------------)-------- (B)
17759 // m- v m+
17760 //
17761 // First scale v (and m- and m+) such that the exponent is in the range
17762 // [alpha, gamma].
17763
17764 const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
17765
17766 const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
17767
17768 // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
17769 const diyfp w = diyfp::mul(v, c_minus_k);
17770 const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
17771 const diyfp w_plus = diyfp::mul(m_plus, c_minus_k);
17772
17773 // ----(---+---)---------------(---+---)---------------(---+---)----
17774 // w- w w+
17775 // = c*m- = c*v = c*m+
17776 //
17777 // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
17778 // w+ are now off by a small amount.
17779 // In fact:
17780 //
17781 // w - v * 10^k < 1 ulp
17782 //
17783 // To account for this inaccuracy, add resp. subtract 1 ulp.
17784 //
17785 // --------+---[---------------(---+---)---------------]---+--------
17786 // w- M- w M+ w+
17787 //
17788 // Now any number in [M-, M+] (bounds included) will round to w when input,
17789 // regardless of how the input rounding algorithm breaks ties.
17790 //
17791 // And digit_gen generates the shortest possible such number in [M-, M+].
17792 // Note that this does not mean that Grisu2 always generates the shortest
17793 // possible number in the interval (m-, m+).
17794 const diyfp M_minus(w_minus.f + 1, w_minus.e);
17795 const diyfp M_plus (w_plus.f - 1, w_plus.e );
17796
17797 decimal_exponent = -cached.k; // = -(-k) = k
17798
17799 grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
17800}
17801
17807template<typename FloatType>
17808JSON_HEDLEY_NON_NULL(1)
17809void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
17810{
17811 static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
17812 "internal error: not enough precision");
17813
17814 JSON_ASSERT(std::isfinite(value));
17815 JSON_ASSERT(value > 0);
17816
17817 // If the neighbors (and boundaries) of 'value' are always computed for double-precision
17818 // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
17819 // decimal representations are not exactly "short".
17820 //
17821 // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
17822 // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
17823 // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
17824 // does.
17825 // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
17826 // representation using the corresponding std::from_chars function recovers value exactly". That
17827 // indicates that single precision floating-point numbers should be recovered using
17828 // 'std::strtof'.
17829 //
17830 // NB: If the neighbors are computed for single-precision numbers, there is a single float
17831 // (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
17832 // value is off by 1 ulp.
17833#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
17834 const boundaries w = compute_boundaries(static_cast<double>(value));
17835#else
17837#endif
17838
17839 grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
17840}
17841
17847JSON_HEDLEY_NON_NULL(1)
17848JSON_HEDLEY_RETURNS_NON_NULL
17849inline char* append_exponent(char* buf, int e)
17850{
17851 JSON_ASSERT(e > -1000);
17852 JSON_ASSERT(e < 1000);
17853
17854 if (e < 0)
17855 {
17856 e = -e;
17857 *buf++ = '-';
17858 }
17859 else
17860 {
17861 *buf++ = '+';
17862 }
17863
17864 auto k = static_cast<std::uint32_t>(e);
17865 if (k < 10)
17866 {
17867 // Always print at least two digits in the exponent.
17868 // This is for compatibility with printf("%g").
17869 *buf++ = '0';
17870 *buf++ = static_cast<char>('0' + k);
17871 }
17872 else if (k < 100)
17873 {
17874 *buf++ = static_cast<char>('0' + k / 10);
17875 k %= 10;
17876 *buf++ = static_cast<char>('0' + k);
17877 }
17878 else
17879 {
17880 *buf++ = static_cast<char>('0' + k / 100);
17881 k %= 100;
17882 *buf++ = static_cast<char>('0' + k / 10);
17883 k %= 10;
17884 *buf++ = static_cast<char>('0' + k);
17885 }
17886
17887 return buf;
17888}
17889
17899JSON_HEDLEY_NON_NULL(1)
17900JSON_HEDLEY_RETURNS_NON_NULL
17901inline char* format_buffer(char* buf, int len, int decimal_exponent,
17902 int min_exp, int max_exp)
17903{
17904 JSON_ASSERT(min_exp < 0);
17905 JSON_ASSERT(max_exp > 0);
17906
17907 const int k = len;
17908 const int n = len + decimal_exponent;
17909
17910 // v = buf * 10^(n-k)
17911 // k is the length of the buffer (number of decimal digits)
17912 // n is the position of the decimal point relative to the start of the buffer.
17913
17914 if (k <= n && n <= max_exp)
17915 {
17916 // digits[000]
17917 // len <= max_exp + 2
17918
17919 std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
17920 // Make it look like a floating-point number (#362, #378)
17921 buf[n + 0] = '.';
17922 buf[n + 1] = '0';
17923 return buf + (static_cast<size_t>(n) + 2);
17924 }
17925
17926 if (0 < n && n <= max_exp)
17927 {
17928 // dig.its
17929 // len <= max_digits10 + 1
17930
17931 JSON_ASSERT(k > n);
17932
17933 std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
17934 buf[n] = '.';
17935 return buf + (static_cast<size_t>(k) + 1U);
17936 }
17937
17938 if (min_exp < n && n <= 0)
17939 {
17940 // 0.[000]digits
17941 // len <= 2 + (-min_exp - 1) + max_digits10
17942
17943 std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
17944 buf[0] = '0';
17945 buf[1] = '.';
17946 std::memset(buf + 2, '0', static_cast<size_t>(-n));
17947 return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
17948 }
17949
17950 if (k == 1)
17951 {
17952 // dE+123
17953 // len <= 1 + 5
17954
17955 buf += 1;
17956 }
17957 else
17958 {
17959 // d.igitsE+123
17960 // len <= max_digits10 + 1 + 5
17961
17962 std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
17963 buf[1] = '.';
17964 buf += 1 + static_cast<size_t>(k);
17965 }
17966
17967 *buf++ = 'e';
17968 return append_exponent(buf, n - 1);
17969}
17970
17971} // namespace dtoa_impl
17972
17983template<typename FloatType>
17984JSON_HEDLEY_NON_NULL(1, 2)
17985JSON_HEDLEY_RETURNS_NON_NULL
17986char* to_chars(char* first, const char* last, FloatType value)
17987{
17988 static_cast<void>(last); // maybe unused - fix warning
17989 JSON_ASSERT(std::isfinite(value));
17990
17991 // Use signbit(value) instead of (value < 0) since signbit works for -0.
17992 if (std::signbit(value))
17993 {
17994 value = -value;
17995 *first++ = '-';
17996 }
17997
17998#ifdef __GNUC__
17999#pragma GCC diagnostic push
18000#pragma GCC diagnostic ignored "-Wfloat-equal"
18001#endif
18002 if (value == 0) // +-0
18003 {
18004 *first++ = '0';
18005 // Make it look like a floating-point number (#362, #378)
18006 *first++ = '.';
18007 *first++ = '0';
18008 return first;
18009 }
18010#ifdef __GNUC__
18011#pragma GCC diagnostic pop
18012#endif
18013
18014 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18015
18016 // Compute v = buffer * 10^decimal_exponent.
18017 // The decimal digits are stored in the buffer, which needs to be interpreted
18018 // as an unsigned decimal integer.
18019 // len is the length of the buffer, i.e. the number of decimal digits.
18020 int len = 0;
18021 int decimal_exponent = 0;
18022 dtoa_impl::grisu2(first, len, decimal_exponent, value);
18023
18024 JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18025
18026 // Format the buffer like printf("%.*g", prec, value)
18027 constexpr int kMinExp = -4;
18028 // Use digits10 here to increase compatibility with version 2.
18029 constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18030
18031 JSON_ASSERT(last - first >= kMaxExp + 2);
18032 JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18033 JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18034
18035 return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18036}
18037
18038} // namespace detail
18039NLOHMANN_JSON_NAMESPACE_END
18040
18041// #include <nlohmann/detail/exceptions.hpp>
18042
18043// #include <nlohmann/detail/macro_scope.hpp>
18044
18045// #include <nlohmann/detail/meta/cpp_future.hpp>
18046
18047// #include <nlohmann/detail/output/binary_writer.hpp>
18048
18049// #include <nlohmann/detail/output/output_adapters.hpp>
18050
18051// #include <nlohmann/detail/string_concat.hpp>
18052
18053// #include <nlohmann/detail/value_t.hpp>
18054
18055
18056NLOHMANN_JSON_NAMESPACE_BEGIN
18057namespace detail
18058{
18059
18061// serialization //
18063
18066{
18067 strict,
18068 replace,
18069 ignore
18070};
18071
18072template<typename BasicJsonType>
18074{
18075 using string_t = typename BasicJsonType::string_t;
18076 using number_float_t = typename BasicJsonType::number_float_t;
18077 using number_integer_t = typename BasicJsonType::number_integer_t;
18078 using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18079 using binary_char_t = typename BasicJsonType::binary_t::value_type;
18080 static constexpr std::uint8_t UTF8_ACCEPT = 0;
18081 static constexpr std::uint8_t UTF8_REJECT = 1;
18082
18083 public:
18090 error_handler_t error_handler_ = error_handler_t::strict)
18091 : o(std::move(s))
18092 , loc(std::localeconv())
18093 , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18094 , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18095 , indent_char(ichar)
18096 , indent_string(512, indent_char)
18097 , error_handler(error_handler_)
18098 {}
18099
18100 // delete because of pointer members
18101 serializer(const serializer&) = delete;
18102 serializer& operator=(const serializer&) = delete;
18103 serializer(serializer&&) = delete;
18104 serializer& operator=(serializer&&) = delete;
18105 ~serializer() = default;
18106
18129 void dump(const BasicJsonType& val,
18130 const bool pretty_print,
18131 const bool ensure_ascii,
18132 const unsigned int indent_step,
18133 const unsigned int current_indent = 0)
18134 {
18135 switch (val.m_data.m_type)
18136 {
18137 case value_t::object:
18138 {
18139 if (val.m_data.m_value.object->empty())
18140 {
18141 o->write_characters("{}", 2);
18142 return;
18143 }
18144
18145 if (pretty_print)
18146 {
18147 o->write_characters("{\n", 2);
18148
18149 // variable to hold indentation for recursive calls
18150 const auto new_indent = current_indent + indent_step;
18151 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18152 {
18153 indent_string.resize(indent_string.size() * 2, ' ');
18154 }
18155
18156 // first n-1 elements
18157 auto i = val.m_data.m_value.object->cbegin();
18158 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18159 {
18160 o->write_characters(indent_string.c_str(), new_indent);
18161 o->write_character('\"');
18162 dump_escaped(i->first, ensure_ascii);
18163 o->write_characters("\": ", 3);
18164 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18165 o->write_characters(",\n", 2);
18166 }
18167
18168 // last element
18169 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18170 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18171 o->write_characters(indent_string.c_str(), new_indent);
18172 o->write_character('\"');
18173 dump_escaped(i->first, ensure_ascii);
18174 o->write_characters("\": ", 3);
18175 dump(i->second, true, ensure_ascii, indent_step, new_indent);
18176
18177 o->write_character('\n');
18178 o->write_characters(indent_string.c_str(), current_indent);
18179 o->write_character('}');
18180 }
18181 else
18182 {
18183 o->write_character('{');
18184
18185 // first n-1 elements
18186 auto i = val.m_data.m_value.object->cbegin();
18187 for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18188 {
18189 o->write_character('\"');
18190 dump_escaped(i->first, ensure_ascii);
18191 o->write_characters("\":", 2);
18192 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18193 o->write_character(',');
18194 }
18195
18196 // last element
18197 JSON_ASSERT(i != val.m_data.m_value.object->cend());
18198 JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18199 o->write_character('\"');
18200 dump_escaped(i->first, ensure_ascii);
18201 o->write_characters("\":", 2);
18202 dump(i->second, false, ensure_ascii, indent_step, current_indent);
18203
18204 o->write_character('}');
18205 }
18206
18207 return;
18208 }
18209
18210 case value_t::array:
18211 {
18212 if (val.m_data.m_value.array->empty())
18213 {
18214 o->write_characters("[]", 2);
18215 return;
18216 }
18217
18218 if (pretty_print)
18219 {
18220 o->write_characters("[\n", 2);
18221
18222 // variable to hold indentation for recursive calls
18223 const auto new_indent = current_indent + indent_step;
18224 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18225 {
18226 indent_string.resize(indent_string.size() * 2, ' ');
18227 }
18228
18229 // first n-1 elements
18230 for (auto i = val.m_data.m_value.array->cbegin();
18231 i != val.m_data.m_value.array->cend() - 1; ++i)
18232 {
18233 o->write_characters(indent_string.c_str(), new_indent);
18234 dump(*i, true, ensure_ascii, indent_step, new_indent);
18235 o->write_characters(",\n", 2);
18236 }
18237
18238 // last element
18239 JSON_ASSERT(!val.m_data.m_value.array->empty());
18240 o->write_characters(indent_string.c_str(), new_indent);
18241 dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18242
18243 o->write_character('\n');
18244 o->write_characters(indent_string.c_str(), current_indent);
18245 o->write_character(']');
18246 }
18247 else
18248 {
18249 o->write_character('[');
18250
18251 // first n-1 elements
18252 for (auto i = val.m_data.m_value.array->cbegin();
18253 i != val.m_data.m_value.array->cend() - 1; ++i)
18254 {
18255 dump(*i, false, ensure_ascii, indent_step, current_indent);
18256 o->write_character(',');
18257 }
18258
18259 // last element
18260 JSON_ASSERT(!val.m_data.m_value.array->empty());
18261 dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18262
18263 o->write_character(']');
18264 }
18265
18266 return;
18267 }
18268
18269 case value_t::string:
18270 {
18271 o->write_character('\"');
18272 dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18273 o->write_character('\"');
18274 return;
18275 }
18276
18277 case value_t::binary:
18278 {
18279 if (pretty_print)
18280 {
18281 o->write_characters("{\n", 2);
18282
18283 // variable to hold indentation for recursive calls
18284 const auto new_indent = current_indent + indent_step;
18285 if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18286 {
18287 indent_string.resize(indent_string.size() * 2, ' ');
18288 }
18289
18290 o->write_characters(indent_string.c_str(), new_indent);
18291
18292 o->write_characters("\"bytes\": [", 10);
18293
18294 if (!val.m_data.m_value.binary->empty())
18295 {
18296 for (auto i = val.m_data.m_value.binary->cbegin();
18297 i != val.m_data.m_value.binary->cend() - 1; ++i)
18298 {
18299 dump_integer(*i);
18300 o->write_characters(", ", 2);
18301 }
18302 dump_integer(val.m_data.m_value.binary->back());
18303 }
18304
18305 o->write_characters("],\n", 3);
18306 o->write_characters(indent_string.c_str(), new_indent);
18307
18308 o->write_characters("\"subtype\": ", 11);
18309 if (val.m_data.m_value.binary->has_subtype())
18310 {
18311 dump_integer(val.m_data.m_value.binary->subtype());
18312 }
18313 else
18314 {
18315 o->write_characters("null", 4);
18316 }
18317 o->write_character('\n');
18318 o->write_characters(indent_string.c_str(), current_indent);
18319 o->write_character('}');
18320 }
18321 else
18322 {
18323 o->write_characters("{\"bytes\":[", 10);
18324
18325 if (!val.m_data.m_value.binary->empty())
18326 {
18327 for (auto i = val.m_data.m_value.binary->cbegin();
18328 i != val.m_data.m_value.binary->cend() - 1; ++i)
18329 {
18330 dump_integer(*i);
18331 o->write_character(',');
18332 }
18333 dump_integer(val.m_data.m_value.binary->back());
18334 }
18335
18336 o->write_characters("],\"subtype\":", 12);
18337 if (val.m_data.m_value.binary->has_subtype())
18338 {
18339 dump_integer(val.m_data.m_value.binary->subtype());
18340 o->write_character('}');
18341 }
18342 else
18343 {
18344 o->write_characters("null}", 5);
18345 }
18346 }
18347 return;
18348 }
18349
18350 case value_t::boolean:
18351 {
18352 if (val.m_data.m_value.boolean)
18353 {
18354 o->write_characters("true", 4);
18355 }
18356 else
18357 {
18358 o->write_characters("false", 5);
18359 }
18360 return;
18361 }
18362
18363 case value_t::number_integer:
18364 {
18365 dump_integer(val.m_data.m_value.number_integer);
18366 return;
18367 }
18368
18369 case value_t::number_unsigned:
18370 {
18371 dump_integer(val.m_data.m_value.number_unsigned);
18372 return;
18373 }
18374
18375 case value_t::number_float:
18376 {
18377 dump_float(val.m_data.m_value.number_float);
18378 return;
18379 }
18380
18381 case value_t::discarded:
18382 {
18383 o->write_characters("<discarded>", 11);
18384 return;
18385 }
18386
18387 case value_t::null:
18388 {
18389 o->write_characters("null", 4);
18390 return;
18391 }
18392
18393 default: // LCOV_EXCL_LINE
18394 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18395 }
18396 }
18397
18398 JSON_PRIVATE_UNLESS_TESTED:
18413 void dump_escaped(const string_t& s, const bool ensure_ascii)
18414 {
18415 std::uint32_t codepoint{};
18416 std::uint8_t state = UTF8_ACCEPT;
18417 std::size_t bytes = 0; // number of bytes written to string_buffer
18418
18419 // number of bytes written at the point of the last valid byte
18420 std::size_t bytes_after_last_accept = 0;
18421 std::size_t undumped_chars = 0;
18422
18423 for (std::size_t i = 0; i < s.size(); ++i)
18424 {
18425 const auto byte = static_cast<std::uint8_t>(s[i]);
18426
18427 switch (decode(state, codepoint, byte))
18428 {
18429 case UTF8_ACCEPT: // decode found a new code point
18430 {
18431 switch (codepoint)
18432 {
18433 case 0x08: // backspace
18434 {
18435 string_buffer[bytes++] = '\\';
18436 string_buffer[bytes++] = 'b';
18437 break;
18438 }
18439
18440 case 0x09: // horizontal tab
18441 {
18442 string_buffer[bytes++] = '\\';
18443 string_buffer[bytes++] = 't';
18444 break;
18445 }
18446
18447 case 0x0A: // newline
18448 {
18449 string_buffer[bytes++] = '\\';
18450 string_buffer[bytes++] = 'n';
18451 break;
18452 }
18453
18454 case 0x0C: // formfeed
18455 {
18456 string_buffer[bytes++] = '\\';
18457 string_buffer[bytes++] = 'f';
18458 break;
18459 }
18460
18461 case 0x0D: // carriage return
18462 {
18463 string_buffer[bytes++] = '\\';
18464 string_buffer[bytes++] = 'r';
18465 break;
18466 }
18467
18468 case 0x22: // quotation mark
18469 {
18470 string_buffer[bytes++] = '\\';
18471 string_buffer[bytes++] = '\"';
18472 break;
18473 }
18474
18475 case 0x5C: // reverse solidus
18476 {
18477 string_buffer[bytes++] = '\\';
18478 string_buffer[bytes++] = '\\';
18479 break;
18480 }
18481
18482 default:
18483 {
18484 // escape control characters (0x00..0x1F) or, if
18485 // ensure_ascii parameter is used, non-ASCII characters
18486 if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
18487 {
18488 if (codepoint <= 0xFFFF)
18489 {
18490 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18491 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
18492 static_cast<std::uint16_t>(codepoint)));
18493 bytes += 6;
18494 }
18495 else
18496 {
18497 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18498 static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
18499 static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
18500 static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
18501 bytes += 12;
18502 }
18503 }
18504 else
18505 {
18506 // copy byte to buffer (all previous bytes
18507 // been copied have in default case above)
18508 string_buffer[bytes++] = s[i];
18509 }
18510 break;
18511 }
18512 }
18513
18514 // write buffer and reset index; there must be 13 bytes
18515 // left, as this is the maximal number of bytes to be
18516 // written ("\uxxxx\uxxxx\0") for one code point
18517 if (string_buffer.size() - bytes < 13)
18518 {
18519 o->write_characters(string_buffer.data(), bytes);
18520 bytes = 0;
18521 }
18522
18523 // remember the byte position of this accept
18524 bytes_after_last_accept = bytes;
18525 undumped_chars = 0;
18526 break;
18527 }
18528
18529 case UTF8_REJECT: // decode found invalid UTF-8 byte
18530 {
18531 switch (error_handler)
18532 {
18533 case error_handler_t::strict:
18534 {
18535 JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
18536 }
18537
18538 case error_handler_t::ignore:
18539 case error_handler_t::replace:
18540 {
18541 // in case we saw this character the first time, we
18542 // would like to read it again, because the byte
18543 // may be OK for itself, but just not OK for the
18544 // previous sequence
18545 if (undumped_chars > 0)
18546 {
18547 --i;
18548 }
18549
18550 // reset length buffer to the last accepted index;
18551 // thus removing/ignoring the invalid characters
18552 bytes = bytes_after_last_accept;
18553
18554 if (error_handler == error_handler_t::replace)
18555 {
18556 // add a replacement character
18557 if (ensure_ascii)
18558 {
18559 string_buffer[bytes++] = '\\';
18560 string_buffer[bytes++] = 'u';
18561 string_buffer[bytes++] = 'f';
18562 string_buffer[bytes++] = 'f';
18563 string_buffer[bytes++] = 'f';
18564 string_buffer[bytes++] = 'd';
18565 }
18566 else
18567 {
18568 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
18569 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
18570 string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
18571 }
18572
18573 // write buffer and reset index; there must be 13 bytes
18574 // left, as this is the maximal number of bytes to be
18575 // written ("\uxxxx\uxxxx\0") for one code point
18576 if (string_buffer.size() - bytes < 13)
18577 {
18578 o->write_characters(string_buffer.data(), bytes);
18579 bytes = 0;
18580 }
18581
18582 bytes_after_last_accept = bytes;
18583 }
18584
18585 undumped_chars = 0;
18586
18587 // continue processing the string
18588 state = UTF8_ACCEPT;
18589 break;
18590 }
18591
18592 default: // LCOV_EXCL_LINE
18593 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18594 }
18595 break;
18596 }
18597
18598 default: // decode found yet incomplete multi-byte code point
18599 {
18600 if (!ensure_ascii)
18601 {
18602 // code point will not be escaped - copy byte to buffer
18603 string_buffer[bytes++] = s[i];
18604 }
18605 ++undumped_chars;
18606 break;
18607 }
18608 }
18609 }
18610
18611 // we finished processing the string
18612 if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
18613 {
18614 // write buffer
18615 if (bytes > 0)
18616 {
18617 o->write_characters(string_buffer.data(), bytes);
18618 }
18619 }
18620 else
18621 {
18622 // we finish reading, but do not accept: string was incomplete
18623 switch (error_handler)
18624 {
18625 case error_handler_t::strict:
18626 {
18627 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));
18628 }
18629
18630 case error_handler_t::ignore:
18631 {
18632 // write all accepted bytes
18633 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18634 break;
18635 }
18636
18637 case error_handler_t::replace:
18638 {
18639 // write all accepted bytes
18640 o->write_characters(string_buffer.data(), bytes_after_last_accept);
18641 // add a replacement character
18642 if (ensure_ascii)
18643 {
18644 o->write_characters("\\ufffd", 6);
18645 }
18646 else
18647 {
18648 o->write_characters("\xEF\xBF\xBD", 3);
18649 }
18650 break;
18651 }
18652
18653 default: // LCOV_EXCL_LINE
18654 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18655 }
18656 }
18657 }
18658
18659 private:
18668 inline unsigned int count_digits(number_unsigned_t x) noexcept
18669 {
18670 unsigned int n_digits = 1;
18671 for (;;)
18672 {
18673 if (x < 10)
18674 {
18675 return n_digits;
18676 }
18677 if (x < 100)
18678 {
18679 return n_digits + 1;
18680 }
18681 if (x < 1000)
18682 {
18683 return n_digits + 2;
18684 }
18685 if (x < 10000)
18686 {
18687 return n_digits + 3;
18688 }
18689 x = x / 10000u;
18690 n_digits += 4;
18691 }
18692 }
18693
18699 static std::string hex_bytes(std::uint8_t byte)
18700 {
18701 std::string result = "FF";
18702 constexpr const char* nibble_to_hex = "0123456789ABCDEF";
18703 result[0] = nibble_to_hex[byte / 16];
18704 result[1] = nibble_to_hex[byte % 16];
18705 return result;
18706 }
18707
18708 // templates to avoid warnings about useless casts
18709 template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
18710 bool is_negative_number(NumberType x)
18711 {
18712 return x < 0;
18713 }
18714
18715 template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
18716 bool is_negative_number(NumberType /*unused*/)
18717 {
18718 return false;
18719 }
18720
18730 template < typename NumberType, detail::enable_if_t <
18731 std::is_integral<NumberType>::value ||
18732 std::is_same<NumberType, number_unsigned_t>::value ||
18733 std::is_same<NumberType, number_integer_t>::value ||
18734 std::is_same<NumberType, binary_char_t>::value,
18735 int > = 0 >
18736 void dump_integer(NumberType x)
18737 {
18738 static constexpr std::array<std::array<char, 2>, 100> digits_to_99
18739 {
18740 {
18741 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
18742 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
18743 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
18744 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
18745 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
18746 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
18747 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
18748 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
18749 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
18750 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
18751 }
18752 };
18753
18754 // special case for "0"
18755 if (x == 0)
18756 {
18757 o->write_character('0');
18758 return;
18759 }
18760
18761 // use a pointer to fill the buffer
18762 auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18763
18764 number_unsigned_t abs_value;
18765
18766 unsigned int n_chars{};
18767
18768 if (is_negative_number(x))
18769 {
18770 *buffer_ptr = '-';
18771 abs_value = remove_sign(static_cast<number_integer_t>(x));
18772
18773 // account one more byte for the minus sign
18774 n_chars = 1 + count_digits(abs_value);
18775 }
18776 else
18777 {
18778 abs_value = static_cast<number_unsigned_t>(x);
18779 n_chars = count_digits(abs_value);
18780 }
18781
18782 // spare 1 byte for '\0'
18783 JSON_ASSERT(n_chars < number_buffer.size() - 1);
18784
18785 // jump to the end to generate the string from backward,
18786 // so we later avoid reversing the result
18787 buffer_ptr += n_chars;
18788
18789 // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
18790 // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
18791 while (abs_value >= 100)
18792 {
18793 const auto digits_index = static_cast<unsigned>((abs_value % 100));
18794 abs_value /= 100;
18795 *(--buffer_ptr) = digits_to_99[digits_index][1];
18796 *(--buffer_ptr) = digits_to_99[digits_index][0];
18797 }
18798
18799 if (abs_value >= 10)
18800 {
18801 const auto digits_index = static_cast<unsigned>(abs_value);
18802 *(--buffer_ptr) = digits_to_99[digits_index][1];
18803 *(--buffer_ptr) = digits_to_99[digits_index][0];
18804 }
18805 else
18806 {
18807 *(--buffer_ptr) = static_cast<char>('0' + abs_value);
18808 }
18809
18810 o->write_characters(number_buffer.data(), n_chars);
18811 }
18812
18821 void dump_float(number_float_t x)
18822 {
18823 // NaN / inf
18824 if (!std::isfinite(x))
18825 {
18826 o->write_characters("null", 4);
18827 return;
18828 }
18829
18830 // If number_float_t is an IEEE-754 single or double precision number,
18831 // use the Grisu2 algorithm to produce short numbers which are
18832 // guaranteed to round-trip, using strtof and strtod, resp.
18833 //
18834 // NB: The test below works if <long double> == <double>.
18835 static constexpr bool is_ieee_single_or_double
18836 = (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) ||
18837 (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);
18838
18839 dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
18840 }
18841
18842 void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
18843 {
18844 auto* begin = number_buffer.data();
18845 auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
18846
18847 o->write_characters(begin, static_cast<size_t>(end - begin));
18848 }
18849
18850 void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
18851 {
18852 // get number of digits for a float -> text -> float round-trip
18853 static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
18854
18855 // the actual conversion
18856 // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
18857 std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
18858
18859 // negative value indicates an error
18860 JSON_ASSERT(len > 0);
18861 // check if buffer was large enough
18862 JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
18863
18864 // erase thousands separator
18865 if (thousands_sep != '\0')
18866 {
18867 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
18868 const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
18869 std::fill(end, number_buffer.end(), '\0');
18870 JSON_ASSERT((end - number_buffer.begin()) <= len);
18871 len = (end - number_buffer.begin());
18872 }
18873
18874 // convert decimal point to '.'
18875 if (decimal_point != '\0' && decimal_point != '.')
18876 {
18877 // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
18878 const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
18879 if (dec_pos != number_buffer.end())
18880 {
18881 *dec_pos = '.';
18882 }
18883 }
18884
18885 o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
18886
18887 // determine if we need to append ".0"
18888 const bool value_is_int_like =
18889 std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
18890 [](char c)
18891 {
18892 return c == '.' || c == 'e';
18893 });
18894
18895 if (value_is_int_like)
18896 {
18897 o->write_characters(".0", 2);
18898 }
18899 }
18900
18922 static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
18923 {
18924 static const std::array<std::uint8_t, 400> utf8d =
18925 {
18926 {
18927 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
18928 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
18929 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
18930 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
18931 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
18932 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
18933 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
18934 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
18935 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
18936 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
18937 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
18938 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
18939 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
18940 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
18941 }
18942 };
18943
18944 JSON_ASSERT(byte < utf8d.size());
18945 const std::uint8_t type = utf8d[byte];
18946
18947 codep = (state != UTF8_ACCEPT)
18948 ? (byte & 0x3fu) | (codep << 6u)
18949 : (0xFFu >> type) & (byte);
18950
18951 const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
18952 JSON_ASSERT(index < utf8d.size());
18953 state = utf8d[index];
18954 return state;
18955 }
18956
18957 /*
18958 * Overload to make the compiler happy while it is instantiating
18959 * dump_integer for number_unsigned_t.
18960 * Must never be called.
18961 */
18962 number_unsigned_t remove_sign(number_unsigned_t x)
18963 {
18964 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
18965 return x; // LCOV_EXCL_LINE
18966 }
18967
18968 /*
18969 * Helper function for dump_integer
18970 *
18971 * This function takes a negative signed integer and returns its absolute
18972 * value as unsigned integer. The plus/minus shuffling is necessary as we can
18973 * not directly remove the sign of an arbitrary signed integer as the
18974 * absolute values of INT_MIN and INT_MAX are usually not the same. See
18975 * #1708 for details.
18976 */
18977 inline number_unsigned_t remove_sign(number_integer_t x) noexcept
18978 {
18979 JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
18980 return static_cast<number_unsigned_t>(-(x + 1)) + 1;
18981 }
18982
18983 private:
18985 output_adapter_t<char> o = nullptr;
18986
18988 std::array<char, 64> number_buffer{{}};
18989
18991 const std::lconv* loc = nullptr;
18993 const char thousands_sep = '\0';
18995 const char decimal_point = '\0';
18996
18998 std::array<char, 512> string_buffer{{}};
18999
19001 const char indent_char;
19004
19007};
19008
19009} // namespace detail
19010NLOHMANN_JSON_NAMESPACE_END
19011
19012// #include <nlohmann/detail/value_t.hpp>
19013
19014// #include <nlohmann/json_fwd.hpp>
19015
19016// #include <nlohmann/ordered_map.hpp>
19017// __ _____ _____ _____
19018// __| | __| | | | JSON for Modern C++
19019// | | |__ | | | | | | version 3.11.3
19020// |_____|_____|_____|_|___| https://github.com/nlohmann/json
19021//
19022// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
19023// SPDX-License-Identifier: MIT
19024
19025
19026
19027#include <functional> // equal_to, less
19028#include <initializer_list> // initializer_list
19029#include <iterator> // input_iterator_tag, iterator_traits
19030#include <memory> // allocator
19031#include <stdexcept> // for out_of_range
19032#include <type_traits> // enable_if, is_convertible
19033#include <utility> // pair
19034#include <vector> // vector
19035
19036// #include <nlohmann/detail/macro_scope.hpp>
19037
19038// #include <nlohmann/detail/meta/type_traits.hpp>
19039
19040
19041NLOHMANN_JSON_NAMESPACE_BEGIN
19042
19045template <class Key, class T, class IgnoredLess = std::less<Key>,
19046 class Allocator = std::allocator<std::pair<const Key, T>>>
19047 struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19048{
19049 using key_type = Key;
19050 using mapped_type = T;
19051 using Container = std::vector<std::pair<const Key, T>, Allocator>;
19052 using iterator = typename Container::iterator;
19053 using const_iterator = typename Container::const_iterator;
19054 using size_type = typename Container::size_type;
19055 using value_type = typename Container::value_type;
19056#ifdef JSON_HAS_CPP_14
19057 using key_compare = std::equal_to<>;
19058#else
19059 using key_compare = std::equal_to<Key>;
19060#endif
19061
19062 // Explicit constructors instead of `using Container::Container`
19063 // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19064 ordered_map() noexcept(noexcept(Container())) : Container{} {}
19065 explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19066 template <class It>
19067 ordered_map(It first, It last, const Allocator& alloc = Allocator())
19068 : Container{first, last, alloc} {}
19069 ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19070 : Container{init, alloc} {}
19071
19072 std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19073 {
19074 for (auto it = this->begin(); it != this->end(); ++it)
19075 {
19076 if (m_compare(it->first, key))
19077 {
19078 return {it, false};
19079 }
19080 }
19081 Container::emplace_back(key, std::forward<T>(t));
19082 return {std::prev(this->end()), true};
19083 }
19084
19085 template<class KeyType, detail::enable_if_t<
19086 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19087 std::pair<iterator, bool> emplace(KeyType && key, T && t)
19088 {
19089 for (auto it = this->begin(); it != this->end(); ++it)
19090 {
19091 if (m_compare(it->first, key))
19092 {
19093 return {it, false};
19094 }
19095 }
19096 Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19097 return {std::prev(this->end()), true};
19098 }
19099
19100 T& operator[](const key_type& key)
19101 {
19102 return emplace(key, T{}).first->second;
19103 }
19104
19105 template<class KeyType, detail::enable_if_t<
19106 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19107 T & operator[](KeyType && key)
19108 {
19109 return emplace(std::forward<KeyType>(key), T{}).first->second;
19110 }
19111
19112 const T& operator[](const key_type& key) const
19113 {
19114 return at(key);
19115 }
19116
19117 template<class KeyType, detail::enable_if_t<
19118 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19119 const T & operator[](KeyType && key) const
19120 {
19121 return at(std::forward<KeyType>(key));
19122 }
19123
19124 T& at(const key_type& key)
19125 {
19126 for (auto it = this->begin(); it != this->end(); ++it)
19127 {
19128 if (m_compare(it->first, key))
19129 {
19130 return it->second;
19131 }
19132 }
19133
19134 JSON_THROW(std::out_of_range("key not found"));
19135 }
19136
19137 template<class KeyType, detail::enable_if_t<
19138 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19139 T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19140 {
19141 for (auto it = this->begin(); it != this->end(); ++it)
19142 {
19143 if (m_compare(it->first, key))
19144 {
19145 return it->second;
19146 }
19147 }
19148
19149 JSON_THROW(std::out_of_range("key not found"));
19150 }
19151
19152 const T& at(const key_type& key) const
19153 {
19154 for (auto it = this->begin(); it != this->end(); ++it)
19155 {
19156 if (m_compare(it->first, key))
19157 {
19158 return it->second;
19159 }
19160 }
19161
19162 JSON_THROW(std::out_of_range("key not found"));
19163 }
19164
19165 template<class KeyType, detail::enable_if_t<
19166 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19167 const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19168 {
19169 for (auto it = this->begin(); it != this->end(); ++it)
19170 {
19171 if (m_compare(it->first, key))
19172 {
19173 return it->second;
19174 }
19175 }
19176
19177 JSON_THROW(std::out_of_range("key not found"));
19178 }
19179
19180 size_type erase(const key_type& key)
19181 {
19182 for (auto it = this->begin(); it != this->end(); ++it)
19183 {
19184 if (m_compare(it->first, key))
19185 {
19186 // Since we cannot move const Keys, re-construct them in place
19187 for (auto next = it; ++next != this->end(); ++it)
19188 {
19189 it->~value_type(); // Destroy but keep allocation
19190 new (&*it) value_type{std::move(*next)};
19191 }
19192 Container::pop_back();
19193 return 1;
19194 }
19195 }
19196 return 0;
19197 }
19198
19199 template<class KeyType, detail::enable_if_t<
19200 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19201 size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19202 {
19203 for (auto it = this->begin(); it != this->end(); ++it)
19204 {
19205 if (m_compare(it->first, key))
19206 {
19207 // Since we cannot move const Keys, re-construct them in place
19208 for (auto next = it; ++next != this->end(); ++it)
19209 {
19210 it->~value_type(); // Destroy but keep allocation
19211 new (&*it) value_type{std::move(*next)};
19212 }
19213 Container::pop_back();
19214 return 1;
19215 }
19216 }
19217 return 0;
19218 }
19219
19220 iterator erase(iterator pos)
19221 {
19222 return erase(pos, std::next(pos));
19223 }
19224
19225 iterator erase(iterator first, iterator last)
19226 {
19227 if (first == last)
19228 {
19229 return first;
19230 }
19231
19232 const auto elements_affected = std::distance(first, last);
19233 const auto offset = std::distance(Container::begin(), first);
19234
19235 // This is the start situation. We need to delete elements_affected
19236 // elements (3 in this example: e, f, g), and need to return an
19237 // iterator past the last deleted element (h in this example).
19238 // Note that offset is the distance from the start of the vector
19239 // to first. We will need this later.
19240
19241 // [ a, b, c, d, e, f, g, h, i, j ]
19242 // ^ ^
19243 // first last
19244
19245 // Since we cannot move const Keys, we re-construct them in place.
19246 // We start at first and re-construct (viz. copy) the elements from
19247 // the back of the vector. Example for first iteration:
19248
19249 // ,--------.
19250 // v | destroy e and re-construct with h
19251 // [ a, b, c, d, e, f, g, h, i, j ]
19252 // ^ ^
19253 // it it + elements_affected
19254
19255 for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19256 {
19257 it->~value_type(); // destroy but keep allocation
19258 new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19259 }
19260
19261 // [ a, b, c, d, h, i, j, h, i, j ]
19262 // ^ ^
19263 // first last
19264
19265 // remove the unneeded elements at the end of the vector
19266 Container::resize(this->size() - static_cast<size_type>(elements_affected));
19267
19268 // [ a, b, c, d, h, i, j ]
19269 // ^ ^
19270 // first last
19271
19272 // first is now pointing past the last deleted element, but we cannot
19273 // use this iterator, because it may have been invalidated by the
19274 // resize call. Instead, we can return begin() + offset.
19275 return Container::begin() + offset;
19276 }
19277
19278 size_type count(const key_type& key) const
19279 {
19280 for (auto it = this->begin(); it != this->end(); ++it)
19281 {
19282 if (m_compare(it->first, key))
19283 {
19284 return 1;
19285 }
19286 }
19287 return 0;
19288 }
19289
19290 template<class KeyType, detail::enable_if_t<
19291 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19292 size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19293 {
19294 for (auto it = this->begin(); it != this->end(); ++it)
19295 {
19296 if (m_compare(it->first, key))
19297 {
19298 return 1;
19299 }
19300 }
19301 return 0;
19302 }
19303
19304 iterator find(const key_type& key)
19305 {
19306 for (auto it = this->begin(); it != this->end(); ++it)
19307 {
19308 if (m_compare(it->first, key))
19309 {
19310 return it;
19311 }
19312 }
19313 return Container::end();
19314 }
19315
19316 template<class KeyType, detail::enable_if_t<
19317 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19318 iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19319 {
19320 for (auto it = this->begin(); it != this->end(); ++it)
19321 {
19322 if (m_compare(it->first, key))
19323 {
19324 return it;
19325 }
19326 }
19327 return Container::end();
19328 }
19329
19330 const_iterator find(const key_type& key) const
19331 {
19332 for (auto it = this->begin(); it != this->end(); ++it)
19333 {
19334 if (m_compare(it->first, key))
19335 {
19336 return it;
19337 }
19338 }
19339 return Container::end();
19340 }
19341
19342 std::pair<iterator, bool> insert( value_type&& value )
19343 {
19344 return emplace(value.first, std::move(value.second));
19345 }
19346
19347 std::pair<iterator, bool> insert( const value_type& value )
19348 {
19349 for (auto it = this->begin(); it != this->end(); ++it)
19350 {
19351 if (m_compare(it->first, value.first))
19352 {
19353 return {it, false};
19354 }
19355 }
19356 Container::push_back(value);
19357 return {--this->end(), true};
19358 }
19359
19360 template<typename InputIt>
19361 using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
19362 std::input_iterator_tag>::value>::type;
19363
19364 template<typename InputIt, typename = require_input_iter<InputIt>>
19365 void insert(InputIt first, InputIt last)
19366 {
19367 for (auto it = first; it != last; ++it)
19368 {
19369 insert(*it);
19370 }
19371 }
19372
19373private:
19374 JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
19375};
19376
19377NLOHMANN_JSON_NAMESPACE_END
19378
19379
19380#if defined(JSON_HAS_CPP_17)
19381 #if JSON_HAS_STATIC_RTTI
19382 #include <any>
19383 #endif
19384 #include <string_view>
19385#endif
19386
19392NLOHMANN_JSON_NAMESPACE_BEGIN
19393
19412NLOHMANN_BASIC_JSON_TPL_DECLARATION
19413class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
19414 : public ::nlohmann::detail::json_base_class<CustomBaseClass>
19415{
19416 private:
19417 template<detail::value_t> friend struct detail::external_constructor;
19418
19419 template<typename>
19420 friend class ::nlohmann::json_pointer;
19421 // can be restored when json_pointer backwards compatibility is removed
19422 // friend ::nlohmann::json_pointer<StringType>;
19423
19424 template<typename BasicJsonType, typename InputType>
19425 friend class ::nlohmann::detail::parser;
19426 friend ::nlohmann::detail::serializer<basic_json>;
19427 template<typename BasicJsonType>
19428 friend class ::nlohmann::detail::iter_impl;
19429 template<typename BasicJsonType, typename CharType>
19430 friend class ::nlohmann::detail::binary_writer;
19431 template<typename BasicJsonType, typename InputType, typename SAX>
19432 friend class ::nlohmann::detail::binary_reader;
19433 template<typename BasicJsonType>
19434 friend class ::nlohmann::detail::json_sax_dom_parser;
19435 template<typename BasicJsonType>
19436 friend class ::nlohmann::detail::json_sax_dom_callback_parser;
19437 friend class ::nlohmann::detail::exception;
19438
19440 using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
19441 using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
19442
19443 JSON_PRIVATE_UNLESS_TESTED:
19444 // convenience aliases for types residing in namespace detail;
19445 using lexer = ::nlohmann::detail::lexer_base<basic_json>;
19446
19447 template<typename InputAdapterType>
19448 static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
19449 InputAdapterType adapter,
19450 detail::parser_callback_t<basic_json>cb = nullptr,
19451 const bool allow_exceptions = true,
19452 const bool ignore_comments = false
19453 )
19454 {
19455 return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
19456 std::move(cb), allow_exceptions, ignore_comments);
19457 }
19458
19459 private:
19460 using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
19461 template<typename BasicJsonType>
19462 using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
19463 template<typename BasicJsonType>
19464 using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
19465 template<typename Iterator>
19466 using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
19467 template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
19468
19469 template<typename CharType>
19470 using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
19471
19472 template<typename InputType>
19473 using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
19474 template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
19475
19476 JSON_PRIVATE_UNLESS_TESTED:
19477 using serializer = ::nlohmann::detail::serializer<basic_json>;
19478
19479 public:
19480 using value_t = detail::value_t;
19482 using json_pointer = ::nlohmann::json_pointer<StringType>;
19483 template<typename T, typename SFINAE>
19484 using json_serializer = JSONSerializer<T, SFINAE>;
19490 using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
19491
19495
19497 // exceptions //
19499
19503
19510
19512
19514 // container types //
19516
19521
19524
19529
19531 using difference_type = std::ptrdiff_t;
19533 using size_type = std::size_t;
19534
19536 using allocator_type = AllocatorType<basic_json>;
19537
19539 using pointer = typename std::allocator_traits<allocator_type>::pointer;
19541 using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
19542
19544 using iterator = iter_impl<basic_json>;
19546 using const_iterator = iter_impl<const basic_json>;
19548 using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
19550 using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
19551
19553
19557 {
19558 return allocator_type();
19559 }
19560
19563 JSON_HEDLEY_WARN_UNUSED_RESULT
19565 {
19566 basic_json result;
19567
19568 result["copyright"] = "(C) 2013-2023 Niels Lohmann";
19569 result["name"] = "JSON for Modern C++";
19570 result["url"] = "https://github.com/nlohmann/json";
19571 result["version"]["string"] =
19572 detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
19573 std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
19574 std::to_string(NLOHMANN_JSON_VERSION_PATCH));
19575 result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
19576 result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
19577 result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
19578
19579#ifdef _WIN32
19580 result["platform"] = "win32";
19581#elif defined __linux__
19582 result["platform"] = "linux";
19583#elif defined __APPLE__
19584 result["platform"] = "apple";
19585#elif defined __unix__
19586 result["platform"] = "unix";
19587#else
19588 result["platform"] = "unknown";
19589#endif
19590
19591#if defined(__ICC) || defined(__INTEL_COMPILER)
19592 result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
19593#elif defined(__clang__)
19594 result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
19595#elif defined(__GNUC__) || defined(__GNUG__)
19596 result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
19597 std::to_string(__GNUC__), '.',
19598 std::to_string(__GNUC_MINOR__), '.',
19599 std::to_string(__GNUC_PATCHLEVEL__))
19600 }
19601 };
19602#elif defined(__HP_cc) || defined(__HP_aCC)
19603 result["compiler"] = "hp"
19604#elif defined(__IBMCPP__)
19605 result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
19606#elif defined(_MSC_VER)
19607 result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
19608#elif defined(__PGI)
19609 result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
19610#elif defined(__SUNPRO_CC)
19611 result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
19612#else
19613 result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
19614#endif
19615
19616#if defined(_MSVC_LANG)
19617 result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
19618#elif defined(__cplusplus)
19619 result["compiler"]["c++"] = std::to_string(__cplusplus);
19620#else
19621 result["compiler"]["c++"] = "unknown";
19622#endif
19623 return result;
19624 }
19625
19627 // JSON value data types //
19629
19634
19639#if defined(JSON_HAS_CPP_14)
19640 // use of transparent comparator avoids unnecessary repeated construction of temporaries
19641 // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
19642 using default_object_comparator_t = std::less<>;
19643#else
19644 using default_object_comparator_t = std::less<StringType>;
19645#endif
19646
19649 using object_t = ObjectType<StringType,
19650 basic_json,
19652 AllocatorType<std::pair<const StringType,
19653 basic_json>>>;
19654
19657 using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
19658
19661 using string_t = StringType;
19662
19665 using boolean_t = BooleanType;
19666
19669 using number_integer_t = NumberIntegerType;
19670
19673 using number_unsigned_t = NumberUnsignedType;
19674
19677 using number_float_t = NumberFloatType;
19678
19681 using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
19682
19685 using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
19686
19688
19689 private:
19690
19692 template<typename T, typename... Args>
19693 JSON_HEDLEY_RETURNS_NON_NULL
19694 static T* create(Args&& ... args)
19695 {
19696 AllocatorType<T> alloc;
19697 using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
19698
19699 auto deleter = [&](T * obj)
19700 {
19701 AllocatorTraits::deallocate(alloc, obj, 1);
19702 };
19703 std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
19704 AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
19705 JSON_ASSERT(obj != nullptr);
19706 return obj.release();
19707 }
19708
19710 // JSON value storage //
19712
19713 JSON_PRIVATE_UNLESS_TESTED:
19739 union json_value
19740 {
19742 object_t* object;
19744 array_t* array;
19746 string_t* string;
19748 binary_t* binary;
19750 boolean_t boolean;
19752 number_integer_t number_integer;
19754 number_unsigned_t number_unsigned;
19756 number_float_t number_float;
19757
19759 json_value() = default;
19761 json_value(boolean_t v) noexcept : boolean(v) {}
19763 json_value(number_integer_t v) noexcept : number_integer(v) {}
19765 json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
19767 json_value(number_float_t v) noexcept : number_float(v) {}
19769 json_value(value_t t)
19770 {
19771 switch (t)
19772 {
19773 case value_t::object:
19774 {
19775 object = create<object_t>();
19776 break;
19777 }
19778
19779 case value_t::array:
19780 {
19781 array = create<array_t>();
19782 break;
19783 }
19784
19785 case value_t::string:
19786 {
19787 string = create<string_t>("");
19788 break;
19789 }
19790
19791 case value_t::binary:
19792 {
19793 binary = create<binary_t>();
19794 break;
19795 }
19796
19797 case value_t::boolean:
19798 {
19799 boolean = static_cast<boolean_t>(false);
19800 break;
19801 }
19802
19803 case value_t::number_integer:
19804 {
19805 number_integer = static_cast<number_integer_t>(0);
19806 break;
19807 }
19808
19809 case value_t::number_unsigned:
19810 {
19811 number_unsigned = static_cast<number_unsigned_t>(0);
19812 break;
19813 }
19814
19815 case value_t::number_float:
19816 {
19817 number_float = static_cast<number_float_t>(0.0);
19818 break;
19819 }
19820
19821 case value_t::null:
19822 {
19823 object = nullptr; // silence warning, see #821
19824 break;
19825 }
19826
19827 case value_t::discarded:
19828 default:
19829 {
19830 object = nullptr; // silence warning, see #821
19831 if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
19832 {
19833 JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
19834 }
19835 break;
19836 }
19837 }
19838 }
19839
19841 json_value(const string_t& value) : string(create<string_t>(value)) {}
19842
19844 json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
19845
19847 json_value(const object_t& value) : object(create<object_t>(value)) {}
19848
19850 json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
19851
19853 json_value(const array_t& value) : array(create<array_t>(value)) {}
19854
19856 json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
19857
19859 json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
19860
19862 json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
19863
19865 json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
19866
19868 json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
19869
19870 void destroy(value_t t)
19871 {
19872 if (
19873 (t == value_t::object && object == nullptr) ||
19874 (t == value_t::array && array == nullptr) ||
19875 (t == value_t::string && string == nullptr) ||
19876 (t == value_t::binary && binary == nullptr)
19877 )
19878 {
19879 //not initialized (e.g. due to exception in the ctor)
19880 return;
19881 }
19882 if (t == value_t::array || t == value_t::object)
19883 {
19884 // flatten the current json_value to a heap-allocated stack
19885 std::vector<basic_json> stack;
19886
19887 // move the top-level items to stack
19888 if (t == value_t::array)
19889 {
19890 stack.reserve(array->size());
19891 std::move(array->begin(), array->end(), std::back_inserter(stack));
19892 }
19893 else
19894 {
19895 stack.reserve(object->size());
19896 for (auto&& it : *object)
19897 {
19898 stack.push_back(std::move(it.second));
19899 }
19900 }
19901
19902 while (!stack.empty())
19903 {
19904 // move the last item to local variable to be processed
19905 basic_json current_item(std::move(stack.back()));
19906 stack.pop_back();
19907
19908 // if current_item is array/object, move
19909 // its children to the stack to be processed later
19910 if (current_item.is_array())
19911 {
19912 std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
19913
19914 current_item.m_data.m_value.array->clear();
19915 }
19916 else if (current_item.is_object())
19917 {
19918 for (auto&& it : *current_item.m_data.m_value.object)
19919 {
19920 stack.push_back(std::move(it.second));
19921 }
19922
19923 current_item.m_data.m_value.object->clear();
19924 }
19925
19926 // it's now safe that current_item get destructed
19927 // since it doesn't have any children
19928 }
19929 }
19930
19931 switch (t)
19932 {
19933 case value_t::object:
19934 {
19935 AllocatorType<object_t> alloc;
19936 std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
19937 std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
19938 break;
19939 }
19940
19941 case value_t::array:
19942 {
19943 AllocatorType<array_t> alloc;
19944 std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
19945 std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
19946 break;
19947 }
19948
19949 case value_t::string:
19950 {
19951 AllocatorType<string_t> alloc;
19952 std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
19953 std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
19954 break;
19955 }
19956
19957 case value_t::binary:
19958 {
19959 AllocatorType<binary_t> alloc;
19960 std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
19961 std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
19962 break;
19963 }
19964
19965 case value_t::null:
19966 case value_t::boolean:
19967 case value_t::number_integer:
19968 case value_t::number_unsigned:
19969 case value_t::number_float:
19970 case value_t::discarded:
19971 default:
19972 {
19973 break;
19974 }
19975 }
19976 }
19977 };
19978
19979 private:
19998 void assert_invariant(bool check_parents = true) const noexcept
19999 {
20000 JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20001 JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20002 JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20003 JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20004
20005#if JSON_DIAGNOSTICS
20006 JSON_TRY
20007 {
20008 // cppcheck-suppress assertWithSideEffect
20009 JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20010 {
20011 return j.m_parent == this;
20012 }));
20013 }
20014 JSON_CATCH(...) {} // LCOV_EXCL_LINE
20015#endif
20016 static_cast<void>(check_parents);
20017 }
20018
20019 void set_parents()
20020 {
20021#if JSON_DIAGNOSTICS
20022 switch (m_data.m_type)
20023 {
20024 case value_t::array:
20025 {
20026 for (auto& element : *m_data.m_value.array)
20027 {
20028 element.m_parent = this;
20029 }
20030 break;
20031 }
20032
20033 case value_t::object:
20034 {
20035 for (auto& element : *m_data.m_value.object)
20036 {
20037 element.second.m_parent = this;
20038 }
20039 break;
20040 }
20041
20042 case value_t::null:
20043 case value_t::string:
20044 case value_t::boolean:
20045 case value_t::number_integer:
20046 case value_t::number_unsigned:
20047 case value_t::number_float:
20048 case value_t::binary:
20049 case value_t::discarded:
20050 default:
20051 break;
20052 }
20053#endif
20054 }
20055
20056 iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20057 {
20058#if JSON_DIAGNOSTICS
20059 for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20060 {
20061 (it + i)->m_parent = this;
20062 }
20063#else
20064 static_cast<void>(count_set_parents);
20065#endif
20066 return it;
20067 }
20068
20069 reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
20070 {
20071#if JSON_DIAGNOSTICS
20072 if (old_capacity != static_cast<std::size_t>(-1))
20073 {
20074 // see https://github.com/nlohmann/json/issues/2838
20075 JSON_ASSERT(type() == value_t::array);
20076 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20077 {
20078 // capacity has changed: update all parents
20079 set_parents();
20080 return j;
20081 }
20082 }
20083
20084 // ordered_json uses a vector internally, so pointers could have
20085 // been invalidated; see https://github.com/nlohmann/json/issues/2962
20086#ifdef JSON_HEDLEY_MSVC_VERSION
20087#pragma warning(push )
20088#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20089#endif
20091 {
20092 set_parents();
20093 return j;
20094 }
20095#ifdef JSON_HEDLEY_MSVC_VERSION
20096#pragma warning( pop )
20097#endif
20098
20099 j.m_parent = this;
20100#else
20101 static_cast<void>(j);
20102 static_cast<void>(old_capacity);
20103#endif
20104 return j;
20105 }
20106
20107 public:
20109 // JSON parser callback //
20111
20115
20118 using parser_callback_t = detail::parser_callback_t<basic_json>;
20119
20121 // constructors //
20123
20128
20132 : m_data(v)
20133 {
20134 assert_invariant();
20135 }
20136
20139 basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20140 : basic_json(value_t::null)
20141 {
20142 assert_invariant();
20143 }
20144
20147 template < typename CompatibleType,
20148 typename U = detail::uncvref_t<CompatibleType>,
20149 detail::enable_if_t <
20151 basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20152 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20153 std::forward<CompatibleType>(val))))
20154 {
20155 JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20156 set_parents();
20157 assert_invariant();
20158 }
20159
20162 template < typename BasicJsonType,
20163 detail::enable_if_t <
20164 detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20165 basic_json(const BasicJsonType& val)
20166 {
20167 using other_boolean_t = typename BasicJsonType::boolean_t;
20168 using other_number_float_t = typename BasicJsonType::number_float_t;
20169 using other_number_integer_t = typename BasicJsonType::number_integer_t;
20170 using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20171 using other_string_t = typename BasicJsonType::string_t;
20172 using other_object_t = typename BasicJsonType::object_t;
20173 using other_array_t = typename BasicJsonType::array_t;
20174 using other_binary_t = typename BasicJsonType::binary_t;
20175
20176 switch (val.type())
20177 {
20178 case value_t::boolean:
20179 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20180 break;
20181 case value_t::number_float:
20182 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20183 break;
20184 case value_t::number_integer:
20185 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20186 break;
20187 case value_t::number_unsigned:
20188 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20189 break;
20190 case value_t::string:
20191 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20192 break;
20193 case value_t::object:
20194 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20195 break;
20196 case value_t::array:
20197 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20198 break;
20199 case value_t::binary:
20200 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20201 break;
20202 case value_t::null:
20203 *this = nullptr;
20204 break;
20205 case value_t::discarded:
20206 m_data.m_type = value_t::discarded;
20207 break;
20208 default: // LCOV_EXCL_LINE
20209 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20210 }
20211 JSON_ASSERT(m_data.m_type == val.type());
20212 set_parents();
20213 assert_invariant();
20214 }
20215
20219 bool type_deduction = true,
20220 value_t manual_type = value_t::array)
20221 {
20222 // check if each element is an array with two elements whose first
20223 // element is a string
20224 bool is_an_object = std::all_of(init.begin(), init.end(),
20225 [](const detail::json_ref<basic_json>& element_ref)
20226 {
20227 // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20228 // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20229 // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20230 return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20231 });
20232
20233 // adjust type if type deduction is not wanted
20234 if (!type_deduction)
20235 {
20236 // if array is wanted, do not create an object though possible
20237 if (manual_type == value_t::array)
20238 {
20239 is_an_object = false;
20240 }
20241
20242 // if object is wanted but impossible, throw an exception
20243 if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20244 {
20245 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20246 }
20247 }
20248
20249 if (is_an_object)
20250 {
20251 // the initializer list is a list of pairs -> create object
20252 m_data.m_type = value_t::object;
20253 m_data.m_value = value_t::object;
20254
20255 for (auto& element_ref : init)
20256 {
20257 auto element = element_ref.moved_or_copied();
20258 m_data.m_value.object->emplace(
20259 std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20260 std::move((*element.m_data.m_value.array)[1]));
20261 }
20262 }
20263 else
20264 {
20265 // the initializer list describes an array -> create array
20266 m_data.m_type = value_t::array;
20267 m_data.m_value.array = create<array_t>(init.begin(), init.end());
20268 }
20269
20270 set_parents();
20271 assert_invariant();
20272 }
20273
20276 JSON_HEDLEY_WARN_UNUSED_RESULT
20277 static basic_json binary(const typename binary_t::container_type& init)
20278 {
20279 auto res = basic_json();
20280 res.m_data.m_type = value_t::binary;
20281 res.m_data.m_value = init;
20282 return res;
20283 }
20284
20287 JSON_HEDLEY_WARN_UNUSED_RESULT
20288 static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20289 {
20290 auto res = basic_json();
20291 res.m_data.m_type = value_t::binary;
20292 res.m_data.m_value = binary_t(init, subtype);
20293 return res;
20294 }
20295
20298 JSON_HEDLEY_WARN_UNUSED_RESULT
20299 static basic_json binary(typename binary_t::container_type&& init)
20300 {
20301 auto res = basic_json();
20302 res.m_data.m_type = value_t::binary;
20303 res.m_data.m_value = std::move(init);
20304 return res;
20305 }
20306
20309 JSON_HEDLEY_WARN_UNUSED_RESULT
20310 static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
20311 {
20312 auto res = basic_json();
20313 res.m_data.m_type = value_t::binary;
20314 res.m_data.m_value = binary_t(std::move(init), subtype);
20315 return res;
20316 }
20317
20320 JSON_HEDLEY_WARN_UNUSED_RESULT
20322 {
20323 return basic_json(init, false, value_t::array);
20324 }
20325
20328 JSON_HEDLEY_WARN_UNUSED_RESULT
20330 {
20331 return basic_json(init, false, value_t::object);
20332 }
20333
20337 m_data{cnt, val}
20338 {
20339 set_parents();
20340 assert_invariant();
20341 }
20342
20345 template < class InputIT, typename std::enable_if <
20346 std::is_same<InputIT, typename basic_json_t::iterator>::value ||
20347 std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
20348 basic_json(InputIT first, InputIT last)
20349 {
20350 JSON_ASSERT(first.m_object != nullptr);
20351 JSON_ASSERT(last.m_object != nullptr);
20352
20353 // make sure iterator fits the current value
20354 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
20355 {
20356 JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
20357 }
20358
20359 // copy type from first iterator
20360 m_data.m_type = first.m_object->m_data.m_type;
20361
20362 // check if iterator range is complete for primitive values
20363 switch (m_data.m_type)
20364 {
20365 case value_t::boolean:
20366 case value_t::number_float:
20367 case value_t::number_integer:
20368 case value_t::number_unsigned:
20369 case value_t::string:
20370 {
20371 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
20372 || !last.m_it.primitive_iterator.is_end()))
20373 {
20374 JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
20375 }
20376 break;
20377 }
20378
20379 case value_t::null:
20380 case value_t::object:
20381 case value_t::array:
20382 case value_t::binary:
20383 case value_t::discarded:
20384 default:
20385 break;
20386 }
20387
20388 switch (m_data.m_type)
20389 {
20390 case value_t::number_integer:
20391 {
20392 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
20393 break;
20394 }
20395
20396 case value_t::number_unsigned:
20397 {
20398 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
20399 break;
20400 }
20401
20402 case value_t::number_float:
20403 {
20404 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
20405 break;
20406 }
20407
20408 case value_t::boolean:
20409 {
20410 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
20411 break;
20412 }
20413
20414 case value_t::string:
20415 {
20416 m_data.m_value = *first.m_object->m_data.m_value.string;
20417 break;
20418 }
20419
20420 case value_t::object:
20421 {
20422 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
20423 last.m_it.object_iterator);
20424 break;
20425 }
20426
20427 case value_t::array:
20428 {
20429 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
20430 last.m_it.array_iterator);
20431 break;
20432 }
20433
20434 case value_t::binary:
20435 {
20436 m_data.m_value = *first.m_object->m_data.m_value.binary;
20437 break;
20438 }
20439
20440 case value_t::null:
20441 case value_t::discarded:
20442 default:
20443 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
20444 }
20445
20446 set_parents();
20447 assert_invariant();
20448 }
20449
20451 // other constructors and destructor //
20453
20454 template<typename JsonRef,
20455 detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
20456 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
20457 basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
20458
20462 : json_base_class_t(other)
20463 {
20464 m_data.m_type = other.m_data.m_type;
20465 // check of passed value is valid
20466 other.assert_invariant();
20467
20468 switch (m_data.m_type)
20469 {
20470 case value_t::object:
20471 {
20472 m_data.m_value = *other.m_data.m_value.object;
20473 break;
20474 }
20475
20476 case value_t::array:
20477 {
20478 m_data.m_value = *other.m_data.m_value.array;
20479 break;
20480 }
20481
20482 case value_t::string:
20483 {
20484 m_data.m_value = *other.m_data.m_value.string;
20485 break;
20486 }
20487
20488 case value_t::boolean:
20489 {
20490 m_data.m_value = other.m_data.m_value.boolean;
20491 break;
20492 }
20493
20494 case value_t::number_integer:
20495 {
20496 m_data.m_value = other.m_data.m_value.number_integer;
20497 break;
20498 }
20499
20500 case value_t::number_unsigned:
20501 {
20502 m_data.m_value = other.m_data.m_value.number_unsigned;
20503 break;
20504 }
20505
20506 case value_t::number_float:
20507 {
20508 m_data.m_value = other.m_data.m_value.number_float;
20509 break;
20510 }
20511
20512 case value_t::binary:
20513 {
20514 m_data.m_value = *other.m_data.m_value.binary;
20515 break;
20516 }
20517
20518 case value_t::null:
20519 case value_t::discarded:
20520 default:
20521 break;
20522 }
20523
20524 set_parents();
20525 assert_invariant();
20526 }
20527
20530 basic_json(basic_json&& other) noexcept
20531 : json_base_class_t(std::forward<json_base_class_t>(other)),
20532 m_data(std::move(other.m_data))
20533 {
20534 // check that passed value is valid
20535 other.assert_invariant(false);
20536
20537 // invalidate payload
20538 other.m_data.m_type = value_t::null;
20539 other.m_data.m_value = {};
20540
20541 set_parents();
20542 assert_invariant();
20543 }
20544
20548 std::is_nothrow_move_constructible<value_t>::value&&
20549 std::is_nothrow_move_assignable<value_t>::value&&
20550 std::is_nothrow_move_constructible<json_value>::value&&
20551 std::is_nothrow_move_assignable<json_value>::value&&
20552 std::is_nothrow_move_assignable<json_base_class_t>::value
20553 )
20554 {
20555 // check that passed value is valid
20556 other.assert_invariant();
20557
20558 using std::swap;
20559 swap(m_data.m_type, other.m_data.m_type);
20560 swap(m_data.m_value, other.m_data.m_value);
20561 json_base_class_t::operator=(std::move(other));
20562
20563 set_parents();
20564 assert_invariant();
20565 return *this;
20566 }
20567
20570 ~basic_json() noexcept
20571 {
20572 assert_invariant(false);
20573 }
20574
20576
20577 public:
20579 // object inspection //
20581
20585
20588 string_t dump(const int indent = -1,
20589 const char indent_char = ' ',
20590 const bool ensure_ascii = false,
20591 const error_handler_t error_handler = error_handler_t::strict) const
20592 {
20593 string_t result;
20594 serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
20595
20596 if (indent >= 0)
20597 {
20598 s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
20599 }
20600 else
20601 {
20602 s.dump(*this, false, ensure_ascii, 0);
20603 }
20604
20605 return result;
20606 }
20607
20610 constexpr value_t type() const noexcept
20611 {
20612 return m_data.m_type;
20613 }
20614
20617 constexpr bool is_primitive() const noexcept
20618 {
20619 return is_null() || is_string() || is_boolean() || is_number() || is_binary();
20620 }
20621
20624 constexpr bool is_structured() const noexcept
20625 {
20626 return is_array() || is_object();
20627 }
20628
20631 constexpr bool is_null() const noexcept
20632 {
20633 return m_data.m_type == value_t::null;
20634 }
20635
20638 constexpr bool is_boolean() const noexcept
20639 {
20640 return m_data.m_type == value_t::boolean;
20641 }
20642
20645 constexpr bool is_number() const noexcept
20646 {
20647 return is_number_integer() || is_number_float();
20648 }
20649
20652 constexpr bool is_number_integer() const noexcept
20653 {
20654 return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
20655 }
20656
20659 constexpr bool is_number_unsigned() const noexcept
20660 {
20661 return m_data.m_type == value_t::number_unsigned;
20662 }
20663
20666 constexpr bool is_number_float() const noexcept
20667 {
20668 return m_data.m_type == value_t::number_float;
20669 }
20670
20673 constexpr bool is_object() const noexcept
20674 {
20675 return m_data.m_type == value_t::object;
20676 }
20677
20680 constexpr bool is_array() const noexcept
20681 {
20682 return m_data.m_type == value_t::array;
20683 }
20684
20687 constexpr bool is_string() const noexcept
20688 {
20689 return m_data.m_type == value_t::string;
20690 }
20691
20694 constexpr bool is_binary() const noexcept
20695 {
20696 return m_data.m_type == value_t::binary;
20697 }
20698
20701 constexpr bool is_discarded() const noexcept
20702 {
20703 return m_data.m_type == value_t::discarded;
20704 }
20705
20708 constexpr operator value_t() const noexcept
20709 {
20710 return m_data.m_type;
20711 }
20712
20714
20715 private:
20717 // value access //
20719
20721 boolean_t get_impl(boolean_t* /*unused*/) const
20722 {
20723 if (JSON_HEDLEY_LIKELY(is_boolean()))
20724 {
20725 return m_data.m_value.boolean;
20726 }
20727
20728 JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
20729 }
20730
20732 object_t* get_impl_ptr(object_t* /*unused*/) noexcept
20733 {
20734 return is_object() ? m_data.m_value.object : nullptr;
20735 }
20736
20738 constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
20739 {
20740 return is_object() ? m_data.m_value.object : nullptr;
20741 }
20742
20744 array_t* get_impl_ptr(array_t* /*unused*/) noexcept
20745 {
20746 return is_array() ? m_data.m_value.array : nullptr;
20747 }
20748
20750 constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
20751 {
20752 return is_array() ? m_data.m_value.array : nullptr;
20753 }
20754
20756 string_t* get_impl_ptr(string_t* /*unused*/) noexcept
20757 {
20758 return is_string() ? m_data.m_value.string : nullptr;
20759 }
20760
20762 constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
20763 {
20764 return is_string() ? m_data.m_value.string : nullptr;
20765 }
20766
20768 boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
20769 {
20770 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20771 }
20772
20774 constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
20775 {
20776 return is_boolean() ? &m_data.m_value.boolean : nullptr;
20777 }
20778
20780 number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
20781 {
20782 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20783 }
20784
20786 constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
20787 {
20788 return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
20789 }
20790
20792 number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
20793 {
20794 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20795 }
20796
20798 constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
20799 {
20800 return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
20801 }
20802
20804 number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
20805 {
20806 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20807 }
20808
20810 constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
20811 {
20812 return is_number_float() ? &m_data.m_value.number_float : nullptr;
20813 }
20814
20816 binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
20817 {
20818 return is_binary() ? m_data.m_value.binary : nullptr;
20819 }
20820
20822 constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
20823 {
20824 return is_binary() ? m_data.m_value.binary : nullptr;
20825 }
20826
20838 template<typename ReferenceType, typename ThisType>
20839 static ReferenceType get_ref_impl(ThisType& obj)
20840 {
20841 // delegate the call to get_ptr<>()
20842 auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
20843
20844 if (JSON_HEDLEY_LIKELY(ptr != nullptr))
20845 {
20846 return *ptr;
20847 }
20848
20849 JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
20850 }
20851
20852 public:
20856
20859 template<typename PointerType, typename std::enable_if<
20860 std::is_pointer<PointerType>::value, int>::type = 0>
20861 auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20862 {
20863 // delegate the call to get_impl_ptr<>()
20864 return get_impl_ptr(static_cast<PointerType>(nullptr));
20865 }
20866
20869 template < typename PointerType, typename std::enable_if <
20870 std::is_pointer<PointerType>::value&&
20871 std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
20872 constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
20873 {
20874 // delegate the call to get_impl_ptr<>() const
20875 return get_impl_ptr(static_cast<PointerType>(nullptr));
20876 }
20877
20878 private:
20917 template < typename ValueType,
20918 detail::enable_if_t <
20921 int > = 0 >
20922 ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
20923 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
20924 {
20925 auto ret = ValueType();
20926 JSONSerializer<ValueType>::from_json(*this, ret);
20927 return ret;
20928 }
20929
20960 template < typename ValueType,
20961 detail::enable_if_t <
20963 int > = 0 >
20964 ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
20965 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
20966 {
20967 return JSONSerializer<ValueType>::from_json(*this);
20968 }
20969
20985 template < typename BasicJsonType,
20986 detail::enable_if_t <
20988 int > = 0 >
20989 BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
20990 {
20991 return *this;
20992 }
20993
21008 template<typename BasicJsonType,
21009 detail::enable_if_t<
21010 std::is_same<BasicJsonType, basic_json_t>::value,
21011 int> = 0>
21012 basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21013 {
21014 return *this;
21015 }
21016
21021 template<typename PointerType,
21022 detail::enable_if_t<
21023 std::is_pointer<PointerType>::value,
21024 int> = 0>
21025 constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21026 -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21027 {
21028 // delegate the call to get_ptr
21029 return get_ptr<PointerType>();
21030 }
21031
21032 public:
21056 template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21057#if defined(JSON_HAS_CPP_14)
21058 constexpr
21059#endif
21060 auto get() const noexcept(
21061 noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21062 -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21063 {
21064 // we cannot static_assert on ValueTypeCV being non-const, because
21065 // there is support for get<const basic_json_t>(), which is why we
21066 // still need the uncvref
21067 static_assert(!std::is_reference<ValueTypeCV>::value,
21068 "get() cannot be used with reference types, you might want to use get_ref()");
21069 return get_impl<ValueType>(detail::priority_tag<4> {});
21070 }
21071
21099 template<typename PointerType, typename std::enable_if<
21100 std::is_pointer<PointerType>::value, int>::type = 0>
21101 auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21102 {
21103 // delegate the call to get_ptr
21104 return get_ptr<PointerType>();
21105 }
21106
21109 template < typename ValueType,
21110 detail::enable_if_t <
21113 int > = 0 >
21114 ValueType & get_to(ValueType& v) const noexcept(noexcept(
21115 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21116 {
21117 JSONSerializer<ValueType>::from_json(*this, v);
21118 return v;
21119 }
21120
21121 // specialization to allow calling get_to with a basic_json value
21122 // see https://github.com/nlohmann/json/issues/2175
21123 template<typename ValueType,
21124 detail::enable_if_t <
21126 int> = 0>
21127 ValueType & get_to(ValueType& v) const
21128 {
21129 v = *this;
21130 return v;
21131 }
21132
21133 template <
21134 typename T, std::size_t N,
21135 typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21136 detail::enable_if_t <
21138 Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21139 noexcept(noexcept(JSONSerializer<Array>::from_json(
21140 std::declval<const basic_json_t&>(), v)))
21141 {
21142 JSONSerializer<Array>::from_json(*this, v);
21143 return v;
21144 }
21145
21148 template<typename ReferenceType, typename std::enable_if<
21149 std::is_reference<ReferenceType>::value, int>::type = 0>
21150 ReferenceType get_ref()
21151 {
21152 // delegate call to get_ref_impl
21153 return get_ref_impl<ReferenceType>(*this);
21154 }
21155
21158 template < typename ReferenceType, typename std::enable_if <
21159 std::is_reference<ReferenceType>::value&&
21160 std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21161 ReferenceType get_ref() const
21162 {
21163 // delegate call to get_ref_impl
21164 return get_ref_impl<ReferenceType>(*this);
21165 }
21166
21196 template < typename ValueType, typename std::enable_if <
21204#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21206#endif
21207#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21209#endif
21211 >::value, int >::type = 0 >
21212 JSON_EXPLICIT operator ValueType() const
21213 {
21214 // delegate the call to get<>() const
21215 return get<ValueType>();
21216 }
21217
21221 {
21222 if (!is_binary())
21223 {
21224 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21225 }
21226
21227 return *get_ptr<binary_t*>();
21228 }
21229
21232 const binary_t& get_binary() const
21233 {
21234 if (!is_binary())
21235 {
21236 JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21237 }
21238
21239 return *get_ptr<const binary_t*>();
21240 }
21241
21243
21245 // element access //
21247
21251
21255 {
21256 // at only works for arrays
21257 if (JSON_HEDLEY_LIKELY(is_array()))
21258 {
21259 JSON_TRY
21260 {
21261 return set_parent(m_data.m_value.array->at(idx));
21262 }
21263 JSON_CATCH (std::out_of_range&)
21264 {
21265 // create better exception explanation
21266 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21267 }
21268 }
21269 else
21270 {
21271 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21272 }
21273 }
21274
21278 {
21279 // at only works for arrays
21280 if (JSON_HEDLEY_LIKELY(is_array()))
21281 {
21282 JSON_TRY
21283 {
21284 return m_data.m_value.array->at(idx);
21285 }
21286 JSON_CATCH (std::out_of_range&)
21287 {
21288 // create better exception explanation
21289 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21290 }
21291 }
21292 else
21293 {
21294 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21295 }
21296 }
21297
21300 reference at(const typename object_t::key_type& key)
21301 {
21302 // at only works for objects
21303 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21304 {
21305 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21306 }
21307
21308 auto it = m_data.m_value.object->find(key);
21309 if (it == m_data.m_value.object->end())
21310 {
21311 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21312 }
21313 return set_parent(it->second);
21314 }
21315
21318 template<class KeyType, detail::enable_if_t<
21319 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21320 reference at(KeyType && key)
21321 {
21322 // at only works for objects
21323 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21324 {
21325 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21326 }
21327
21328 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21329 if (it == m_data.m_value.object->end())
21330 {
21331 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21332 }
21333 return set_parent(it->second);
21334 }
21335
21338 const_reference at(const typename object_t::key_type& key) const
21339 {
21340 // at only works for objects
21341 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21342 {
21343 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21344 }
21345
21346 auto it = m_data.m_value.object->find(key);
21347 if (it == m_data.m_value.object->end())
21348 {
21349 JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
21350 }
21351 return it->second;
21352 }
21353
21356 template<class KeyType, detail::enable_if_t<
21357 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21358 const_reference at(KeyType && key) const
21359 {
21360 // at only works for objects
21361 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21362 {
21363 JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21364 }
21365
21366 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21367 if (it == m_data.m_value.object->end())
21368 {
21369 JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
21370 }
21371 return it->second;
21372 }
21373
21377 {
21378 // implicitly convert null value to an empty array
21379 if (is_null())
21380 {
21381 m_data.m_type = value_t::array;
21382 m_data.m_value.array = create<array_t>();
21383 assert_invariant();
21384 }
21385
21386 // operator[] only works for arrays
21387 if (JSON_HEDLEY_LIKELY(is_array()))
21388 {
21389 // fill up array with null values if given idx is outside range
21390 if (idx >= m_data.m_value.array->size())
21391 {
21392#if JSON_DIAGNOSTICS
21393 // remember array size & capacity before resizing
21394 const auto old_size = m_data.m_value.array->size();
21395 const auto old_capacity = m_data.m_value.array->capacity();
21396#endif
21397 m_data.m_value.array->resize(idx + 1);
21398
21399#if JSON_DIAGNOSTICS
21400 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
21401 {
21402 // capacity has changed: update all parents
21403 set_parents();
21404 }
21405 else
21406 {
21407 // set parent for values added above
21408 set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
21409 }
21410#endif
21411 assert_invariant();
21412 }
21413
21414 return m_data.m_value.array->operator[](idx);
21415 }
21416
21417 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21418 }
21419
21423 {
21424 // const operator[] only works for arrays
21425 if (JSON_HEDLEY_LIKELY(is_array()))
21426 {
21427 return m_data.m_value.array->operator[](idx);
21428 }
21429
21430 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
21431 }
21432
21435 reference operator[](typename object_t::key_type key)
21436 {
21437 // implicitly convert null value to an empty object
21438 if (is_null())
21439 {
21440 m_data.m_type = value_t::object;
21441 m_data.m_value.object = create<object_t>();
21442 assert_invariant();
21443 }
21444
21445 // operator[] only works for objects
21446 if (JSON_HEDLEY_LIKELY(is_object()))
21447 {
21448 auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
21449 return set_parent(result.first->second);
21450 }
21451
21452 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21453 }
21454
21457 const_reference operator[](const typename object_t::key_type& key) const
21458 {
21459 // const operator[] only works for objects
21460 if (JSON_HEDLEY_LIKELY(is_object()))
21461 {
21462 auto it = m_data.m_value.object->find(key);
21463 JSON_ASSERT(it != m_data.m_value.object->end());
21464 return it->second;
21465 }
21466
21467 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21468 }
21469
21470 // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
21471 // (they seemingly cannot be constrained to resolve the ambiguity)
21472 template<typename T>
21473 reference operator[](T* key)
21474 {
21475 return operator[](typename object_t::key_type(key));
21476 }
21477
21478 template<typename T>
21479 const_reference operator[](T* key) const
21480 {
21481 return operator[](typename object_t::key_type(key));
21482 }
21483
21486 template<class KeyType, detail::enable_if_t<
21487 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21489 {
21490 // implicitly convert null value to an empty object
21491 if (is_null())
21492 {
21493 m_data.m_type = value_t::object;
21494 m_data.m_value.object = create<object_t>();
21495 assert_invariant();
21496 }
21497
21498 // operator[] only works for objects
21499 if (JSON_HEDLEY_LIKELY(is_object()))
21500 {
21501 auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
21502 return set_parent(result.first->second);
21503 }
21504
21505 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21506 }
21507
21510 template<class KeyType, detail::enable_if_t<
21511 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
21513 {
21514 // const operator[] only works for objects
21515 if (JSON_HEDLEY_LIKELY(is_object()))
21516 {
21517 auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21518 JSON_ASSERT(it != m_data.m_value.object->end());
21519 return it->second;
21520 }
21521
21522 JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
21523 }
21524
21525 private:
21526 template<typename KeyType>
21527 using is_comparable_with_object_key = detail::is_comparable <
21528 object_comparator_t, const typename object_t::key_type&, KeyType >;
21529
21530 template<typename ValueType>
21531 using value_return_type = std::conditional <
21533 string_t, typename std::decay<ValueType>::type >;
21534
21535 public:
21538 template < class ValueType, detail::enable_if_t <
21541 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21542 ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
21543 {
21544 // value only works for objects
21545 if (JSON_HEDLEY_LIKELY(is_object()))
21546 {
21547 // if key is found, return value and given default value otherwise
21548 const auto it = find(key);
21549 if (it != end())
21550 {
21551 return it->template get<ValueType>();
21552 }
21553
21554 return default_value;
21555 }
21556
21557 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21558 }
21559
21562 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21563 detail::enable_if_t <
21566 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21567 ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
21568 {
21569 // value only works for objects
21570 if (JSON_HEDLEY_LIKELY(is_object()))
21571 {
21572 // if key is found, return value and given default value otherwise
21573 const auto it = find(key);
21574 if (it != end())
21575 {
21576 return it->template get<ReturnType>();
21577 }
21578
21579 return std::forward<ValueType>(default_value);
21580 }
21581
21582 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21583 }
21584
21587 template < class ValueType, class KeyType, detail::enable_if_t <
21590 && is_comparable_with_object_key<KeyType>::value
21592 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21593 ValueType value(KeyType && key, const ValueType& default_value) const
21594 {
21595 // value only works for objects
21596 if (JSON_HEDLEY_LIKELY(is_object()))
21597 {
21598 // if key is found, return value and given default value otherwise
21599 const auto it = find(std::forward<KeyType>(key));
21600 if (it != end())
21601 {
21602 return it->template get<ValueType>();
21603 }
21604
21605 return default_value;
21606 }
21607
21608 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21609 }
21610
21613 template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
21614 detail::enable_if_t <
21617 && is_comparable_with_object_key<KeyType>::value
21619 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21620 ReturnType value(KeyType && key, ValueType && default_value) const
21621 {
21622 // value only works for objects
21623 if (JSON_HEDLEY_LIKELY(is_object()))
21624 {
21625 // if key is found, return value and given default value otherwise
21626 const auto it = find(std::forward<KeyType>(key));
21627 if (it != end())
21628 {
21629 return it->template get<ReturnType>();
21630 }
21631
21632 return std::forward<ValueType>(default_value);
21633 }
21634
21635 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21636 }
21637
21640 template < class ValueType, detail::enable_if_t <
21642 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21643 ValueType value(const json_pointer& ptr, const ValueType& default_value) const
21644 {
21645 // value only works for objects
21646 if (JSON_HEDLEY_LIKELY(is_object()))
21647 {
21648 // if pointer resolves a value, return it or use default value
21649 JSON_TRY
21650 {
21651 return ptr.get_checked(this).template get<ValueType>();
21652 }
21653 JSON_INTERNAL_CATCH (out_of_range&)
21654 {
21655 return default_value;
21656 }
21657 }
21658
21659 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21660 }
21661
21664 template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
21665 detail::enable_if_t <
21667 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21668 ReturnType value(const json_pointer& ptr, ValueType && default_value) const
21669 {
21670 // value only works for objects
21671 if (JSON_HEDLEY_LIKELY(is_object()))
21672 {
21673 // if pointer resolves a value, return it or use default value
21674 JSON_TRY
21675 {
21676 return ptr.get_checked(this).template get<ReturnType>();
21677 }
21678 JSON_INTERNAL_CATCH (out_of_range&)
21679 {
21680 return std::forward<ValueType>(default_value);
21681 }
21682 }
21683
21684 JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
21685 }
21686
21687 template < class ValueType, class BasicJsonType, detail::enable_if_t <
21690 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21691 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21692 ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
21693 {
21694 return value(ptr.convert(), default_value);
21695 }
21696
21697 template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
21698 detail::enable_if_t <
21701 && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
21702 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
21703 ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
21704 {
21705 return value(ptr.convert(), std::forward<ValueType>(default_value));
21706 }
21707
21711 {
21712 return *begin();
21713 }
21714
21718 {
21719 return *cbegin();
21720 }
21721
21725 {
21726 auto tmp = end();
21727 --tmp;
21728 return *tmp;
21729 }
21730
21734 {
21735 auto tmp = cend();
21736 --tmp;
21737 return *tmp;
21738 }
21739
21742 template < class IteratorType, detail::enable_if_t <
21743 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21744 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21745 IteratorType erase(IteratorType pos)
21746 {
21747 // make sure iterator fits the current value
21748 if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
21749 {
21750 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
21751 }
21752
21753 IteratorType result = end();
21754
21755 switch (m_data.m_type)
21756 {
21757 case value_t::boolean:
21758 case value_t::number_float:
21759 case value_t::number_integer:
21760 case value_t::number_unsigned:
21761 case value_t::string:
21762 case value_t::binary:
21763 {
21764 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
21765 {
21766 JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
21767 }
21768
21769 if (is_string())
21770 {
21771 AllocatorType<string_t> alloc;
21772 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21773 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21774 m_data.m_value.string = nullptr;
21775 }
21776 else if (is_binary())
21777 {
21778 AllocatorType<binary_t> alloc;
21779 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21780 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21781 m_data.m_value.binary = nullptr;
21782 }
21783
21784 m_data.m_type = value_t::null;
21785 assert_invariant();
21786 break;
21787 }
21788
21789 case value_t::object:
21790 {
21791 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
21792 break;
21793 }
21794
21795 case value_t::array:
21796 {
21797 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
21798 break;
21799 }
21800
21801 case value_t::null:
21802 case value_t::discarded:
21803 default:
21804 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21805 }
21806
21807 return result;
21808 }
21809
21812 template < class IteratorType, detail::enable_if_t <
21813 std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
21814 std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
21815 IteratorType erase(IteratorType first, IteratorType last)
21816 {
21817 // make sure iterator fits the current value
21818 if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
21819 {
21820 JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
21821 }
21822
21823 IteratorType result = end();
21824
21825 switch (m_data.m_type)
21826 {
21827 case value_t::boolean:
21828 case value_t::number_float:
21829 case value_t::number_integer:
21830 case value_t::number_unsigned:
21831 case value_t::string:
21832 case value_t::binary:
21833 {
21834 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
21835 || !last.m_it.primitive_iterator.is_end()))
21836 {
21837 JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
21838 }
21839
21840 if (is_string())
21841 {
21842 AllocatorType<string_t> alloc;
21843 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
21844 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
21845 m_data.m_value.string = nullptr;
21846 }
21847 else if (is_binary())
21848 {
21849 AllocatorType<binary_t> alloc;
21850 std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
21851 std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
21852 m_data.m_value.binary = nullptr;
21853 }
21854
21855 m_data.m_type = value_t::null;
21856 assert_invariant();
21857 break;
21858 }
21859
21860 case value_t::object:
21861 {
21862 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
21863 last.m_it.object_iterator);
21864 break;
21865 }
21866
21867 case value_t::array:
21868 {
21869 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
21870 last.m_it.array_iterator);
21871 break;
21872 }
21873
21874 case value_t::null:
21875 case value_t::discarded:
21876 default:
21877 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21878 }
21879
21880 return result;
21881 }
21882
21883 private:
21884 template < typename KeyType, detail::enable_if_t <
21885 detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21886 size_type erase_internal(KeyType && key)
21887 {
21888 // this erase only works for objects
21889 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21890 {
21891 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21892 }
21893
21894 return m_data.m_value.object->erase(std::forward<KeyType>(key));
21895 }
21896
21897 template < typename KeyType, detail::enable_if_t <
21898 !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
21899 size_type erase_internal(KeyType && key)
21900 {
21901 // this erase only works for objects
21902 if (JSON_HEDLEY_UNLIKELY(!is_object()))
21903 {
21904 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21905 }
21906
21907 const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
21908 if (it != m_data.m_value.object->end())
21909 {
21910 m_data.m_value.object->erase(it);
21911 return 1;
21912 }
21913 return 0;
21914 }
21915
21916 public:
21917
21920 size_type erase(const typename object_t::key_type& key)
21921 {
21922 // the indirection via erase_internal() is added to avoid making this
21923 // function a template and thus de-rank it during overload resolution
21924 return erase_internal(key);
21925 }
21926
21929 template<class KeyType, detail::enable_if_t<
21930 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21931 size_type erase(KeyType && key)
21932 {
21933 return erase_internal(std::forward<KeyType>(key));
21934 }
21935
21938 void erase(const size_type idx)
21939 {
21940 // this erase only works for arrays
21941 if (JSON_HEDLEY_LIKELY(is_array()))
21942 {
21943 if (JSON_HEDLEY_UNLIKELY(idx >= size()))
21944 {
21945 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21946 }
21947
21948 m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
21949 }
21950 else
21951 {
21952 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
21953 }
21954 }
21955
21957
21959 // lookup //
21961
21964
21967 iterator find(const typename object_t::key_type& key)
21968 {
21969 auto result = end();
21970
21971 if (is_object())
21972 {
21973 result.m_it.object_iterator = m_data.m_value.object->find(key);
21974 }
21975
21976 return result;
21977 }
21978
21981 const_iterator find(const typename object_t::key_type& key) const
21982 {
21983 auto result = cend();
21984
21985 if (is_object())
21986 {
21987 result.m_it.object_iterator = m_data.m_value.object->find(key);
21988 }
21989
21990 return result;
21991 }
21992
21995 template<class KeyType, detail::enable_if_t<
21996 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
21997 iterator find(KeyType && key)
21998 {
21999 auto result = end();
22000
22001 if (is_object())
22002 {
22003 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22004 }
22005
22006 return result;
22007 }
22008
22011 template<class KeyType, detail::enable_if_t<
22012 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22013 const_iterator find(KeyType && key) const
22014 {
22015 auto result = cend();
22016
22017 if (is_object())
22018 {
22019 result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22020 }
22021
22022 return result;
22023 }
22024
22027 size_type count(const typename object_t::key_type& key) const
22028 {
22029 // return 0 for all nonobject types
22030 return is_object() ? m_data.m_value.object->count(key) : 0;
22031 }
22032
22035 template<class KeyType, detail::enable_if_t<
22036 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22037 size_type count(KeyType && key) const
22038 {
22039 // return 0 for all nonobject types
22040 return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22041 }
22042
22045 bool contains(const typename object_t::key_type& key) const
22046 {
22047 return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22048 }
22049
22052 template<class KeyType, detail::enable_if_t<
22053 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22054 bool contains(KeyType && key) const
22055 {
22056 return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22057 }
22058
22061 bool contains(const json_pointer& ptr) const
22062 {
22063 return ptr.contains(this);
22064 }
22065
22066 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22067 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22068 bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22069 {
22070 return ptr.contains(this);
22071 }
22072
22074
22076 // iterators //
22078
22081
22084 iterator begin() noexcept
22085 {
22086 iterator result(this);
22087 result.set_begin();
22088 return result;
22089 }
22090
22093 const_iterator begin() const noexcept
22094 {
22095 return cbegin();
22096 }
22097
22100 const_iterator cbegin() const noexcept
22101 {
22102 const_iterator result(this);
22103 result.set_begin();
22104 return result;
22105 }
22106
22109 iterator end() noexcept
22110 {
22111 iterator result(this);
22112 result.set_end();
22113 return result;
22114 }
22115
22118 const_iterator end() const noexcept
22119 {
22120 return cend();
22121 }
22122
22125 const_iterator cend() const noexcept
22126 {
22127 const_iterator result(this);
22128 result.set_end();
22129 return result;
22130 }
22131
22135 {
22136 return reverse_iterator(end());
22137 }
22138
22142 {
22143 return crbegin();
22144 }
22145
22149 {
22150 return reverse_iterator(begin());
22151 }
22152
22156 {
22157 return crend();
22158 }
22159
22163 {
22164 return const_reverse_iterator(cend());
22165 }
22166
22170 {
22171 return const_reverse_iterator(cbegin());
22172 }
22173
22174 public:
22180 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22181 static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22182 {
22183 return ref.items();
22184 }
22185
22191 JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22192 static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22193 {
22194 return ref.items();
22195 }
22196
22199 iteration_proxy<iterator> items() noexcept
22200 {
22201 return iteration_proxy<iterator>(*this);
22202 }
22203
22206 iteration_proxy<const_iterator> items() const noexcept
22207 {
22208 return iteration_proxy<const_iterator>(*this);
22209 }
22210
22212
22214 // capacity //
22216
22219
22222 bool empty() const noexcept
22223 {
22224 switch (m_data.m_type)
22225 {
22226 case value_t::null:
22227 {
22228 // null values are empty
22229 return true;
22230 }
22231
22232 case value_t::array:
22233 {
22234 // delegate call to array_t::empty()
22235 return m_data.m_value.array->empty();
22236 }
22237
22238 case value_t::object:
22239 {
22240 // delegate call to object_t::empty()
22241 return m_data.m_value.object->empty();
22242 }
22243
22244 case value_t::string:
22245 case value_t::boolean:
22246 case value_t::number_integer:
22247 case value_t::number_unsigned:
22248 case value_t::number_float:
22249 case value_t::binary:
22250 case value_t::discarded:
22251 default:
22252 {
22253 // all other types are nonempty
22254 return false;
22255 }
22256 }
22257 }
22258
22261 size_type size() const noexcept
22262 {
22263 switch (m_data.m_type)
22264 {
22265 case value_t::null:
22266 {
22267 // null values are empty
22268 return 0;
22269 }
22270
22271 case value_t::array:
22272 {
22273 // delegate call to array_t::size()
22274 return m_data.m_value.array->size();
22275 }
22276
22277 case value_t::object:
22278 {
22279 // delegate call to object_t::size()
22280 return m_data.m_value.object->size();
22281 }
22282
22283 case value_t::string:
22284 case value_t::boolean:
22285 case value_t::number_integer:
22286 case value_t::number_unsigned:
22287 case value_t::number_float:
22288 case value_t::binary:
22289 case value_t::discarded:
22290 default:
22291 {
22292 // all other types have size 1
22293 return 1;
22294 }
22295 }
22296 }
22297
22300 size_type max_size() const noexcept
22301 {
22302 switch (m_data.m_type)
22303 {
22304 case value_t::array:
22305 {
22306 // delegate call to array_t::max_size()
22307 return m_data.m_value.array->max_size();
22308 }
22309
22310 case value_t::object:
22311 {
22312 // delegate call to object_t::max_size()
22313 return m_data.m_value.object->max_size();
22314 }
22315
22316 case value_t::null:
22317 case value_t::string:
22318 case value_t::boolean:
22319 case value_t::number_integer:
22320 case value_t::number_unsigned:
22321 case value_t::number_float:
22322 case value_t::binary:
22323 case value_t::discarded:
22324 default:
22325 {
22326 // all other types have max_size() == size()
22327 return size();
22328 }
22329 }
22330 }
22331
22333
22335 // modifiers //
22337
22340
22343 void clear() noexcept
22344 {
22345 switch (m_data.m_type)
22346 {
22347 case value_t::number_integer:
22348 {
22349 m_data.m_value.number_integer = 0;
22350 break;
22351 }
22352
22353 case value_t::number_unsigned:
22354 {
22355 m_data.m_value.number_unsigned = 0;
22356 break;
22357 }
22358
22359 case value_t::number_float:
22360 {
22361 m_data.m_value.number_float = 0.0;
22362 break;
22363 }
22364
22365 case value_t::boolean:
22366 {
22367 m_data.m_value.boolean = false;
22368 break;
22369 }
22370
22371 case value_t::string:
22372 {
22373 m_data.m_value.string->clear();
22374 break;
22375 }
22376
22377 case value_t::binary:
22378 {
22379 m_data.m_value.binary->clear();
22380 break;
22381 }
22382
22383 case value_t::array:
22384 {
22385 m_data.m_value.array->clear();
22386 break;
22387 }
22388
22389 case value_t::object:
22390 {
22391 m_data.m_value.object->clear();
22392 break;
22393 }
22394
22395 case value_t::null:
22396 case value_t::discarded:
22397 default:
22398 break;
22399 }
22400 }
22401
22405 {
22406 // push_back only works for null objects or arrays
22407 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22408 {
22409 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22410 }
22411
22412 // transform null object into an array
22413 if (is_null())
22414 {
22415 m_data.m_type = value_t::array;
22416 m_data.m_value = value_t::array;
22417 assert_invariant();
22418 }
22419
22420 // add element to array (move semantics)
22421 const auto old_capacity = m_data.m_value.array->capacity();
22422 m_data.m_value.array->push_back(std::move(val));
22423 set_parent(m_data.m_value.array->back(), old_capacity);
22424 // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
22425 }
22426
22430 {
22431 push_back(std::move(val));
22432 return *this;
22433 }
22434
22437 void push_back(const basic_json& val)
22438 {
22439 // push_back only works for null objects or arrays
22440 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22441 {
22442 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22443 }
22444
22445 // transform null object into an array
22446 if (is_null())
22447 {
22448 m_data.m_type = value_t::array;
22449 m_data.m_value = value_t::array;
22450 assert_invariant();
22451 }
22452
22453 // add element to array
22454 const auto old_capacity = m_data.m_value.array->capacity();
22455 m_data.m_value.array->push_back(val);
22456 set_parent(m_data.m_value.array->back(), old_capacity);
22457 }
22458
22462 {
22463 push_back(val);
22464 return *this;
22465 }
22466
22469 void push_back(const typename object_t::value_type& val)
22470 {
22471 // push_back only works for null objects or objects
22472 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22473 {
22474 JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
22475 }
22476
22477 // transform null object into an object
22478 if (is_null())
22479 {
22480 m_data.m_type = value_t::object;
22481 m_data.m_value = value_t::object;
22482 assert_invariant();
22483 }
22484
22485 // add element to object
22486 auto res = m_data.m_value.object->insert(val);
22487 set_parent(res.first->second);
22488 }
22489
22492 reference operator+=(const typename object_t::value_type& val)
22493 {
22494 push_back(val);
22495 return *this;
22496 }
22497
22501 {
22502 if (is_object() && init.size() == 2 && (*init.begin())->is_string())
22503 {
22504 basic_json&& key = init.begin()->moved_or_copied();
22505 push_back(typename object_t::value_type(
22506 std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
22507 }
22508 else
22509 {
22510 push_back(basic_json(init));
22511 }
22512 }
22513
22517 {
22518 push_back(init);
22519 return *this;
22520 }
22521
22524 template<class... Args>
22525 reference emplace_back(Args&& ... args)
22526 {
22527 // emplace_back only works for null objects or arrays
22528 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
22529 {
22530 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
22531 }
22532
22533 // transform null object into an array
22534 if (is_null())
22535 {
22536 m_data.m_type = value_t::array;
22537 m_data.m_value = value_t::array;
22538 assert_invariant();
22539 }
22540
22541 // add element to array (perfect forwarding)
22542 const auto old_capacity = m_data.m_value.array->capacity();
22543 m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
22544 return set_parent(m_data.m_value.array->back(), old_capacity);
22545 }
22546
22549 template<class... Args>
22550 std::pair<iterator, bool> emplace(Args&& ... args)
22551 {
22552 // emplace only works for null objects or arrays
22553 if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
22554 {
22555 JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
22556 }
22557
22558 // transform null object into an object
22559 if (is_null())
22560 {
22561 m_data.m_type = value_t::object;
22562 m_data.m_value = value_t::object;
22563 assert_invariant();
22564 }
22565
22566 // add element to array (perfect forwarding)
22567 auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
22568 set_parent(res.first->second);
22569
22570 // create result iterator and set iterator to the result of emplace
22571 auto it = begin();
22572 it.m_it.object_iterator = res.first;
22573
22574 // return pair of iterator and boolean
22575 return {it, res.second};
22576 }
22577
22581 template<typename... Args>
22583 {
22584 iterator result(this);
22585 JSON_ASSERT(m_data.m_value.array != nullptr);
22586
22587 auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
22588 m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
22589 result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
22590
22591 // This could have been written as:
22592 // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
22593 // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
22594
22595 set_parents();
22596 return result;
22597 }
22598
22602 {
22603 // insert only works for arrays
22604 if (JSON_HEDLEY_LIKELY(is_array()))
22605 {
22606 // check if iterator pos fits to this JSON value
22607 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22608 {
22609 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22610 }
22611
22612 // insert to array and return iterator
22613 return insert_iterator(pos, val);
22614 }
22615
22616 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22617 }
22618
22622 {
22623 return insert(pos, val);
22624 }
22625
22629 {
22630 // insert only works for arrays
22631 if (JSON_HEDLEY_LIKELY(is_array()))
22632 {
22633 // check if iterator pos fits to this JSON value
22634 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22635 {
22636 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22637 }
22638
22639 // insert to array and return iterator
22640 return insert_iterator(pos, cnt, val);
22641 }
22642
22643 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22644 }
22645
22649 {
22650 // insert only works for arrays
22651 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22652 {
22653 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22654 }
22655
22656 // check if iterator pos fits to this JSON value
22657 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22658 {
22659 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22660 }
22661
22662 // check if range iterators belong to the same JSON object
22663 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22664 {
22665 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22666 }
22667
22668 if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
22669 {
22670 JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
22671 }
22672
22673 // insert to array and return iterator
22674 return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
22675 }
22676
22680 {
22681 // insert only works for arrays
22682 if (JSON_HEDLEY_UNLIKELY(!is_array()))
22683 {
22684 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22685 }
22686
22687 // check if iterator pos fits to this JSON value
22688 if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
22689 {
22690 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22691 }
22692
22693 // insert to array and return iterator
22694 return insert_iterator(pos, ilist.begin(), ilist.end());
22695 }
22696
22700 {
22701 // insert only works for objects
22702 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22703 {
22704 JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
22705 }
22706
22707 // check if range iterators belong to the same JSON object
22708 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22709 {
22710 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22711 }
22712
22713 // passed iterators must belong to objects
22714 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22715 {
22716 JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
22717 }
22718
22719 m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
22720 }
22721
22724 void update(const_reference j, bool merge_objects = false)
22725 {
22726 update(j.begin(), j.end(), merge_objects);
22727 }
22728
22731 void update(const_iterator first, const_iterator last, bool merge_objects = false)
22732 {
22733 // implicitly convert null value to an empty object
22734 if (is_null())
22735 {
22736 m_data.m_type = value_t::object;
22737 m_data.m_value.object = create<object_t>();
22738 assert_invariant();
22739 }
22740
22741 if (JSON_HEDLEY_UNLIKELY(!is_object()))
22742 {
22743 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
22744 }
22745
22746 // check if range iterators belong to the same JSON object
22747 if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
22748 {
22749 JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
22750 }
22751
22752 // passed iterators must belong to objects
22753 if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
22754 {
22755 JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
22756 }
22757
22758 for (auto it = first; it != last; ++it)
22759 {
22760 if (merge_objects && it.value().is_object())
22761 {
22762 auto it2 = m_data.m_value.object->find(it.key());
22763 if (it2 != m_data.m_value.object->end())
22764 {
22765 it2->second.update(it.value(), true);
22766 continue;
22767 }
22768 }
22769 m_data.m_value.object->operator[](it.key()) = it.value();
22770#if JSON_DIAGNOSTICS
22771 m_data.m_value.object->operator[](it.key()).m_parent = this;
22772#endif
22773 }
22774 }
22775
22778 void swap(reference other) noexcept (
22779 std::is_nothrow_move_constructible<value_t>::value&&
22780 std::is_nothrow_move_assignable<value_t>::value&&
22781 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22782 std::is_nothrow_move_assignable<json_value>::value
22783 )
22784 {
22785 std::swap(m_data.m_type, other.m_data.m_type);
22786 std::swap(m_data.m_value, other.m_data.m_value);
22787
22788 set_parents();
22789 other.set_parents();
22790 assert_invariant();
22791 }
22792
22795 friend void swap(reference left, reference right) noexcept (
22796 std::is_nothrow_move_constructible<value_t>::value&&
22797 std::is_nothrow_move_assignable<value_t>::value&&
22798 std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22799 std::is_nothrow_move_assignable<json_value>::value
22800 )
22801 {
22802 left.swap(right);
22803 }
22804
22807 void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22808 {
22809 // swap only works for arrays
22810 if (JSON_HEDLEY_LIKELY(is_array()))
22811 {
22812 using std::swap;
22813 swap(*(m_data.m_value.array), other);
22814 }
22815 else
22816 {
22817 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
22818 }
22819 }
22820
22823 void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22824 {
22825 // swap only works for objects
22826 if (JSON_HEDLEY_LIKELY(is_object()))
22827 {
22828 using std::swap;
22829 swap(*(m_data.m_value.object), other);
22830 }
22831 else
22832 {
22833 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
22834 }
22835 }
22836
22839 void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22840 {
22841 // swap only works for strings
22842 if (JSON_HEDLEY_LIKELY(is_string()))
22843 {
22844 using std::swap;
22845 swap(*(m_data.m_value.string), other);
22846 }
22847 else
22848 {
22849 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
22850 }
22851 }
22852
22855 void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
22856 {
22857 // swap only works for strings
22858 if (JSON_HEDLEY_LIKELY(is_binary()))
22859 {
22860 using std::swap;
22861 swap(*(m_data.m_value.binary), other);
22862 }
22863 else
22864 {
22865 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
22866 }
22867 }
22868
22871 void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
22872 {
22873 // swap only works for strings
22874 if (JSON_HEDLEY_LIKELY(is_binary()))
22875 {
22876 using std::swap;
22877 swap(*(m_data.m_value.binary), other);
22878 }
22879 else
22880 {
22881 JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
22882 }
22883 }
22884
22886
22888 // lexicographical comparison operators //
22890
22893
22894 // note parentheses around operands are necessary; see
22895 // https://github.com/nlohmann/json/issues/1530
22896#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result) \
22897 const auto lhs_type = lhs.type(); \
22898 const auto rhs_type = rhs.type(); \
22899 \
22900 if (lhs_type == rhs_type) /* NOLINT(readability/braces) */ \
22901 { \
22902 switch (lhs_type) \
22903 { \
22904 case value_t::array: \
22905 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array); \
22906 \
22907 case value_t::object: \
22908 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object); \
22909 \
22910 case value_t::null: \
22911 return (null_result); \
22912 \
22913 case value_t::string: \
22914 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string); \
22915 \
22916 case value_t::boolean: \
22917 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean); \
22918 \
22919 case value_t::number_integer: \
22920 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer); \
22921 \
22922 case value_t::number_unsigned: \
22923 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned); \
22924 \
22925 case value_t::number_float: \
22926 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float); \
22927 \
22928 case value_t::binary: \
22929 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary); \
22930 \
22931 case value_t::discarded: \
22932 default: \
22933 return (unordered_result); \
22934 } \
22935 } \
22936 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float) \
22937 { \
22938 return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float; \
22939 } \
22940 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer) \
22941 { \
22942 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer); \
22943 } \
22944 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float) \
22945 { \
22946 return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float; \
22947 } \
22948 else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned) \
22949 { \
22950 return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned); \
22951 } \
22952 else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer) \
22953 { \
22954 return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
22955 } \
22956 else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned) \
22957 { \
22958 return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
22959 } \
22960 else if(compares_unordered(lhs, rhs))\
22961 {\
22962 return (unordered_result);\
22963 }\
22964 \
22965 return (default_result);
22966
22967 JSON_PRIVATE_UNLESS_TESTED:
22968 // returns true if:
22969 // - any operand is NaN and the other operand is of number type
22970 // - any operand is discarded
22971 // in legacy mode, discarded values are considered ordered if
22972 // an operation is computed as an odd number of inverses of others
22973 static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
22974 {
22975 if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
22976 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
22977 {
22978 return true;
22979 }
22980#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
22981 return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
22982#else
22983 static_cast<void>(inverse);
22984 return lhs.is_discarded() || rhs.is_discarded();
22985#endif
22986 }
22987
22988 private:
22989 bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
22990 {
22991 return compares_unordered(*this, rhs, inverse);
22992 }
22993
22994 public:
22995#if JSON_HAS_THREE_WAY_COMPARISON
22998 bool operator==(const_reference rhs) const noexcept
22999 {
23000#ifdef __GNUC__
23001#pragma GCC diagnostic push
23002#pragma GCC diagnostic ignored "-Wfloat-equal"
23003#endif
23004 const_reference lhs = *this;
23005 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23006#ifdef __GNUC__
23007#pragma GCC diagnostic pop
23008#endif
23009 }
23010
23013 template<typename ScalarType>
23014 requires std::is_scalar_v<ScalarType>
23015 bool operator==(ScalarType rhs) const noexcept
23016 {
23017 return *this == basic_json(rhs);
23018 }
23019
23022 bool operator!=(const_reference rhs) const noexcept
23023 {
23024 if (compares_unordered(rhs, true))
23025 {
23026 return false;
23027 }
23028 return !operator==(rhs);
23029 }
23030
23033 std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23034 {
23035 const_reference lhs = *this;
23036 // default_result is used if we cannot compare values. In that case,
23037 // we compare types.
23038 JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23039 std::partial_ordering::equivalent,
23040 std::partial_ordering::unordered,
23041 lhs_type <=> rhs_type) // *NOPAD*
23042 }
23043
23046 template<typename ScalarType>
23047 requires std::is_scalar_v<ScalarType>
23048 std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23049 {
23050 return *this <=> basic_json(rhs); // *NOPAD*
23051 }
23052
23053#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23054 // all operators that are computed as an odd number of inverses of others
23055 // need to be overloaded to emulate the legacy comparison behavior
23056
23059 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23060 bool operator<=(const_reference rhs) const noexcept
23061 {
23062 if (compares_unordered(rhs, true))
23063 {
23064 return false;
23065 }
23066 return !(rhs < *this);
23067 }
23068
23071 template<typename ScalarType>
23072 requires std::is_scalar_v<ScalarType>
23073 bool operator<=(ScalarType rhs) const noexcept
23074 {
23075 return *this <= basic_json(rhs);
23076 }
23077
23080 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23081 bool operator>=(const_reference rhs) const noexcept
23082 {
23083 if (compares_unordered(rhs, true))
23084 {
23085 return false;
23086 }
23087 return !(*this < rhs);
23088 }
23089
23092 template<typename ScalarType>
23093 requires std::is_scalar_v<ScalarType>
23094 bool operator>=(ScalarType rhs) const noexcept
23095 {
23096 return *this >= basic_json(rhs);
23097 }
23098#endif
23099#else
23102 friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23103 {
23104#ifdef __GNUC__
23105#pragma GCC diagnostic push
23106#pragma GCC diagnostic ignored "-Wfloat-equal"
23107#endif
23108 JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23109#ifdef __GNUC__
23110#pragma GCC diagnostic pop
23111#endif
23112 }
23113
23116 template<typename ScalarType, typename std::enable_if<
23117 std::is_scalar<ScalarType>::value, int>::type = 0>
23118 friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23119 {
23120 return lhs == basic_json(rhs);
23121 }
23122
23125 template<typename ScalarType, typename std::enable_if<
23126 std::is_scalar<ScalarType>::value, int>::type = 0>
23127 friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23128 {
23129 return basic_json(lhs) == rhs;
23130 }
23131
23134 friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23135 {
23136 if (compares_unordered(lhs, rhs, true))
23137 {
23138 return false;
23139 }
23140 return !(lhs == rhs);
23141 }
23142
23145 template<typename ScalarType, typename std::enable_if<
23146 std::is_scalar<ScalarType>::value, int>::type = 0>
23147 friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23148 {
23149 return lhs != basic_json(rhs);
23150 }
23151
23154 template<typename ScalarType, typename std::enable_if<
23155 std::is_scalar<ScalarType>::value, int>::type = 0>
23156 friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23157 {
23158 return basic_json(lhs) != rhs;
23159 }
23160
23163 friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23164 {
23165 // default_result is used if we cannot compare values. In that case,
23166 // we compare types. Note we have to call the operator explicitly,
23167 // because MSVC has problems otherwise.
23168 JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23169 }
23170
23173 template<typename ScalarType, typename std::enable_if<
23174 std::is_scalar<ScalarType>::value, int>::type = 0>
23175 friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23176 {
23177 return lhs < basic_json(rhs);
23178 }
23179
23182 template<typename ScalarType, typename std::enable_if<
23183 std::is_scalar<ScalarType>::value, int>::type = 0>
23184 friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23185 {
23186 return basic_json(lhs) < rhs;
23187 }
23188
23191 friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23192 {
23193 if (compares_unordered(lhs, rhs, true))
23194 {
23195 return false;
23196 }
23197 return !(rhs < lhs);
23198 }
23199
23202 template<typename ScalarType, typename std::enable_if<
23203 std::is_scalar<ScalarType>::value, int>::type = 0>
23204 friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23205 {
23206 return lhs <= basic_json(rhs);
23207 }
23208
23211 template<typename ScalarType, typename std::enable_if<
23212 std::is_scalar<ScalarType>::value, int>::type = 0>
23213 friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23214 {
23215 return basic_json(lhs) <= rhs;
23216 }
23217
23220 friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23221 {
23222 // double inverse
23223 if (compares_unordered(lhs, rhs))
23224 {
23225 return false;
23226 }
23227 return !(lhs <= rhs);
23228 }
23229
23232 template<typename ScalarType, typename std::enable_if<
23233 std::is_scalar<ScalarType>::value, int>::type = 0>
23234 friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23235 {
23236 return lhs > basic_json(rhs);
23237 }
23238
23241 template<typename ScalarType, typename std::enable_if<
23242 std::is_scalar<ScalarType>::value, int>::type = 0>
23243 friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23244 {
23245 return basic_json(lhs) > rhs;
23246 }
23247
23250 friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23251 {
23252 if (compares_unordered(lhs, rhs, true))
23253 {
23254 return false;
23255 }
23256 return !(lhs < rhs);
23257 }
23258
23261 template<typename ScalarType, typename std::enable_if<
23262 std::is_scalar<ScalarType>::value, int>::type = 0>
23263 friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23264 {
23265 return lhs >= basic_json(rhs);
23266 }
23267
23270 template<typename ScalarType, typename std::enable_if<
23271 std::is_scalar<ScalarType>::value, int>::type = 0>
23272 friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23273 {
23274 return basic_json(lhs) >= rhs;
23275 }
23276#endif
23277
23278#undef JSON_IMPLEMENT_OPERATOR
23279
23281
23283 // serialization //
23285
23288#ifndef JSON_NO_IO
23291 friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
23292 {
23293 // read width member and use it as indentation parameter if nonzero
23294 const bool pretty_print = o.width() > 0;
23295 const auto indentation = pretty_print ? o.width() : 0;
23296
23297 // reset width to 0 for subsequent calls to this stream
23298 o.width(0);
23299
23300 // do the actual serialization
23301 serializer s(detail::output_adapter<char>(o), o.fill());
23302 s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
23303 return o;
23304 }
23305
23312 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
23313 friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
23314 {
23315 return o << j;
23316 }
23317#endif // JSON_NO_IO
23319
23321 // deserialization //
23323
23326
23329 template<typename InputType>
23330 JSON_HEDLEY_WARN_UNUSED_RESULT
23331 static basic_json parse(InputType&& i,
23332 const parser_callback_t cb = nullptr,
23333 const bool allow_exceptions = true,
23334 const bool ignore_comments = false)
23335 {
23336 basic_json result;
23337 parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
23338 return result;
23339 }
23340
23343 template<typename IteratorType>
23344 JSON_HEDLEY_WARN_UNUSED_RESULT
23345 static basic_json parse(IteratorType first,
23346 IteratorType last,
23347 const parser_callback_t cb = nullptr,
23348 const bool allow_exceptions = true,
23349 const bool ignore_comments = false)
23350 {
23351 basic_json result;
23352 parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
23353 return result;
23354 }
23355
23356 JSON_HEDLEY_WARN_UNUSED_RESULT
23357 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
23358 static basic_json parse(detail::span_input_adapter&& i,
23359 const parser_callback_t cb = nullptr,
23360 const bool allow_exceptions = true,
23361 const bool ignore_comments = false)
23362 {
23363 basic_json result;
23364 parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
23365 return result;
23366 }
23367
23370 template<typename InputType>
23371 static bool accept(InputType&& i,
23372 const bool ignore_comments = false)
23373 {
23374 return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
23375 }
23376
23379 template<typename IteratorType>
23380 static bool accept(IteratorType first, IteratorType last,
23381 const bool ignore_comments = false)
23382 {
23383 return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
23384 }
23385
23386 JSON_HEDLEY_WARN_UNUSED_RESULT
23387 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
23388 static bool accept(detail::span_input_adapter&& i,
23389 const bool ignore_comments = false)
23390 {
23391 return parser(i.get(), nullptr, false, ignore_comments).accept(true);
23392 }
23393
23396 template <typename InputType, typename SAX>
23397 JSON_HEDLEY_NON_NULL(2)
23398 static bool sax_parse(InputType&& i, SAX* sax,
23399 input_format_t format = input_format_t::json,
23400 const bool strict = true,
23401 const bool ignore_comments = false)
23402 {
23403 auto ia = detail::input_adapter(std::forward<InputType>(i));
23404 return format == input_format_t::json
23405 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23406 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23407 }
23408
23411 template<class IteratorType, class SAX>
23412 JSON_HEDLEY_NON_NULL(3)
23413 static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
23415 const bool strict = true,
23416 const bool ignore_comments = false)
23417 {
23418 auto ia = detail::input_adapter(std::move(first), std::move(last));
23419 return format == input_format_t::json
23420 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23421 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23422 }
23423
23429 template <typename SAX>
23430 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
23431 JSON_HEDLEY_NON_NULL(2)
23432 static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
23434 const bool strict = true,
23435 const bool ignore_comments = false)
23436 {
23437 auto ia = i.get();
23438 return format == input_format_t::json
23439 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23440 ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
23441 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23442 : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
23443 }
23444#ifndef JSON_NO_IO
23451 JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
23452 friend std::istream& operator<<(basic_json& j, std::istream& i)
23453 {
23454 return operator>>(i, j);
23455 }
23456
23459 friend std::istream& operator>>(std::istream& i, basic_json& j)
23460 {
23461 parser(detail::input_adapter(i)).parse(false, j);
23462 return i;
23463 }
23464#endif // JSON_NO_IO
23466
23468 // convenience functions //
23470
23473 JSON_HEDLEY_RETURNS_NON_NULL
23474 const char* type_name() const noexcept
23475 {
23476 switch (m_data.m_type)
23477 {
23478 case value_t::null:
23479 return "null";
23480 case value_t::object:
23481 return "object";
23482 case value_t::array:
23483 return "array";
23484 case value_t::string:
23485 return "string";
23486 case value_t::boolean:
23487 return "boolean";
23488 case value_t::binary:
23489 return "binary";
23490 case value_t::discarded:
23491 return "discarded";
23492 case value_t::number_integer:
23493 case value_t::number_unsigned:
23494 case value_t::number_float:
23495 default:
23496 return "number";
23497 }
23498 }
23499
23500 JSON_PRIVATE_UNLESS_TESTED:
23502 // member variables //
23504
23505 struct data
23506 {
23508 value_t m_type = value_t::null;
23509
23511 json_value m_value = {};
23512
23513 data(const value_t v)
23514 : m_type(v), m_value(v)
23515 {
23516 }
23517
23518 data(size_type cnt, const basic_json& val)
23519 : m_type(value_t::array)
23520 {
23521 m_value.array = create<array_t>(cnt, val);
23522 }
23523
23524 data() noexcept = default;
23525 data(data&&) noexcept = default;
23526 data(const data&) noexcept = delete;
23527 data& operator=(data&&) noexcept = delete;
23528 data& operator=(const data&) noexcept = delete;
23529
23530 ~data() noexcept
23531 {
23532 m_value.destroy(m_type);
23533 }
23534 };
23535
23536 data m_data = {};
23537
23538#if JSON_DIAGNOSTICS
23540 basic_json* m_parent = nullptr;
23541#endif
23542
23544 // binary serialization/deserialization //
23546
23549
23550 public:
23553 static std::vector<std::uint8_t> to_cbor(const basic_json& j)
23554 {
23555 std::vector<std::uint8_t> result;
23556 to_cbor(j, result);
23557 return result;
23558 }
23559
23563 {
23564 binary_writer<std::uint8_t>(o).write_cbor(j);
23565 }
23566
23570 {
23571 binary_writer<char>(o).write_cbor(j);
23572 }
23573
23576 static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
23577 {
23578 std::vector<std::uint8_t> result;
23579 to_msgpack(j, result);
23580 return result;
23581 }
23582
23586 {
23587 binary_writer<std::uint8_t>(o).write_msgpack(j);
23588 }
23589
23593 {
23594 binary_writer<char>(o).write_msgpack(j);
23595 }
23596
23599 static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
23600 const bool use_size = false,
23601 const bool use_type = false)
23602 {
23603 std::vector<std::uint8_t> result;
23604 to_ubjson(j, result, use_size, use_type);
23605 return result;
23606 }
23607
23611 const bool use_size = false, const bool use_type = false)
23612 {
23613 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
23614 }
23615
23619 const bool use_size = false, const bool use_type = false)
23620 {
23621 binary_writer<char>(o).write_ubjson(j, use_size, use_type);
23622 }
23623
23626 static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
23627 const bool use_size = false,
23628 const bool use_type = false)
23629 {
23630 std::vector<std::uint8_t> result;
23631 to_bjdata(j, result, use_size, use_type);
23632 return result;
23633 }
23634
23638 const bool use_size = false, const bool use_type = false)
23639 {
23640 binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
23641 }
23642
23646 const bool use_size = false, const bool use_type = false)
23647 {
23648 binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
23649 }
23650
23653 static std::vector<std::uint8_t> to_bson(const basic_json& j)
23654 {
23655 std::vector<std::uint8_t> result;
23656 to_bson(j, result);
23657 return result;
23658 }
23659
23663 {
23664 binary_writer<std::uint8_t>(o).write_bson(j);
23665 }
23666
23670 {
23671 binary_writer<char>(o).write_bson(j);
23672 }
23673
23676 template<typename InputType>
23677 JSON_HEDLEY_WARN_UNUSED_RESULT
23678 static basic_json from_cbor(InputType&& i,
23679 const bool strict = true,
23680 const bool allow_exceptions = true,
23681 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23682 {
23683 basic_json result;
23684 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23685 auto ia = detail::input_adapter(std::forward<InputType>(i));
23686 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23687 return res ? result : basic_json(value_t::discarded);
23688 }
23689
23692 template<typename IteratorType>
23693 JSON_HEDLEY_WARN_UNUSED_RESULT
23694 static basic_json from_cbor(IteratorType first, IteratorType last,
23695 const bool strict = true,
23696 const bool allow_exceptions = true,
23697 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23698 {
23699 basic_json result;
23700 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23701 auto ia = detail::input_adapter(std::move(first), std::move(last));
23702 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23703 return res ? result : basic_json(value_t::discarded);
23704 }
23705
23706 template<typename T>
23707 JSON_HEDLEY_WARN_UNUSED_RESULT
23708 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23709 static basic_json from_cbor(const T* ptr, std::size_t len,
23710 const bool strict = true,
23711 const bool allow_exceptions = true,
23712 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23713 {
23714 return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
23715 }
23716
23717 JSON_HEDLEY_WARN_UNUSED_RESULT
23718 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
23719 static basic_json from_cbor(detail::span_input_adapter&& i,
23720 const bool strict = true,
23721 const bool allow_exceptions = true,
23722 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
23723 {
23724 basic_json result;
23725 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23726 auto ia = i.get();
23727 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23728 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
23729 return res ? result : basic_json(value_t::discarded);
23730 }
23731
23734 template<typename InputType>
23735 JSON_HEDLEY_WARN_UNUSED_RESULT
23736 static basic_json from_msgpack(InputType&& 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 = detail::input_adapter(std::forward<InputType>(i));
23743 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23744 return res ? result : basic_json(value_t::discarded);
23745 }
23746
23749 template<typename IteratorType>
23750 JSON_HEDLEY_WARN_UNUSED_RESULT
23751 static basic_json from_msgpack(IteratorType first, IteratorType last,
23752 const bool strict = true,
23753 const bool allow_exceptions = true)
23754 {
23755 basic_json result;
23756 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23757 auto ia = detail::input_adapter(std::move(first), std::move(last));
23758 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23759 return res ? result : basic_json(value_t::discarded);
23760 }
23761
23762 template<typename T>
23763 JSON_HEDLEY_WARN_UNUSED_RESULT
23764 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23765 static basic_json from_msgpack(const T* ptr, std::size_t len,
23766 const bool strict = true,
23767 const bool allow_exceptions = true)
23768 {
23769 return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
23770 }
23771
23772 JSON_HEDLEY_WARN_UNUSED_RESULT
23773 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
23774 static basic_json from_msgpack(detail::span_input_adapter&& i,
23775 const bool strict = true,
23776 const bool allow_exceptions = true)
23777 {
23778 basic_json result;
23779 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23780 auto ia = i.get();
23781 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23782 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
23783 return res ? result : basic_json(value_t::discarded);
23784 }
23785
23788 template<typename InputType>
23789 JSON_HEDLEY_WARN_UNUSED_RESULT
23790 static basic_json from_ubjson(InputType&& i,
23791 const bool strict = true,
23792 const bool allow_exceptions = true)
23793 {
23794 basic_json result;
23795 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23796 auto ia = detail::input_adapter(std::forward<InputType>(i));
23797 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23798 return res ? result : basic_json(value_t::discarded);
23799 }
23800
23803 template<typename IteratorType>
23804 JSON_HEDLEY_WARN_UNUSED_RESULT
23805 static basic_json from_ubjson(IteratorType first, IteratorType last,
23806 const bool strict = true,
23807 const bool allow_exceptions = true)
23808 {
23809 basic_json result;
23810 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23811 auto ia = detail::input_adapter(std::move(first), std::move(last));
23812 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23813 return res ? result : basic_json(value_t::discarded);
23814 }
23815
23816 template<typename T>
23817 JSON_HEDLEY_WARN_UNUSED_RESULT
23818 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23819 static basic_json from_ubjson(const T* ptr, std::size_t len,
23820 const bool strict = true,
23821 const bool allow_exceptions = true)
23822 {
23823 return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
23824 }
23825
23826 JSON_HEDLEY_WARN_UNUSED_RESULT
23827 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
23828 static basic_json from_ubjson(detail::span_input_adapter&& i,
23829 const bool strict = true,
23830 const bool allow_exceptions = true)
23831 {
23832 basic_json result;
23833 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23834 auto ia = i.get();
23835 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23836 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
23837 return res ? result : basic_json(value_t::discarded);
23838 }
23839
23842 template<typename InputType>
23843 JSON_HEDLEY_WARN_UNUSED_RESULT
23844 static basic_json from_bjdata(InputType&& i,
23845 const bool strict = true,
23846 const bool allow_exceptions = true)
23847 {
23848 basic_json result;
23849 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23850 auto ia = detail::input_adapter(std::forward<InputType>(i));
23851 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23852 return res ? result : basic_json(value_t::discarded);
23853 }
23854
23857 template<typename IteratorType>
23858 JSON_HEDLEY_WARN_UNUSED_RESULT
23859 static basic_json from_bjdata(IteratorType first, IteratorType last,
23860 const bool strict = true,
23861 const bool allow_exceptions = true)
23862 {
23863 basic_json result;
23864 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23865 auto ia = detail::input_adapter(std::move(first), std::move(last));
23866 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
23867 return res ? result : basic_json(value_t::discarded);
23868 }
23869
23872 template<typename InputType>
23873 JSON_HEDLEY_WARN_UNUSED_RESULT
23874 static basic_json from_bson(InputType&& i,
23875 const bool strict = true,
23876 const bool allow_exceptions = true)
23877 {
23878 basic_json result;
23879 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23880 auto ia = detail::input_adapter(std::forward<InputType>(i));
23881 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23882 return res ? result : basic_json(value_t::discarded);
23883 }
23884
23887 template<typename IteratorType>
23888 JSON_HEDLEY_WARN_UNUSED_RESULT
23889 static basic_json from_bson(IteratorType first, IteratorType last,
23890 const bool strict = true,
23891 const bool allow_exceptions = true)
23892 {
23893 basic_json result;
23894 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23895 auto ia = detail::input_adapter(std::move(first), std::move(last));
23896 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23897 return res ? result : basic_json(value_t::discarded);
23898 }
23899
23900 template<typename T>
23901 JSON_HEDLEY_WARN_UNUSED_RESULT
23902 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23903 static basic_json from_bson(const T* ptr, std::size_t len,
23904 const bool strict = true,
23905 const bool allow_exceptions = true)
23906 {
23907 return from_bson(ptr, ptr + len, strict, allow_exceptions);
23908 }
23909
23910 JSON_HEDLEY_WARN_UNUSED_RESULT
23911 JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
23912 static basic_json from_bson(detail::span_input_adapter&& i,
23913 const bool strict = true,
23914 const bool allow_exceptions = true)
23915 {
23916 basic_json result;
23917 detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
23918 auto ia = i.get();
23919 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
23920 const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
23921 return res ? result : basic_json(value_t::discarded);
23922 }
23924
23926 // JSON Pointer support //
23928
23931
23935 {
23936 return ptr.get_unchecked(this);
23937 }
23938
23939 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23940 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23941 reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23942 {
23943 return ptr.get_unchecked(this);
23944 }
23945
23949 {
23950 return ptr.get_unchecked(this);
23951 }
23952
23953 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23954 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23955 const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23956 {
23957 return ptr.get_unchecked(this);
23958 }
23959
23963 {
23964 return ptr.get_checked(this);
23965 }
23966
23967 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23968 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23969 reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
23970 {
23971 return ptr.get_checked(this);
23972 }
23973
23977 {
23978 return ptr.get_checked(this);
23979 }
23980
23981 template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
23982 JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
23983 const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
23984 {
23985 return ptr.get_checked(this);
23986 }
23987
23991 {
23992 basic_json result(value_t::object);
23993 json_pointer::flatten("", *this, result);
23994 return result;
23995 }
23996
24000 {
24001 return json_pointer::unflatten(*this);
24002 }
24003
24005
24007 // JSON Patch functions //
24009
24012
24015 void patch_inplace(const basic_json& json_patch)
24016 {
24017 basic_json& result = *this;
24018 // the valid JSON Patch operations
24019 enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24020
24021 const auto get_op = [](const std::string & op)
24022 {
24023 if (op == "add")
24024 {
24025 return patch_operations::add;
24026 }
24027 if (op == "remove")
24028 {
24029 return patch_operations::remove;
24030 }
24031 if (op == "replace")
24032 {
24033 return patch_operations::replace;
24034 }
24035 if (op == "move")
24036 {
24037 return patch_operations::move;
24038 }
24039 if (op == "copy")
24040 {
24041 return patch_operations::copy;
24042 }
24043 if (op == "test")
24044 {
24045 return patch_operations::test;
24046 }
24047
24048 return patch_operations::invalid;
24049 };
24050
24051 // wrapper for "add" operation; add value at ptr
24052 const auto operation_add = [&result](json_pointer & ptr, basic_json val)
24053 {
24054 // adding to the root of the target document means replacing it
24055 if (ptr.empty())
24056 {
24057 result = val;
24058 return;
24059 }
24060
24061 // make sure the top element of the pointer exists
24062 json_pointer const top_pointer = ptr.top();
24063 if (top_pointer != ptr)
24064 {
24065 result.at(top_pointer);
24066 }
24067
24068 // get reference to parent of JSON pointer ptr
24069 const auto last_path = ptr.back();
24070 ptr.pop_back();
24071 // parent must exist when performing patch add per RFC6902 specs
24072 basic_json& parent = result.at(ptr);
24073
24074 switch (parent.m_data.m_type)
24075 {
24076 case value_t::null:
24077 case value_t::object:
24078 {
24079 // use operator[] to add value
24080 parent[last_path] = val;
24081 break;
24082 }
24083
24084 case value_t::array:
24085 {
24086 if (last_path == "-")
24087 {
24088 // special case: append to back
24089 parent.push_back(val);
24090 }
24091 else
24092 {
24093 const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24094 if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24095 {
24096 // avoid undefined behavior
24097 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24098 }
24099
24100 // default case: insert add offset
24101 parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24102 }
24103 break;
24104 }
24105
24106 // if there exists a parent it cannot be primitive
24107 case value_t::string: // LCOV_EXCL_LINE
24108 case value_t::boolean: // LCOV_EXCL_LINE
24109 case value_t::number_integer: // LCOV_EXCL_LINE
24110 case value_t::number_unsigned: // LCOV_EXCL_LINE
24111 case value_t::number_float: // LCOV_EXCL_LINE
24112 case value_t::binary: // LCOV_EXCL_LINE
24113 case value_t::discarded: // LCOV_EXCL_LINE
24114 default: // LCOV_EXCL_LINE
24115 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24116 }
24117 };
24118
24119 // wrapper for "remove" operation; remove value at ptr
24120 const auto operation_remove = [this, & result](json_pointer & ptr)
24121 {
24122 // get reference to parent of JSON pointer ptr
24123 const auto last_path = ptr.back();
24124 ptr.pop_back();
24125 basic_json& parent = result.at(ptr);
24126
24127 // remove child
24128 if (parent.is_object())
24129 {
24130 // perform range check
24131 auto it = parent.find(last_path);
24132 if (JSON_HEDLEY_LIKELY(it != parent.end()))
24133 {
24134 parent.erase(it);
24135 }
24136 else
24137 {
24138 JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24139 }
24140 }
24141 else if (parent.is_array())
24142 {
24143 // note erase performs range check
24144 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24145 }
24146 };
24147
24148 // type check: top level value must be an array
24149 if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24150 {
24151 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24152 }
24153
24154 // iterate and apply the operations
24155 for (const auto& val : json_patch)
24156 {
24157 // wrapper to get a value for an operation
24158 const auto get_value = [&val](const std::string & op,
24159 const std::string & member,
24160 bool string_type) -> basic_json &
24161 {
24162 // find value
24163 auto it = val.m_data.m_value.object->find(member);
24164
24165 // context-sensitive error message
24166 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
24167
24168 // check if desired value is present
24169 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24170 {
24171 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24172 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24173 }
24174
24175 // check if result is of type string
24176 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24177 {
24178 // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24179 JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24180 }
24181
24182 // no error: return value
24183 return it->second;
24184 };
24185
24186 // type check: every element of the array must be an object
24187 if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24188 {
24189 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24190 }
24191
24192 // collect mandatory members
24193 const auto op = get_value("op", "op", true).template get<std::string>();
24194 const auto path = get_value(op, "path", true).template get<std::string>();
24195 json_pointer ptr(path);
24196
24197 switch (get_op(op))
24198 {
24199 case patch_operations::add:
24200 {
24201 operation_add(ptr, get_value("add", "value", false));
24202 break;
24203 }
24204
24205 case patch_operations::remove:
24206 {
24207 operation_remove(ptr);
24208 break;
24209 }
24210
24211 case patch_operations::replace:
24212 {
24213 // the "path" location must exist - use at()
24214 result.at(ptr) = get_value("replace", "value", false);
24215 break;
24216 }
24217
24218 case patch_operations::move:
24219 {
24220 const auto from_path = get_value("move", "from", true).template get<std::string>();
24221 json_pointer from_ptr(from_path);
24222
24223 // the "from" location must exist - use at()
24224 basic_json const v = result.at(from_ptr);
24225
24226 // The move operation is functionally identical to a
24227 // "remove" operation on the "from" location, followed
24228 // immediately by an "add" operation at the target
24229 // location with the value that was just removed.
24230 operation_remove(from_ptr);
24231 operation_add(ptr, v);
24232 break;
24233 }
24234
24235 case patch_operations::copy:
24236 {
24237 const auto from_path = get_value("copy", "from", true).template get<std::string>();
24238 const json_pointer from_ptr(from_path);
24239
24240 // the "from" location must exist - use at()
24241 basic_json const v = result.at(from_ptr);
24242
24243 // The copy is functionally identical to an "add"
24244 // operation at the target location using the value
24245 // specified in the "from" member.
24246 operation_add(ptr, v);
24247 break;
24248 }
24249
24250 case patch_operations::test:
24251 {
24252 bool success = false;
24253 JSON_TRY
24254 {
24255 // check if "value" matches the one at "path"
24256 // the "path" location must exist - use at()
24257 success = (result.at(ptr) == get_value("test", "value", false));
24258 }
24259 JSON_INTERNAL_CATCH (out_of_range&)
24260 {
24261 // ignore out of range errors: success remains false
24262 }
24263
24264 // throw an exception if test fails
24265 if (JSON_HEDLEY_UNLIKELY(!success))
24266 {
24267 JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
24268 }
24269
24270 break;
24271 }
24272
24273 case patch_operations::invalid:
24274 default:
24275 {
24276 // op must be "add", "remove", "replace", "move", "copy", or
24277 // "test"
24278 JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
24279 }
24280 }
24281 }
24282 }
24283
24286 basic_json patch(const basic_json& json_patch) const
24287 {
24288 basic_json result = *this;
24289 result.patch_inplace(json_patch);
24290 return result;
24291 }
24292
24295 JSON_HEDLEY_WARN_UNUSED_RESULT
24296 static basic_json diff(const basic_json& source, const basic_json& target,
24297 const std::string& path = "")
24298 {
24299 // the patch
24300 basic_json result(value_t::array);
24301
24302 // if the values are the same, return empty patch
24303 if (source == target)
24304 {
24305 return result;
24306 }
24307
24308 if (source.type() != target.type())
24309 {
24310 // different types: replace value
24311 result.push_back(
24312 {
24313 {"op", "replace"}, {"path", path}, {"value", target}
24314 });
24315 return result;
24316 }
24317
24318 switch (source.type())
24319 {
24320 case value_t::array:
24321 {
24322 // first pass: traverse common elements
24323 std::size_t i = 0;
24324 while (i < source.size() && i < target.size())
24325 {
24326 // recursive call to compare array values at index i
24327 auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
24328 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24329 ++i;
24330 }
24331
24332 // We now reached the end of at least one array
24333 // in a second pass, traverse the remaining elements
24334
24335 // remove my remaining elements
24336 const auto end_index = static_cast<difference_type>(result.size());
24337 while (i < source.size())
24338 {
24339 // add operations in reverse order to avoid invalid
24340 // indices
24341 result.insert(result.begin() + end_index, object(
24342 {
24343 {"op", "remove"},
24344 {"path", detail::concat(path, '/', std::to_string(i))}
24345 }));
24346 ++i;
24347 }
24348
24349 // add other remaining elements
24350 while (i < target.size())
24351 {
24352 result.push_back(
24353 {
24354 {"op", "add"},
24355 {"path", detail::concat(path, "/-")},
24356 {"value", target[i]}
24357 });
24358 ++i;
24359 }
24360
24361 break;
24362 }
24363
24364 case value_t::object:
24365 {
24366 // first pass: traverse this object's elements
24367 for (auto it = source.cbegin(); it != source.cend(); ++it)
24368 {
24369 // escape the key name to be used in a JSON patch
24370 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24371
24372 if (target.find(it.key()) != target.end())
24373 {
24374 // recursive call to compare object values at key it
24375 auto temp_diff = diff(it.value(), target[it.key()], path_key);
24376 result.insert(result.end(), temp_diff.begin(), temp_diff.end());
24377 }
24378 else
24379 {
24380 // found a key that is not in o -> remove it
24381 result.push_back(object(
24382 {
24383 {"op", "remove"}, {"path", path_key}
24384 }));
24385 }
24386 }
24387
24388 // second pass: traverse other object's elements
24389 for (auto it = target.cbegin(); it != target.cend(); ++it)
24390 {
24391 if (source.find(it.key()) == source.end())
24392 {
24393 // found a key that is not in this -> add it
24394 const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
24395 result.push_back(
24396 {
24397 {"op", "add"}, {"path", path_key},
24398 {"value", it.value()}
24399 });
24400 }
24401 }
24402
24403 break;
24404 }
24405
24406 case value_t::null:
24407 case value_t::string:
24408 case value_t::boolean:
24409 case value_t::number_integer:
24410 case value_t::number_unsigned:
24411 case value_t::number_float:
24412 case value_t::binary:
24413 case value_t::discarded:
24414 default:
24415 {
24416 // both primitive type: replace value
24417 result.push_back(
24418 {
24419 {"op", "replace"}, {"path", path}, {"value", target}
24420 });
24421 break;
24422 }
24423 }
24424
24425 return result;
24426 }
24428
24430 // JSON Merge Patch functions //
24432
24435
24438 void merge_patch(const basic_json& apply_patch)
24439 {
24440 if (apply_patch.is_object())
24441 {
24442 if (!is_object())
24443 {
24444 *this = object();
24445 }
24446 for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
24447 {
24448 if (it.value().is_null())
24449 {
24450 erase(it.key());
24451 }
24452 else
24453 {
24454 operator[](it.key()).merge_patch(it.value());
24455 }
24456 }
24457 }
24458 else
24459 {
24460 *this = apply_patch;
24461 }
24462 }
24463
24465};
24466
24469NLOHMANN_BASIC_JSON_TPL_DECLARATION
24470std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
24471{
24472 return j.dump();
24473}
24474
24475inline namespace literals
24476{
24477inline namespace json_literals
24478{
24479
24482JSON_HEDLEY_NON_NULL(1)
24483#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24484 inline nlohmann::json operator ""_json(const char* s, std::size_t n)
24485#else
24486 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
24487#endif
24488{
24489 return nlohmann::json::parse(s, s + n);
24490}
24491
24494JSON_HEDLEY_NON_NULL(1)
24495#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24496 inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
24497#else
24498 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
24499#endif
24500{
24501 return nlohmann::json::json_pointer(std::string(s, n));
24502}
24503
24504} // namespace json_literals
24505} // namespace literals
24506NLOHMANN_JSON_NAMESPACE_END
24507
24509// nonmember support //
24511
24512namespace std // NOLINT(cert-dcl58-cpp)
24513{
24514
24517NLOHMANN_BASIC_JSON_TPL_DECLARATION
24518struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
24519{
24520 std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
24521 {
24522 return nlohmann::detail::hash(j);
24523 }
24524};
24525
24526// specialization for std::less<value_t>
24527template<>
24528struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
24529{
24534 bool operator()(::nlohmann::detail::value_t lhs,
24535 ::nlohmann::detail::value_t rhs) const noexcept
24536 {
24537#if JSON_HAS_THREE_WAY_COMPARISON
24538 return std::is_lt(lhs <=> rhs); // *NOPAD*
24539#else
24540 return ::nlohmann::detail::operator<(lhs, rhs);
24541#endif
24542 }
24543};
24544
24545// C++20 prohibit function specialization in the std namespace.
24546#ifndef JSON_HAS_CPP_20
24547
24550NLOHMANN_BASIC_JSON_TPL_DECLARATION
24551inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept( // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
24552 is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&& // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
24553 is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
24554{
24555 j1.swap(j2);
24556}
24557
24558#endif
24559
24560} // namespace std
24561
24562#if JSON_USE_GLOBAL_UDLS
24563 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
24564 using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24565 using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24566 #else
24567 using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24568 using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
24569 #endif
24570#endif
24571
24572// #include <nlohmann/detail/macro_unscope.hpp>
24573// __ _____ _____ _____
24574// __| | __| | | | JSON for Modern C++
24575// | | |__ | | | | | | version 3.11.3
24576// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24577//
24578// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24579// SPDX-License-Identifier: MIT
24580
24581
24582
24583// restore clang diagnostic settings
24584#if defined(__clang__)
24585 #pragma clang diagnostic pop
24586#endif
24587
24588// clean up
24589#undef JSON_ASSERT
24590#undef JSON_INTERNAL_CATCH
24591#undef JSON_THROW
24592#undef JSON_PRIVATE_UNLESS_TESTED
24593#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
24594#undef NLOHMANN_BASIC_JSON_TPL
24595#undef JSON_EXPLICIT
24596#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
24597#undef JSON_INLINE_VARIABLE
24598#undef JSON_NO_UNIQUE_ADDRESS
24599#undef JSON_DISABLE_ENUM_SERIALIZATION
24600#undef JSON_USE_GLOBAL_UDLS
24601
24602#ifndef JSON_TEST_KEEP_MACROS
24603 #undef JSON_CATCH
24604 #undef JSON_TRY
24605 #undef JSON_HAS_CPP_11
24606 #undef JSON_HAS_CPP_14
24607 #undef JSON_HAS_CPP_17
24608 #undef JSON_HAS_CPP_20
24609 #undef JSON_HAS_FILESYSTEM
24610 #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
24611 #undef JSON_HAS_THREE_WAY_COMPARISON
24612 #undef JSON_HAS_RANGES
24613 #undef JSON_HAS_STATIC_RTTI
24614 #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
24615#endif
24616
24617// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
24618// __ _____ _____ _____
24619// __| | __| | | | JSON for Modern C++
24620// | | |__ | | | | | | version 3.11.3
24621// |_____|_____|_____|_|___| https://github.com/nlohmann/json
24622//
24623// SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
24624// SPDX-License-Identifier: MIT
24625
24626
24627
24628#undef JSON_HEDLEY_ALWAYS_INLINE
24629#undef JSON_HEDLEY_ARM_VERSION
24630#undef JSON_HEDLEY_ARM_VERSION_CHECK
24631#undef JSON_HEDLEY_ARRAY_PARAM
24632#undef JSON_HEDLEY_ASSUME
24633#undef JSON_HEDLEY_BEGIN_C_DECLS
24634#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
24635#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
24636#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
24637#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
24638#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
24639#undef JSON_HEDLEY_CLANG_HAS_FEATURE
24640#undef JSON_HEDLEY_CLANG_HAS_WARNING
24641#undef JSON_HEDLEY_COMPCERT_VERSION
24642#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
24643#undef JSON_HEDLEY_CONCAT
24644#undef JSON_HEDLEY_CONCAT3
24645#undef JSON_HEDLEY_CONCAT3_EX
24646#undef JSON_HEDLEY_CONCAT_EX
24647#undef JSON_HEDLEY_CONST
24648#undef JSON_HEDLEY_CONSTEXPR
24649#undef JSON_HEDLEY_CONST_CAST
24650#undef JSON_HEDLEY_CPP_CAST
24651#undef JSON_HEDLEY_CRAY_VERSION
24652#undef JSON_HEDLEY_CRAY_VERSION_CHECK
24653#undef JSON_HEDLEY_C_DECL
24654#undef JSON_HEDLEY_DEPRECATED
24655#undef JSON_HEDLEY_DEPRECATED_FOR
24656#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
24657#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
24658#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
24659#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
24660#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
24661#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
24662#undef JSON_HEDLEY_DIAGNOSTIC_POP
24663#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
24664#undef JSON_HEDLEY_DMC_VERSION
24665#undef JSON_HEDLEY_DMC_VERSION_CHECK
24666#undef JSON_HEDLEY_EMPTY_BASES
24667#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
24668#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
24669#undef JSON_HEDLEY_END_C_DECLS
24670#undef JSON_HEDLEY_FLAGS
24671#undef JSON_HEDLEY_FLAGS_CAST
24672#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
24673#undef JSON_HEDLEY_GCC_HAS_BUILTIN
24674#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
24675#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
24676#undef JSON_HEDLEY_GCC_HAS_EXTENSION
24677#undef JSON_HEDLEY_GCC_HAS_FEATURE
24678#undef JSON_HEDLEY_GCC_HAS_WARNING
24679#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
24680#undef JSON_HEDLEY_GCC_VERSION
24681#undef JSON_HEDLEY_GCC_VERSION_CHECK
24682#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
24683#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
24684#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
24685#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
24686#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
24687#undef JSON_HEDLEY_GNUC_HAS_FEATURE
24688#undef JSON_HEDLEY_GNUC_HAS_WARNING
24689#undef JSON_HEDLEY_GNUC_VERSION
24690#undef JSON_HEDLEY_GNUC_VERSION_CHECK
24691#undef JSON_HEDLEY_HAS_ATTRIBUTE
24692#undef JSON_HEDLEY_HAS_BUILTIN
24693#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
24694#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
24695#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
24696#undef JSON_HEDLEY_HAS_EXTENSION
24697#undef JSON_HEDLEY_HAS_FEATURE
24698#undef JSON_HEDLEY_HAS_WARNING
24699#undef JSON_HEDLEY_IAR_VERSION
24700#undef JSON_HEDLEY_IAR_VERSION_CHECK
24701#undef JSON_HEDLEY_IBM_VERSION
24702#undef JSON_HEDLEY_IBM_VERSION_CHECK
24703#undef JSON_HEDLEY_IMPORT
24704#undef JSON_HEDLEY_INLINE
24705#undef JSON_HEDLEY_INTEL_CL_VERSION
24706#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
24707#undef JSON_HEDLEY_INTEL_VERSION
24708#undef JSON_HEDLEY_INTEL_VERSION_CHECK
24709#undef JSON_HEDLEY_IS_CONSTANT
24710#undef JSON_HEDLEY_IS_CONSTEXPR_
24711#undef JSON_HEDLEY_LIKELY
24712#undef JSON_HEDLEY_MALLOC
24713#undef JSON_HEDLEY_MCST_LCC_VERSION
24714#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
24715#undef JSON_HEDLEY_MESSAGE
24716#undef JSON_HEDLEY_MSVC_VERSION
24717#undef JSON_HEDLEY_MSVC_VERSION_CHECK
24718#undef JSON_HEDLEY_NEVER_INLINE
24719#undef JSON_HEDLEY_NON_NULL
24720#undef JSON_HEDLEY_NO_ESCAPE
24721#undef JSON_HEDLEY_NO_RETURN
24722#undef JSON_HEDLEY_NO_THROW
24723#undef JSON_HEDLEY_NULL
24724#undef JSON_HEDLEY_PELLES_VERSION
24725#undef JSON_HEDLEY_PELLES_VERSION_CHECK
24726#undef JSON_HEDLEY_PGI_VERSION
24727#undef JSON_HEDLEY_PGI_VERSION_CHECK
24728#undef JSON_HEDLEY_PREDICT
24729#undef JSON_HEDLEY_PRINTF_FORMAT
24730#undef JSON_HEDLEY_PRIVATE
24731#undef JSON_HEDLEY_PUBLIC
24732#undef JSON_HEDLEY_PURE
24733#undef JSON_HEDLEY_REINTERPRET_CAST
24734#undef JSON_HEDLEY_REQUIRE
24735#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
24736#undef JSON_HEDLEY_REQUIRE_MSG
24737#undef JSON_HEDLEY_RESTRICT
24738#undef JSON_HEDLEY_RETURNS_NON_NULL
24739#undef JSON_HEDLEY_SENTINEL
24740#undef JSON_HEDLEY_STATIC_ASSERT
24741#undef JSON_HEDLEY_STATIC_CAST
24742#undef JSON_HEDLEY_STRINGIFY
24743#undef JSON_HEDLEY_STRINGIFY_EX
24744#undef JSON_HEDLEY_SUNPRO_VERSION
24745#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
24746#undef JSON_HEDLEY_TINYC_VERSION
24747#undef JSON_HEDLEY_TINYC_VERSION_CHECK
24748#undef JSON_HEDLEY_TI_ARMCL_VERSION
24749#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
24750#undef JSON_HEDLEY_TI_CL2000_VERSION
24751#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
24752#undef JSON_HEDLEY_TI_CL430_VERSION
24753#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
24754#undef JSON_HEDLEY_TI_CL6X_VERSION
24755#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
24756#undef JSON_HEDLEY_TI_CL7X_VERSION
24757#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
24758#undef JSON_HEDLEY_TI_CLPRU_VERSION
24759#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
24760#undef JSON_HEDLEY_TI_VERSION
24761#undef JSON_HEDLEY_TI_VERSION_CHECK
24762#undef JSON_HEDLEY_UNAVAILABLE
24763#undef JSON_HEDLEY_UNLIKELY
24764#undef JSON_HEDLEY_UNPREDICTABLE
24765#undef JSON_HEDLEY_UNREACHABLE
24766#undef JSON_HEDLEY_UNREACHABLE_RETURN
24767#undef JSON_HEDLEY_VERSION
24768#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
24769#undef JSON_HEDLEY_VERSION_DECODE_MINOR
24770#undef JSON_HEDLEY_VERSION_DECODE_REVISION
24771#undef JSON_HEDLEY_VERSION_ENCODE
24772#undef JSON_HEDLEY_WARNING
24773#undef JSON_HEDLEY_WARN_UNUSED_RESULT
24774#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
24775#undef JSON_HEDLEY_FALL_THROUGH
24776
24777
24778
24779#endif // INCLUDE_NLOHMANN_JSON_HPP_
namespace for Niels Lohmann
Definition json.hpp:19415
constexpr bool is_string() const noexcept
return whether value is a string
Definition json.hpp:20687
size_type erase(const typename object_t::key_type &key)
remove element from a JSON object given a key
Definition json.hpp:21920
reference operator[](KeyType &&key)
access specified object element
Definition json.hpp:21488
size_type size() const noexcept
returns the number of elements
Definition json.hpp:22261
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:23694
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:23626
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:21060
const_iterator end() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22118
reference back()
access the last element
Definition json.hpp:21724
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:20151
reverse_iterator rbegin() noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22134
basic_json patch(const basic_json &json_patch) const
applies a JSON patch to a copy of the current object
Definition json.hpp:24286
JSON_HEDLEY_RETURNS_NON_NULL const char * type_name() const noexcept
return the type as string
Definition json.hpp:23474
const_reference front() const
access the first element
Definition json.hpp:21717
constexpr bool is_array() const noexcept
return whether value is an array
Definition json.hpp:20680
void swap(reference other) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22778
ReturnType value(const json_pointer &ptr, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21668
size_type count(KeyType &&key) const
returns the number of occurrences of a key in a JSON object
Definition json.hpp:22037
iter_impl< const basic_json > const_iterator
a const iterator for a basic_json container
Definition json.hpp:19546
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:23645
constexpr bool is_number_integer() const noexcept
return whether value is an integer number
Definition json.hpp:20652
json_reverse_iterator< typename basic_json::const_iterator > const_reverse_iterator
a const reverse iterator for a basic_json container
Definition json.hpp:19550
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:23889
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:23637
reference operator[](const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:23934
typename std::allocator_traits< allocator_type >::const_pointer const_pointer
the type of an element const pointer
Definition json.hpp:19541
std::size_t size_type
a type to represent container sizes
Definition json.hpp:19533
constexpr bool is_structured() const noexcept
return whether type is structured
Definition json.hpp:20624
const_reference operator[](KeyType &&key) const
access specified object element
Definition json.hpp:21512
void swap(binary_t &other)
exchanges the values
Definition json.hpp:22855
ReferenceType get_ref()
get a reference value (implicit)
Definition json.hpp:21150
size_type max_size() const noexcept
returns the maximum possible number of elements
Definition json.hpp:22300
void update(const_reference j, bool merge_objects=false)
updates a JSON object from another object, overwriting existing keys
Definition json.hpp:22724
ReferenceType get_ref() const
get a reference value (implicit)
Definition json.hpp:21161
constexpr bool is_discarded() const noexcept
return whether value is discarded
Definition json.hpp:20701
reference operator+=(initializer_list_t init)
add an object to an object
Definition json.hpp:22516
void push_back(basic_json &&val)
add an object to an array
Definition json.hpp:22404
const_reference operator[](const typename object_t::key_type &key) const
access specified object element
Definition json.hpp:21457
iteration_proxy< const_iterator > items() const noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22206
const_reference back() const
access the last element
Definition json.hpp:21733
IteratorType erase(IteratorType first, IteratorType last)
remove elements given an iterator range
Definition json.hpp:21815
reference operator+=(const basic_json &val)
add an object to an array
Definition json.hpp:22461
friend void swap(reference left, reference right) noexcept(std::is_nothrow_move_constructible< value_t >::value &&std::is_nothrow_move_assignable< value_t >::value &&std::is_nothrow_move_constructible< json_value >::value &&//NOLINT(cppcoreguidelines-noexcept-swap, performance-noexcept-swap) std::is_nothrow_move_assignable< json_value >::value)
exchanges the values
Definition json.hpp:22795
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:23790
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:20288
iterator insert(const_iterator pos, size_type cnt, const basic_json &val)
inserts copies of element into array
Definition json.hpp:22628
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:23874
static allocator_type get_allocator()
returns the allocator associated with the container
Definition json.hpp:19556
nlohmann::byte_container_with_subtype< BinaryType > binary_t
a type for a packed binary type
Definition json.hpp:19681
reference at(KeyType &&key)
access specified object element with bounds checking
Definition json.hpp:21320
iterator end() noexcept
returns an iterator to one past the last element
Definition json.hpp:22109
constexpr bool is_number_unsigned() const noexcept
return whether value is an unsigned integer number
Definition json.hpp:20659
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:22731
static std::vector< std::uint8_t > to_bson(const basic_json &j)
create a BSON serialization of a given JSON value
Definition json.hpp:23653
const_reverse_iterator rbegin() const noexcept
returns an iterator to the reverse-beginning
Definition json.hpp:22141
void push_back(initializer_list_t init)
add an object to an object
Definition json.hpp:22500
detail::parser_callback_t< basic_json > parser_callback_t
per-element parser callback type
Definition json.hpp:20118
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json object(initializer_list_t init={})
explicitly create an object from an initializer list
Definition json.hpp:20329
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:23592
iterator begin() noexcept
returns an iterator to the first element
Definition json.hpp:22084
ReturnType value(const typename object_t::key_type &key, ValueType &&default_value) const
access specified object element with default value
Definition json.hpp:21567
const_iterator cend() const noexcept
returns an iterator to one past the last element
Definition json.hpp:22125
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:23844
const_reference at(const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:23976
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json binary(typename binary_t::container_type &&init)
explicitly create a binary array
Definition json.hpp:20299
basic_json(std::nullptr_t=nullptr) noexcept
create a null object
Definition json.hpp:20139
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:23678
basic_json flatten() const
return flattened JSON value
Definition json.hpp:23990
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:23805
size_type erase(KeyType &&key)
remove element from a JSON object given a key
Definition json.hpp:21931
ArrayType< basic_json, AllocatorType< basic_json > > array_t
a type for an array
Definition json.hpp:19657
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:19649
const binary_t & get_binary() const
get a binary value
Definition json.hpp:21232
iterator insert(const_iterator pos, const_iterator first, const_iterator last)
inserts range of elements into array
Definition json.hpp:22648
void patch_inplace(const basic_json &json_patch)
applies a JSON patch in-place without copying the object
Definition json.hpp:24015
ReturnType value(KeyType &&key, ValueType &&default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21620
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:24296
const_reference operator[](const json_pointer &ptr) const
access specified element via JSON Pointer
Definition json.hpp:23948
std::initializer_list< detail::json_ref< basic_json > > initializer_list_t
helper type for initializer lists of basic_json values
Definition json.hpp:19490
bool contains(KeyType &&key) const
check the existence of an element in a JSON object
Definition json.hpp:22054
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:23562
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:23669
iterator find(const typename object_t::key_type &key)
find an element in a JSON object
Definition json.hpp:21967
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:20277
const_reference at(KeyType &&key) const
access specified object element with bounds checking
Definition json.hpp:21358
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json meta()
returns version information on the library
Definition json.hpp:19564
basic_json(size_type cnt, const basic_json &val)
construct an array with count copies of given value
Definition json.hpp:20336
const_iterator find(const typename object_t::key_type &key) const
find an element in a JSON object
Definition json.hpp:21981
static std::vector< std::uint8_t > to_cbor(const basic_json &j)
create a CBOR serialization of a given JSON value
Definition json.hpp:23553
IteratorType erase(IteratorType pos)
remove element given an iterator
Definition json.hpp:21745
iterator insert(const_iterator pos, const basic_json &val)
inserts element into array
Definition json.hpp:22601
NumberFloatType number_float_t
a type for a number (floating-point)
Definition json.hpp:19677
ValueType value(const typename object_t::key_type &key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21542
AllocatorType< basic_json > allocator_type
the allocator type
Definition json.hpp:19536
typename std::allocator_traits< allocator_type >::pointer pointer
the type of an element pointer
Definition json.hpp:19539
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:20588
void merge_patch(const basic_json &apply_patch)
applies a JSON Merge Patch
Definition json.hpp:24438
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:21114
reference at(size_type idx)
access specified array element with bounds checking
Definition json.hpp:21254
iterator find(KeyType &&key)
find an element in a JSON object
Definition json.hpp:21997
constexpr bool is_number_float() const noexcept
return whether value is a floating-point number
Definition json.hpp:20666
reverse_iterator rend() noexcept
returns an iterator to the reverse-end
Definition json.hpp:22148
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:23599
reference at(const json_pointer &ptr)
access specified element via JSON Pointer
Definition json.hpp:23962
BooleanType boolean_t
a type for a boolean
Definition json.hpp:19665
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:19644
reference operator+=(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22492
const_iterator cbegin() const noexcept
returns a const iterator to the first element
Definition json.hpp:22100
reference operator[](typename object_t::key_type key)
access specified object element
Definition json.hpp:21435
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:20872
~basic_json() noexcept
destructor
Definition json.hpp:20570
const_reverse_iterator crend() const noexcept
returns a const reverse iterator to one before the first
Definition json.hpp:22169
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:20218
void swap(typename binary_t::container_type &other)
exchanges the values
Definition json.hpp:22871
binary_t & get_binary()
get a binary value
Definition json.hpp:21220
const_iterator begin() const noexcept
returns an iterator to the first element
Definition json.hpp:22093
constexpr bool is_number() const noexcept
return whether value is a number
Definition json.hpp:20645
void insert(const_iterator first, const_iterator last)
inserts range of elements into object
Definition json.hpp:22699
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:23736
auto get() noexcept -> decltype(std::declval< basic_json_t & >().template get_ptr< PointerType >())
get a pointer value (explicit)
Definition json.hpp:21101
reference operator[](size_type idx)
access specified array element
Definition json.hpp:21376
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:20547
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:23618
NumberIntegerType number_integer_t
a type for a number (integer)
Definition json.hpp:19669
auto get_ptr() noexcept -> decltype(std::declval< basic_json_t & >().get_impl_ptr(std::declval< PointerType >()))
get a pointer value (implicit)
Definition json.hpp:20861
const_reference at(const typename object_t::key_type &key) const
access specified object element with bounds checking
Definition json.hpp:21338
constexpr bool is_binary() const noexcept
return whether value is a binary array
Definition json.hpp:20694
void swap(object_t &other)
exchanges the values
Definition json.hpp:22823
basic_json unflatten() const
unflatten a previously flattened JSON value
Definition json.hpp:23999
iterator insert(const_iterator pos, initializer_list_t ilist)
inserts elements from initializer list into array
Definition json.hpp:22679
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:20310
iteration_proxy< iterator > items() noexcept
helper to access iterator member functions in range-based for
Definition json.hpp:22199
bool empty() const noexcept
checks whether the container is empty.
Definition json.hpp:22222
void swap(array_t &other)
exchanges the values
Definition json.hpp:22807
void erase(const size_type idx)
remove element from a JSON array given an index
Definition json.hpp:21938
reference operator+=(basic_json &&val)
add an object to an array
Definition json.hpp:22429
bool contains(const json_pointer &ptr) const
check the existence of an element in a JSON object given a JSON pointer
Definition json.hpp:22061
constexpr value_t type() const noexcept
return the type of the JSON value (explicit)
Definition json.hpp:20610
reference emplace_back(Args &&... args)
add an object to an array
Definition json.hpp:22525
ValueType value(const json_pointer &ptr, const ValueType &default_value) const
access specified object element via JSON Pointer with default value
Definition json.hpp:21643
static JSON_HEDLEY_WARN_UNUSED_RESULT basic_json array(initializer_list_t init={})
explicitly create an array from an initializer list
Definition json.hpp:20321
StringType string_t
a type for a string
Definition json.hpp:19661
void push_back(const basic_json &val)
add an object to an array
Definition json.hpp:22437
ValueType value(KeyType &&key, const ValueType &default_value) const
access specified object element with default value
Definition json.hpp:21593
reference at(const typename object_t::key_type &key)
access specified object element with bounds checking
Definition json.hpp:21300
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:23859
json_value m_value
the value of the current element
Definition json.hpp:23511
const_reverse_iterator crbegin() const noexcept
returns a const reverse iterator to the last element
Definition json.hpp:22162
constexpr bool is_boolean() const noexcept
return whether value is a boolean
Definition json.hpp:20638
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:22027
reference front()
access the first element
Definition json.hpp:21710
constexpr bool is_primitive() const noexcept
return whether type is primitive
Definition json.hpp:20617
constexpr bool is_null() const noexcept
return whether value is null
Definition json.hpp:20631
void clear() noexcept
clears the contents
Definition json.hpp:22343
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:23610
basic_json(basic_json &&other) noexcept
move constructor
Definition json.hpp:20530
iter_impl< basic_json > iterator
an iterator for a basic_json container
Definition json.hpp:19544
basic_json(const value_t v)
create an empty value with a given type
Definition json.hpp:20131
const_reference operator[](size_type idx) const
access specified array element
Definition json.hpp:21422
std::ptrdiff_t difference_type
a type to represent differences between iterators
Definition json.hpp:19531
iterator insert(const_iterator pos, basic_json &&val)
inserts element into array
Definition json.hpp:22621
const_reverse_iterator rend() const noexcept
returns an iterator to the reverse-end
Definition json.hpp:22155
NumberUnsignedType number_unsigned_t
a type for a number (unsigned)
Definition json.hpp:19673
friend std::istream & operator>>(std::istream &i, basic_json &j)
deserialize from stream
Definition json.hpp:23459
static std::vector< std::uint8_t > to_msgpack(const basic_json &j)
create a MessagePack serialization of a given JSON value
Definition json.hpp:23576
void swap(string_t &other)
exchanges the values
Definition json.hpp:22839
basic_json(const BasicJsonType &val)
create a JSON value from an existing one
Definition json.hpp:20165
json_reverse_iterator< typename basic_json::iterator > reverse_iterator
a reverse iterator for a basic_json container
Definition json.hpp:19548
const_reference at(size_type idx) const
access specified array element with bounds checking
Definition json.hpp:21277
detail::actual_object_comparator_t< basic_json > object_comparator_t
object key comparator type
Definition json.hpp:19685
basic_json(const basic_json &other)
copy constructor
Definition json.hpp:20461
void push_back(const typename object_t::value_type &val)
add an object to an object
Definition json.hpp:22469
std::pair< iterator, bool > emplace(Args &&... args)
add an object to an object if key does not exist
Definition json.hpp:22550
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:23569
constexpr bool is_object() const noexcept
return whether value is an object
Definition json.hpp:20673
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:23585
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:23751
iterator insert_iterator(const_iterator pos, Args &&... args)
Definition json.hpp:22582
basic_json(InputIT first, InputIT last)
construct a JSON container given an iterator range
Definition json.hpp:20348
bool contains(const typename object_t::key_type &key) const
check the existence of an element in a JSON object
Definition json.hpp:22045
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:23662
const_iterator find(KeyType &&key) const
find an element in a JSON object
Definition json.hpp:22013
::nlohmann::json_pointer< StringType > json_pointer
JSON Pointer, see nlohmann::json_pointer.
Definition json.hpp:19482
an internal type for a backed binary type
Definition json.hpp:5905
byte_container_with_subtype() noexcept(noexcept(container_type()))
Definition json.hpp:5911
byte_container_with_subtype(container_type &&b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5933
byte_container_with_subtype(container_type &&b) noexcept(noexcept(container_type(std::move(b))))
Definition json.hpp:5921
constexpr subtype_type subtype() const noexcept
return the binary subtype
Definition json.hpp:5960
byte_container_with_subtype(const container_type &b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
Definition json.hpp:5926
constexpr bool has_subtype() const noexcept
return whether the value has a subtype
Definition json.hpp:5967
byte_container_with_subtype(const container_type &b) noexcept(noexcept(container_type(b)))
Definition json.hpp:5916
void set_subtype(subtype_type subtype_) noexcept
sets the binary subtype
Definition json.hpp:5952
void clear_subtype() noexcept
clears the binary subtype
Definition json.hpp:5974
deserialization of CBOR, MessagePack, and UBJSON values
Definition json.hpp:9226
binary_reader(InputAdapterType &&adapter, const input_format_t format=input_format_t::json) noexcept
create a binary reader
Definition json.hpp:9242
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:9263
serialization to CBOR and MessagePack values
Definition json.hpp:15093
void write_bson(const BasicJsonType &j)
Definition json.hpp:15113
binary_writer(output_adapter_t< CharType > adapter)
create a binary writer
Definition json.hpp:15104
void write_ubjson(const BasicJsonType &j, const bool use_count, const bool use_type, const bool add_prefix=true, const bool use_bjdata=false)
Definition json.hpp:15792
void write_msgpack(const BasicJsonType &j)
Definition json.hpp:15466
void write_cbor(const BasicJsonType &j)
Definition json.hpp:15142
general exception of the basic_json class
Definition json.hpp:4386
const int id
the id of the exception
Definition json.hpp:4395
const char * what() const noexcept override
returns the explanatory string
Definition json.hpp:4389
Definition json.hpp:6202
Definition json.hpp:6240
exception indicating errors with iterators
Definition json.hpp:4537
a template for a bidirectional iterator for the basic_json class This class implements a both iterato...
Definition json.hpp:12930
iter_impl operator+(difference_type i) const
add to iterator
Definition json.hpp:13504
iter_impl & operator=(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting assignment
Definition json.hpp:13067
bool operator>=(const iter_impl &other) const
comparison: greater than or equal
Definition json.hpp:13449
iter_impl(const iter_impl< typename std::remove_const< BasicJsonType >::type > &other) noexcept
converting constructor
Definition json.hpp:13057
bool operator<(const iter_impl &other) const
comparison: smaller
Definition json.hpp:13396
bool operator<=(const iter_impl &other) const
comparison: less than or equal
Definition json.hpp:13431
iter_impl & operator-=(difference_type i)
subtract from iterator
Definition json.hpp:13495
iter_impl & operator--()
pre-decrement (–it)
Definition json.hpp:13310
const object_t::key_type & key() const
return the key of an object iterator
Definition json.hpp:13604
bool operator==(const IterImpl &other) const
comparison: equal
Definition json.hpp:13351
iter_impl operator++(int) &
post-increment (it++)
Definition json.hpp:13248
iter_impl & operator+=(difference_type i)
add to iterator
Definition json.hpp:13458
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13566
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:12962
typename BasicJsonType::difference_type difference_type
a type to represent differences between iterators
Definition json.hpp:12960
pointer operator->() const
dereference the iterator
Definition json.hpp:13206
internal_iterator< typename std::remove_const< BasicJsonType >::type > m_it
the actual iterator of the associated instance
Definition json.hpp:13629
difference_type operator-(const iter_impl &other) const
return difference
Definition json.hpp:13537
std::bidirectional_iterator_tag iterator_category
Definition json.hpp:12955
friend iter_impl operator+(difference_type i, const iter_impl &it)
addition of distance and iterator
Definition json.hpp:13515
reference value() const
return the value of an iterator
Definition json.hpp:13620
bool operator>(const iter_impl &other) const
comparison: greater than
Definition json.hpp:13440
iter_impl & operator++()
pre-increment (++it)
Definition json.hpp:13259
typename BasicJsonType::value_type value_type
the type of the values when the iterator is dereferenced
Definition json.hpp:12958
reference operator*() const
return a reference to the value pointed to by the iterator
Definition json.hpp:13162
iter_impl operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13526
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:12966
iter_impl & operator=(const iter_impl< const BasicJsonType > &other) noexcept
converting assignment
Definition json.hpp:13042
bool operator!=(const IterImpl &other) const
comparison: not equal
Definition json.hpp:13387
iter_impl operator--(int) &
post-decrement (it–)
Definition json.hpp:13299
iter_impl(const iter_impl< const BasicJsonType > &other) noexcept
const copy constructor
Definition json.hpp:13032
void set_end() noexcept
set the iterator past the last value
Definition json.hpp:13123
Definition json.hpp:12910
bool operator==(const iteration_proxy_value &o) const
equality operator (needed for InputIterator)
Definition json.hpp:5265
bool operator!=(const iteration_proxy_value &o) const
inequality operator (needed for range-based for)
Definition json.hpp:5271
iteration_proxy_value & operator++()
increment operator (needed for range-based for)
Definition json.hpp:5248
IteratorType::reference value() const
return value of the iterator
Definition json.hpp:5313
const string_type & key() const
return key of the iterator
Definition json.hpp:5277
proxy class for the items() function
Definition json.hpp:12909
iteration_proxy_value< IteratorType > end() const noexcept
return iterator end (needed for range-based for)
Definition json.hpp:5346
iteration_proxy(typename IteratorType::reference cont) noexcept
construct iteration proxy from a container
Definition json.hpp:5330
Definition json.hpp:6295
Definition json.hpp:14834
a template for a reverse iterator class
Definition json.hpp:13683
json_reverse_iterator operator++(int) &
post-increment (it++)
Definition json.hpp:13699
json_reverse_iterator operator--(int) &
post-decrement (it–)
Definition json.hpp:13711
json_reverse_iterator & operator++()
pre-increment (++it)
Definition json.hpp:13705
json_reverse_iterator & operator+=(difference_type i)
add to iterator
Definition json.hpp:13723
reference operator[](difference_type n) const
access to successor
Definition json.hpp:13747
auto key() const -> decltype(std::declval< Base >().key())
return the key of an object iterator
Definition json.hpp:13753
difference_type operator-(const json_reverse_iterator &other) const
return difference
Definition json.hpp:13741
typename Base::reference reference
the reference type for the pointed-to element
Definition json.hpp:13689
reference value() const
return the value of an iterator
Definition json.hpp:13760
json_reverse_iterator(const base_iterator &it) noexcept
create reverse iterator from base class
Definition json.hpp:13696
json_reverse_iterator & operator--()
pre-decrement (–it)
Definition json.hpp:13717
std::reverse_iterator< Base > base_iterator
shortcut to the reverse iterator adapter
Definition json.hpp:13687
json_reverse_iterator operator-(difference_type i) const
subtract from iterator
Definition json.hpp:13735
json_reverse_iterator(const typename base_iterator::iterator_type &it) noexcept
create reverse iterator from iterator
Definition json.hpp:13692
json_reverse_iterator operator+(difference_type i) const
add to iterator
Definition json.hpp:13729
Definition json.hpp:7304
Definition json.hpp:6997
SAX implementation to create a JSON value from SAX events.
Definition json.hpp:6814
json_sax_dom_parser(BasicJsonType &r, const bool allow_exceptions_=true)
Definition json.hpp:6827
Definition json.hpp:7421
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:7448
token_type
token types for the parser
Definition json.hpp:7425
lexical analysis
Definition json.hpp:7498
bool skip_bom()
skip the UTF-8 byte order mark
Definition json.hpp:8872
JSON_HEDLEY_RETURNS_NON_NULL constexpr const char * get_error_message() const noexcept
return syntax error message
Definition json.hpp:8859
std::string get_token_string() const
Definition json.hpp:8834
constexpr number_integer_t get_number_integer() const noexcept
return integer value
Definition json.hpp:8798
constexpr position_t get_position() const noexcept
return position of last read token
Definition json.hpp:8826
constexpr number_unsigned_t get_number_unsigned() const noexcept
return unsigned integer value
Definition json.hpp:8804
string_t & get_string()
return current string value (implicitly resets the token; useful only once)
Definition json.hpp:8816
constexpr number_float_t get_number_float() const noexcept
return floating-point value
Definition json.hpp:8810
exception indicating other library errors
Definition json.hpp:4589
exception indicating access out of the defined range
Definition json.hpp:4572
Definition json.hpp:15051
output adapter for output streams
Definition json.hpp:15003
output adapter for basic_string
Definition json.hpp:15028
output adapter for byte vectors
Definition json.hpp:14978
exception indicating a parse error
Definition json.hpp:4484
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:4496
const std::size_t byte
byte index of the parse error
Definition json.hpp:4521
syntax analysis
Definition json.hpp:12243
parser(InputAdapterType &&adapter, const parser_callback_t< BasicJsonType > cb=nullptr, const bool allow_exceptions_=true, const bool skip_comments=false)
a parser reading from an input adapter
Definition json.hpp:12253
void parse(const bool strict, BasicJsonType &result)
public parser interface
Definition json.hpp:12275
bool accept(const bool strict=true)
public accept interface
Definition json.hpp:12335
Definition json.hpp:12747
constexpr bool is_begin() const noexcept
return whether the iterator can be dereferenced
Definition json.hpp:12776
void set_end() noexcept
set iterator to a defined past the end
Definition json.hpp:12770
constexpr bool is_end() const noexcept
return whether the iterator is at end
Definition json.hpp:12782
void set_begin() noexcept
set iterator to a defined beginning
Definition json.hpp:12764
Definition json.hpp:18074
serializer(output_adapter_t< char > s, const char ichar, error_handler_t error_handler_=error_handler_t::strict)
Definition json.hpp:18089
const error_handler_t error_handler
error_handler how to react on decoding errors
Definition json.hpp:19006
string_t indent_string
the indentation string
Definition json.hpp:19003
const char indent_char
the indentation character
Definition json.hpp:19001
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:18129
Definition json.hpp:6619
exception indicating executing a member function with a wrong type
Definition json.hpp:4555
Definition json.hpp:6454
JSON Pointer defines a string syntax for identifying a specific value within a JSON document.
Definition json.hpp:13855
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:13950
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:13957
json_pointer(const string_t &s="")
create JSON pointer
Definition json.hpp:13881
bool empty() const noexcept
return whether pointer points to the root document
Definition json.hpp:14016
void pop_back()
remove last reference token
Definition json.hpp:13978
string_t to_string() const
return a string representation of the JSON pointer
Definition json.hpp:13887
json_pointer & operator/=(std::size_t array_idx)
append an array index at the end of this JSON pointer
Definition json.hpp:13935
void push_back(string_t &&token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14009
json_pointer & operator/=(const json_pointer &ptr)
append another JSON pointer at the end of this JSON pointer
Definition json.hpp:13917
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:13942
json_pointer parent_pointer() const
returns the parent of this JSON pointer
Definition json.hpp:13964
json_pointer & operator/=(string_t token)
append an unescaped reference token at the end of this JSON pointer
Definition json.hpp:13927
const string_t & back() const
return last reference token
Definition json.hpp:13990
friend std::ostream & operator<<(std::ostream &o, const json_pointer &ptr)
write string representation of the JSON pointer to stream
Definition json.hpp:13908
void push_back(const string_t &token)
append an unescaped token at the end of the reference pointer
Definition json.hpp:14002
int find_largest_pow10(const std::uint32_t n, std::uint32_t &pow10)
Definition json.hpp:17413
cached_power get_cached_power_for_binary_exponent(int e)
Definition json.hpp:17249
boundaries compute_boundaries(FloatType value)
Definition json.hpp:17110
void grisu2(char *buf, int &len, int &decimal_exponent, diyfp m_minus, diyfp v, diyfp m_plus)
Definition json.hpp:17749
void grisu2_digit_gen(char *buffer, int &length, int &decimal_exponent, diyfp M_minus, diyfp w, diyfp M_plus)
Definition json.hpp:17508
JSON_HEDLEY_RETURNS_NON_NULL char * append_exponent(char *buf, int e)
appends a decimal representation of e to buf
Definition json.hpp:17849
detail namespace with internal helper functions
Definition json.hpp:263
input_format_t
the supported input formats
Definition json.hpp:6190
parse_event_t
Definition json.hpp:12217
@ value
the parser finished reading a JSON value
@ key
the parser read a key of a value in an object
@ array_end
the parser read ] and finished processing a JSON array
@ array_start
the parser read [ and started to process a JSON array
@ object_start
the parser read { and started to process a JSON object
@ object_end
the parser read } and finished processing a JSON object
std::shared_ptr< output_adapter_protocol< CharType > > output_adapter_t
a type to simplify interfaces
Definition json.hpp:14973
void replace_substring(StringType &s, const StringType &f, const StringType &t)
replace all occurrences of a substring by another string
Definition json.hpp:2985
cbor_tag_handler_t
how to treat CBOR tags
Definition json.hpp:9199
@ store
store tags as binary type
@ error
throw a parse_error exception in case of a tag
value_t
the JSON type enumeration
Definition json.hpp:2887
@ null
null value
@ number_integer
number value (signed integer)
@ boolean
boolean value
@ discarded
discarded by the parser callback function
@ binary
binary array (ordered collection of bytes)
@ object
object (unordered set of name/value pairs)
@ string
string value
@ number_float
number value (floating-point)
@ number_unsigned
number value (unsigned integer)
@ array
array (ordered collection of values)
std::size_t hash(const BasicJsonType &j)
hash a JSON value
Definition json.hpp:6036
bool operator<(const value_t lhs, const value_t rhs) noexcept
comparison operator for JSON types
Definition json.hpp:2916
error_handler_t
how to treat decoding errors
Definition json.hpp:18066
@ strict
throw a type_error exception in case of invalid UTF-8
@ replace
replace invalid UTF-8 sequences with U+FFFD
StringType escape(StringType s)
string escaping as described in RFC 6901 (Sect. 4)
Definition json.hpp:3004
namespace for Niels Lohmann
Definition json.hpp:5847
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:5871
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:5861
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:5851
Definition json.hpp:3602
Definition json.hpp:3619
Definition json.hpp:3674
Definition json.hpp:295
Definition json.hpp:17097
Definition json.hpp:17236
Definition json.hpp:16979
static diyfp mul(const diyfp &x, const diyfp &y) noexcept
returns x * y
Definition json.hpp:17003
static diyfp normalize_to(const diyfp &x, const int target_exponent) noexcept
normalize x such that the result has the exponent E
Definition json.hpp:17085
static diyfp normalize(diyfp x) noexcept
normalize x such that the significand is >= 2^(q-1)
Definition json.hpp:17068
static diyfp sub(const diyfp &x, const diyfp &y) noexcept
returns x - y
Definition json.hpp:16991
Definition json.hpp:5433
Definition json.hpp:5113
Definition json.hpp:3541
Definition json.hpp:3597
Definition json.hpp:3566
Definition json.hpp:3581
Definition json.hpp:4629
Definition json.hpp:3137
an iterator value
Definition json.hpp:12863
Definition json.hpp:3490
Definition json.hpp:3477
Definition json.hpp:4195
Definition json.hpp:3991
Definition json.hpp:3874
Definition json.hpp:3945
Definition json.hpp:3795
Definition json.hpp:3832
Definition json.hpp:3948
Definition json.hpp:3961
Definition json.hpp:3768
Definition json.hpp:3918
Definition json.hpp:3828
Definition json.hpp:3839
Definition json.hpp:3964
Definition json.hpp:3706
Definition json.hpp:3687
Definition json.hpp:311
Definition json.hpp:3549
Definition json.hpp:6511
Definition json.hpp:3721
Definition json.hpp:3970
Definition json.hpp:3500
Definition json.hpp:4052
Definition json.hpp:4048
Definition json.hpp:3740
Definition json.hpp:9131
Definition json.hpp:9100
Definition json.hpp:3981
Definition json.hpp:4217
Definition json.hpp:3305
Definition json.hpp:3286
Default base class of the basic_json class.
Definition json.hpp:13802
Definition json.hpp:266
Definition json.hpp:3681
Definition json.hpp:281
abstract output adapter interface
Definition json.hpp:14959
struct to capture the start position of the current token
Definition json.hpp:3050
std::size_t chars_read_current_line
the number of characters read in the current line
Definition json.hpp:3054
std::size_t lines_read
the number of lines read
Definition json.hpp:3056
std::size_t chars_read_total
the total number of characters read
Definition json.hpp:3052
Definition json.hpp:3220
Definition json.hpp:3226
Definition json.hpp:5814
Definition json.hpp:3157
Definition json.hpp:3176
Definition json.hpp:4143
Definition json.hpp:4097
Definition json.hpp:6329
SAX interface.
Definition json.hpp:6684
virtual bool binary(binary_t &val)=0
a binary value was read
virtual bool number_float(number_float_t val, const string_t &s)=0
a floating-point number was read
virtual bool number_unsigned(number_unsigned_t val)=0
an unsigned integer number was read
virtual bool key(string_t &val)=0
an object key was read
virtual bool string(string_t &val)=0
a string value was read
virtual bool number_integer(number_integer_t val)=0
an integer number was read
virtual bool start_object(std::size_t elements)=0
the beginning of an object was read
virtual bool end_array()=0
the end of an array was read
virtual bool boolean(bool val)=0
a boolean value was read
virtual bool end_object()=0
the end of an object was read
virtual bool null()=0
a null value was read
virtual bool parse_error(std::size_t position, const std::string &last_token, const detail::exception &ex)=0
a parse error occurred
virtual bool start_array(std::size_t elements)=0
the beginning of an array was read
a minimal map-like container that preserves insertion order
Definition json.hpp:19048
bool operator()(::nlohmann::detail::value_t lhs, ::nlohmann::detail::value_t rhs) const noexcept
compare two value_t enum values
Definition json.hpp:24534