information-retrieval

Exploration of information retrieval topics
git clone git://git.laack.co/information-retrieval.git
Log | Files | Refs

json.hpp (909622B)


      1 //     __ _____ _____ _____
      2 //  __|  |   __|     |   | |  JSON for Modern C++
      3 // |  |  |__   |  |  | | | |  version 3.11.2
      4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
      5 //
      6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
      7 // SPDX-License-Identifier: MIT
      8 
      9 /****************************************************************************\
     10  * Note on documentation: The source files contain links to the online      *
     11  * documentation of the public API at https://json.nlohmann.me. This URL    *
     12  * contains the most recent documentation and should also be applicable to  *
     13  * previous versions; documentation for deprecated functions is not         *
     14  * removed, but marked deprecated. See "Generate documentation" section in  *
     15  * file docs/README.md.                                                     *
     16 \****************************************************************************/
     17 
     18 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
     19 #define INCLUDE_NLOHMANN_JSON_HPP_
     20 
     21 #include <algorithm> // all_of, find, for_each
     22 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
     23 #include <functional> // hash, less
     24 #include <initializer_list> // initializer_list
     25 #ifndef JSON_NO_IO
     26     #include <iosfwd> // istream, ostream
     27 #endif  // JSON_NO_IO
     28 #include <iterator> // random_access_iterator_tag
     29 #include <memory> // unique_ptr
     30 #include <string> // string, stoi, to_string
     31 #include <utility> // declval, forward, move, pair, swap
     32 #include <vector> // vector
     33 
     34 // #include <nlohmann/adl_serializer.hpp>
     35 //     __ _____ _____ _____
     36 //  __|  |   __|     |   | |  JSON for Modern C++
     37 // |  |  |__   |  |  | | | |  version 3.11.2
     38 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
     39 //
     40 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
     41 // SPDX-License-Identifier: MIT
     42 
     43 
     44 
     45 #include <utility>
     46 
     47 // #include <nlohmann/detail/abi_macros.hpp>
     48 //     __ _____ _____ _____
     49 //  __|  |   __|     |   | |  JSON for Modern C++
     50 // |  |  |__   |  |  | | | |  version 3.11.2
     51 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
     52 //
     53 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
     54 // SPDX-License-Identifier: MIT
     55 
     56 
     57 
     58 // This file contains all macro definitions affecting or depending on the ABI
     59 
     60 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
     61     #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
     62         #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 2
     63             #warning "Already included a different version of the library!"
     64         #endif
     65     #endif
     66 #endif
     67 
     68 #define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum)
     69 #define NLOHMANN_JSON_VERSION_MINOR 11  // NOLINT(modernize-macro-to-enum)
     70 #define NLOHMANN_JSON_VERSION_PATCH 2   // NOLINT(modernize-macro-to-enum)
     71 
     72 #ifndef JSON_DIAGNOSTICS
     73     #define JSON_DIAGNOSTICS 0
     74 #endif
     75 
     76 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
     77     #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
     78 #endif
     79 
     80 #if JSON_DIAGNOSTICS
     81     #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
     82 #else
     83     #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
     84 #endif
     85 
     86 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
     87     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
     88 #else
     89     #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
     90 #endif
     91 
     92 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
     93     #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
     94 #endif
     95 
     96 // Construct the namespace ABI tags component
     97 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
     98 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
     99     NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
    100 
    101 #define NLOHMANN_JSON_ABI_TAGS                                       \
    102     NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
    103             NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
    104             NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
    105 
    106 // Construct the namespace version component
    107 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
    108     _v ## major ## _ ## minor ## _ ## patch
    109 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
    110     NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
    111 
    112 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION
    113 #define NLOHMANN_JSON_NAMESPACE_VERSION
    114 #else
    115 #define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
    116     NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
    117                                            NLOHMANN_JSON_VERSION_MINOR, \
    118                                            NLOHMANN_JSON_VERSION_PATCH)
    119 #endif
    120 
    121 // Combine namespace components
    122 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
    123 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
    124     NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
    125 
    126 #ifndef NLOHMANN_JSON_NAMESPACE
    127 #define NLOHMANN_JSON_NAMESPACE               \
    128     nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
    129             NLOHMANN_JSON_ABI_TAGS,           \
    130             NLOHMANN_JSON_NAMESPACE_VERSION)
    131 #endif
    132 
    133 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
    134 #define NLOHMANN_JSON_NAMESPACE_BEGIN                \
    135     namespace nlohmann                               \
    136     {                                                \
    137     inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
    138                 NLOHMANN_JSON_ABI_TAGS,              \
    139                 NLOHMANN_JSON_NAMESPACE_VERSION)     \
    140     {
    141 #endif
    142 
    143 #ifndef NLOHMANN_JSON_NAMESPACE_END
    144 #define NLOHMANN_JSON_NAMESPACE_END                                     \
    145     }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
    146     }  // namespace nlohmann
    147 #endif
    148 
    149 // #include <nlohmann/detail/conversions/from_json.hpp>
    150 //     __ _____ _____ _____
    151 //  __|  |   __|     |   | |  JSON for Modern C++
    152 // |  |  |__   |  |  | | | |  version 3.11.2
    153 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    154 //
    155 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    156 // SPDX-License-Identifier: MIT
    157 
    158 
    159 
    160 #include <algorithm> // transform
    161 #include <array> // array
    162 #include <forward_list> // forward_list
    163 #include <iterator> // inserter, front_inserter, end
    164 #include <map> // map
    165 #include <string> // string
    166 #include <tuple> // tuple, make_tuple
    167 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
    168 #include <unordered_map> // unordered_map
    169 #include <utility> // pair, declval
    170 #include <valarray> // valarray
    171 
    172 // #include <nlohmann/detail/exceptions.hpp>
    173 //     __ _____ _____ _____
    174 //  __|  |   __|     |   | |  JSON for Modern C++
    175 // |  |  |__   |  |  | | | |  version 3.11.2
    176 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    177 //
    178 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    179 // SPDX-License-Identifier: MIT
    180 
    181 
    182 
    183 #include <cstddef> // nullptr_t
    184 #include <exception> // exception
    185 #if JSON_DIAGNOSTICS
    186     #include <numeric> // accumulate
    187 #endif
    188 #include <stdexcept> // runtime_error
    189 #include <string> // to_string
    190 #include <vector> // vector
    191 
    192 // #include <nlohmann/detail/value_t.hpp>
    193 //     __ _____ _____ _____
    194 //  __|  |   __|     |   | |  JSON for Modern C++
    195 // |  |  |__   |  |  | | | |  version 3.11.2
    196 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    197 //
    198 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    199 // SPDX-License-Identifier: MIT
    200 
    201 
    202 
    203 #include <array> // array
    204 #include <cstddef> // size_t
    205 #include <cstdint> // uint8_t
    206 #include <string> // string
    207 
    208 // #include <nlohmann/detail/macro_scope.hpp>
    209 //     __ _____ _____ _____
    210 //  __|  |   __|     |   | |  JSON for Modern C++
    211 // |  |  |__   |  |  | | | |  version 3.11.2
    212 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    213 //
    214 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    215 // SPDX-License-Identifier: MIT
    216 
    217 
    218 
    219 #include <utility> // declval, pair
    220 // #include <nlohmann/detail/meta/detected.hpp>
    221 //     __ _____ _____ _____
    222 //  __|  |   __|     |   | |  JSON for Modern C++
    223 // |  |  |__   |  |  | | | |  version 3.11.2
    224 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    225 //
    226 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    227 // SPDX-License-Identifier: MIT
    228 
    229 
    230 
    231 #include <type_traits>
    232 
    233 // #include <nlohmann/detail/meta/void_t.hpp>
    234 //     __ _____ _____ _____
    235 //  __|  |   __|     |   | |  JSON for Modern C++
    236 // |  |  |__   |  |  | | | |  version 3.11.2
    237 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    238 //
    239 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    240 // SPDX-License-Identifier: MIT
    241 
    242 
    243 
    244 // #include <nlohmann/detail/abi_macros.hpp>
    245 
    246 
    247 NLOHMANN_JSON_NAMESPACE_BEGIN
    248 namespace detail
    249 {
    250 
    251 template<typename ...Ts> struct make_void
    252 {
    253     using type = void;
    254 };
    255 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
    256 
    257 }  // namespace detail
    258 NLOHMANN_JSON_NAMESPACE_END
    259 
    260 
    261 NLOHMANN_JSON_NAMESPACE_BEGIN
    262 namespace detail
    263 {
    264 
    265 // https://en.cppreference.com/w/cpp/experimental/is_detected
    266 struct nonesuch
    267 {
    268     nonesuch() = delete;
    269     ~nonesuch() = delete;
    270     nonesuch(nonesuch const&) = delete;
    271     nonesuch(nonesuch const&&) = delete;
    272     void operator=(nonesuch const&) = delete;
    273     void operator=(nonesuch&&) = delete;
    274 };
    275 
    276 template<class Default,
    277          class AlwaysVoid,
    278          template<class...> class Op,
    279          class... Args>
    280 struct detector
    281 {
    282     using value_t = std::false_type;
    283     using type = Default;
    284 };
    285 
    286 template<class Default, template<class...> class Op, class... Args>
    287 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
    288 {
    289     using value_t = std::true_type;
    290     using type = Op<Args...>;
    291 };
    292 
    293 template<template<class...> class Op, class... Args>
    294 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
    295 
    296 template<template<class...> class Op, class... Args>
    297 struct is_detected_lazy : is_detected<Op, Args...> { };
    298 
    299 template<template<class...> class Op, class... Args>
    300 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
    301 
    302 template<class Default, template<class...> class Op, class... Args>
    303 using detected_or = detector<Default, void, Op, Args...>;
    304 
    305 template<class Default, template<class...> class Op, class... Args>
    306 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
    307 
    308 template<class Expected, template<class...> class Op, class... Args>
    309 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
    310 
    311 template<class To, template<class...> class Op, class... Args>
    312 using is_detected_convertible =
    313     std::is_convertible<detected_t<Op, Args...>, To>;
    314 
    315 }  // namespace detail
    316 NLOHMANN_JSON_NAMESPACE_END
    317 
    318 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
    319 
    320 
    321 //     __ _____ _____ _____
    322 //  __|  |   __|     |   | |  JSON for Modern C++
    323 // |  |  |__   |  |  | | | |  version 3.11.2
    324 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    325 //
    326 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
    327 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
    328 // SPDX-License-Identifier: MIT
    329 
    330 /* Hedley - https://nemequ.github.io/hedley
    331  * Created by Evan Nemerson <evan@nemerson.com>
    332  */
    333 
    334 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
    335 #if defined(JSON_HEDLEY_VERSION)
    336     #undef JSON_HEDLEY_VERSION
    337 #endif
    338 #define JSON_HEDLEY_VERSION 15
    339 
    340 #if defined(JSON_HEDLEY_STRINGIFY_EX)
    341     #undef JSON_HEDLEY_STRINGIFY_EX
    342 #endif
    343 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
    344 
    345 #if defined(JSON_HEDLEY_STRINGIFY)
    346     #undef JSON_HEDLEY_STRINGIFY
    347 #endif
    348 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
    349 
    350 #if defined(JSON_HEDLEY_CONCAT_EX)
    351     #undef JSON_HEDLEY_CONCAT_EX
    352 #endif
    353 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
    354 
    355 #if defined(JSON_HEDLEY_CONCAT)
    356     #undef JSON_HEDLEY_CONCAT
    357 #endif
    358 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
    359 
    360 #if defined(JSON_HEDLEY_CONCAT3_EX)
    361     #undef JSON_HEDLEY_CONCAT3_EX
    362 #endif
    363 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
    364 
    365 #if defined(JSON_HEDLEY_CONCAT3)
    366     #undef JSON_HEDLEY_CONCAT3
    367 #endif
    368 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
    369 
    370 #if defined(JSON_HEDLEY_VERSION_ENCODE)
    371     #undef JSON_HEDLEY_VERSION_ENCODE
    372 #endif
    373 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
    374 
    375 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
    376     #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
    377 #endif
    378 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
    379 
    380 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
    381     #undef JSON_HEDLEY_VERSION_DECODE_MINOR
    382 #endif
    383 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
    384 
    385 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
    386     #undef JSON_HEDLEY_VERSION_DECODE_REVISION
    387 #endif
    388 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
    389 
    390 #if defined(JSON_HEDLEY_GNUC_VERSION)
    391     #undef JSON_HEDLEY_GNUC_VERSION
    392 #endif
    393 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
    394     #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
    395 #elif defined(__GNUC__)
    396     #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
    397 #endif
    398 
    399 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
    400     #undef JSON_HEDLEY_GNUC_VERSION_CHECK
    401 #endif
    402 #if defined(JSON_HEDLEY_GNUC_VERSION)
    403     #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    404 #else
    405     #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
    406 #endif
    407 
    408 #if defined(JSON_HEDLEY_MSVC_VERSION)
    409     #undef JSON_HEDLEY_MSVC_VERSION
    410 #endif
    411 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
    412     #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
    413 #elif defined(_MSC_FULL_VER) && !defined(__ICL)
    414     #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
    415 #elif defined(_MSC_VER) && !defined(__ICL)
    416     #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
    417 #endif
    418 
    419 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
    420     #undef JSON_HEDLEY_MSVC_VERSION_CHECK
    421 #endif
    422 #if !defined(JSON_HEDLEY_MSVC_VERSION)
    423     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
    424 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
    425     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
    426 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
    427     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
    428 #else
    429     #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
    430 #endif
    431 
    432 #if defined(JSON_HEDLEY_INTEL_VERSION)
    433     #undef JSON_HEDLEY_INTEL_VERSION
    434 #endif
    435 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
    436     #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
    437 #elif defined(__INTEL_COMPILER) && !defined(__ICL)
    438     #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
    439 #endif
    440 
    441 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
    442     #undef JSON_HEDLEY_INTEL_VERSION_CHECK
    443 #endif
    444 #if defined(JSON_HEDLEY_INTEL_VERSION)
    445     #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    446 #else
    447     #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
    448 #endif
    449 
    450 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
    451     #undef JSON_HEDLEY_INTEL_CL_VERSION
    452 #endif
    453 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
    454     #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
    455 #endif
    456 
    457 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
    458     #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
    459 #endif
    460 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
    461     #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    462 #else
    463     #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
    464 #endif
    465 
    466 #if defined(JSON_HEDLEY_PGI_VERSION)
    467     #undef JSON_HEDLEY_PGI_VERSION
    468 #endif
    469 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
    470     #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
    471 #endif
    472 
    473 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
    474     #undef JSON_HEDLEY_PGI_VERSION_CHECK
    475 #endif
    476 #if defined(JSON_HEDLEY_PGI_VERSION)
    477     #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    478 #else
    479     #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
    480 #endif
    481 
    482 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
    483     #undef JSON_HEDLEY_SUNPRO_VERSION
    484 #endif
    485 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
    486     #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
    487 #elif defined(__SUNPRO_C)
    488     #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
    489 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
    490     #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
    491 #elif defined(__SUNPRO_CC)
    492     #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
    493 #endif
    494 
    495 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
    496     #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
    497 #endif
    498 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
    499     #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    500 #else
    501     #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
    502 #endif
    503 
    504 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
    505     #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
    506 #endif
    507 #if defined(__EMSCRIPTEN__)
    508     #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
    509 #endif
    510 
    511 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
    512     #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
    513 #endif
    514 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
    515     #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    516 #else
    517     #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
    518 #endif
    519 
    520 #if defined(JSON_HEDLEY_ARM_VERSION)
    521     #undef JSON_HEDLEY_ARM_VERSION
    522 #endif
    523 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
    524     #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
    525 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
    526     #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
    527 #endif
    528 
    529 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
    530     #undef JSON_HEDLEY_ARM_VERSION_CHECK
    531 #endif
    532 #if defined(JSON_HEDLEY_ARM_VERSION)
    533     #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    534 #else
    535     #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
    536 #endif
    537 
    538 #if defined(JSON_HEDLEY_IBM_VERSION)
    539     #undef JSON_HEDLEY_IBM_VERSION
    540 #endif
    541 #if defined(__ibmxl__)
    542     #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
    543 #elif defined(__xlC__) && defined(__xlC_ver__)
    544     #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
    545 #elif defined(__xlC__)
    546     #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
    547 #endif
    548 
    549 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
    550     #undef JSON_HEDLEY_IBM_VERSION_CHECK
    551 #endif
    552 #if defined(JSON_HEDLEY_IBM_VERSION)
    553     #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    554 #else
    555     #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
    556 #endif
    557 
    558 #if defined(JSON_HEDLEY_TI_VERSION)
    559     #undef JSON_HEDLEY_TI_VERSION
    560 #endif
    561 #if \
    562     defined(__TI_COMPILER_VERSION__) && \
    563     ( \
    564       defined(__TMS470__) || defined(__TI_ARM__) || \
    565       defined(__MSP430__) || \
    566       defined(__TMS320C2000__) \
    567     )
    568 #if (__TI_COMPILER_VERSION__ >= 16000000)
    569     #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    570 #endif
    571 #endif
    572 
    573 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
    574     #undef JSON_HEDLEY_TI_VERSION_CHECK
    575 #endif
    576 #if defined(JSON_HEDLEY_TI_VERSION)
    577     #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    578 #else
    579     #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
    580 #endif
    581 
    582 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
    583     #undef JSON_HEDLEY_TI_CL2000_VERSION
    584 #endif
    585 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
    586     #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    587 #endif
    588 
    589 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
    590     #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
    591 #endif
    592 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
    593     #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    594 #else
    595     #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
    596 #endif
    597 
    598 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
    599     #undef JSON_HEDLEY_TI_CL430_VERSION
    600 #endif
    601 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
    602     #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    603 #endif
    604 
    605 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
    606     #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
    607 #endif
    608 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
    609     #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    610 #else
    611     #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
    612 #endif
    613 
    614 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
    615     #undef JSON_HEDLEY_TI_ARMCL_VERSION
    616 #endif
    617 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
    618     #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    619 #endif
    620 
    621 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
    622     #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
    623 #endif
    624 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
    625     #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    626 #else
    627     #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
    628 #endif
    629 
    630 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
    631     #undef JSON_HEDLEY_TI_CL6X_VERSION
    632 #endif
    633 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
    634     #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    635 #endif
    636 
    637 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
    638     #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
    639 #endif
    640 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
    641     #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    642 #else
    643     #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
    644 #endif
    645 
    646 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
    647     #undef JSON_HEDLEY_TI_CL7X_VERSION
    648 #endif
    649 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
    650     #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    651 #endif
    652 
    653 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
    654     #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
    655 #endif
    656 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
    657     #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    658 #else
    659     #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
    660 #endif
    661 
    662 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
    663     #undef JSON_HEDLEY_TI_CLPRU_VERSION
    664 #endif
    665 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
    666     #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    667 #endif
    668 
    669 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
    670     #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
    671 #endif
    672 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
    673     #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    674 #else
    675     #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
    676 #endif
    677 
    678 #if defined(JSON_HEDLEY_CRAY_VERSION)
    679     #undef JSON_HEDLEY_CRAY_VERSION
    680 #endif
    681 #if defined(_CRAYC)
    682     #if defined(_RELEASE_PATCHLEVEL)
    683         #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
    684     #else
    685         #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
    686     #endif
    687 #endif
    688 
    689 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
    690     #undef JSON_HEDLEY_CRAY_VERSION_CHECK
    691 #endif
    692 #if defined(JSON_HEDLEY_CRAY_VERSION)
    693     #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    694 #else
    695     #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
    696 #endif
    697 
    698 #if defined(JSON_HEDLEY_IAR_VERSION)
    699     #undef JSON_HEDLEY_IAR_VERSION
    700 #endif
    701 #if defined(__IAR_SYSTEMS_ICC__)
    702     #if __VER__ > 1000
    703         #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
    704     #else
    705         #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
    706     #endif
    707 #endif
    708 
    709 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
    710     #undef JSON_HEDLEY_IAR_VERSION_CHECK
    711 #endif
    712 #if defined(JSON_HEDLEY_IAR_VERSION)
    713     #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    714 #else
    715     #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
    716 #endif
    717 
    718 #if defined(JSON_HEDLEY_TINYC_VERSION)
    719     #undef JSON_HEDLEY_TINYC_VERSION
    720 #endif
    721 #if defined(__TINYC__)
    722     #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
    723 #endif
    724 
    725 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
    726     #undef JSON_HEDLEY_TINYC_VERSION_CHECK
    727 #endif
    728 #if defined(JSON_HEDLEY_TINYC_VERSION)
    729     #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    730 #else
    731     #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
    732 #endif
    733 
    734 #if defined(JSON_HEDLEY_DMC_VERSION)
    735     #undef JSON_HEDLEY_DMC_VERSION
    736 #endif
    737 #if defined(__DMC__)
    738     #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
    739 #endif
    740 
    741 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
    742     #undef JSON_HEDLEY_DMC_VERSION_CHECK
    743 #endif
    744 #if defined(JSON_HEDLEY_DMC_VERSION)
    745     #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    746 #else
    747     #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
    748 #endif
    749 
    750 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
    751     #undef JSON_HEDLEY_COMPCERT_VERSION
    752 #endif
    753 #if defined(__COMPCERT_VERSION__)
    754     #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
    755 #endif
    756 
    757 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
    758     #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
    759 #endif
    760 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
    761     #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    762 #else
    763     #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
    764 #endif
    765 
    766 #if defined(JSON_HEDLEY_PELLES_VERSION)
    767     #undef JSON_HEDLEY_PELLES_VERSION
    768 #endif
    769 #if defined(__POCC__)
    770     #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
    771 #endif
    772 
    773 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
    774     #undef JSON_HEDLEY_PELLES_VERSION_CHECK
    775 #endif
    776 #if defined(JSON_HEDLEY_PELLES_VERSION)
    777     #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    778 #else
    779     #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
    780 #endif
    781 
    782 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
    783     #undef JSON_HEDLEY_MCST_LCC_VERSION
    784 #endif
    785 #if defined(__LCC__) && defined(__LCC_MINOR__)
    786     #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
    787 #endif
    788 
    789 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
    790     #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
    791 #endif
    792 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
    793     #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    794 #else
    795     #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
    796 #endif
    797 
    798 #if defined(JSON_HEDLEY_GCC_VERSION)
    799     #undef JSON_HEDLEY_GCC_VERSION
    800 #endif
    801 #if \
    802     defined(JSON_HEDLEY_GNUC_VERSION) && \
    803     !defined(__clang__) && \
    804     !defined(JSON_HEDLEY_INTEL_VERSION) && \
    805     !defined(JSON_HEDLEY_PGI_VERSION) && \
    806     !defined(JSON_HEDLEY_ARM_VERSION) && \
    807     !defined(JSON_HEDLEY_CRAY_VERSION) && \
    808     !defined(JSON_HEDLEY_TI_VERSION) && \
    809     !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
    810     !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
    811     !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
    812     !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
    813     !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
    814     !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
    815     !defined(__COMPCERT__) && \
    816     !defined(JSON_HEDLEY_MCST_LCC_VERSION)
    817     #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
    818 #endif
    819 
    820 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
    821     #undef JSON_HEDLEY_GCC_VERSION_CHECK
    822 #endif
    823 #if defined(JSON_HEDLEY_GCC_VERSION)
    824     #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    825 #else
    826     #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
    827 #endif
    828 
    829 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
    830     #undef JSON_HEDLEY_HAS_ATTRIBUTE
    831 #endif
    832 #if \
    833   defined(__has_attribute) && \
    834   ( \
    835     (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
    836   )
    837 #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
    838 #else
    839 #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
    840 #endif
    841 
    842 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
    843     #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
    844 #endif
    845 #if defined(__has_attribute)
    846     #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
    847 #else
    848     #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    849 #endif
    850 
    851 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
    852     #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
    853 #endif
    854 #if defined(__has_attribute)
    855     #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
    856 #else
    857     #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    858 #endif
    859 
    860 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
    861     #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
    862 #endif
    863 #if \
    864     defined(__has_cpp_attribute) && \
    865     defined(__cplusplus) && \
    866     (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
    867     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
    868 #else
    869     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
    870 #endif
    871 
    872 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
    873     #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
    874 #endif
    875 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
    876     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
    877 #elif \
    878     !defined(JSON_HEDLEY_PGI_VERSION) && \
    879     !defined(JSON_HEDLEY_IAR_VERSION) && \
    880     (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
    881     (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
    882     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
    883 #else
    884     #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
    885 #endif
    886 
    887 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
    888     #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
    889 #endif
    890 #if defined(__has_cpp_attribute) && defined(__cplusplus)
    891     #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
    892 #else
    893     #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    894 #endif
    895 
    896 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
    897     #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
    898 #endif
    899 #if defined(__has_cpp_attribute) && defined(__cplusplus)
    900     #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
    901 #else
    902     #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    903 #endif
    904 
    905 #if defined(JSON_HEDLEY_HAS_BUILTIN)
    906     #undef JSON_HEDLEY_HAS_BUILTIN
    907 #endif
    908 #if defined(__has_builtin)
    909     #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
    910 #else
    911     #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
    912 #endif
    913 
    914 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
    915     #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
    916 #endif
    917 #if defined(__has_builtin)
    918     #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
    919 #else
    920     #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    921 #endif
    922 
    923 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
    924     #undef JSON_HEDLEY_GCC_HAS_BUILTIN
    925 #endif
    926 #if defined(__has_builtin)
    927     #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
    928 #else
    929     #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    930 #endif
    931 
    932 #if defined(JSON_HEDLEY_HAS_FEATURE)
    933     #undef JSON_HEDLEY_HAS_FEATURE
    934 #endif
    935 #if defined(__has_feature)
    936     #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
    937 #else
    938     #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
    939 #endif
    940 
    941 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
    942     #undef JSON_HEDLEY_GNUC_HAS_FEATURE
    943 #endif
    944 #if defined(__has_feature)
    945     #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
    946 #else
    947     #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    948 #endif
    949 
    950 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
    951     #undef JSON_HEDLEY_GCC_HAS_FEATURE
    952 #endif
    953 #if defined(__has_feature)
    954     #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
    955 #else
    956     #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    957 #endif
    958 
    959 #if defined(JSON_HEDLEY_HAS_EXTENSION)
    960     #undef JSON_HEDLEY_HAS_EXTENSION
    961 #endif
    962 #if defined(__has_extension)
    963     #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
    964 #else
    965     #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
    966 #endif
    967 
    968 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
    969     #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
    970 #endif
    971 #if defined(__has_extension)
    972     #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
    973 #else
    974     #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    975 #endif
    976 
    977 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
    978     #undef JSON_HEDLEY_GCC_HAS_EXTENSION
    979 #endif
    980 #if defined(__has_extension)
    981     #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
    982 #else
    983     #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    984 #endif
    985 
    986 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
    987     #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
    988 #endif
    989 #if defined(__has_declspec_attribute)
    990     #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
    991 #else
    992     #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
    993 #endif
    994 
    995 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
    996     #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
    997 #endif
    998 #if defined(__has_declspec_attribute)
    999     #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
   1000 #else
   1001     #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
   1002 #endif
   1003 
   1004 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
   1005     #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
   1006 #endif
   1007 #if defined(__has_declspec_attribute)
   1008     #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
   1009 #else
   1010     #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   1011 #endif
   1012 
   1013 #if defined(JSON_HEDLEY_HAS_WARNING)
   1014     #undef JSON_HEDLEY_HAS_WARNING
   1015 #endif
   1016 #if defined(__has_warning)
   1017     #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
   1018 #else
   1019     #define JSON_HEDLEY_HAS_WARNING(warning) (0)
   1020 #endif
   1021 
   1022 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
   1023     #undef JSON_HEDLEY_GNUC_HAS_WARNING
   1024 #endif
   1025 #if defined(__has_warning)
   1026     #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
   1027 #else
   1028     #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
   1029 #endif
   1030 
   1031 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
   1032     #undef JSON_HEDLEY_GCC_HAS_WARNING
   1033 #endif
   1034 #if defined(__has_warning)
   1035     #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
   1036 #else
   1037     #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   1038 #endif
   1039 
   1040 #if \
   1041     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
   1042     defined(__clang__) || \
   1043     JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
   1044     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1045     JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
   1046     JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
   1047     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1048     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1049     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
   1050     JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
   1051     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
   1052     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
   1053     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1054     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1055     JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
   1056     JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
   1057     JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
   1058     (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
   1059     #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
   1060 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
   1061     #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
   1062 #else
   1063     #define JSON_HEDLEY_PRAGMA(value)
   1064 #endif
   1065 
   1066 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
   1067     #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
   1068 #endif
   1069 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
   1070     #undef JSON_HEDLEY_DIAGNOSTIC_POP
   1071 #endif
   1072 #if defined(__clang__)
   1073     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
   1074     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
   1075 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1076     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
   1077     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
   1078 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
   1079     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
   1080     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
   1081 #elif \
   1082     JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
   1083     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1084     #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
   1085     #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
   1086 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
   1087     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
   1088     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
   1089 #elif \
   1090     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1091     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1092     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
   1093     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
   1094     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1095     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
   1096     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
   1097     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
   1098 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
   1099     #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
   1100     #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
   1101 #else
   1102     #define JSON_HEDLEY_DIAGNOSTIC_PUSH
   1103     #define JSON_HEDLEY_DIAGNOSTIC_POP
   1104 #endif
   1105 
   1106 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
   1107    HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
   1108 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
   1109     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
   1110 #endif
   1111 #if defined(__cplusplus)
   1112 #  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
   1113 #    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
   1114 #      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
   1115 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
   1116     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1117     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
   1118     _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
   1119     _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
   1120     xpr \
   1121     JSON_HEDLEY_DIAGNOSTIC_POP
   1122 #      else
   1123 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
   1124     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1125     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
   1126     _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
   1127     xpr \
   1128     JSON_HEDLEY_DIAGNOSTIC_POP
   1129 #      endif
   1130 #    else
   1131 #      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
   1132     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1133     _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
   1134     xpr \
   1135     JSON_HEDLEY_DIAGNOSTIC_POP
   1136 #    endif
   1137 #  endif
   1138 #endif
   1139 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
   1140     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
   1141 #endif
   1142 
   1143 #if defined(JSON_HEDLEY_CONST_CAST)
   1144     #undef JSON_HEDLEY_CONST_CAST
   1145 #endif
   1146 #if defined(__cplusplus)
   1147 #  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
   1148 #elif \
   1149   JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
   1150   JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
   1151   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1152 #  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
   1153         JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1154         JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
   1155         ((T) (expr)); \
   1156         JSON_HEDLEY_DIAGNOSTIC_POP \
   1157     }))
   1158 #else
   1159 #  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
   1160 #endif
   1161 
   1162 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
   1163     #undef JSON_HEDLEY_REINTERPRET_CAST
   1164 #endif
   1165 #if defined(__cplusplus)
   1166     #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
   1167 #else
   1168     #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
   1169 #endif
   1170 
   1171 #if defined(JSON_HEDLEY_STATIC_CAST)
   1172     #undef JSON_HEDLEY_STATIC_CAST
   1173 #endif
   1174 #if defined(__cplusplus)
   1175     #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
   1176 #else
   1177     #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
   1178 #endif
   1179 
   1180 #if defined(JSON_HEDLEY_CPP_CAST)
   1181     #undef JSON_HEDLEY_CPP_CAST
   1182 #endif
   1183 #if defined(__cplusplus)
   1184 #  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
   1185 #    define JSON_HEDLEY_CPP_CAST(T, expr) \
   1186     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1187     _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
   1188     ((T) (expr)) \
   1189     JSON_HEDLEY_DIAGNOSTIC_POP
   1190 #  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
   1191 #    define JSON_HEDLEY_CPP_CAST(T, expr) \
   1192     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1193     _Pragma("diag_suppress=Pe137") \
   1194     JSON_HEDLEY_DIAGNOSTIC_POP
   1195 #  else
   1196 #    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
   1197 #  endif
   1198 #else
   1199 #  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
   1200 #endif
   1201 
   1202 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
   1203     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
   1204 #endif
   1205 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
   1206     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
   1207 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1208     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
   1209 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1210     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
   1211 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
   1212     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
   1213 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
   1214     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
   1215 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
   1216     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
   1217 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
   1218     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
   1219 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1220     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
   1221 #elif \
   1222     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1223     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1224     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1225     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1226     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1227     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1228     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1229     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1230     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1231     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1232     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
   1233     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
   1234 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
   1235     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
   1236 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
   1237     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
   1238 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1239     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
   1240 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
   1241     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
   1242 #else
   1243     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
   1244 #endif
   1245 
   1246 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
   1247     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
   1248 #endif
   1249 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
   1250     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
   1251 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1252     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
   1253 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1254     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
   1255 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
   1256     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
   1257 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
   1258     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
   1259 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
   1260     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
   1261 #elif \
   1262     JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
   1263     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
   1264     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1265     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
   1266     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
   1267 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
   1268     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
   1269 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1270     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
   1271 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1272     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
   1273 #else
   1274     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
   1275 #endif
   1276 
   1277 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
   1278     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
   1279 #endif
   1280 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
   1281     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
   1282 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
   1283     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
   1284 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
   1285     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
   1286 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1287     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
   1288 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
   1289     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
   1290 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
   1291     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
   1292 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
   1293     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
   1294 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
   1295     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
   1296 #elif \
   1297     JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
   1298     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
   1299     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
   1300     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
   1301 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1302     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
   1303 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1304     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
   1305 #else
   1306     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
   1307 #endif
   1308 
   1309 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
   1310     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
   1311 #endif
   1312 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
   1313     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
   1314 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1315     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
   1316 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
   1317     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
   1318 #else
   1319     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
   1320 #endif
   1321 
   1322 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
   1323     #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
   1324 #endif
   1325 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
   1326     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
   1327 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
   1328     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
   1329 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
   1330     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
   1331 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1332     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
   1333 #else
   1334     #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
   1335 #endif
   1336 
   1337 #if defined(JSON_HEDLEY_DEPRECATED)
   1338     #undef JSON_HEDLEY_DEPRECATED
   1339 #endif
   1340 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
   1341     #undef JSON_HEDLEY_DEPRECATED_FOR
   1342 #endif
   1343 #if \
   1344     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
   1345     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1346     #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
   1347     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
   1348 #elif \
   1349     (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
   1350     JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
   1351     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1352     JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
   1353     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
   1354     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1355     JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
   1356     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
   1357     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
   1358     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1359     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
   1360     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1361     #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
   1362     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
   1363 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
   1364     #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
   1365     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
   1366 #elif \
   1367     JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
   1368     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1369     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1370     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1371     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1372     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1373     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1374     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1375     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1376     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1377     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1378     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1379     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1380     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1381     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
   1382     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1383     #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
   1384     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
   1385 #elif \
   1386     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1387     JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
   1388     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1389     #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
   1390     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
   1391 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1392     #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
   1393     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
   1394 #else
   1395     #define JSON_HEDLEY_DEPRECATED(since)
   1396     #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
   1397 #endif
   1398 
   1399 #if defined(JSON_HEDLEY_UNAVAILABLE)
   1400     #undef JSON_HEDLEY_UNAVAILABLE
   1401 #endif
   1402 #if \
   1403     JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
   1404     JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
   1405     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1406     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1407     #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
   1408 #else
   1409     #define JSON_HEDLEY_UNAVAILABLE(available_since)
   1410 #endif
   1411 
   1412 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
   1413     #undef JSON_HEDLEY_WARN_UNUSED_RESULT
   1414 #endif
   1415 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
   1416     #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
   1417 #endif
   1418 #if \
   1419     JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
   1420     JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
   1421     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1422     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1423     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1424     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1425     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1426     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1427     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1428     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1429     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1430     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1431     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1432     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1433     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
   1434     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1435     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1436     #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
   1437     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
   1438 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
   1439     #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
   1440     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
   1441 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
   1442     #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
   1443     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
   1444 #elif defined(_Check_return_) /* SAL */
   1445     #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
   1446     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
   1447 #else
   1448     #define JSON_HEDLEY_WARN_UNUSED_RESULT
   1449     #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
   1450 #endif
   1451 
   1452 #if defined(JSON_HEDLEY_SENTINEL)
   1453     #undef JSON_HEDLEY_SENTINEL
   1454 #endif
   1455 #if \
   1456     JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
   1457     JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
   1458     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1459     JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
   1460     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1461     #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
   1462 #else
   1463     #define JSON_HEDLEY_SENTINEL(position)
   1464 #endif
   1465 
   1466 #if defined(JSON_HEDLEY_NO_RETURN)
   1467     #undef JSON_HEDLEY_NO_RETURN
   1468 #endif
   1469 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1470     #define JSON_HEDLEY_NO_RETURN __noreturn
   1471 #elif \
   1472     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1473     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1474     #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
   1475 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
   1476     #define JSON_HEDLEY_NO_RETURN _Noreturn
   1477 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
   1478     #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
   1479 #elif \
   1480     JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
   1481     JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
   1482     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1483     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1484     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1485     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1486     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1487     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1488     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1489     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1490     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1491     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1492     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1493     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1494     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1495     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1496     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1497     #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
   1498 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1499     #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
   1500 #elif \
   1501     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1502     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1503     #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
   1504 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
   1505     #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
   1506 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
   1507     #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
   1508 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
   1509     #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
   1510 #else
   1511     #define JSON_HEDLEY_NO_RETURN
   1512 #endif
   1513 
   1514 #if defined(JSON_HEDLEY_NO_ESCAPE)
   1515     #undef JSON_HEDLEY_NO_ESCAPE
   1516 #endif
   1517 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
   1518     #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
   1519 #else
   1520     #define JSON_HEDLEY_NO_ESCAPE
   1521 #endif
   1522 
   1523 #if defined(JSON_HEDLEY_UNREACHABLE)
   1524     #undef JSON_HEDLEY_UNREACHABLE
   1525 #endif
   1526 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
   1527     #undef JSON_HEDLEY_UNREACHABLE_RETURN
   1528 #endif
   1529 #if defined(JSON_HEDLEY_ASSUME)
   1530     #undef JSON_HEDLEY_ASSUME
   1531 #endif
   1532 #if \
   1533     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1534     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1535     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1536     #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
   1537 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
   1538     #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
   1539 #elif \
   1540     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
   1541     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
   1542     #if defined(__cplusplus)
   1543         #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
   1544     #else
   1545         #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
   1546     #endif
   1547 #endif
   1548 #if \
   1549     (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
   1550     JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
   1551     JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
   1552     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1553     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
   1554     JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
   1555     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1556     #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
   1557 #elif defined(JSON_HEDLEY_ASSUME)
   1558     #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
   1559 #endif
   1560 #if !defined(JSON_HEDLEY_ASSUME)
   1561     #if defined(JSON_HEDLEY_UNREACHABLE)
   1562         #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
   1563     #else
   1564         #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
   1565     #endif
   1566 #endif
   1567 #if defined(JSON_HEDLEY_UNREACHABLE)
   1568     #if  \
   1569         JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
   1570         JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
   1571         #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
   1572     #else
   1573         #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
   1574     #endif
   1575 #else
   1576     #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
   1577 #endif
   1578 #if !defined(JSON_HEDLEY_UNREACHABLE)
   1579     #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
   1580 #endif
   1581 
   1582 JSON_HEDLEY_DIAGNOSTIC_PUSH
   1583 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
   1584     #pragma clang diagnostic ignored "-Wpedantic"
   1585 #endif
   1586 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
   1587     #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
   1588 #endif
   1589 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
   1590     #if defined(__clang__)
   1591         #pragma clang diagnostic ignored "-Wvariadic-macros"
   1592     #elif defined(JSON_HEDLEY_GCC_VERSION)
   1593         #pragma GCC diagnostic ignored "-Wvariadic-macros"
   1594     #endif
   1595 #endif
   1596 #if defined(JSON_HEDLEY_NON_NULL)
   1597     #undef JSON_HEDLEY_NON_NULL
   1598 #endif
   1599 #if \
   1600     JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
   1601     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
   1602     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1603     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
   1604     #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
   1605 #else
   1606     #define JSON_HEDLEY_NON_NULL(...)
   1607 #endif
   1608 JSON_HEDLEY_DIAGNOSTIC_POP
   1609 
   1610 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
   1611     #undef JSON_HEDLEY_PRINTF_FORMAT
   1612 #endif
   1613 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
   1614     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
   1615 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
   1616     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
   1617 #elif \
   1618     JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
   1619     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1620     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1621     JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
   1622     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1623     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1624     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1625     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1626     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1627     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1628     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1629     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1630     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1631     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1632     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1633     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1634     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1635     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
   1636 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
   1637     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
   1638 #else
   1639     #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
   1640 #endif
   1641 
   1642 #if defined(JSON_HEDLEY_CONSTEXPR)
   1643     #undef JSON_HEDLEY_CONSTEXPR
   1644 #endif
   1645 #if defined(__cplusplus)
   1646     #if __cplusplus >= 201103L
   1647         #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
   1648     #endif
   1649 #endif
   1650 #if !defined(JSON_HEDLEY_CONSTEXPR)
   1651     #define JSON_HEDLEY_CONSTEXPR
   1652 #endif
   1653 
   1654 #if defined(JSON_HEDLEY_PREDICT)
   1655     #undef JSON_HEDLEY_PREDICT
   1656 #endif
   1657 #if defined(JSON_HEDLEY_LIKELY)
   1658     #undef JSON_HEDLEY_LIKELY
   1659 #endif
   1660 #if defined(JSON_HEDLEY_UNLIKELY)
   1661     #undef JSON_HEDLEY_UNLIKELY
   1662 #endif
   1663 #if defined(JSON_HEDLEY_UNPREDICTABLE)
   1664     #undef JSON_HEDLEY_UNPREDICTABLE
   1665 #endif
   1666 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
   1667     #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
   1668 #endif
   1669 #if \
   1670   (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
   1671   JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
   1672   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1673 #  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
   1674 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
   1675 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
   1676 #  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
   1677 #  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
   1678 #elif \
   1679   (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
   1680   JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
   1681   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1682   (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
   1683   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1684   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1685   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1686   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
   1687   JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
   1688   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
   1689   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
   1690   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1691   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1692   JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
   1693   JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
   1694   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1695 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
   1696     (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
   1697 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
   1698     (__extension__ ({ \
   1699         double hedley_probability_ = (probability); \
   1700         ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
   1701     }))
   1702 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
   1703     (__extension__ ({ \
   1704         double hedley_probability_ = (probability); \
   1705         ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
   1706     }))
   1707 #  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
   1708 #  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
   1709 #else
   1710 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
   1711 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
   1712 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
   1713 #  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
   1714 #  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
   1715 #endif
   1716 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
   1717     #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
   1718 #endif
   1719 
   1720 #if defined(JSON_HEDLEY_MALLOC)
   1721     #undef JSON_HEDLEY_MALLOC
   1722 #endif
   1723 #if \
   1724     JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
   1725     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1726     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1727     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1728     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1729     JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
   1730     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1731     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1732     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1733     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1734     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1735     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1736     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1737     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1738     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1739     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1740     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1741     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1742     #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
   1743 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1744     #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
   1745 #elif \
   1746     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
   1747     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1748     #define JSON_HEDLEY_MALLOC __declspec(restrict)
   1749 #else
   1750     #define JSON_HEDLEY_MALLOC
   1751 #endif
   1752 
   1753 #if defined(JSON_HEDLEY_PURE)
   1754     #undef JSON_HEDLEY_PURE
   1755 #endif
   1756 #if \
   1757   JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
   1758   JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
   1759   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1760   JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1761   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1762   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1763   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1764   (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1765   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1766   (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1767   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1768   (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1769   JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1770   (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1771   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1772   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1773   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1774   JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1775   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1776 #  define JSON_HEDLEY_PURE __attribute__((__pure__))
   1777 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1778 #  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
   1779 #elif defined(__cplusplus) && \
   1780     ( \
   1781       JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
   1782       JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
   1783       JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
   1784     )
   1785 #  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
   1786 #else
   1787 #  define JSON_HEDLEY_PURE
   1788 #endif
   1789 
   1790 #if defined(JSON_HEDLEY_CONST)
   1791     #undef JSON_HEDLEY_CONST
   1792 #endif
   1793 #if \
   1794     JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
   1795     JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
   1796     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1797     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1798     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1799     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1800     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1801     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1802     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1803     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1804     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1805     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1806     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1807     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1808     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1809     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1810     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1811     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1812     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1813     #define JSON_HEDLEY_CONST __attribute__((__const__))
   1814 #elif \
   1815     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1816     #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
   1817 #else
   1818     #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
   1819 #endif
   1820 
   1821 #if defined(JSON_HEDLEY_RESTRICT)
   1822     #undef JSON_HEDLEY_RESTRICT
   1823 #endif
   1824 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
   1825     #define JSON_HEDLEY_RESTRICT restrict
   1826 #elif \
   1827     JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1828     JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
   1829     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1830     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
   1831     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1832     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1833     JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1834     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1835     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
   1836     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
   1837     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1838     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
   1839     JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
   1840     defined(__clang__) || \
   1841     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1842     #define JSON_HEDLEY_RESTRICT __restrict
   1843 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
   1844     #define JSON_HEDLEY_RESTRICT _Restrict
   1845 #else
   1846     #define JSON_HEDLEY_RESTRICT
   1847 #endif
   1848 
   1849 #if defined(JSON_HEDLEY_INLINE)
   1850     #undef JSON_HEDLEY_INLINE
   1851 #endif
   1852 #if \
   1853     (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
   1854     (defined(__cplusplus) && (__cplusplus >= 199711L))
   1855     #define JSON_HEDLEY_INLINE inline
   1856 #elif \
   1857     defined(JSON_HEDLEY_GCC_VERSION) || \
   1858     JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
   1859     #define JSON_HEDLEY_INLINE __inline__
   1860 #elif \
   1861     JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
   1862     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
   1863     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1864     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
   1865     JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
   1866     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
   1867     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
   1868     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1869     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1870     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1871     #define JSON_HEDLEY_INLINE __inline
   1872 #else
   1873     #define JSON_HEDLEY_INLINE
   1874 #endif
   1875 
   1876 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
   1877     #undef JSON_HEDLEY_ALWAYS_INLINE
   1878 #endif
   1879 #if \
   1880   JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
   1881   JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
   1882   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1883   JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1884   JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1885   JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1886   JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1887   (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1888   JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1889   (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1890   JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1891   (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1892   JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1893   (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1894   JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1895   JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1896   JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1897   JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
   1898   JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1899 #  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
   1900 #elif \
   1901   JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
   1902   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1903 #  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
   1904 #elif defined(__cplusplus) && \
   1905     ( \
   1906       JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1907       JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1908       JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1909       JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
   1910       JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1911       JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
   1912     )
   1913 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
   1914 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1915 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
   1916 #else
   1917 #  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
   1918 #endif
   1919 
   1920 #if defined(JSON_HEDLEY_NEVER_INLINE)
   1921     #undef JSON_HEDLEY_NEVER_INLINE
   1922 #endif
   1923 #if \
   1924     JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
   1925     JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
   1926     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1927     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1928     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1929     JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1930     JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1931     (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1932     JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1933     (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1934     JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1935     (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1936     JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1937     (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1938     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1939     JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1940     JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1941     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
   1942     JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1943     #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
   1944 #elif \
   1945     JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1946     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1947     #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
   1948 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
   1949     #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
   1950 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
   1951     #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
   1952 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1953     #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
   1954 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
   1955     #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
   1956 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
   1957     #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
   1958 #else
   1959     #define JSON_HEDLEY_NEVER_INLINE
   1960 #endif
   1961 
   1962 #if defined(JSON_HEDLEY_PRIVATE)
   1963     #undef JSON_HEDLEY_PRIVATE
   1964 #endif
   1965 #if defined(JSON_HEDLEY_PUBLIC)
   1966     #undef JSON_HEDLEY_PUBLIC
   1967 #endif
   1968 #if defined(JSON_HEDLEY_IMPORT)
   1969     #undef JSON_HEDLEY_IMPORT
   1970 #endif
   1971 #if defined(_WIN32) || defined(__CYGWIN__)
   1972 #  define JSON_HEDLEY_PRIVATE
   1973 #  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
   1974 #  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
   1975 #else
   1976 #  if \
   1977     JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
   1978     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
   1979     JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1980     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1981     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1982     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
   1983     ( \
   1984       defined(__TI_EABI__) && \
   1985       ( \
   1986         (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1987         JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
   1988       ) \
   1989     ) || \
   1990     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1991 #    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
   1992 #    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
   1993 #  else
   1994 #    define JSON_HEDLEY_PRIVATE
   1995 #    define JSON_HEDLEY_PUBLIC
   1996 #  endif
   1997 #  define JSON_HEDLEY_IMPORT    extern
   1998 #endif
   1999 
   2000 #if defined(JSON_HEDLEY_NO_THROW)
   2001     #undef JSON_HEDLEY_NO_THROW
   2002 #endif
   2003 #if \
   2004     JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
   2005     JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
   2006     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2007     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2008     #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
   2009 #elif \
   2010     JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
   2011     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
   2012     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
   2013     #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
   2014 #else
   2015     #define JSON_HEDLEY_NO_THROW
   2016 #endif
   2017 
   2018 #if defined(JSON_HEDLEY_FALL_THROUGH)
   2019     #undef JSON_HEDLEY_FALL_THROUGH
   2020 #endif
   2021 #if \
   2022     JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
   2023     JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
   2024     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2025     #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
   2026 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
   2027     #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
   2028 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
   2029     #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
   2030 #elif defined(__fallthrough) /* SAL */
   2031     #define JSON_HEDLEY_FALL_THROUGH __fallthrough
   2032 #else
   2033     #define JSON_HEDLEY_FALL_THROUGH
   2034 #endif
   2035 
   2036 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
   2037     #undef JSON_HEDLEY_RETURNS_NON_NULL
   2038 #endif
   2039 #if \
   2040     JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
   2041     JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
   2042     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2043     #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
   2044 #elif defined(_Ret_notnull_) /* SAL */
   2045     #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
   2046 #else
   2047     #define JSON_HEDLEY_RETURNS_NON_NULL
   2048 #endif
   2049 
   2050 #if defined(JSON_HEDLEY_ARRAY_PARAM)
   2051     #undef JSON_HEDLEY_ARRAY_PARAM
   2052 #endif
   2053 #if \
   2054     defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
   2055     !defined(__STDC_NO_VLA__) && \
   2056     !defined(__cplusplus) && \
   2057     !defined(JSON_HEDLEY_PGI_VERSION) && \
   2058     !defined(JSON_HEDLEY_TINYC_VERSION)
   2059     #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
   2060 #else
   2061     #define JSON_HEDLEY_ARRAY_PARAM(name)
   2062 #endif
   2063 
   2064 #if defined(JSON_HEDLEY_IS_CONSTANT)
   2065     #undef JSON_HEDLEY_IS_CONSTANT
   2066 #endif
   2067 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
   2068     #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
   2069 #endif
   2070 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
   2071    HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
   2072 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
   2073     #undef JSON_HEDLEY_IS_CONSTEXPR_
   2074 #endif
   2075 #if \
   2076     JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
   2077     JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
   2078     JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2079     JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
   2080     JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   2081     JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
   2082     JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
   2083     (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
   2084     JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
   2085     JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2086     #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
   2087 #endif
   2088 #if !defined(__cplusplus)
   2089 #  if \
   2090        JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
   2091        JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
   2092        JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2093        JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
   2094        JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
   2095        JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
   2096        JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
   2097 #if defined(__INTPTR_TYPE__)
   2098     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
   2099 #else
   2100     #include <stdint.h>
   2101     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
   2102 #endif
   2103 #  elif \
   2104        ( \
   2105           defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
   2106           !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
   2107           !defined(JSON_HEDLEY_PGI_VERSION) && \
   2108           !defined(JSON_HEDLEY_IAR_VERSION)) || \
   2109        (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
   2110        JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
   2111        JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
   2112        JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
   2113        JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
   2114 #if defined(__INTPTR_TYPE__)
   2115     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
   2116 #else
   2117     #include <stdint.h>
   2118     #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
   2119 #endif
   2120 #  elif \
   2121        defined(JSON_HEDLEY_GCC_VERSION) || \
   2122        defined(JSON_HEDLEY_INTEL_VERSION) || \
   2123        defined(JSON_HEDLEY_TINYC_VERSION) || \
   2124        defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
   2125        JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
   2126        defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
   2127        defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
   2128        defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
   2129        defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
   2130        defined(__clang__)
   2131 #    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
   2132         sizeof(void) != \
   2133         sizeof(*( \
   2134                   1 ? \
   2135                   ((void*) ((expr) * 0L) ) : \
   2136 ((struct { char v[sizeof(void) * 2]; } *) 1) \
   2137                 ) \
   2138               ) \
   2139                                             )
   2140 #  endif
   2141 #endif
   2142 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
   2143     #if !defined(JSON_HEDLEY_IS_CONSTANT)
   2144         #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
   2145     #endif
   2146     #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
   2147 #else
   2148     #if !defined(JSON_HEDLEY_IS_CONSTANT)
   2149         #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
   2150     #endif
   2151     #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
   2152 #endif
   2153 
   2154 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
   2155     #undef JSON_HEDLEY_BEGIN_C_DECLS
   2156 #endif
   2157 #if defined(JSON_HEDLEY_END_C_DECLS)
   2158     #undef JSON_HEDLEY_END_C_DECLS
   2159 #endif
   2160 #if defined(JSON_HEDLEY_C_DECL)
   2161     #undef JSON_HEDLEY_C_DECL
   2162 #endif
   2163 #if defined(__cplusplus)
   2164     #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
   2165     #define JSON_HEDLEY_END_C_DECLS }
   2166     #define JSON_HEDLEY_C_DECL extern "C"
   2167 #else
   2168     #define JSON_HEDLEY_BEGIN_C_DECLS
   2169     #define JSON_HEDLEY_END_C_DECLS
   2170     #define JSON_HEDLEY_C_DECL
   2171 #endif
   2172 
   2173 #if defined(JSON_HEDLEY_STATIC_ASSERT)
   2174     #undef JSON_HEDLEY_STATIC_ASSERT
   2175 #endif
   2176 #if \
   2177   !defined(__cplusplus) && ( \
   2178       (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
   2179       (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
   2180       JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
   2181       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2182       defined(_Static_assert) \
   2183     )
   2184 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
   2185 #elif \
   2186   (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
   2187   JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
   2188   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   2189 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
   2190 #else
   2191 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
   2192 #endif
   2193 
   2194 #if defined(JSON_HEDLEY_NULL)
   2195     #undef JSON_HEDLEY_NULL
   2196 #endif
   2197 #if defined(__cplusplus)
   2198     #if __cplusplus >= 201103L
   2199         #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
   2200     #elif defined(NULL)
   2201         #define JSON_HEDLEY_NULL NULL
   2202     #else
   2203         #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
   2204     #endif
   2205 #elif defined(NULL)
   2206     #define JSON_HEDLEY_NULL NULL
   2207 #else
   2208     #define JSON_HEDLEY_NULL ((void*) 0)
   2209 #endif
   2210 
   2211 #if defined(JSON_HEDLEY_MESSAGE)
   2212     #undef JSON_HEDLEY_MESSAGE
   2213 #endif
   2214 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
   2215 #  define JSON_HEDLEY_MESSAGE(msg) \
   2216     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2217     JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
   2218     JSON_HEDLEY_PRAGMA(message msg) \
   2219     JSON_HEDLEY_DIAGNOSTIC_POP
   2220 #elif \
   2221   JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
   2222   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   2223 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
   2224 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
   2225 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
   2226 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   2227 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
   2228 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
   2229 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
   2230 #else
   2231 #  define JSON_HEDLEY_MESSAGE(msg)
   2232 #endif
   2233 
   2234 #if defined(JSON_HEDLEY_WARNING)
   2235     #undef JSON_HEDLEY_WARNING
   2236 #endif
   2237 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
   2238 #  define JSON_HEDLEY_WARNING(msg) \
   2239     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2240     JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
   2241     JSON_HEDLEY_PRAGMA(clang warning msg) \
   2242     JSON_HEDLEY_DIAGNOSTIC_POP
   2243 #elif \
   2244   JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
   2245   JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
   2246   JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   2247 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
   2248 #elif \
   2249   JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
   2250   JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   2251 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
   2252 #else
   2253 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
   2254 #endif
   2255 
   2256 #if defined(JSON_HEDLEY_REQUIRE)
   2257     #undef JSON_HEDLEY_REQUIRE
   2258 #endif
   2259 #if defined(JSON_HEDLEY_REQUIRE_MSG)
   2260     #undef JSON_HEDLEY_REQUIRE_MSG
   2261 #endif
   2262 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
   2263 #  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
   2264 #    define JSON_HEDLEY_REQUIRE(expr) \
   2265     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2266     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
   2267     __attribute__((diagnose_if(!(expr), #expr, "error"))) \
   2268     JSON_HEDLEY_DIAGNOSTIC_POP
   2269 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
   2270     JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2271     _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
   2272     __attribute__((diagnose_if(!(expr), msg, "error"))) \
   2273     JSON_HEDLEY_DIAGNOSTIC_POP
   2274 #  else
   2275 #    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
   2276 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
   2277 #  endif
   2278 #else
   2279 #  define JSON_HEDLEY_REQUIRE(expr)
   2280 #  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
   2281 #endif
   2282 
   2283 #if defined(JSON_HEDLEY_FLAGS)
   2284     #undef JSON_HEDLEY_FLAGS
   2285 #endif
   2286 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
   2287     #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
   2288 #else
   2289     #define JSON_HEDLEY_FLAGS
   2290 #endif
   2291 
   2292 #if defined(JSON_HEDLEY_FLAGS_CAST)
   2293     #undef JSON_HEDLEY_FLAGS_CAST
   2294 #endif
   2295 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
   2296 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
   2297         JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2298         _Pragma("warning(disable:188)") \
   2299         ((T) (expr)); \
   2300         JSON_HEDLEY_DIAGNOSTIC_POP \
   2301     }))
   2302 #else
   2303 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
   2304 #endif
   2305 
   2306 #if defined(JSON_HEDLEY_EMPTY_BASES)
   2307     #undef JSON_HEDLEY_EMPTY_BASES
   2308 #endif
   2309 #if \
   2310     (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
   2311     JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   2312     #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
   2313 #else
   2314     #define JSON_HEDLEY_EMPTY_BASES
   2315 #endif
   2316 
   2317 /* Remaining macros are deprecated. */
   2318 
   2319 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
   2320     #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
   2321 #endif
   2322 #if defined(__clang__)
   2323     #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
   2324 #else
   2325     #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   2326 #endif
   2327 
   2328 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
   2329     #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
   2330 #endif
   2331 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
   2332 
   2333 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
   2334     #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
   2335 #endif
   2336 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
   2337 
   2338 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
   2339     #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
   2340 #endif
   2341 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
   2342 
   2343 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
   2344     #undef JSON_HEDLEY_CLANG_HAS_FEATURE
   2345 #endif
   2346 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
   2347 
   2348 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
   2349     #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
   2350 #endif
   2351 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
   2352 
   2353 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
   2354     #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
   2355 #endif
   2356 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
   2357 
   2358 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
   2359     #undef JSON_HEDLEY_CLANG_HAS_WARNING
   2360 #endif
   2361 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
   2362 
   2363 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
   2364 
   2365 
   2366 // This file contains all internal macro definitions (except those affecting ABI)
   2367 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
   2368 
   2369 // #include <nlohmann/detail/abi_macros.hpp>
   2370 
   2371 
   2372 // exclude unsupported compilers
   2373 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
   2374     #if defined(__clang__)
   2375         #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
   2376             #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
   2377         #endif
   2378     #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
   2379         #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
   2380             #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
   2381         #endif
   2382     #endif
   2383 #endif
   2384 
   2385 // C++ language standard detection
   2386 // if the user manually specified the used c++ version this is skipped
   2387 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
   2388     #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
   2389         #define JSON_HAS_CPP_20
   2390         #define JSON_HAS_CPP_17
   2391         #define JSON_HAS_CPP_14
   2392     #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
   2393         #define JSON_HAS_CPP_17
   2394         #define JSON_HAS_CPP_14
   2395     #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
   2396         #define JSON_HAS_CPP_14
   2397     #endif
   2398     // the cpp 11 flag is always specified because it is the minimal required version
   2399     #define JSON_HAS_CPP_11
   2400 #endif
   2401 
   2402 #ifdef __has_include
   2403     #if __has_include(<version>)
   2404         #include <version>
   2405     #endif
   2406 #endif
   2407 
   2408 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
   2409     #ifdef JSON_HAS_CPP_17
   2410         #if defined(__cpp_lib_filesystem)
   2411             #define JSON_HAS_FILESYSTEM 1
   2412         #elif defined(__cpp_lib_experimental_filesystem)
   2413             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
   2414         #elif !defined(__has_include)
   2415             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
   2416         #elif __has_include(<filesystem>)
   2417             #define JSON_HAS_FILESYSTEM 1
   2418         #elif __has_include(<experimental/filesystem>)
   2419             #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
   2420         #endif
   2421 
   2422         // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
   2423         #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
   2424             #undef JSON_HAS_FILESYSTEM
   2425             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2426         #endif
   2427 
   2428         // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
   2429         #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
   2430             #undef JSON_HAS_FILESYSTEM
   2431             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2432         #endif
   2433 
   2434         // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
   2435         #if defined(__clang_major__) && __clang_major__ < 7
   2436             #undef JSON_HAS_FILESYSTEM
   2437             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2438         #endif
   2439 
   2440         // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
   2441         #if defined(_MSC_VER) && _MSC_VER < 1914
   2442             #undef JSON_HAS_FILESYSTEM
   2443             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2444         #endif
   2445 
   2446         // no filesystem support before iOS 13
   2447         #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
   2448             #undef JSON_HAS_FILESYSTEM
   2449             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2450         #endif
   2451 
   2452         // no filesystem support before macOS Catalina
   2453         #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
   2454             #undef JSON_HAS_FILESYSTEM
   2455             #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2456         #endif
   2457     #endif
   2458 #endif
   2459 
   2460 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2461     #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
   2462 #endif
   2463 
   2464 #ifndef JSON_HAS_FILESYSTEM
   2465     #define JSON_HAS_FILESYSTEM 0
   2466 #endif
   2467 
   2468 #ifndef JSON_HAS_THREE_WAY_COMPARISON
   2469     #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
   2470         && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
   2471         #define JSON_HAS_THREE_WAY_COMPARISON 1
   2472     #else
   2473         #define JSON_HAS_THREE_WAY_COMPARISON 0
   2474     #endif
   2475 #endif
   2476 
   2477 #ifndef JSON_HAS_RANGES
   2478     // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
   2479     #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
   2480         #define JSON_HAS_RANGES 0
   2481     #elif defined(__cpp_lib_ranges)
   2482         #define JSON_HAS_RANGES 1
   2483     #else
   2484         #define JSON_HAS_RANGES 0
   2485     #endif
   2486 #endif
   2487 
   2488 #ifdef JSON_HAS_CPP_17
   2489     #define JSON_INLINE_VARIABLE inline
   2490 #else
   2491     #define JSON_INLINE_VARIABLE
   2492 #endif
   2493 
   2494 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
   2495     #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
   2496 #else
   2497     #define JSON_NO_UNIQUE_ADDRESS
   2498 #endif
   2499 
   2500 // disable documentation warnings on clang
   2501 #if defined(__clang__)
   2502     #pragma clang diagnostic push
   2503     #pragma clang diagnostic ignored "-Wdocumentation"
   2504     #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
   2505 #endif
   2506 
   2507 // allow disabling exceptions
   2508 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
   2509     #define JSON_THROW(exception) throw exception
   2510     #define JSON_TRY try
   2511     #define JSON_CATCH(exception) catch(exception)
   2512     #define JSON_INTERNAL_CATCH(exception) catch(exception)
   2513 #else
   2514     #include <cstdlib>
   2515     #define JSON_THROW(exception) std::abort()
   2516     #define JSON_TRY if(true)
   2517     #define JSON_CATCH(exception) if(false)
   2518     #define JSON_INTERNAL_CATCH(exception) if(false)
   2519 #endif
   2520 
   2521 // override exception macros
   2522 #if defined(JSON_THROW_USER)
   2523     #undef JSON_THROW
   2524     #define JSON_THROW JSON_THROW_USER
   2525 #endif
   2526 #if defined(JSON_TRY_USER)
   2527     #undef JSON_TRY
   2528     #define JSON_TRY JSON_TRY_USER
   2529 #endif
   2530 #if defined(JSON_CATCH_USER)
   2531     #undef JSON_CATCH
   2532     #define JSON_CATCH JSON_CATCH_USER
   2533     #undef JSON_INTERNAL_CATCH
   2534     #define JSON_INTERNAL_CATCH JSON_CATCH_USER
   2535 #endif
   2536 #if defined(JSON_INTERNAL_CATCH_USER)
   2537     #undef JSON_INTERNAL_CATCH
   2538     #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
   2539 #endif
   2540 
   2541 // allow overriding assert
   2542 #if !defined(JSON_ASSERT)
   2543     #include <cassert> // assert
   2544     #define JSON_ASSERT(x) assert(x)
   2545 #endif
   2546 
   2547 // allow to access some private functions (needed by the test suite)
   2548 #if defined(JSON_TESTS_PRIVATE)
   2549     #define JSON_PRIVATE_UNLESS_TESTED public
   2550 #else
   2551     #define JSON_PRIVATE_UNLESS_TESTED private
   2552 #endif
   2553 
   2554 /*!
   2555 @brief macro to briefly define a mapping between an enum and JSON
   2556 @def NLOHMANN_JSON_SERIALIZE_ENUM
   2557 @since version 3.4.0
   2558 */
   2559 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
   2560     template<typename BasicJsonType>                                                            \
   2561     inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
   2562     {                                                                                           \
   2563         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
   2564         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
   2565         auto it = std::find_if(std::begin(m), std::end(m),                                      \
   2566                                [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
   2567         {                                                                                       \
   2568             return ej_pair.first == e;                                                          \
   2569         });                                                                                     \
   2570         j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
   2571     }                                                                                           \
   2572     template<typename BasicJsonType>                                                            \
   2573     inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
   2574     {                                                                                           \
   2575         static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
   2576         static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
   2577         auto it = std::find_if(std::begin(m), std::end(m),                                      \
   2578                                [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
   2579         {                                                                                       \
   2580             return ej_pair.second == j;                                                         \
   2581         });                                                                                     \
   2582         e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
   2583     }
   2584 
   2585 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
   2586 // may be removed in the future once the class is split.
   2587 
   2588 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
   2589     template<template<typename, typename, typename...> class ObjectType,   \
   2590              template<typename, typename...> class ArrayType,              \
   2591              class StringType, class BooleanType, class NumberIntegerType, \
   2592              class NumberUnsignedType, class NumberFloatType,              \
   2593              template<typename> class AllocatorType,                       \
   2594              template<typename, typename = void> class JSONSerializer,     \
   2595              class BinaryType,                                             \
   2596              class CustomBaseClass>
   2597 
   2598 #define NLOHMANN_BASIC_JSON_TPL                                            \
   2599     basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
   2600     NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
   2601     AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
   2602 
   2603 // Macros to simplify conversion from/to types
   2604 
   2605 #define NLOHMANN_JSON_EXPAND( x ) x
   2606 #define NLOHMANN_JSON_GET_MACRO(_1, _2, _3, _4, _5, _6, _7, _8, _9, _10, _11, _12, _13, _14, _15, _16, _17, _18, _19, _20, _21, _22, _23, _24, _25, _26, _27, _28, _29, _30, _31, _32, _33, _34, _35, _36, _37, _38, _39, _40, _41, _42, _43, _44, _45, _46, _47, _48, _49, _50, _51, _52, _53, _54, _55, _56, _57, _58, _59, _60, _61, _62, _63, _64, NAME,...) NAME
   2607 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
   2608         NLOHMANN_JSON_PASTE64, \
   2609         NLOHMANN_JSON_PASTE63, \
   2610         NLOHMANN_JSON_PASTE62, \
   2611         NLOHMANN_JSON_PASTE61, \
   2612         NLOHMANN_JSON_PASTE60, \
   2613         NLOHMANN_JSON_PASTE59, \
   2614         NLOHMANN_JSON_PASTE58, \
   2615         NLOHMANN_JSON_PASTE57, \
   2616         NLOHMANN_JSON_PASTE56, \
   2617         NLOHMANN_JSON_PASTE55, \
   2618         NLOHMANN_JSON_PASTE54, \
   2619         NLOHMANN_JSON_PASTE53, \
   2620         NLOHMANN_JSON_PASTE52, \
   2621         NLOHMANN_JSON_PASTE51, \
   2622         NLOHMANN_JSON_PASTE50, \
   2623         NLOHMANN_JSON_PASTE49, \
   2624         NLOHMANN_JSON_PASTE48, \
   2625         NLOHMANN_JSON_PASTE47, \
   2626         NLOHMANN_JSON_PASTE46, \
   2627         NLOHMANN_JSON_PASTE45, \
   2628         NLOHMANN_JSON_PASTE44, \
   2629         NLOHMANN_JSON_PASTE43, \
   2630         NLOHMANN_JSON_PASTE42, \
   2631         NLOHMANN_JSON_PASTE41, \
   2632         NLOHMANN_JSON_PASTE40, \
   2633         NLOHMANN_JSON_PASTE39, \
   2634         NLOHMANN_JSON_PASTE38, \
   2635         NLOHMANN_JSON_PASTE37, \
   2636         NLOHMANN_JSON_PASTE36, \
   2637         NLOHMANN_JSON_PASTE35, \
   2638         NLOHMANN_JSON_PASTE34, \
   2639         NLOHMANN_JSON_PASTE33, \
   2640         NLOHMANN_JSON_PASTE32, \
   2641         NLOHMANN_JSON_PASTE31, \
   2642         NLOHMANN_JSON_PASTE30, \
   2643         NLOHMANN_JSON_PASTE29, \
   2644         NLOHMANN_JSON_PASTE28, \
   2645         NLOHMANN_JSON_PASTE27, \
   2646         NLOHMANN_JSON_PASTE26, \
   2647         NLOHMANN_JSON_PASTE25, \
   2648         NLOHMANN_JSON_PASTE24, \
   2649         NLOHMANN_JSON_PASTE23, \
   2650         NLOHMANN_JSON_PASTE22, \
   2651         NLOHMANN_JSON_PASTE21, \
   2652         NLOHMANN_JSON_PASTE20, \
   2653         NLOHMANN_JSON_PASTE19, \
   2654         NLOHMANN_JSON_PASTE18, \
   2655         NLOHMANN_JSON_PASTE17, \
   2656         NLOHMANN_JSON_PASTE16, \
   2657         NLOHMANN_JSON_PASTE15, \
   2658         NLOHMANN_JSON_PASTE14, \
   2659         NLOHMANN_JSON_PASTE13, \
   2660         NLOHMANN_JSON_PASTE12, \
   2661         NLOHMANN_JSON_PASTE11, \
   2662         NLOHMANN_JSON_PASTE10, \
   2663         NLOHMANN_JSON_PASTE9, \
   2664         NLOHMANN_JSON_PASTE8, \
   2665         NLOHMANN_JSON_PASTE7, \
   2666         NLOHMANN_JSON_PASTE6, \
   2667         NLOHMANN_JSON_PASTE5, \
   2668         NLOHMANN_JSON_PASTE4, \
   2669         NLOHMANN_JSON_PASTE3, \
   2670         NLOHMANN_JSON_PASTE2, \
   2671         NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
   2672 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
   2673 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
   2674 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
   2675 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
   2676 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
   2677 #define NLOHMANN_JSON_PASTE7(func, v1, v2, v3, v4, v5, v6) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE6(func, v2, v3, v4, v5, v6)
   2678 #define NLOHMANN_JSON_PASTE8(func, v1, v2, v3, v4, v5, v6, v7) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE7(func, v2, v3, v4, v5, v6, v7)
   2679 #define NLOHMANN_JSON_PASTE9(func, v1, v2, v3, v4, v5, v6, v7, v8) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE8(func, v2, v3, v4, v5, v6, v7, v8)
   2680 #define NLOHMANN_JSON_PASTE10(func, v1, v2, v3, v4, v5, v6, v7, v8, v9) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE9(func, v2, v3, v4, v5, v6, v7, v8, v9)
   2681 #define NLOHMANN_JSON_PASTE11(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE10(func, v2, v3, v4, v5, v6, v7, v8, v9, v10)
   2682 #define NLOHMANN_JSON_PASTE12(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE11(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11)
   2683 #define NLOHMANN_JSON_PASTE13(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE12(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12)
   2684 #define NLOHMANN_JSON_PASTE14(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE13(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13)
   2685 #define NLOHMANN_JSON_PASTE15(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE14(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14)
   2686 #define NLOHMANN_JSON_PASTE16(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE15(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15)
   2687 #define NLOHMANN_JSON_PASTE17(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE16(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16)
   2688 #define NLOHMANN_JSON_PASTE18(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE17(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17)
   2689 #define NLOHMANN_JSON_PASTE19(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE18(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18)
   2690 #define NLOHMANN_JSON_PASTE20(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE19(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19)
   2691 #define NLOHMANN_JSON_PASTE21(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE20(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20)
   2692 #define NLOHMANN_JSON_PASTE22(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE21(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21)
   2693 #define NLOHMANN_JSON_PASTE23(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE22(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22)
   2694 #define NLOHMANN_JSON_PASTE24(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE23(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23)
   2695 #define NLOHMANN_JSON_PASTE25(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE24(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24)
   2696 #define NLOHMANN_JSON_PASTE26(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE25(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25)
   2697 #define NLOHMANN_JSON_PASTE27(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE26(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26)
   2698 #define NLOHMANN_JSON_PASTE28(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE27(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27)
   2699 #define NLOHMANN_JSON_PASTE29(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE28(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28)
   2700 #define NLOHMANN_JSON_PASTE30(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE29(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29)
   2701 #define NLOHMANN_JSON_PASTE31(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE30(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30)
   2702 #define NLOHMANN_JSON_PASTE32(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE31(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31)
   2703 #define NLOHMANN_JSON_PASTE33(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE32(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32)
   2704 #define NLOHMANN_JSON_PASTE34(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE33(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33)
   2705 #define NLOHMANN_JSON_PASTE35(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE34(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34)
   2706 #define NLOHMANN_JSON_PASTE36(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE35(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35)
   2707 #define NLOHMANN_JSON_PASTE37(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE36(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36)
   2708 #define NLOHMANN_JSON_PASTE38(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE37(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37)
   2709 #define NLOHMANN_JSON_PASTE39(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE38(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38)
   2710 #define NLOHMANN_JSON_PASTE40(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE39(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39)
   2711 #define NLOHMANN_JSON_PASTE41(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE40(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40)
   2712 #define NLOHMANN_JSON_PASTE42(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE41(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41)
   2713 #define NLOHMANN_JSON_PASTE43(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE42(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42)
   2714 #define NLOHMANN_JSON_PASTE44(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE43(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43)
   2715 #define NLOHMANN_JSON_PASTE45(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE44(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44)
   2716 #define NLOHMANN_JSON_PASTE46(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE45(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45)
   2717 #define NLOHMANN_JSON_PASTE47(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE46(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46)
   2718 #define NLOHMANN_JSON_PASTE48(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE47(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47)
   2719 #define NLOHMANN_JSON_PASTE49(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE48(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48)
   2720 #define NLOHMANN_JSON_PASTE50(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE49(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49)
   2721 #define NLOHMANN_JSON_PASTE51(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE50(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50)
   2722 #define NLOHMANN_JSON_PASTE52(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE51(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51)
   2723 #define NLOHMANN_JSON_PASTE53(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE52(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52)
   2724 #define NLOHMANN_JSON_PASTE54(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE53(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53)
   2725 #define NLOHMANN_JSON_PASTE55(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE54(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54)
   2726 #define NLOHMANN_JSON_PASTE56(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE55(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55)
   2727 #define NLOHMANN_JSON_PASTE57(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE56(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56)
   2728 #define NLOHMANN_JSON_PASTE58(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE57(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57)
   2729 #define NLOHMANN_JSON_PASTE59(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE58(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58)
   2730 #define NLOHMANN_JSON_PASTE60(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE59(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59)
   2731 #define NLOHMANN_JSON_PASTE61(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE60(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60)
   2732 #define NLOHMANN_JSON_PASTE62(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE61(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61)
   2733 #define NLOHMANN_JSON_PASTE63(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE62(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62)
   2734 #define NLOHMANN_JSON_PASTE64(func, v1, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE63(func, v2, v3, v4, v5, v6, v7, v8, v9, v10, v11, v12, v13, v14, v15, v16, v17, v18, v19, v20, v21, v22, v23, v24, v25, v26, v27, v28, v29, v30, v31, v32, v33, v34, v35, v36, v37, v38, v39, v40, v41, v42, v43, v44, v45, v46, v47, v48, v49, v50, v51, v52, v53, v54, v55, v56, v57, v58, v59, v60, v61, v62, v63)
   2735 
   2736 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
   2737 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
   2738 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
   2739 
   2740 /*!
   2741 @brief macro
   2742 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
   2743 @since version 3.9.0
   2744 */
   2745 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
   2746     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
   2747     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
   2748 
   2749 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
   2750     friend void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
   2751     friend void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
   2752 
   2753 /*!
   2754 @brief macro
   2755 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
   2756 @since version 3.9.0
   2757 */
   2758 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
   2759     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
   2760     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
   2761 
   2762 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
   2763     inline void to_json(nlohmann::json& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
   2764     inline void from_json(const nlohmann::json& nlohmann_json_j, Type& nlohmann_json_t) { const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
   2765 
   2766 
   2767 // inspired from https://stackoverflow.com/a/26745591
   2768 // allows to call any std function as if (e.g. with begin):
   2769 // using std::begin; begin(x);
   2770 //
   2771 // it allows using the detected idiom to retrieve the return type
   2772 // of such an expression
   2773 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \
   2774     namespace detail {                                                            \
   2775     using std::std_name;                                                          \
   2776     \
   2777     template<typename... T>                                                       \
   2778     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
   2779     }                                                                             \
   2780     \
   2781     namespace detail2 {                                                           \
   2782     struct std_name##_tag                                                         \
   2783     {                                                                             \
   2784     };                                                                            \
   2785     \
   2786     template<typename... T>                                                       \
   2787     std_name##_tag std_name(T&&...);                                              \
   2788     \
   2789     template<typename... T>                                                       \
   2790     using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
   2791     \
   2792     template<typename... T>                                                       \
   2793     struct would_call_std_##std_name                                              \
   2794     {                                                                             \
   2795         static constexpr auto const value = ::nlohmann::detail::                  \
   2796                                             is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
   2797     };                                                                            \
   2798     } /* namespace detail2 */ \
   2799     \
   2800     template<typename... T>                                                       \
   2801     struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \
   2802     {                                                                             \
   2803     }
   2804 
   2805 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
   2806     #define JSON_USE_IMPLICIT_CONVERSIONS 1
   2807 #endif
   2808 
   2809 #if JSON_USE_IMPLICIT_CONVERSIONS
   2810     #define JSON_EXPLICIT
   2811 #else
   2812     #define JSON_EXPLICIT explicit
   2813 #endif
   2814 
   2815 #ifndef JSON_DISABLE_ENUM_SERIALIZATION
   2816     #define JSON_DISABLE_ENUM_SERIALIZATION 0
   2817 #endif
   2818 
   2819 #ifndef JSON_USE_GLOBAL_UDLS
   2820     #define JSON_USE_GLOBAL_UDLS 1
   2821 #endif
   2822 
   2823 #if JSON_HAS_THREE_WAY_COMPARISON
   2824     #include <compare> // partial_ordering
   2825 #endif
   2826 
   2827 NLOHMANN_JSON_NAMESPACE_BEGIN
   2828 namespace detail
   2829 {
   2830 
   2831 ///////////////////////////
   2832 // JSON type enumeration //
   2833 ///////////////////////////
   2834 
   2835 /*!
   2836 @brief the JSON type enumeration
   2837 
   2838 This enumeration collects the different JSON types. It is internally used to
   2839 distinguish the stored values, and the functions @ref basic_json::is_null(),
   2840 @ref basic_json::is_object(), @ref basic_json::is_array(),
   2841 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
   2842 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
   2843 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
   2844 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
   2845 @ref basic_json::is_structured() rely on it.
   2846 
   2847 @note There are three enumeration entries (number_integer, number_unsigned, and
   2848 number_float), because the library distinguishes these three types for numbers:
   2849 @ref basic_json::number_unsigned_t is used for unsigned integers,
   2850 @ref basic_json::number_integer_t is used for signed integers, and
   2851 @ref basic_json::number_float_t is used for floating-point numbers or to
   2852 approximate integers which do not fit in the limits of their respective type.
   2853 
   2854 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
   2855 value with the default value for a given type
   2856 
   2857 @since version 1.0.0
   2858 */
   2859 enum class value_t : std::uint8_t
   2860 {
   2861     null,             ///< null value
   2862     object,           ///< object (unordered set of name/value pairs)
   2863     array,            ///< array (ordered collection of values)
   2864     string,           ///< string value
   2865     boolean,          ///< boolean value
   2866     number_integer,   ///< number value (signed integer)
   2867     number_unsigned,  ///< number value (unsigned integer)
   2868     number_float,     ///< number value (floating-point)
   2869     binary,           ///< binary array (ordered collection of bytes)
   2870     discarded         ///< discarded by the parser callback function
   2871 };
   2872 
   2873 /*!
   2874 @brief comparison operator for JSON types
   2875 
   2876 Returns an ordering that is similar to Python:
   2877 - order: null < boolean < number < object < array < string < binary
   2878 - furthermore, each type is not smaller than itself
   2879 - discarded values are not comparable
   2880 - binary is represented as a b"" string in python and directly comparable to a
   2881   string; however, making a binary array directly comparable with a string would
   2882   be surprising behavior in a JSON file.
   2883 
   2884 @since version 1.0.0
   2885 */
   2886 #if JSON_HAS_THREE_WAY_COMPARISON
   2887     inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
   2888 #else
   2889     inline bool operator<(const value_t lhs, const value_t rhs) noexcept
   2890 #endif
   2891 {
   2892     static constexpr std::array<std::uint8_t, 9> order = {{
   2893             0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
   2894             1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
   2895             6 /* binary */
   2896         }
   2897     };
   2898 
   2899     const auto l_index = static_cast<std::size_t>(lhs);
   2900     const auto r_index = static_cast<std::size_t>(rhs);
   2901 #if JSON_HAS_THREE_WAY_COMPARISON
   2902     if (l_index < order.size() && r_index < order.size())
   2903     {
   2904         return order[l_index] <=> order[r_index]; // *NOPAD*
   2905     }
   2906     return std::partial_ordering::unordered;
   2907 #else
   2908     return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
   2909 #endif
   2910 }
   2911 
   2912 // GCC selects the built-in operator< over an operator rewritten from
   2913 // a user-defined spaceship operator
   2914 // Clang, MSVC, and ICC select the rewritten candidate
   2915 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
   2916 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
   2917 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
   2918 {
   2919     return std::is_lt(lhs <=> rhs); // *NOPAD*
   2920 }
   2921 #endif
   2922 
   2923 }  // namespace detail
   2924 NLOHMANN_JSON_NAMESPACE_END
   2925 
   2926 // #include <nlohmann/detail/string_escape.hpp>
   2927 //     __ _____ _____ _____
   2928 //  __|  |   __|     |   | |  JSON for Modern C++
   2929 // |  |  |__   |  |  | | | |  version 3.11.2
   2930 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   2931 //
   2932 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   2933 // SPDX-License-Identifier: MIT
   2934 
   2935 
   2936 
   2937 // #include <nlohmann/detail/abi_macros.hpp>
   2938 
   2939 
   2940 NLOHMANN_JSON_NAMESPACE_BEGIN
   2941 namespace detail
   2942 {
   2943 
   2944 /*!
   2945 @brief replace all occurrences of a substring by another string
   2946 
   2947 @param[in,out] s  the string to manipulate; changed so that all
   2948                occurrences of @a f are replaced with @a t
   2949 @param[in]     f  the substring to replace with @a t
   2950 @param[in]     t  the string to replace @a f
   2951 
   2952 @pre The search string @a f must not be empty. **This precondition is
   2953 enforced with an assertion.**
   2954 
   2955 @since version 2.0.0
   2956 */
   2957 template<typename StringType>
   2958 inline void replace_substring(StringType& s, const StringType& f,
   2959                               const StringType& t)
   2960 {
   2961     JSON_ASSERT(!f.empty());
   2962     for (auto pos = s.find(f);                // find first occurrence of f
   2963             pos != StringType::npos;          // make sure f was found
   2964             s.replace(pos, f.size(), t),      // replace with t, and
   2965             pos = s.find(f, pos + t.size()))  // find next occurrence of f
   2966     {}
   2967 }
   2968 
   2969 /*!
   2970  * @brief string escaping as described in RFC 6901 (Sect. 4)
   2971  * @param[in] s string to escape
   2972  * @return    escaped string
   2973  *
   2974  * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
   2975  */
   2976 template<typename StringType>
   2977 inline StringType escape(StringType s)
   2978 {
   2979     replace_substring(s, StringType{"~"}, StringType{"~0"});
   2980     replace_substring(s, StringType{"/"}, StringType{"~1"});
   2981     return s;
   2982 }
   2983 
   2984 /*!
   2985  * @brief string unescaping as described in RFC 6901 (Sect. 4)
   2986  * @param[in] s string to unescape
   2987  * @return    unescaped string
   2988  *
   2989  * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
   2990  */
   2991 template<typename StringType>
   2992 static void unescape(StringType& s)
   2993 {
   2994     replace_substring(s, StringType{"~1"}, StringType{"/"});
   2995     replace_substring(s, StringType{"~0"}, StringType{"~"});
   2996 }
   2997 
   2998 }  // namespace detail
   2999 NLOHMANN_JSON_NAMESPACE_END
   3000 
   3001 // #include <nlohmann/detail/input/position_t.hpp>
   3002 //     __ _____ _____ _____
   3003 //  __|  |   __|     |   | |  JSON for Modern C++
   3004 // |  |  |__   |  |  | | | |  version 3.11.2
   3005 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3006 //
   3007 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3008 // SPDX-License-Identifier: MIT
   3009 
   3010 
   3011 
   3012 #include <cstddef> // size_t
   3013 
   3014 // #include <nlohmann/detail/abi_macros.hpp>
   3015 
   3016 
   3017 NLOHMANN_JSON_NAMESPACE_BEGIN
   3018 namespace detail
   3019 {
   3020 
   3021 /// struct to capture the start position of the current token
   3022 struct position_t
   3023 {
   3024     /// the total number of characters read
   3025     std::size_t chars_read_total = 0;
   3026     /// the number of characters read in the current line
   3027     std::size_t chars_read_current_line = 0;
   3028     /// the number of lines read
   3029     std::size_t lines_read = 0;
   3030 
   3031     /// conversion to size_t to preserve SAX interface
   3032     constexpr operator size_t() const
   3033     {
   3034         return chars_read_total;
   3035     }
   3036 };
   3037 
   3038 }  // namespace detail
   3039 NLOHMANN_JSON_NAMESPACE_END
   3040 
   3041 // #include <nlohmann/detail/macro_scope.hpp>
   3042 
   3043 // #include <nlohmann/detail/meta/cpp_future.hpp>
   3044 //     __ _____ _____ _____
   3045 //  __|  |   __|     |   | |  JSON for Modern C++
   3046 // |  |  |__   |  |  | | | |  version 3.11.2
   3047 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3048 //
   3049 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3050 // SPDX-FileCopyrightText: 2018 The Abseil Authors
   3051 // SPDX-License-Identifier: MIT
   3052 
   3053 
   3054 
   3055 #include <array> // array
   3056 #include <cstddef> // size_t
   3057 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
   3058 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
   3059 
   3060 // #include <nlohmann/detail/macro_scope.hpp>
   3061 
   3062 
   3063 NLOHMANN_JSON_NAMESPACE_BEGIN
   3064 namespace detail
   3065 {
   3066 
   3067 template<typename T>
   3068 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
   3069 
   3070 #ifdef JSON_HAS_CPP_14
   3071 
   3072 // the following utilities are natively available in C++14
   3073 using std::enable_if_t;
   3074 using std::index_sequence;
   3075 using std::make_index_sequence;
   3076 using std::index_sequence_for;
   3077 
   3078 #else
   3079 
   3080 // alias templates to reduce boilerplate
   3081 template<bool B, typename T = void>
   3082 using enable_if_t = typename std::enable_if<B, T>::type;
   3083 
   3084 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
   3085 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
   3086 
   3087 //// START OF CODE FROM GOOGLE ABSEIL
   3088 
   3089 // integer_sequence
   3090 //
   3091 // Class template representing a compile-time integer sequence. An instantiation
   3092 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
   3093 // type through its template arguments (which is a common need when
   3094 // working with C++11 variadic templates). `absl::integer_sequence` is designed
   3095 // to be a drop-in replacement for C++14's `std::integer_sequence`.
   3096 //
   3097 // Example:
   3098 //
   3099 //   template< class T, T... Ints >
   3100 //   void user_function(integer_sequence<T, Ints...>);
   3101 //
   3102 //   int main()
   3103 //   {
   3104 //     // user_function's `T` will be deduced to `int` and `Ints...`
   3105 //     // will be deduced to `0, 1, 2, 3, 4`.
   3106 //     user_function(make_integer_sequence<int, 5>());
   3107 //   }
   3108 template <typename T, T... Ints>
   3109 struct integer_sequence
   3110 {
   3111     using value_type = T;
   3112     static constexpr std::size_t size() noexcept
   3113     {
   3114         return sizeof...(Ints);
   3115     }
   3116 };
   3117 
   3118 // index_sequence
   3119 //
   3120 // A helper template for an `integer_sequence` of `size_t`,
   3121 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
   3122 // `std::index_sequence`.
   3123 template <size_t... Ints>
   3124 using index_sequence = integer_sequence<size_t, Ints...>;
   3125 
   3126 namespace utility_internal
   3127 {
   3128 
   3129 template <typename Seq, size_t SeqSize, size_t Rem>
   3130 struct Extend;
   3131 
   3132 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
   3133 template <typename T, T... Ints, size_t SeqSize>
   3134 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
   3135 {
   3136     using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
   3137 };
   3138 
   3139 template <typename T, T... Ints, size_t SeqSize>
   3140 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
   3141 {
   3142     using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
   3143 };
   3144 
   3145 // Recursion helper for 'make_integer_sequence<T, N>'.
   3146 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
   3147 template <typename T, size_t N>
   3148 struct Gen
   3149 {
   3150     using type =
   3151         typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
   3152 };
   3153 
   3154 template <typename T>
   3155 struct Gen<T, 0>
   3156 {
   3157     using type = integer_sequence<T>;
   3158 };
   3159 
   3160 }  // namespace utility_internal
   3161 
   3162 // Compile-time sequences of integers
   3163 
   3164 // make_integer_sequence
   3165 //
   3166 // This template alias is equivalent to
   3167 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
   3168 // replacement for C++14's `std::make_integer_sequence`.
   3169 template <typename T, T N>
   3170 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
   3171 
   3172 // make_index_sequence
   3173 //
   3174 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
   3175 // and is designed to be a drop-in replacement for C++14's
   3176 // `std::make_index_sequence`.
   3177 template <size_t N>
   3178 using make_index_sequence = make_integer_sequence<size_t, N>;
   3179 
   3180 // index_sequence_for
   3181 //
   3182 // Converts a typename pack into an index sequence of the same length, and
   3183 // is designed to be a drop-in replacement for C++14's
   3184 // `std::index_sequence_for()`
   3185 template <typename... Ts>
   3186 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
   3187 
   3188 //// END OF CODE FROM GOOGLE ABSEIL
   3189 
   3190 #endif
   3191 
   3192 // dispatch utility (taken from ranges-v3)
   3193 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
   3194 template<> struct priority_tag<0> {};
   3195 
   3196 // taken from ranges-v3
   3197 template<typename T>
   3198 struct static_const
   3199 {
   3200     static JSON_INLINE_VARIABLE constexpr T value{};
   3201 };
   3202 
   3203 #ifndef JSON_HAS_CPP_17
   3204     template<typename T>
   3205     constexpr T static_const<T>::value;
   3206 #endif
   3207 
   3208 template<typename T, typename... Args>
   3209 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
   3210 {
   3211     return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
   3212 }
   3213 
   3214 }  // namespace detail
   3215 NLOHMANN_JSON_NAMESPACE_END
   3216 
   3217 // #include <nlohmann/detail/meta/type_traits.hpp>
   3218 //     __ _____ _____ _____
   3219 //  __|  |   __|     |   | |  JSON for Modern C++
   3220 // |  |  |__   |  |  | | | |  version 3.11.2
   3221 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3222 //
   3223 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3224 // SPDX-License-Identifier: MIT
   3225 
   3226 
   3227 
   3228 #include <limits> // numeric_limits
   3229 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
   3230 #include <utility> // declval
   3231 #include <tuple> // tuple
   3232 
   3233 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
   3234 //     __ _____ _____ _____
   3235 //  __|  |   __|     |   | |  JSON for Modern C++
   3236 // |  |  |__   |  |  | | | |  version 3.11.2
   3237 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3238 //
   3239 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3240 // SPDX-License-Identifier: MIT
   3241 
   3242 
   3243 
   3244 #include <iterator> // random_access_iterator_tag
   3245 
   3246 // #include <nlohmann/detail/abi_macros.hpp>
   3247 
   3248 // #include <nlohmann/detail/meta/void_t.hpp>
   3249 
   3250 // #include <nlohmann/detail/meta/cpp_future.hpp>
   3251 
   3252 
   3253 NLOHMANN_JSON_NAMESPACE_BEGIN
   3254 namespace detail
   3255 {
   3256 
   3257 template<typename It, typename = void>
   3258 struct iterator_types {};
   3259 
   3260 template<typename It>
   3261 struct iterator_types <
   3262     It,
   3263     void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
   3264     typename It::reference, typename It::iterator_category >>
   3265 {
   3266     using difference_type = typename It::difference_type;
   3267     using value_type = typename It::value_type;
   3268     using pointer = typename It::pointer;
   3269     using reference = typename It::reference;
   3270     using iterator_category = typename It::iterator_category;
   3271 };
   3272 
   3273 // This is required as some compilers implement std::iterator_traits in a way that
   3274 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
   3275 template<typename T, typename = void>
   3276 struct iterator_traits
   3277 {
   3278 };
   3279 
   3280 template<typename T>
   3281 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
   3282             : iterator_types<T>
   3283 {
   3284 };
   3285 
   3286 template<typename T>
   3287 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
   3288 {
   3289     using iterator_category = std::random_access_iterator_tag;
   3290     using value_type = T;
   3291     using difference_type = ptrdiff_t;
   3292     using pointer = T*;
   3293     using reference = T&;
   3294 };
   3295 
   3296 }  // namespace detail
   3297 NLOHMANN_JSON_NAMESPACE_END
   3298 
   3299 // #include <nlohmann/detail/macro_scope.hpp>
   3300 
   3301 // #include <nlohmann/detail/meta/call_std/begin.hpp>
   3302 //     __ _____ _____ _____
   3303 //  __|  |   __|     |   | |  JSON for Modern C++
   3304 // |  |  |__   |  |  | | | |  version 3.11.2
   3305 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3306 //
   3307 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3308 // SPDX-License-Identifier: MIT
   3309 
   3310 
   3311 
   3312 // #include <nlohmann/detail/macro_scope.hpp>
   3313 
   3314 
   3315 NLOHMANN_JSON_NAMESPACE_BEGIN
   3316 
   3317 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
   3318 
   3319 NLOHMANN_JSON_NAMESPACE_END
   3320 
   3321 // #include <nlohmann/detail/meta/call_std/end.hpp>
   3322 //     __ _____ _____ _____
   3323 //  __|  |   __|     |   | |  JSON for Modern C++
   3324 // |  |  |__   |  |  | | | |  version 3.11.2
   3325 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3326 //
   3327 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3328 // SPDX-License-Identifier: MIT
   3329 
   3330 
   3331 
   3332 // #include <nlohmann/detail/macro_scope.hpp>
   3333 
   3334 
   3335 NLOHMANN_JSON_NAMESPACE_BEGIN
   3336 
   3337 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
   3338 
   3339 NLOHMANN_JSON_NAMESPACE_END
   3340 
   3341 // #include <nlohmann/detail/meta/cpp_future.hpp>
   3342 
   3343 // #include <nlohmann/detail/meta/detected.hpp>
   3344 
   3345 // #include <nlohmann/json_fwd.hpp>
   3346 //     __ _____ _____ _____
   3347 //  __|  |   __|     |   | |  JSON for Modern C++
   3348 // |  |  |__   |  |  | | | |  version 3.11.2
   3349 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3350 //
   3351 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   3352 // SPDX-License-Identifier: MIT
   3353 
   3354 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
   3355     #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
   3356 
   3357     #include <cstdint> // int64_t, uint64_t
   3358     #include <map> // map
   3359     #include <memory> // allocator
   3360     #include <string> // string
   3361     #include <vector> // vector
   3362 
   3363     // #include <nlohmann/detail/abi_macros.hpp>
   3364 
   3365 
   3366     /*!
   3367     @brief namespace for Niels Lohmann
   3368     @see https://github.com/nlohmann
   3369     @since version 1.0.0
   3370     */
   3371     NLOHMANN_JSON_NAMESPACE_BEGIN
   3372 
   3373     /*!
   3374     @brief default JSONSerializer template argument
   3375 
   3376     This serializer ignores the template arguments and uses ADL
   3377     ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
   3378     for serialization.
   3379     */
   3380     template<typename T = void, typename SFINAE = void>
   3381     struct adl_serializer;
   3382 
   3383     /// a class to store JSON values
   3384     /// @sa https://json.nlohmann.me/api/basic_json/
   3385     template<template<typename U, typename V, typename... Args> class ObjectType =
   3386     std::map,
   3387     template<typename U, typename... Args> class ArrayType = std::vector,
   3388     class StringType = std::string, class BooleanType = bool,
   3389     class NumberIntegerType = std::int64_t,
   3390     class NumberUnsignedType = std::uint64_t,
   3391     class NumberFloatType = double,
   3392     template<typename U> class AllocatorType = std::allocator,
   3393     template<typename T, typename SFINAE = void> class JSONSerializer =
   3394     adl_serializer,
   3395     class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
   3396     class CustomBaseClass = void>
   3397     class basic_json;
   3398 
   3399     /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
   3400     /// @sa https://json.nlohmann.me/api/json_pointer/
   3401     template<typename RefStringType>
   3402     class json_pointer;
   3403 
   3404     /*!
   3405     @brief default specialization
   3406     @sa https://json.nlohmann.me/api/json/
   3407     */
   3408     using json = basic_json<>;
   3409 
   3410     /// @brief a minimal map-like container that preserves insertion order
   3411     /// @sa https://json.nlohmann.me/api/ordered_map/
   3412     template<class Key, class T, class IgnoredLess, class Allocator>
   3413     struct ordered_map;
   3414 
   3415     /// @brief specialization that maintains the insertion order of object keys
   3416     /// @sa https://json.nlohmann.me/api/ordered_json/
   3417     using ordered_json = basic_json<nlohmann::ordered_map>;
   3418 
   3419     NLOHMANN_JSON_NAMESPACE_END
   3420 
   3421 #endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
   3422 
   3423 
   3424 NLOHMANN_JSON_NAMESPACE_BEGIN
   3425 /*!
   3426 @brief detail namespace with internal helper functions
   3427 
   3428 This namespace collects functions that should not be exposed,
   3429 implementations of some @ref basic_json methods, and meta-programming helpers.
   3430 
   3431 @since version 2.1.0
   3432 */
   3433 namespace detail
   3434 {
   3435 
   3436 /////////////
   3437 // helpers //
   3438 /////////////
   3439 
   3440 // Note to maintainers:
   3441 //
   3442 // Every trait in this file expects a non CV-qualified type.
   3443 // The only exceptions are in the 'aliases for detected' section
   3444 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
   3445 //
   3446 // In this case, T has to be properly CV-qualified to constraint the function arguments
   3447 // (e.g. to_json(BasicJsonType&, const T&))
   3448 
   3449 template<typename> struct is_basic_json : std::false_type {};
   3450 
   3451 NLOHMANN_BASIC_JSON_TPL_DECLARATION
   3452 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
   3453 
   3454 // used by exceptions create() member functions
   3455 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
   3456 // false_type otherwise
   3457 template<typename BasicJsonContext>
   3458 struct is_basic_json_context :
   3459     std::integral_constant < bool,
   3460     is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
   3461     || std::is_same<BasicJsonContext, std::nullptr_t>::value >
   3462 {};
   3463 
   3464 //////////////////////
   3465 // json_ref helpers //
   3466 //////////////////////
   3467 
   3468 template<typename>
   3469 class json_ref;
   3470 
   3471 template<typename>
   3472 struct is_json_ref : std::false_type {};
   3473 
   3474 template<typename T>
   3475 struct is_json_ref<json_ref<T>> : std::true_type {};
   3476 
   3477 //////////////////////////
   3478 // aliases for detected //
   3479 //////////////////////////
   3480 
   3481 template<typename T>
   3482 using mapped_type_t = typename T::mapped_type;
   3483 
   3484 template<typename T>
   3485 using key_type_t = typename T::key_type;
   3486 
   3487 template<typename T>
   3488 using value_type_t = typename T::value_type;
   3489 
   3490 template<typename T>
   3491 using difference_type_t = typename T::difference_type;
   3492 
   3493 template<typename T>
   3494 using pointer_t = typename T::pointer;
   3495 
   3496 template<typename T>
   3497 using reference_t = typename T::reference;
   3498 
   3499 template<typename T>
   3500 using iterator_category_t = typename T::iterator_category;
   3501 
   3502 template<typename T, typename... Args>
   3503 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
   3504 
   3505 template<typename T, typename... Args>
   3506 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
   3507 
   3508 template<typename T, typename U>
   3509 using get_template_function = decltype(std::declval<T>().template get<U>());
   3510 
   3511 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
   3512 template<typename BasicJsonType, typename T, typename = void>
   3513 struct has_from_json : std::false_type {};
   3514 
   3515 // trait checking if j.get<T> is valid
   3516 // use this trait instead of std::is_constructible or std::is_convertible,
   3517 // both rely on, or make use of implicit conversions, and thus fail when T
   3518 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
   3519 template <typename BasicJsonType, typename T>
   3520 struct is_getable
   3521 {
   3522     static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
   3523 };
   3524 
   3525 template<typename BasicJsonType, typename T>
   3526 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
   3527 {
   3528     using serializer = typename BasicJsonType::template json_serializer<T, void>;
   3529 
   3530     static constexpr bool value =
   3531         is_detected_exact<void, from_json_function, serializer,
   3532         const BasicJsonType&, T&>::value;
   3533 };
   3534 
   3535 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
   3536 // this overload is used for non-default-constructible user-defined-types
   3537 template<typename BasicJsonType, typename T, typename = void>
   3538 struct has_non_default_from_json : std::false_type {};
   3539 
   3540 template<typename BasicJsonType, typename T>
   3541 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
   3542 {
   3543     using serializer = typename BasicJsonType::template json_serializer<T, void>;
   3544 
   3545     static constexpr bool value =
   3546         is_detected_exact<T, from_json_function, serializer,
   3547         const BasicJsonType&>::value;
   3548 };
   3549 
   3550 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
   3551 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
   3552 template<typename BasicJsonType, typename T, typename = void>
   3553 struct has_to_json : std::false_type {};
   3554 
   3555 template<typename BasicJsonType, typename T>
   3556 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
   3557 {
   3558     using serializer = typename BasicJsonType::template json_serializer<T, void>;
   3559 
   3560     static constexpr bool value =
   3561         is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
   3562         T>::value;
   3563 };
   3564 
   3565 template<typename T>
   3566 using detect_key_compare = typename T::key_compare;
   3567 
   3568 template<typename T>
   3569 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
   3570 
   3571 // obtains the actual object key comparator
   3572 template<typename BasicJsonType>
   3573 struct actual_object_comparator
   3574 {
   3575     using object_t = typename BasicJsonType::object_t;
   3576     using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
   3577     using type = typename std::conditional < has_key_compare<object_t>::value,
   3578           typename object_t::key_compare, object_comparator_t>::type;
   3579 };
   3580 
   3581 template<typename BasicJsonType>
   3582 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
   3583 
   3584 ///////////////////
   3585 // is_ functions //
   3586 ///////////////////
   3587 
   3588 // https://en.cppreference.com/w/cpp/types/conjunction
   3589 template<class...> struct conjunction : std::true_type { };
   3590 template<class B> struct conjunction<B> : B { };
   3591 template<class B, class... Bn>
   3592 struct conjunction<B, Bn...>
   3593 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
   3594 
   3595 // https://en.cppreference.com/w/cpp/types/negation
   3596 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
   3597 
   3598 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
   3599 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
   3600 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
   3601 template <typename T>
   3602 struct is_default_constructible : std::is_default_constructible<T> {};
   3603 
   3604 template <typename T1, typename T2>
   3605 struct is_default_constructible<std::pair<T1, T2>>
   3606             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
   3607 
   3608 template <typename T1, typename T2>
   3609 struct is_default_constructible<const std::pair<T1, T2>>
   3610             : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
   3611 
   3612 template <typename... Ts>
   3613 struct is_default_constructible<std::tuple<Ts...>>
   3614             : conjunction<is_default_constructible<Ts>...> {};
   3615 
   3616 template <typename... Ts>
   3617 struct is_default_constructible<const std::tuple<Ts...>>
   3618             : conjunction<is_default_constructible<Ts>...> {};
   3619 
   3620 
   3621 template <typename T, typename... Args>
   3622 struct is_constructible : std::is_constructible<T, Args...> {};
   3623 
   3624 template <typename T1, typename T2>
   3625 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
   3626 
   3627 template <typename T1, typename T2>
   3628 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
   3629 
   3630 template <typename... Ts>
   3631 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
   3632 
   3633 template <typename... Ts>
   3634 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
   3635 
   3636 
   3637 template<typename T, typename = void>
   3638 struct is_iterator_traits : std::false_type {};
   3639 
   3640 template<typename T>
   3641 struct is_iterator_traits<iterator_traits<T>>
   3642 {
   3643   private:
   3644     using traits = iterator_traits<T>;
   3645 
   3646   public:
   3647     static constexpr auto value =
   3648         is_detected<value_type_t, traits>::value &&
   3649         is_detected<difference_type_t, traits>::value &&
   3650         is_detected<pointer_t, traits>::value &&
   3651         is_detected<iterator_category_t, traits>::value &&
   3652         is_detected<reference_t, traits>::value;
   3653 };
   3654 
   3655 template<typename T>
   3656 struct is_range
   3657 {
   3658   private:
   3659     using t_ref = typename std::add_lvalue_reference<T>::type;
   3660 
   3661     using iterator = detected_t<result_of_begin, t_ref>;
   3662     using sentinel = detected_t<result_of_end, t_ref>;
   3663 
   3664     // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
   3665     // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
   3666     // but reimplementing these would be too much work, as a lot of other concepts are used underneath
   3667     static constexpr auto is_iterator_begin =
   3668         is_iterator_traits<iterator_traits<iterator>>::value;
   3669 
   3670   public:
   3671     static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
   3672 };
   3673 
   3674 template<typename R>
   3675 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
   3676 
   3677 template<typename T>
   3678 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
   3679 
   3680 // The following implementation of is_complete_type is taken from
   3681 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
   3682 // and is written by Xiang Fan who agreed to using it in this library.
   3683 
   3684 template<typename T, typename = void>
   3685 struct is_complete_type : std::false_type {};
   3686 
   3687 template<typename T>
   3688 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
   3689 
   3690 template<typename BasicJsonType, typename CompatibleObjectType,
   3691          typename = void>
   3692 struct is_compatible_object_type_impl : std::false_type {};
   3693 
   3694 template<typename BasicJsonType, typename CompatibleObjectType>
   3695 struct is_compatible_object_type_impl <
   3696     BasicJsonType, CompatibleObjectType,
   3697     enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
   3698     is_detected<key_type_t, CompatibleObjectType>::value >>
   3699 {
   3700     using object_t = typename BasicJsonType::object_t;
   3701 
   3702     // macOS's is_constructible does not play well with nonesuch...
   3703     static constexpr bool value =
   3704         is_constructible<typename object_t::key_type,
   3705         typename CompatibleObjectType::key_type>::value &&
   3706         is_constructible<typename object_t::mapped_type,
   3707         typename CompatibleObjectType::mapped_type>::value;
   3708 };
   3709 
   3710 template<typename BasicJsonType, typename CompatibleObjectType>
   3711 struct is_compatible_object_type
   3712     : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
   3713 
   3714 template<typename BasicJsonType, typename ConstructibleObjectType,
   3715          typename = void>
   3716 struct is_constructible_object_type_impl : std::false_type {};
   3717 
   3718 template<typename BasicJsonType, typename ConstructibleObjectType>
   3719 struct is_constructible_object_type_impl <
   3720     BasicJsonType, ConstructibleObjectType,
   3721     enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
   3722     is_detected<key_type_t, ConstructibleObjectType>::value >>
   3723 {
   3724     using object_t = typename BasicJsonType::object_t;
   3725 
   3726     static constexpr bool value =
   3727         (is_default_constructible<ConstructibleObjectType>::value &&
   3728          (std::is_move_assignable<ConstructibleObjectType>::value ||
   3729           std::is_copy_assignable<ConstructibleObjectType>::value) &&
   3730          (is_constructible<typename ConstructibleObjectType::key_type,
   3731           typename object_t::key_type>::value &&
   3732           std::is_same <
   3733           typename object_t::mapped_type,
   3734           typename ConstructibleObjectType::mapped_type >::value)) ||
   3735         (has_from_json<BasicJsonType,
   3736          typename ConstructibleObjectType::mapped_type>::value ||
   3737          has_non_default_from_json <
   3738          BasicJsonType,
   3739          typename ConstructibleObjectType::mapped_type >::value);
   3740 };
   3741 
   3742 template<typename BasicJsonType, typename ConstructibleObjectType>
   3743 struct is_constructible_object_type
   3744     : is_constructible_object_type_impl<BasicJsonType,
   3745       ConstructibleObjectType> {};
   3746 
   3747 template<typename BasicJsonType, typename CompatibleStringType>
   3748 struct is_compatible_string_type
   3749 {
   3750     static constexpr auto value =
   3751         is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
   3752 };
   3753 
   3754 template<typename BasicJsonType, typename ConstructibleStringType>
   3755 struct is_constructible_string_type
   3756 {
   3757     // launder type through decltype() to fix compilation failure on ICPC
   3758 #ifdef __INTEL_COMPILER
   3759     using laundered_type = decltype(std::declval<ConstructibleStringType>());
   3760 #else
   3761     using laundered_type = ConstructibleStringType;
   3762 #endif
   3763 
   3764     static constexpr auto value =
   3765         conjunction <
   3766         is_constructible<laundered_type, typename BasicJsonType::string_t>,
   3767         is_detected_exact<typename BasicJsonType::string_t::value_type,
   3768         value_type_t, laundered_type >>::value;
   3769 };
   3770 
   3771 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
   3772 struct is_compatible_array_type_impl : std::false_type {};
   3773 
   3774 template<typename BasicJsonType, typename CompatibleArrayType>
   3775 struct is_compatible_array_type_impl <
   3776     BasicJsonType, CompatibleArrayType,
   3777     enable_if_t <
   3778     is_detected<iterator_t, CompatibleArrayType>::value&&
   3779     is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
   3780 // special case for types like std::filesystem::path whose iterator's value_type are themselves
   3781 // c.f. https://github.com/nlohmann/json/pull/3073
   3782     !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
   3783 {
   3784     static constexpr bool value =
   3785         is_constructible<BasicJsonType,
   3786         range_value_t<CompatibleArrayType>>::value;
   3787 };
   3788 
   3789 template<typename BasicJsonType, typename CompatibleArrayType>
   3790 struct is_compatible_array_type
   3791     : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
   3792 
   3793 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
   3794 struct is_constructible_array_type_impl : std::false_type {};
   3795 
   3796 template<typename BasicJsonType, typename ConstructibleArrayType>
   3797 struct is_constructible_array_type_impl <
   3798     BasicJsonType, ConstructibleArrayType,
   3799     enable_if_t<std::is_same<ConstructibleArrayType,
   3800     typename BasicJsonType::value_type>::value >>
   3801             : std::true_type {};
   3802 
   3803 template<typename BasicJsonType, typename ConstructibleArrayType>
   3804 struct is_constructible_array_type_impl <
   3805     BasicJsonType, ConstructibleArrayType,
   3806     enable_if_t < !std::is_same<ConstructibleArrayType,
   3807     typename BasicJsonType::value_type>::value&&
   3808     !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
   3809     is_default_constructible<ConstructibleArrayType>::value&&
   3810 (std::is_move_assignable<ConstructibleArrayType>::value ||
   3811  std::is_copy_assignable<ConstructibleArrayType>::value)&&
   3812 is_detected<iterator_t, ConstructibleArrayType>::value&&
   3813 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
   3814 is_detected<range_value_t, ConstructibleArrayType>::value&&
   3815 // special case for types like std::filesystem::path whose iterator's value_type are themselves
   3816 // c.f. https://github.com/nlohmann/json/pull/3073
   3817 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
   3818         is_complete_type <
   3819         detected_t<range_value_t, ConstructibleArrayType >>::value >>
   3820 {
   3821     using value_type = range_value_t<ConstructibleArrayType>;
   3822 
   3823     static constexpr bool value =
   3824         std::is_same<value_type,
   3825         typename BasicJsonType::array_t::value_type>::value ||
   3826         has_from_json<BasicJsonType,
   3827         value_type>::value ||
   3828         has_non_default_from_json <
   3829         BasicJsonType,
   3830         value_type >::value;
   3831 };
   3832 
   3833 template<typename BasicJsonType, typename ConstructibleArrayType>
   3834 struct is_constructible_array_type
   3835     : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
   3836 
   3837 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
   3838          typename = void>
   3839 struct is_compatible_integer_type_impl : std::false_type {};
   3840 
   3841 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
   3842 struct is_compatible_integer_type_impl <
   3843     RealIntegerType, CompatibleNumberIntegerType,
   3844     enable_if_t < std::is_integral<RealIntegerType>::value&&
   3845     std::is_integral<CompatibleNumberIntegerType>::value&&
   3846     !std::is_same<bool, CompatibleNumberIntegerType>::value >>
   3847 {
   3848     // is there an assert somewhere on overflows?
   3849     using RealLimits = std::numeric_limits<RealIntegerType>;
   3850     using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
   3851 
   3852     static constexpr auto value =
   3853         is_constructible<RealIntegerType,
   3854         CompatibleNumberIntegerType>::value &&
   3855         CompatibleLimits::is_integer &&
   3856         RealLimits::is_signed == CompatibleLimits::is_signed;
   3857 };
   3858 
   3859 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
   3860 struct is_compatible_integer_type
   3861     : is_compatible_integer_type_impl<RealIntegerType,
   3862       CompatibleNumberIntegerType> {};
   3863 
   3864 template<typename BasicJsonType, typename CompatibleType, typename = void>
   3865 struct is_compatible_type_impl: std::false_type {};
   3866 
   3867 template<typename BasicJsonType, typename CompatibleType>
   3868 struct is_compatible_type_impl <
   3869     BasicJsonType, CompatibleType,
   3870     enable_if_t<is_complete_type<CompatibleType>::value >>
   3871 {
   3872     static constexpr bool value =
   3873         has_to_json<BasicJsonType, CompatibleType>::value;
   3874 };
   3875 
   3876 template<typename BasicJsonType, typename CompatibleType>
   3877 struct is_compatible_type
   3878     : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
   3879 
   3880 template<typename T1, typename T2>
   3881 struct is_constructible_tuple : std::false_type {};
   3882 
   3883 template<typename T1, typename... Args>
   3884 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
   3885 
   3886 template<typename BasicJsonType, typename T>
   3887 struct is_json_iterator_of : std::false_type {};
   3888 
   3889 template<typename BasicJsonType>
   3890 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
   3891 
   3892 template<typename BasicJsonType>
   3893 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
   3894 {};
   3895 
   3896 // checks if a given type T is a template specialization of Primary
   3897 template<template <typename...> class Primary, typename T>
   3898 struct is_specialization_of : std::false_type {};
   3899 
   3900 template<template <typename...> class Primary, typename... Args>
   3901 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
   3902 
   3903 template<typename T>
   3904 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
   3905 
   3906 // checks if A and B are comparable using Compare functor
   3907 template<typename Compare, typename A, typename B, typename = void>
   3908 struct is_comparable : std::false_type {};
   3909 
   3910 template<typename Compare, typename A, typename B>
   3911 struct is_comparable<Compare, A, B, void_t<
   3912 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
   3913 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
   3914 >> : std::true_type {};
   3915 
   3916 template<typename T>
   3917 using detect_is_transparent = typename T::is_transparent;
   3918 
   3919 // type trait to check if KeyType can be used as object key (without a BasicJsonType)
   3920 // see is_usable_as_basic_json_key_type below
   3921 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
   3922          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
   3923 using is_usable_as_key_type = typename std::conditional <
   3924                               is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
   3925                               && !(ExcludeObjectKeyType && std::is_same<KeyType,
   3926                                    ObjectKeyType>::value)
   3927                               && (!RequireTransparentComparator
   3928                                   || is_detected <detect_is_transparent, Comparator>::value)
   3929                               && !is_json_pointer<KeyType>::value,
   3930                               std::true_type,
   3931                               std::false_type >::type;
   3932 
   3933 // type trait to check if KeyType can be used as object key
   3934 // true if:
   3935 //   - KeyType is comparable with BasicJsonType::object_t::key_type
   3936 //   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
   3937 //   - the comparator is transparent or RequireTransparentComparator is false
   3938 //   - KeyType is not a JSON iterator or json_pointer
   3939 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
   3940          bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
   3941 using is_usable_as_basic_json_key_type = typename std::conditional <
   3942         is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
   3943         typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
   3944         RequireTransparentComparator, ExcludeObjectKeyType>::value
   3945         && !is_json_iterator_of<BasicJsonType, KeyType>::value,
   3946         std::true_type,
   3947         std::false_type >::type;
   3948 
   3949 template<typename ObjectType, typename KeyType>
   3950 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
   3951 
   3952 // type trait to check if object_t has an erase() member functions accepting KeyType
   3953 template<typename BasicJsonType, typename KeyType>
   3954 using has_erase_with_key_type = typename std::conditional <
   3955                                 is_detected <
   3956                                 detect_erase_with_key_type,
   3957                                 typename BasicJsonType::object_t, KeyType >::value,
   3958                                 std::true_type,
   3959                                 std::false_type >::type;
   3960 
   3961 // a naive helper to check if a type is an ordered_map (exploits the fact that
   3962 // ordered_map inherits capacity() from std::vector)
   3963 template <typename T>
   3964 struct is_ordered_map
   3965 {
   3966     using one = char;
   3967 
   3968     struct two
   3969     {
   3970         char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   3971     };
   3972 
   3973     template <typename C> static one test( decltype(&C::capacity) ) ;
   3974     template <typename C> static two test(...);
   3975 
   3976     enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   3977 };
   3978 
   3979 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
   3980 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
   3981 T conditional_static_cast(U value)
   3982 {
   3983     return static_cast<T>(value);
   3984 }
   3985 
   3986 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
   3987 T conditional_static_cast(U value)
   3988 {
   3989     return value;
   3990 }
   3991 
   3992 template<typename... Types>
   3993 using all_integral = conjunction<std::is_integral<Types>...>;
   3994 
   3995 template<typename... Types>
   3996 using all_signed = conjunction<std::is_signed<Types>...>;
   3997 
   3998 template<typename... Types>
   3999 using all_unsigned = conjunction<std::is_unsigned<Types>...>;
   4000 
   4001 // there's a disjunction trait in another PR; replace when merged
   4002 template<typename... Types>
   4003 using same_sign = std::integral_constant < bool,
   4004       all_signed<Types...>::value || all_unsigned<Types...>::value >;
   4005 
   4006 template<typename OfType, typename T>
   4007 using never_out_of_range = std::integral_constant < bool,
   4008       (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
   4009       || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
   4010 
   4011 template<typename OfType, typename T,
   4012          bool OfTypeSigned = std::is_signed<OfType>::value,
   4013          bool TSigned = std::is_signed<T>::value>
   4014 struct value_in_range_of_impl2;
   4015 
   4016 template<typename OfType, typename T>
   4017 struct value_in_range_of_impl2<OfType, T, false, false>
   4018 {
   4019     static constexpr bool test(T val)
   4020     {
   4021         using CommonType = typename std::common_type<OfType, T>::type;
   4022         return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4023     }
   4024 };
   4025 
   4026 template<typename OfType, typename T>
   4027 struct value_in_range_of_impl2<OfType, T, true, false>
   4028 {
   4029     static constexpr bool test(T val)
   4030     {
   4031         using CommonType = typename std::common_type<OfType, T>::type;
   4032         return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4033     }
   4034 };
   4035 
   4036 template<typename OfType, typename T>
   4037 struct value_in_range_of_impl2<OfType, T, false, true>
   4038 {
   4039     static constexpr bool test(T val)
   4040     {
   4041         using CommonType = typename std::common_type<OfType, T>::type;
   4042         return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4043     }
   4044 };
   4045 
   4046 
   4047 template<typename OfType, typename T>
   4048 struct value_in_range_of_impl2<OfType, T, true, true>
   4049 {
   4050     static constexpr bool test(T val)
   4051     {
   4052         using CommonType = typename std::common_type<OfType, T>::type;
   4053         return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
   4054                && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4055     }
   4056 };
   4057 
   4058 template<typename OfType, typename T,
   4059          bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
   4060          typename = detail::enable_if_t<all_integral<OfType, T>::value>>
   4061 struct value_in_range_of_impl1;
   4062 
   4063 template<typename OfType, typename T>
   4064 struct value_in_range_of_impl1<OfType, T, false>
   4065 {
   4066     static constexpr bool test(T val)
   4067     {
   4068         return value_in_range_of_impl2<OfType, T>::test(val);
   4069     }
   4070 };
   4071 
   4072 template<typename OfType, typename T>
   4073 struct value_in_range_of_impl1<OfType, T, true>
   4074 {
   4075     static constexpr bool test(T /*val*/)
   4076     {
   4077         return true;
   4078     }
   4079 };
   4080 
   4081 template<typename OfType, typename T>
   4082 inline constexpr bool value_in_range_of(T val)
   4083 {
   4084     return value_in_range_of_impl1<OfType, T>::test(val);
   4085 }
   4086 
   4087 template<bool Value>
   4088 using bool_constant = std::integral_constant<bool, Value>;
   4089 
   4090 ///////////////////////////////////////////////////////////////////////////////
   4091 // is_c_string
   4092 ///////////////////////////////////////////////////////////////////////////////
   4093 
   4094 namespace impl
   4095 {
   4096 
   4097 template<typename T>
   4098 inline constexpr bool is_c_string()
   4099 {
   4100     using TUnExt = typename std::remove_extent<T>::type;
   4101     using TUnCVExt = typename std::remove_cv<TUnExt>::type;
   4102     using TUnPtr = typename std::remove_pointer<T>::type;
   4103     using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
   4104     return
   4105         (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
   4106         || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
   4107 }
   4108 
   4109 }  // namespace impl
   4110 
   4111 // checks whether T is a [cv] char */[cv] char[] C string
   4112 template<typename T>
   4113 struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
   4114 
   4115 template<typename T>
   4116 using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
   4117 
   4118 ///////////////////////////////////////////////////////////////////////////////
   4119 // is_transparent
   4120 ///////////////////////////////////////////////////////////////////////////////
   4121 
   4122 namespace impl
   4123 {
   4124 
   4125 template<typename T>
   4126 inline constexpr bool is_transparent()
   4127 {
   4128     return is_detected<detect_is_transparent, T>::value;
   4129 }
   4130 
   4131 }  // namespace impl
   4132 
   4133 // checks whether T has a member named is_transparent
   4134 template<typename T>
   4135 struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
   4136 
   4137 ///////////////////////////////////////////////////////////////////////////////
   4138 
   4139 }  // namespace detail
   4140 NLOHMANN_JSON_NAMESPACE_END
   4141 
   4142 // #include <nlohmann/detail/string_concat.hpp>
   4143 //     __ _____ _____ _____
   4144 //  __|  |   __|     |   | |  JSON for Modern C++
   4145 // |  |  |__   |  |  | | | |  version 3.11.2
   4146 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   4147 //
   4148 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   4149 // SPDX-License-Identifier: MIT
   4150 
   4151 
   4152 
   4153 #include <cstring> // strlen
   4154 #include <string> // string
   4155 #include <utility> // forward
   4156 
   4157 // #include <nlohmann/detail/meta/cpp_future.hpp>
   4158 
   4159 // #include <nlohmann/detail/meta/detected.hpp>
   4160 
   4161 
   4162 NLOHMANN_JSON_NAMESPACE_BEGIN
   4163 namespace detail
   4164 {
   4165 
   4166 inline std::size_t concat_length()
   4167 {
   4168     return 0;
   4169 }
   4170 
   4171 template<typename... Args>
   4172 inline std::size_t concat_length(const char* cstr, const Args& ... rest);
   4173 
   4174 template<typename StringType, typename... Args>
   4175 inline std::size_t concat_length(const StringType& str, const Args& ... rest);
   4176 
   4177 template<typename... Args>
   4178 inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
   4179 {
   4180     return 1 + concat_length(rest...);
   4181 }
   4182 
   4183 template<typename... Args>
   4184 inline std::size_t concat_length(const char* cstr, const Args& ... rest)
   4185 {
   4186     // cppcheck-suppress ignoredReturnValue
   4187     return ::strlen(cstr) + concat_length(rest...);
   4188 }
   4189 
   4190 template<typename StringType, typename... Args>
   4191 inline std::size_t concat_length(const StringType& str, const Args& ... rest)
   4192 {
   4193     return str.size() + concat_length(rest...);
   4194 }
   4195 
   4196 template<typename OutStringType>
   4197 inline void concat_into(OutStringType& /*out*/)
   4198 {}
   4199 
   4200 template<typename StringType, typename Arg>
   4201 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
   4202 
   4203 template<typename StringType, typename Arg>
   4204 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
   4205 
   4206 template<typename StringType, typename Arg>
   4207 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
   4208 
   4209 template<typename StringType, typename Arg>
   4210 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
   4211 
   4212 template<typename StringType, typename Arg>
   4213 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
   4214 
   4215 template<typename StringType, typename Arg>
   4216 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
   4217 
   4218 template<typename StringType, typename Arg>
   4219 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
   4220 
   4221 template<typename StringType, typename Arg>
   4222 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
   4223 
   4224 template < typename OutStringType, typename Arg, typename... Args,
   4225            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4226                          && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
   4227 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
   4228 
   4229 template < typename OutStringType, typename Arg, typename... Args,
   4230            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4231                          && !detect_string_can_append_op<OutStringType, Arg>::value
   4232                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
   4233 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
   4234 
   4235 template < typename OutStringType, typename Arg, typename... Args,
   4236            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4237                          && !detect_string_can_append_op<OutStringType, Arg>::value
   4238                          && !detect_string_can_append_iter<OutStringType, Arg>::value
   4239                          && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
   4240 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
   4241 
   4242 template<typename OutStringType, typename Arg, typename... Args,
   4243          enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
   4244 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
   4245 {
   4246     out.append(std::forward<Arg>(arg));
   4247     concat_into(out, std::forward<Args>(rest)...);
   4248 }
   4249 
   4250 template < typename OutStringType, typename Arg, typename... Args,
   4251            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4252                          && detect_string_can_append_op<OutStringType, Arg>::value, int > >
   4253 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
   4254 {
   4255     out += std::forward<Arg>(arg);
   4256     concat_into(out, std::forward<Args>(rest)...);
   4257 }
   4258 
   4259 template < typename OutStringType, typename Arg, typename... Args,
   4260            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4261                          && !detect_string_can_append_op<OutStringType, Arg>::value
   4262                          && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
   4263 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
   4264 {
   4265     out.append(arg.begin(), arg.end());
   4266     concat_into(out, std::forward<Args>(rest)...);
   4267 }
   4268 
   4269 template < typename OutStringType, typename Arg, typename... Args,
   4270            enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4271                          && !detect_string_can_append_op<OutStringType, Arg>::value
   4272                          && !detect_string_can_append_iter<OutStringType, Arg>::value
   4273                          && detect_string_can_append_data<OutStringType, Arg>::value, int > >
   4274 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
   4275 {
   4276     out.append(arg.data(), arg.size());
   4277     concat_into(out, std::forward<Args>(rest)...);
   4278 }
   4279 
   4280 template<typename OutStringType = std::string, typename... Args>
   4281 inline OutStringType concat(Args && ... args)
   4282 {
   4283     OutStringType str;
   4284     str.reserve(concat_length(args...));
   4285     concat_into(str, std::forward<Args>(args)...);
   4286     return str;
   4287 }
   4288 
   4289 }  // namespace detail
   4290 NLOHMANN_JSON_NAMESPACE_END
   4291 
   4292 
   4293 
   4294 NLOHMANN_JSON_NAMESPACE_BEGIN
   4295 namespace detail
   4296 {
   4297 
   4298 ////////////////
   4299 // exceptions //
   4300 ////////////////
   4301 
   4302 /// @brief general exception of the @ref basic_json class
   4303 /// @sa https://json.nlohmann.me/api/basic_json/exception/
   4304 class exception : public std::exception
   4305 {
   4306   public:
   4307     /// returns the explanatory string
   4308     const char* what() const noexcept override
   4309     {
   4310         return m.what();
   4311     }
   4312 
   4313     /// the id of the exception
   4314     const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
   4315 
   4316   protected:
   4317     JSON_HEDLEY_NON_NULL(3)
   4318     exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
   4319 
   4320     static std::string name(const std::string& ename, int id_)
   4321     {
   4322         return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
   4323     }
   4324 
   4325     static std::string diagnostics(std::nullptr_t /*leaf_element*/)
   4326     {
   4327         return "";
   4328     }
   4329 
   4330     template<typename BasicJsonType>
   4331     static std::string diagnostics(const BasicJsonType* leaf_element)
   4332     {
   4333 #if JSON_DIAGNOSTICS
   4334         std::vector<std::string> tokens;
   4335         for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
   4336         {
   4337             switch (current->m_parent->type())
   4338             {
   4339                 case value_t::array:
   4340                 {
   4341                     for (std::size_t i = 0; i < current->m_parent->m_value.array->size(); ++i)
   4342                     {
   4343                         if (&current->m_parent->m_value.array->operator[](i) == current)
   4344                         {
   4345                             tokens.emplace_back(std::to_string(i));
   4346                             break;
   4347                         }
   4348                     }
   4349                     break;
   4350                 }
   4351 
   4352                 case value_t::object:
   4353                 {
   4354                     for (const auto& element : *current->m_parent->m_value.object)
   4355                     {
   4356                         if (&element.second == current)
   4357                         {
   4358                             tokens.emplace_back(element.first.c_str());
   4359                             break;
   4360                         }
   4361                     }
   4362                     break;
   4363                 }
   4364 
   4365                 case value_t::null: // LCOV_EXCL_LINE
   4366                 case value_t::string: // LCOV_EXCL_LINE
   4367                 case value_t::boolean: // LCOV_EXCL_LINE
   4368                 case value_t::number_integer: // LCOV_EXCL_LINE
   4369                 case value_t::number_unsigned: // LCOV_EXCL_LINE
   4370                 case value_t::number_float: // LCOV_EXCL_LINE
   4371                 case value_t::binary: // LCOV_EXCL_LINE
   4372                 case value_t::discarded: // LCOV_EXCL_LINE
   4373                 default:   // LCOV_EXCL_LINE
   4374                     break; // LCOV_EXCL_LINE
   4375             }
   4376         }
   4377 
   4378         if (tokens.empty())
   4379         {
   4380             return "";
   4381         }
   4382 
   4383         auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
   4384                                    [](const std::string & a, const std::string & b)
   4385         {
   4386             return concat(a, '/', detail::escape(b));
   4387         });
   4388         return concat('(', str, ") ");
   4389 #else
   4390         static_cast<void>(leaf_element);
   4391         return "";
   4392 #endif
   4393     }
   4394 
   4395   private:
   4396     /// an exception object as storage for error messages
   4397     std::runtime_error m;
   4398 };
   4399 
   4400 /// @brief exception indicating a parse error
   4401 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
   4402 class parse_error : public exception
   4403 {
   4404   public:
   4405     /*!
   4406     @brief create a parse error exception
   4407     @param[in] id_       the id of the exception
   4408     @param[in] pos       the position where the error occurred (or with
   4409                          chars_read_total=0 if the position cannot be
   4410                          determined)
   4411     @param[in] what_arg  the explanatory string
   4412     @return parse_error object
   4413     */
   4414     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4415     static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
   4416     {
   4417         const std::string w = concat(exception::name("parse_error", id_), "parse error",
   4418                                      position_string(pos), ": ", exception::diagnostics(context), what_arg);
   4419         return {id_, pos.chars_read_total, w.c_str()};
   4420     }
   4421 
   4422     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4423     static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
   4424     {
   4425         const std::string w = concat(exception::name("parse_error", id_), "parse error",
   4426                                      (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
   4427                                      ": ", exception::diagnostics(context), what_arg);
   4428         return {id_, byte_, w.c_str()};
   4429     }
   4430 
   4431     /*!
   4432     @brief byte index of the parse error
   4433 
   4434     The byte index of the last read character in the input file.
   4435 
   4436     @note For an input with n bytes, 1 is the index of the first character and
   4437           n+1 is the index of the terminating null byte or the end of file.
   4438           This also holds true when reading a byte vector (CBOR or MessagePack).
   4439     */
   4440     const std::size_t byte;
   4441 
   4442   private:
   4443     parse_error(int id_, std::size_t byte_, const char* what_arg)
   4444         : exception(id_, what_arg), byte(byte_) {}
   4445 
   4446     static std::string position_string(const position_t& pos)
   4447     {
   4448         return concat(" at line ", std::to_string(pos.lines_read + 1),
   4449                       ", column ", std::to_string(pos.chars_read_current_line));
   4450     }
   4451 };
   4452 
   4453 /// @brief exception indicating errors with iterators
   4454 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
   4455 class invalid_iterator : public exception
   4456 {
   4457   public:
   4458     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4459     static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
   4460     {
   4461         const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
   4462         return {id_, w.c_str()};
   4463     }
   4464 
   4465   private:
   4466     JSON_HEDLEY_NON_NULL(3)
   4467     invalid_iterator(int id_, const char* what_arg)
   4468         : exception(id_, what_arg) {}
   4469 };
   4470 
   4471 /// @brief exception indicating executing a member function with a wrong type
   4472 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
   4473 class type_error : public exception
   4474 {
   4475   public:
   4476     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4477     static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
   4478     {
   4479         const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
   4480         return {id_, w.c_str()};
   4481     }
   4482 
   4483   private:
   4484     JSON_HEDLEY_NON_NULL(3)
   4485     type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
   4486 };
   4487 
   4488 /// @brief exception indicating access out of the defined range
   4489 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
   4490 class out_of_range : public exception
   4491 {
   4492   public:
   4493     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4494     static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
   4495     {
   4496         const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
   4497         return {id_, w.c_str()};
   4498     }
   4499 
   4500   private:
   4501     JSON_HEDLEY_NON_NULL(3)
   4502     out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
   4503 };
   4504 
   4505 /// @brief exception indicating other library errors
   4506 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
   4507 class other_error : public exception
   4508 {
   4509   public:
   4510     template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4511     static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
   4512     {
   4513         const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
   4514         return {id_, w.c_str()};
   4515     }
   4516 
   4517   private:
   4518     JSON_HEDLEY_NON_NULL(3)
   4519     other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
   4520 };
   4521 
   4522 }  // namespace detail
   4523 NLOHMANN_JSON_NAMESPACE_END
   4524 
   4525 // #include <nlohmann/detail/macro_scope.hpp>
   4526 
   4527 // #include <nlohmann/detail/meta/cpp_future.hpp>
   4528 
   4529 // #include <nlohmann/detail/meta/identity_tag.hpp>
   4530 //     __ _____ _____ _____
   4531 //  __|  |   __|     |   | |  JSON for Modern C++
   4532 // |  |  |__   |  |  | | | |  version 3.11.2
   4533 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   4534 //
   4535 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   4536 // SPDX-License-Identifier: MIT
   4537 
   4538 
   4539 
   4540 // #include <nlohmann/detail/abi_macros.hpp>
   4541 
   4542 
   4543 NLOHMANN_JSON_NAMESPACE_BEGIN
   4544 namespace detail
   4545 {
   4546 
   4547 // dispatching helper struct
   4548 template <class T> struct identity_tag {};
   4549 
   4550 }  // namespace detail
   4551 NLOHMANN_JSON_NAMESPACE_END
   4552 
   4553 // #include <nlohmann/detail/meta/std_fs.hpp>
   4554 //     __ _____ _____ _____
   4555 //  __|  |   __|     |   | |  JSON for Modern C++
   4556 // |  |  |__   |  |  | | | |  version 3.11.2
   4557 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   4558 //
   4559 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   4560 // SPDX-License-Identifier: MIT
   4561 
   4562 
   4563 
   4564 // #include <nlohmann/detail/macro_scope.hpp>
   4565 
   4566 
   4567 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
   4568 #include <experimental/filesystem>
   4569 NLOHMANN_JSON_NAMESPACE_BEGIN
   4570 namespace detail
   4571 {
   4572 namespace std_fs = std::experimental::filesystem;
   4573 }  // namespace detail
   4574 NLOHMANN_JSON_NAMESPACE_END
   4575 #elif JSON_HAS_FILESYSTEM
   4576 #include <filesystem>
   4577 NLOHMANN_JSON_NAMESPACE_BEGIN
   4578 namespace detail
   4579 {
   4580 namespace std_fs = std::filesystem;
   4581 }  // namespace detail
   4582 NLOHMANN_JSON_NAMESPACE_END
   4583 #endif
   4584 
   4585 // #include <nlohmann/detail/meta/type_traits.hpp>
   4586 
   4587 // #include <nlohmann/detail/string_concat.hpp>
   4588 
   4589 // #include <nlohmann/detail/value_t.hpp>
   4590 
   4591 
   4592 NLOHMANN_JSON_NAMESPACE_BEGIN
   4593 namespace detail
   4594 {
   4595 
   4596 template<typename BasicJsonType>
   4597 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
   4598 {
   4599     if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
   4600     {
   4601         JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
   4602     }
   4603     n = nullptr;
   4604 }
   4605 
   4606 // overloads for basic_json template parameters
   4607 template < typename BasicJsonType, typename ArithmeticType,
   4608            enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
   4609                          !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
   4610                          int > = 0 >
   4611 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
   4612 {
   4613     switch (static_cast<value_t>(j))
   4614     {
   4615         case value_t::number_unsigned:
   4616         {
   4617             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
   4618             break;
   4619         }
   4620         case value_t::number_integer:
   4621         {
   4622             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
   4623             break;
   4624         }
   4625         case value_t::number_float:
   4626         {
   4627             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
   4628             break;
   4629         }
   4630 
   4631         case value_t::null:
   4632         case value_t::object:
   4633         case value_t::array:
   4634         case value_t::string:
   4635         case value_t::boolean:
   4636         case value_t::binary:
   4637         case value_t::discarded:
   4638         default:
   4639             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
   4640     }
   4641 }
   4642 
   4643 template<typename BasicJsonType>
   4644 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
   4645 {
   4646     if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
   4647     {
   4648         JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
   4649     }
   4650     b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
   4651 }
   4652 
   4653 template<typename BasicJsonType>
   4654 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
   4655 {
   4656     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
   4657     {
   4658         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
   4659     }
   4660     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
   4661 }
   4662 
   4663 template <
   4664     typename BasicJsonType, typename StringType,
   4665     enable_if_t <
   4666         std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
   4667         && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
   4668         && !std::is_same<typename BasicJsonType::string_t, StringType>::value
   4669         && !is_json_ref<StringType>::value, int > = 0 >
   4670 inline void from_json(const BasicJsonType& j, StringType& s)
   4671 {
   4672     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
   4673     {
   4674         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
   4675     }
   4676 
   4677     s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
   4678 }
   4679 
   4680 template<typename BasicJsonType>
   4681 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
   4682 {
   4683     get_arithmetic_value(j, val);
   4684 }
   4685 
   4686 template<typename BasicJsonType>
   4687 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
   4688 {
   4689     get_arithmetic_value(j, val);
   4690 }
   4691 
   4692 template<typename BasicJsonType>
   4693 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
   4694 {
   4695     get_arithmetic_value(j, val);
   4696 }
   4697 
   4698 #if !JSON_DISABLE_ENUM_SERIALIZATION
   4699 template<typename BasicJsonType, typename EnumType,
   4700          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
   4701 inline void from_json(const BasicJsonType& j, EnumType& e)
   4702 {
   4703     typename std::underlying_type<EnumType>::type val;
   4704     get_arithmetic_value(j, val);
   4705     e = static_cast<EnumType>(val);
   4706 }
   4707 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
   4708 
   4709 // forward_list doesn't have an insert method
   4710 template<typename BasicJsonType, typename T, typename Allocator,
   4711          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
   4712 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
   4713 {
   4714     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4715     {
   4716         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4717     }
   4718     l.clear();
   4719     std::transform(j.rbegin(), j.rend(),
   4720                    std::front_inserter(l), [](const BasicJsonType & i)
   4721     {
   4722         return i.template get<T>();
   4723     });
   4724 }
   4725 
   4726 // valarray doesn't have an insert method
   4727 template<typename BasicJsonType, typename T,
   4728          enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
   4729 inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
   4730 {
   4731     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4732     {
   4733         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4734     }
   4735     l.resize(j.size());
   4736     std::transform(j.begin(), j.end(), std::begin(l),
   4737                    [](const BasicJsonType & elem)
   4738     {
   4739         return elem.template get<T>();
   4740     });
   4741 }
   4742 
   4743 template<typename BasicJsonType, typename T, std::size_t N>
   4744 auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   4745 -> decltype(j.template get<T>(), void())
   4746 {
   4747     for (std::size_t i = 0; i < N; ++i)
   4748     {
   4749         arr[i] = j.at(i).template get<T>();
   4750     }
   4751 }
   4752 
   4753 template<typename BasicJsonType>
   4754 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
   4755 {
   4756     arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
   4757 }
   4758 
   4759 template<typename BasicJsonType, typename T, std::size_t N>
   4760 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
   4761                           priority_tag<2> /*unused*/)
   4762 -> decltype(j.template get<T>(), void())
   4763 {
   4764     for (std::size_t i = 0; i < N; ++i)
   4765     {
   4766         arr[i] = j.at(i).template get<T>();
   4767     }
   4768 }
   4769 
   4770 template<typename BasicJsonType, typename ConstructibleArrayType,
   4771          enable_if_t<
   4772              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
   4773              int> = 0>
   4774 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
   4775 -> decltype(
   4776     arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
   4777     j.template get<typename ConstructibleArrayType::value_type>(),
   4778     void())
   4779 {
   4780     using std::end;
   4781 
   4782     ConstructibleArrayType ret;
   4783     ret.reserve(j.size());
   4784     std::transform(j.begin(), j.end(),
   4785                    std::inserter(ret, end(ret)), [](const BasicJsonType & i)
   4786     {
   4787         // get<BasicJsonType>() returns *this, this won't call a from_json
   4788         // method when value_type is BasicJsonType
   4789         return i.template get<typename ConstructibleArrayType::value_type>();
   4790     });
   4791     arr = std::move(ret);
   4792 }
   4793 
   4794 template<typename BasicJsonType, typename ConstructibleArrayType,
   4795          enable_if_t<
   4796              std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
   4797              int> = 0>
   4798 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
   4799                                  priority_tag<0> /*unused*/)
   4800 {
   4801     using std::end;
   4802 
   4803     ConstructibleArrayType ret;
   4804     std::transform(
   4805         j.begin(), j.end(), std::inserter(ret, end(ret)),
   4806         [](const BasicJsonType & i)
   4807     {
   4808         // get<BasicJsonType>() returns *this, this won't call a from_json
   4809         // method when value_type is BasicJsonType
   4810         return i.template get<typename ConstructibleArrayType::value_type>();
   4811     });
   4812     arr = std::move(ret);
   4813 }
   4814 
   4815 template < typename BasicJsonType, typename ConstructibleArrayType,
   4816            enable_if_t <
   4817                is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
   4818                !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
   4819                !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
   4820                !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
   4821                !is_basic_json<ConstructibleArrayType>::value,
   4822                int > = 0 >
   4823 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
   4824 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
   4825 j.template get<typename ConstructibleArrayType::value_type>(),
   4826 void())
   4827 {
   4828     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4829     {
   4830         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4831     }
   4832 
   4833     from_json_array_impl(j, arr, priority_tag<3> {});
   4834 }
   4835 
   4836 template < typename BasicJsonType, typename T, std::size_t... Idx >
   4837 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
   4838         identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
   4839 {
   4840     return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
   4841 }
   4842 
   4843 template < typename BasicJsonType, typename T, std::size_t N >
   4844 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
   4845 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
   4846 {
   4847     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4848     {
   4849         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4850     }
   4851 
   4852     return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
   4853 }
   4854 
   4855 template<typename BasicJsonType>
   4856 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
   4857 {
   4858     if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
   4859     {
   4860         JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
   4861     }
   4862 
   4863     bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
   4864 }
   4865 
   4866 template<typename BasicJsonType, typename ConstructibleObjectType,
   4867          enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
   4868 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
   4869 {
   4870     if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
   4871     {
   4872         JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
   4873     }
   4874 
   4875     ConstructibleObjectType ret;
   4876     const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
   4877     using value_type = typename ConstructibleObjectType::value_type;
   4878     std::transform(
   4879         inner_object->begin(), inner_object->end(),
   4880         std::inserter(ret, ret.begin()),
   4881         [](typename BasicJsonType::object_t::value_type const & p)
   4882     {
   4883         return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
   4884     });
   4885     obj = std::move(ret);
   4886 }
   4887 
   4888 // overload for arithmetic types, not chosen for basic_json template arguments
   4889 // (BooleanType, etc..); note: Is it really necessary to provide explicit
   4890 // overloads for boolean_t etc. in case of a custom BooleanType which is not
   4891 // an arithmetic type?
   4892 template < typename BasicJsonType, typename ArithmeticType,
   4893            enable_if_t <
   4894                std::is_arithmetic<ArithmeticType>::value&&
   4895                !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
   4896                !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
   4897                !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
   4898                !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
   4899                int > = 0 >
   4900 inline void from_json(const BasicJsonType& j, ArithmeticType& val)
   4901 {
   4902     switch (static_cast<value_t>(j))
   4903     {
   4904         case value_t::number_unsigned:
   4905         {
   4906             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
   4907             break;
   4908         }
   4909         case value_t::number_integer:
   4910         {
   4911             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
   4912             break;
   4913         }
   4914         case value_t::number_float:
   4915         {
   4916             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
   4917             break;
   4918         }
   4919         case value_t::boolean:
   4920         {
   4921             val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
   4922             break;
   4923         }
   4924 
   4925         case value_t::null:
   4926         case value_t::object:
   4927         case value_t::array:
   4928         case value_t::string:
   4929         case value_t::binary:
   4930         case value_t::discarded:
   4931         default:
   4932             JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
   4933     }
   4934 }
   4935 
   4936 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
   4937 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
   4938 {
   4939     return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
   4940 }
   4941 
   4942 template < typename BasicJsonType, class A1, class A2 >
   4943 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
   4944 {
   4945     return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
   4946             std::forward<BasicJsonType>(j).at(1).template get<A2>()};
   4947 }
   4948 
   4949 template<typename BasicJsonType, typename A1, typename A2>
   4950 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
   4951 {
   4952     p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
   4953 }
   4954 
   4955 template<typename BasicJsonType, typename... Args>
   4956 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
   4957 {
   4958     return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
   4959 }
   4960 
   4961 template<typename BasicJsonType, typename... Args>
   4962 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
   4963 {
   4964     t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
   4965 }
   4966 
   4967 template<typename BasicJsonType, typename TupleRelated>
   4968 auto from_json(BasicJsonType&& j, TupleRelated&& t)
   4969 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
   4970 {
   4971     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4972     {
   4973         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4974     }
   4975 
   4976     return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
   4977 }
   4978 
   4979 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
   4980            typename = enable_if_t < !std::is_constructible <
   4981                                         typename BasicJsonType::string_t, Key >::value >>
   4982 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
   4983 {
   4984     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4985     {
   4986         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4987     }
   4988     m.clear();
   4989     for (const auto& p : j)
   4990     {
   4991         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
   4992         {
   4993             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
   4994         }
   4995         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
   4996     }
   4997 }
   4998 
   4999 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
   5000            typename = enable_if_t < !std::is_constructible <
   5001                                         typename BasicJsonType::string_t, Key >::value >>
   5002 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
   5003 {
   5004     if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   5005     {
   5006         JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   5007     }
   5008     m.clear();
   5009     for (const auto& p : j)
   5010     {
   5011         if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
   5012         {
   5013             JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
   5014         }
   5015         m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
   5016     }
   5017 }
   5018 
   5019 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
   5020 template<typename BasicJsonType>
   5021 inline void from_json(const BasicJsonType& j, std_fs::path& p)
   5022 {
   5023     if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
   5024     {
   5025         JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
   5026     }
   5027     p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
   5028 }
   5029 #endif
   5030 
   5031 struct from_json_fn
   5032 {
   5033     template<typename BasicJsonType, typename T>
   5034     auto operator()(const BasicJsonType& j, T&& val) const
   5035     noexcept(noexcept(from_json(j, std::forward<T>(val))))
   5036     -> decltype(from_json(j, std::forward<T>(val)))
   5037     {
   5038         return from_json(j, std::forward<T>(val));
   5039     }
   5040 };
   5041 
   5042 }  // namespace detail
   5043 
   5044 #ifndef JSON_HAS_CPP_17
   5045 /// namespace to hold default `from_json` function
   5046 /// to see why this is required:
   5047 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
   5048 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
   5049 {
   5050 #endif
   5051 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
   5052     detail::static_const<detail::from_json_fn>::value;
   5053 #ifndef JSON_HAS_CPP_17
   5054 }  // namespace
   5055 #endif
   5056 
   5057 NLOHMANN_JSON_NAMESPACE_END
   5058 
   5059 // #include <nlohmann/detail/conversions/to_json.hpp>
   5060 //     __ _____ _____ _____
   5061 //  __|  |   __|     |   | |  JSON for Modern C++
   5062 // |  |  |__   |  |  | | | |  version 3.11.2
   5063 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5064 //
   5065 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   5066 // SPDX-License-Identifier: MIT
   5067 
   5068 
   5069 
   5070 #include <algorithm> // copy
   5071 #include <iterator> // begin, end
   5072 #include <string> // string
   5073 #include <tuple> // tuple, get
   5074 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
   5075 #include <utility> // move, forward, declval, pair
   5076 #include <valarray> // valarray
   5077 #include <vector> // vector
   5078 
   5079 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
   5080 //     __ _____ _____ _____
   5081 //  __|  |   __|     |   | |  JSON for Modern C++
   5082 // |  |  |__   |  |  | | | |  version 3.11.2
   5083 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5084 //
   5085 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   5086 // SPDX-License-Identifier: MIT
   5087 
   5088 
   5089 
   5090 #include <cstddef> // size_t
   5091 #include <iterator> // input_iterator_tag
   5092 #include <string> // string, to_string
   5093 #include <tuple> // tuple_size, get, tuple_element
   5094 #include <utility> // move
   5095 
   5096 #if JSON_HAS_RANGES
   5097     #include <ranges> // enable_borrowed_range
   5098 #endif
   5099 
   5100 // #include <nlohmann/detail/abi_macros.hpp>
   5101 
   5102 // #include <nlohmann/detail/meta/type_traits.hpp>
   5103 
   5104 // #include <nlohmann/detail/value_t.hpp>
   5105 
   5106 
   5107 NLOHMANN_JSON_NAMESPACE_BEGIN
   5108 namespace detail
   5109 {
   5110 
   5111 template<typename string_type>
   5112 void int_to_string( string_type& target, std::size_t value )
   5113 {
   5114     // For ADL
   5115     using std::to_string;
   5116     target = to_string(value);
   5117 }
   5118 template<typename IteratorType> class iteration_proxy_value
   5119 {
   5120   public:
   5121     using difference_type = std::ptrdiff_t;
   5122     using value_type = iteration_proxy_value;
   5123     using pointer = value_type *;
   5124     using reference = value_type &;
   5125     using iterator_category = std::input_iterator_tag;
   5126     using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
   5127 
   5128   private:
   5129     /// the iterator
   5130     IteratorType anchor{};
   5131     /// an index for arrays (used to create key names)
   5132     std::size_t array_index = 0;
   5133     /// last stringified array index
   5134     mutable std::size_t array_index_last = 0;
   5135     /// a string representation of the array index
   5136     mutable string_type array_index_str = "0";
   5137     /// an empty string (to return a reference for primitive values)
   5138     string_type empty_str{};
   5139 
   5140   public:
   5141     explicit iteration_proxy_value() = default;
   5142     explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
   5143     noexcept(std::is_nothrow_move_constructible<IteratorType>::value
   5144              && std::is_nothrow_default_constructible<string_type>::value)
   5145         : anchor(std::move(it))
   5146         , array_index(array_index_)
   5147     {}
   5148 
   5149     iteration_proxy_value(iteration_proxy_value const&) = default;
   5150     iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
   5151     // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
   5152     iteration_proxy_value(iteration_proxy_value&&)
   5153     noexcept(std::is_nothrow_move_constructible<IteratorType>::value
   5154              && std::is_nothrow_move_constructible<string_type>::value) = default;
   5155     iteration_proxy_value& operator=(iteration_proxy_value&&)
   5156     noexcept(std::is_nothrow_move_assignable<IteratorType>::value
   5157              && std::is_nothrow_move_assignable<string_type>::value) = default;
   5158     ~iteration_proxy_value() = default;
   5159 
   5160     /// dereference operator (needed for range-based for)
   5161     const iteration_proxy_value& operator*() const
   5162     {
   5163         return *this;
   5164     }
   5165 
   5166     /// increment operator (needed for range-based for)
   5167     iteration_proxy_value& operator++()
   5168     {
   5169         ++anchor;
   5170         ++array_index;
   5171 
   5172         return *this;
   5173     }
   5174 
   5175     iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
   5176     {
   5177         auto tmp = iteration_proxy_value(anchor, array_index);
   5178         ++anchor;
   5179         ++array_index;
   5180         return tmp;
   5181     }
   5182 
   5183     /// equality operator (needed for InputIterator)
   5184     bool operator==(const iteration_proxy_value& o) const
   5185     {
   5186         return anchor == o.anchor;
   5187     }
   5188 
   5189     /// inequality operator (needed for range-based for)
   5190     bool operator!=(const iteration_proxy_value& o) const
   5191     {
   5192         return anchor != o.anchor;
   5193     }
   5194 
   5195     /// return key of the iterator
   5196     const string_type& key() const
   5197     {
   5198         JSON_ASSERT(anchor.m_object != nullptr);
   5199 
   5200         switch (anchor.m_object->type())
   5201         {
   5202             // use integer array index as key
   5203             case value_t::array:
   5204             {
   5205                 if (array_index != array_index_last)
   5206                 {
   5207                     int_to_string( array_index_str, array_index );
   5208                     array_index_last = array_index;
   5209                 }
   5210                 return array_index_str;
   5211             }
   5212 
   5213             // use key from the object
   5214             case value_t::object:
   5215                 return anchor.key();
   5216 
   5217             // use an empty key for all primitive types
   5218             case value_t::null:
   5219             case value_t::string:
   5220             case value_t::boolean:
   5221             case value_t::number_integer:
   5222             case value_t::number_unsigned:
   5223             case value_t::number_float:
   5224             case value_t::binary:
   5225             case value_t::discarded:
   5226             default:
   5227                 return empty_str;
   5228         }
   5229     }
   5230 
   5231     /// return value of the iterator
   5232     typename IteratorType::reference value() const
   5233     {
   5234         return anchor.value();
   5235     }
   5236 };
   5237 
   5238 /// proxy class for the items() function
   5239 template<typename IteratorType> class iteration_proxy
   5240 {
   5241   private:
   5242     /// the container to iterate
   5243     typename IteratorType::pointer container = nullptr;
   5244 
   5245   public:
   5246     explicit iteration_proxy() = default;
   5247 
   5248     /// construct iteration proxy from a container
   5249     explicit iteration_proxy(typename IteratorType::reference cont) noexcept
   5250         : container(&cont) {}
   5251 
   5252     iteration_proxy(iteration_proxy const&) = default;
   5253     iteration_proxy& operator=(iteration_proxy const&) = default;
   5254     iteration_proxy(iteration_proxy&&) noexcept = default;
   5255     iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
   5256     ~iteration_proxy() = default;
   5257 
   5258     /// return iterator begin (needed for range-based for)
   5259     iteration_proxy_value<IteratorType> begin() const noexcept
   5260     {
   5261         return iteration_proxy_value<IteratorType>(container->begin());
   5262     }
   5263 
   5264     /// return iterator end (needed for range-based for)
   5265     iteration_proxy_value<IteratorType> end() const noexcept
   5266     {
   5267         return iteration_proxy_value<IteratorType>(container->end());
   5268     }
   5269 };
   5270 
   5271 // Structured Bindings Support
   5272 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
   5273 // And see https://github.com/nlohmann/json/pull/1391
   5274 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
   5275 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
   5276 {
   5277     return i.key();
   5278 }
   5279 // Structured Bindings Support
   5280 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
   5281 // And see https://github.com/nlohmann/json/pull/1391
   5282 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
   5283 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
   5284 {
   5285     return i.value();
   5286 }
   5287 
   5288 }  // namespace detail
   5289 NLOHMANN_JSON_NAMESPACE_END
   5290 
   5291 // The Addition to the STD Namespace is required to add
   5292 // Structured Bindings Support to the iteration_proxy_value class
   5293 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
   5294 // And see https://github.com/nlohmann/json/pull/1391
   5295 namespace std
   5296 {
   5297 
   5298 #if defined(__clang__)
   5299     // Fix: https://github.com/nlohmann/json/issues/1401
   5300     #pragma clang diagnostic push
   5301     #pragma clang diagnostic ignored "-Wmismatched-tags"
   5302 #endif
   5303 template<typename IteratorType>
   5304 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
   5305             : public std::integral_constant<std::size_t, 2> {};
   5306 
   5307 template<std::size_t N, typename IteratorType>
   5308 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
   5309 {
   5310   public:
   5311     using type = decltype(
   5312                      get<N>(std::declval <
   5313                             ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
   5314 };
   5315 #if defined(__clang__)
   5316     #pragma clang diagnostic pop
   5317 #endif
   5318 
   5319 }  // namespace std
   5320 
   5321 #if JSON_HAS_RANGES
   5322     template <typename IteratorType>
   5323     inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
   5324 #endif
   5325 
   5326 // #include <nlohmann/detail/macro_scope.hpp>
   5327 
   5328 // #include <nlohmann/detail/meta/cpp_future.hpp>
   5329 
   5330 // #include <nlohmann/detail/meta/std_fs.hpp>
   5331 
   5332 // #include <nlohmann/detail/meta/type_traits.hpp>
   5333 
   5334 // #include <nlohmann/detail/value_t.hpp>
   5335 
   5336 
   5337 NLOHMANN_JSON_NAMESPACE_BEGIN
   5338 namespace detail
   5339 {
   5340 
   5341 //////////////////
   5342 // constructors //
   5343 //////////////////
   5344 
   5345 /*
   5346  * Note all external_constructor<>::construct functions need to call
   5347  * j.m_value.destroy(j.m_type) to avoid a memory leak in case j contains an
   5348  * allocated value (e.g., a string). See bug issue
   5349  * https://github.com/nlohmann/json/issues/2865 for more information.
   5350  */
   5351 
   5352 template<value_t> struct external_constructor;
   5353 
   5354 template<>
   5355 struct external_constructor<value_t::boolean>
   5356 {
   5357     template<typename BasicJsonType>
   5358     static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
   5359     {
   5360         j.m_value.destroy(j.m_type);
   5361         j.m_type = value_t::boolean;
   5362         j.m_value = b;
   5363         j.assert_invariant();
   5364     }
   5365 };
   5366 
   5367 template<>
   5368 struct external_constructor<value_t::string>
   5369 {
   5370     template<typename BasicJsonType>
   5371     static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
   5372     {
   5373         j.m_value.destroy(j.m_type);
   5374         j.m_type = value_t::string;
   5375         j.m_value = s;
   5376         j.assert_invariant();
   5377     }
   5378 
   5379     template<typename BasicJsonType>
   5380     static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
   5381     {
   5382         j.m_value.destroy(j.m_type);
   5383         j.m_type = value_t::string;
   5384         j.m_value = std::move(s);
   5385         j.assert_invariant();
   5386     }
   5387 
   5388     template < typename BasicJsonType, typename CompatibleStringType,
   5389                enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
   5390                              int > = 0 >
   5391     static void construct(BasicJsonType& j, const CompatibleStringType& str)
   5392     {
   5393         j.m_value.destroy(j.m_type);
   5394         j.m_type = value_t::string;
   5395         j.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
   5396         j.assert_invariant();
   5397     }
   5398 };
   5399 
   5400 template<>
   5401 struct external_constructor<value_t::binary>
   5402 {
   5403     template<typename BasicJsonType>
   5404     static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
   5405     {
   5406         j.m_value.destroy(j.m_type);
   5407         j.m_type = value_t::binary;
   5408         j.m_value = typename BasicJsonType::binary_t(b);
   5409         j.assert_invariant();
   5410     }
   5411 
   5412     template<typename BasicJsonType>
   5413     static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
   5414     {
   5415         j.m_value.destroy(j.m_type);
   5416         j.m_type = value_t::binary;
   5417         j.m_value = typename BasicJsonType::binary_t(std::move(b));
   5418         j.assert_invariant();
   5419     }
   5420 };
   5421 
   5422 template<>
   5423 struct external_constructor<value_t::number_float>
   5424 {
   5425     template<typename BasicJsonType>
   5426     static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
   5427     {
   5428         j.m_value.destroy(j.m_type);
   5429         j.m_type = value_t::number_float;
   5430         j.m_value = val;
   5431         j.assert_invariant();
   5432     }
   5433 };
   5434 
   5435 template<>
   5436 struct external_constructor<value_t::number_unsigned>
   5437 {
   5438     template<typename BasicJsonType>
   5439     static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
   5440     {
   5441         j.m_value.destroy(j.m_type);
   5442         j.m_type = value_t::number_unsigned;
   5443         j.m_value = val;
   5444         j.assert_invariant();
   5445     }
   5446 };
   5447 
   5448 template<>
   5449 struct external_constructor<value_t::number_integer>
   5450 {
   5451     template<typename BasicJsonType>
   5452     static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
   5453     {
   5454         j.m_value.destroy(j.m_type);
   5455         j.m_type = value_t::number_integer;
   5456         j.m_value = val;
   5457         j.assert_invariant();
   5458     }
   5459 };
   5460 
   5461 template<>
   5462 struct external_constructor<value_t::array>
   5463 {
   5464     template<typename BasicJsonType>
   5465     static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
   5466     {
   5467         j.m_value.destroy(j.m_type);
   5468         j.m_type = value_t::array;
   5469         j.m_value = arr;
   5470         j.set_parents();
   5471         j.assert_invariant();
   5472     }
   5473 
   5474     template<typename BasicJsonType>
   5475     static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
   5476     {
   5477         j.m_value.destroy(j.m_type);
   5478         j.m_type = value_t::array;
   5479         j.m_value = std::move(arr);
   5480         j.set_parents();
   5481         j.assert_invariant();
   5482     }
   5483 
   5484     template < typename BasicJsonType, typename CompatibleArrayType,
   5485                enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
   5486                              int > = 0 >
   5487     static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
   5488     {
   5489         using std::begin;
   5490         using std::end;
   5491 
   5492         j.m_value.destroy(j.m_type);
   5493         j.m_type = value_t::array;
   5494         j.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
   5495         j.set_parents();
   5496         j.assert_invariant();
   5497     }
   5498 
   5499     template<typename BasicJsonType>
   5500     static void construct(BasicJsonType& j, const std::vector<bool>& arr)
   5501     {
   5502         j.m_value.destroy(j.m_type);
   5503         j.m_type = value_t::array;
   5504         j.m_value = value_t::array;
   5505         j.m_value.array->reserve(arr.size());
   5506         for (const bool x : arr)
   5507         {
   5508             j.m_value.array->push_back(x);
   5509             j.set_parent(j.m_value.array->back());
   5510         }
   5511         j.assert_invariant();
   5512     }
   5513 
   5514     template<typename BasicJsonType, typename T,
   5515              enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
   5516     static void construct(BasicJsonType& j, const std::valarray<T>& arr)
   5517     {
   5518         j.m_value.destroy(j.m_type);
   5519         j.m_type = value_t::array;
   5520         j.m_value = value_t::array;
   5521         j.m_value.array->resize(arr.size());
   5522         if (arr.size() > 0)
   5523         {
   5524             std::copy(std::begin(arr), std::end(arr), j.m_value.array->begin());
   5525         }
   5526         j.set_parents();
   5527         j.assert_invariant();
   5528     }
   5529 };
   5530 
   5531 template<>
   5532 struct external_constructor<value_t::object>
   5533 {
   5534     template<typename BasicJsonType>
   5535     static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
   5536     {
   5537         j.m_value.destroy(j.m_type);
   5538         j.m_type = value_t::object;
   5539         j.m_value = obj;
   5540         j.set_parents();
   5541         j.assert_invariant();
   5542     }
   5543 
   5544     template<typename BasicJsonType>
   5545     static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
   5546     {
   5547         j.m_value.destroy(j.m_type);
   5548         j.m_type = value_t::object;
   5549         j.m_value = std::move(obj);
   5550         j.set_parents();
   5551         j.assert_invariant();
   5552     }
   5553 
   5554     template < typename BasicJsonType, typename CompatibleObjectType,
   5555                enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
   5556     static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
   5557     {
   5558         using std::begin;
   5559         using std::end;
   5560 
   5561         j.m_value.destroy(j.m_type);
   5562         j.m_type = value_t::object;
   5563         j.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
   5564         j.set_parents();
   5565         j.assert_invariant();
   5566     }
   5567 };
   5568 
   5569 /////////////
   5570 // to_json //
   5571 /////////////
   5572 
   5573 template<typename BasicJsonType, typename T,
   5574          enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
   5575 inline void to_json(BasicJsonType& j, T b) noexcept
   5576 {
   5577     external_constructor<value_t::boolean>::construct(j, b);
   5578 }
   5579 
   5580 template < typename BasicJsonType, typename BoolRef,
   5581            enable_if_t <
   5582                ((std::is_same<std::vector<bool>::reference, BoolRef>::value
   5583                  && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
   5584                 || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
   5585                     && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
   5586                                       typename BasicJsonType::boolean_t >::value))
   5587                && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
   5588 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
   5589 {
   5590     external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
   5591 }
   5592 
   5593 template<typename BasicJsonType, typename CompatibleString,
   5594          enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
   5595 inline void to_json(BasicJsonType& j, const CompatibleString& s)
   5596 {
   5597     external_constructor<value_t::string>::construct(j, s);
   5598 }
   5599 
   5600 template<typename BasicJsonType>
   5601 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
   5602 {
   5603     external_constructor<value_t::string>::construct(j, std::move(s));
   5604 }
   5605 
   5606 template<typename BasicJsonType, typename FloatType,
   5607          enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
   5608 inline void to_json(BasicJsonType& j, FloatType val) noexcept
   5609 {
   5610     external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
   5611 }
   5612 
   5613 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
   5614          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
   5615 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
   5616 {
   5617     external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
   5618 }
   5619 
   5620 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
   5621          enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
   5622 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
   5623 {
   5624     external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
   5625 }
   5626 
   5627 #if !JSON_DISABLE_ENUM_SERIALIZATION
   5628 template<typename BasicJsonType, typename EnumType,
   5629          enable_if_t<std::is_enum<EnumType>::value, int> = 0>
   5630 inline void to_json(BasicJsonType& j, EnumType e) noexcept
   5631 {
   5632     using underlying_type = typename std::underlying_type<EnumType>::type;
   5633     external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
   5634 }
   5635 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
   5636 
   5637 template<typename BasicJsonType>
   5638 inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
   5639 {
   5640     external_constructor<value_t::array>::construct(j, e);
   5641 }
   5642 
   5643 template < typename BasicJsonType, typename CompatibleArrayType,
   5644            enable_if_t < is_compatible_array_type<BasicJsonType,
   5645                          CompatibleArrayType>::value&&
   5646                          !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
   5647                          !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
   5648                          !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
   5649                          !is_basic_json<CompatibleArrayType>::value,
   5650                          int > = 0 >
   5651 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
   5652 {
   5653     external_constructor<value_t::array>::construct(j, arr);
   5654 }
   5655 
   5656 template<typename BasicJsonType>
   5657 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
   5658 {
   5659     external_constructor<value_t::binary>::construct(j, bin);
   5660 }
   5661 
   5662 template<typename BasicJsonType, typename T,
   5663          enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
   5664 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
   5665 {
   5666     external_constructor<value_t::array>::construct(j, std::move(arr));
   5667 }
   5668 
   5669 template<typename BasicJsonType>
   5670 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
   5671 {
   5672     external_constructor<value_t::array>::construct(j, std::move(arr));
   5673 }
   5674 
   5675 template < typename BasicJsonType, typename CompatibleObjectType,
   5676            enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
   5677 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
   5678 {
   5679     external_constructor<value_t::object>::construct(j, obj);
   5680 }
   5681 
   5682 template<typename BasicJsonType>
   5683 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
   5684 {
   5685     external_constructor<value_t::object>::construct(j, std::move(obj));
   5686 }
   5687 
   5688 template <
   5689     typename BasicJsonType, typename T, std::size_t N,
   5690     enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
   5691                   const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   5692                   int > = 0 >
   5693 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   5694 {
   5695     external_constructor<value_t::array>::construct(j, arr);
   5696 }
   5697 
   5698 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
   5699 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
   5700 {
   5701     j = { p.first, p.second };
   5702 }
   5703 
   5704 // for https://github.com/nlohmann/json/pull/1134
   5705 template<typename BasicJsonType, typename T,
   5706          enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
   5707 inline void to_json(BasicJsonType& j, const T& b)
   5708 {
   5709     j = { {b.key(), b.value()} };
   5710 }
   5711 
   5712 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
   5713 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
   5714 {
   5715     j = { std::get<Idx>(t)... };
   5716 }
   5717 
   5718 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
   5719 inline void to_json(BasicJsonType& j, const T& t)
   5720 {
   5721     to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
   5722 }
   5723 
   5724 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
   5725 template<typename BasicJsonType>
   5726 inline void to_json(BasicJsonType& j, const std_fs::path& p)
   5727 {
   5728     j = p.string();
   5729 }
   5730 #endif
   5731 
   5732 struct to_json_fn
   5733 {
   5734     template<typename BasicJsonType, typename T>
   5735     auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
   5736     -> decltype(to_json(j, std::forward<T>(val)), void())
   5737     {
   5738         return to_json(j, std::forward<T>(val));
   5739     }
   5740 };
   5741 }  // namespace detail
   5742 
   5743 #ifndef JSON_HAS_CPP_17
   5744 /// namespace to hold default `to_json` function
   5745 /// to see why this is required:
   5746 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
   5747 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
   5748 {
   5749 #endif
   5750 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
   5751     detail::static_const<detail::to_json_fn>::value;
   5752 #ifndef JSON_HAS_CPP_17
   5753 }  // namespace
   5754 #endif
   5755 
   5756 NLOHMANN_JSON_NAMESPACE_END
   5757 
   5758 // #include <nlohmann/detail/meta/identity_tag.hpp>
   5759 
   5760 
   5761 NLOHMANN_JSON_NAMESPACE_BEGIN
   5762 
   5763 /// @sa https://json.nlohmann.me/api/adl_serializer/
   5764 template<typename ValueType, typename>
   5765 struct adl_serializer
   5766 {
   5767     /// @brief convert a JSON value to any value type
   5768     /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
   5769     template<typename BasicJsonType, typename TargetType = ValueType>
   5770     static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
   5771         noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
   5772     -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
   5773     {
   5774         ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
   5775     }
   5776 
   5777     /// @brief convert a JSON value to any value type
   5778     /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
   5779     template<typename BasicJsonType, typename TargetType = ValueType>
   5780     static auto from_json(BasicJsonType && j) noexcept(
   5781     noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
   5782     -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
   5783     {
   5784         return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
   5785     }
   5786 
   5787     /// @brief convert any value type to a JSON value
   5788     /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
   5789     template<typename BasicJsonType, typename TargetType = ValueType>
   5790     static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
   5791         noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
   5792     -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
   5793     {
   5794         ::nlohmann::to_json(j, std::forward<TargetType>(val));
   5795     }
   5796 };
   5797 
   5798 NLOHMANN_JSON_NAMESPACE_END
   5799 
   5800 // #include <nlohmann/byte_container_with_subtype.hpp>
   5801 //     __ _____ _____ _____
   5802 //  __|  |   __|     |   | |  JSON for Modern C++
   5803 // |  |  |__   |  |  | | | |  version 3.11.2
   5804 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5805 //
   5806 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   5807 // SPDX-License-Identifier: MIT
   5808 
   5809 
   5810 
   5811 #include <cstdint> // uint8_t, uint64_t
   5812 #include <tuple> // tie
   5813 #include <utility> // move
   5814 
   5815 // #include <nlohmann/detail/abi_macros.hpp>
   5816 
   5817 
   5818 NLOHMANN_JSON_NAMESPACE_BEGIN
   5819 
   5820 /// @brief an internal type for a backed binary type
   5821 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
   5822 template<typename BinaryType>
   5823 class byte_container_with_subtype : public BinaryType
   5824 {
   5825   public:
   5826     using container_type = BinaryType;
   5827     using subtype_type = std::uint64_t;
   5828 
   5829     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5830     byte_container_with_subtype() noexcept(noexcept(container_type()))
   5831         : container_type()
   5832     {}
   5833 
   5834     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5835     byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
   5836         : container_type(b)
   5837     {}
   5838 
   5839     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5840     byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
   5841         : container_type(std::move(b))
   5842     {}
   5843 
   5844     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5845     byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
   5846         : container_type(b)
   5847         , m_subtype(subtype_)
   5848         , m_has_subtype(true)
   5849     {}
   5850 
   5851     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5852     byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
   5853         : container_type(std::move(b))
   5854         , m_subtype(subtype_)
   5855         , m_has_subtype(true)
   5856     {}
   5857 
   5858     bool operator==(const byte_container_with_subtype& rhs) const
   5859     {
   5860         return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
   5861                std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
   5862     }
   5863 
   5864     bool operator!=(const byte_container_with_subtype& rhs) const
   5865     {
   5866         return !(rhs == *this);
   5867     }
   5868 
   5869     /// @brief sets the binary subtype
   5870     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
   5871     void set_subtype(subtype_type subtype_) noexcept
   5872     {
   5873         m_subtype = subtype_;
   5874         m_has_subtype = true;
   5875     }
   5876 
   5877     /// @brief return the binary subtype
   5878     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
   5879     constexpr subtype_type subtype() const noexcept
   5880     {
   5881         return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
   5882     }
   5883 
   5884     /// @brief return whether the value has a subtype
   5885     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
   5886     constexpr bool has_subtype() const noexcept
   5887     {
   5888         return m_has_subtype;
   5889     }
   5890 
   5891     /// @brief clears the binary subtype
   5892     /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
   5893     void clear_subtype() noexcept
   5894     {
   5895         m_subtype = 0;
   5896         m_has_subtype = false;
   5897     }
   5898 
   5899   private:
   5900     subtype_type m_subtype = 0;
   5901     bool m_has_subtype = false;
   5902 };
   5903 
   5904 NLOHMANN_JSON_NAMESPACE_END
   5905 
   5906 // #include <nlohmann/detail/conversions/from_json.hpp>
   5907 
   5908 // #include <nlohmann/detail/conversions/to_json.hpp>
   5909 
   5910 // #include <nlohmann/detail/exceptions.hpp>
   5911 
   5912 // #include <nlohmann/detail/hash.hpp>
   5913 //     __ _____ _____ _____
   5914 //  __|  |   __|     |   | |  JSON for Modern C++
   5915 // |  |  |__   |  |  | | | |  version 3.11.2
   5916 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5917 //
   5918 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   5919 // SPDX-License-Identifier: MIT
   5920 
   5921 
   5922 
   5923 #include <cstdint> // uint8_t
   5924 #include <cstddef> // size_t
   5925 #include <functional> // hash
   5926 
   5927 // #include <nlohmann/detail/abi_macros.hpp>
   5928 
   5929 // #include <nlohmann/detail/value_t.hpp>
   5930 
   5931 
   5932 NLOHMANN_JSON_NAMESPACE_BEGIN
   5933 namespace detail
   5934 {
   5935 
   5936 // boost::hash_combine
   5937 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
   5938 {
   5939     seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
   5940     return seed;
   5941 }
   5942 
   5943 /*!
   5944 @brief hash a JSON value
   5945 
   5946 The hash function tries to rely on std::hash where possible. Furthermore, the
   5947 type of the JSON value is taken into account to have different hash values for
   5948 null, 0, 0U, and false, etc.
   5949 
   5950 @tparam BasicJsonType basic_json specialization
   5951 @param j JSON value to hash
   5952 @return hash value of j
   5953 */
   5954 template<typename BasicJsonType>
   5955 std::size_t hash(const BasicJsonType& j)
   5956 {
   5957     using string_t = typename BasicJsonType::string_t;
   5958     using number_integer_t = typename BasicJsonType::number_integer_t;
   5959     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   5960     using number_float_t = typename BasicJsonType::number_float_t;
   5961 
   5962     const auto type = static_cast<std::size_t>(j.type());
   5963     switch (j.type())
   5964     {
   5965         case BasicJsonType::value_t::null:
   5966         case BasicJsonType::value_t::discarded:
   5967         {
   5968             return combine(type, 0);
   5969         }
   5970 
   5971         case BasicJsonType::value_t::object:
   5972         {
   5973             auto seed = combine(type, j.size());
   5974             for (const auto& element : j.items())
   5975             {
   5976                 const auto h = std::hash<string_t> {}(element.key());
   5977                 seed = combine(seed, h);
   5978                 seed = combine(seed, hash(element.value()));
   5979             }
   5980             return seed;
   5981         }
   5982 
   5983         case BasicJsonType::value_t::array:
   5984         {
   5985             auto seed = combine(type, j.size());
   5986             for (const auto& element : j)
   5987             {
   5988                 seed = combine(seed, hash(element));
   5989             }
   5990             return seed;
   5991         }
   5992 
   5993         case BasicJsonType::value_t::string:
   5994         {
   5995             const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
   5996             return combine(type, h);
   5997         }
   5998 
   5999         case BasicJsonType::value_t::boolean:
   6000         {
   6001             const auto h = std::hash<bool> {}(j.template get<bool>());
   6002             return combine(type, h);
   6003         }
   6004 
   6005         case BasicJsonType::value_t::number_integer:
   6006         {
   6007             const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
   6008             return combine(type, h);
   6009         }
   6010 
   6011         case BasicJsonType::value_t::number_unsigned:
   6012         {
   6013             const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
   6014             return combine(type, h);
   6015         }
   6016 
   6017         case BasicJsonType::value_t::number_float:
   6018         {
   6019             const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
   6020             return combine(type, h);
   6021         }
   6022 
   6023         case BasicJsonType::value_t::binary:
   6024         {
   6025             auto seed = combine(type, j.get_binary().size());
   6026             const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
   6027             seed = combine(seed, h);
   6028             seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
   6029             for (const auto byte : j.get_binary())
   6030             {
   6031                 seed = combine(seed, std::hash<std::uint8_t> {}(byte));
   6032             }
   6033             return seed;
   6034         }
   6035 
   6036         default:                   // LCOV_EXCL_LINE
   6037             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   6038             return 0;              // LCOV_EXCL_LINE
   6039     }
   6040 }
   6041 
   6042 }  // namespace detail
   6043 NLOHMANN_JSON_NAMESPACE_END
   6044 
   6045 // #include <nlohmann/detail/input/binary_reader.hpp>
   6046 //     __ _____ _____ _____
   6047 //  __|  |   __|     |   | |  JSON for Modern C++
   6048 // |  |  |__   |  |  | | | |  version 3.11.2
   6049 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6050 //
   6051 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   6052 // SPDX-License-Identifier: MIT
   6053 
   6054 
   6055 
   6056 #include <algorithm> // generate_n
   6057 #include <array> // array
   6058 #include <cmath> // ldexp
   6059 #include <cstddef> // size_t
   6060 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
   6061 #include <cstdio> // snprintf
   6062 #include <cstring> // memcpy
   6063 #include <iterator> // back_inserter
   6064 #include <limits> // numeric_limits
   6065 #include <string> // char_traits, string
   6066 #include <utility> // make_pair, move
   6067 #include <vector> // vector
   6068 
   6069 // #include <nlohmann/detail/exceptions.hpp>
   6070 
   6071 // #include <nlohmann/detail/input/input_adapters.hpp>
   6072 //     __ _____ _____ _____
   6073 //  __|  |   __|     |   | |  JSON for Modern C++
   6074 // |  |  |__   |  |  | | | |  version 3.11.2
   6075 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6076 //
   6077 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   6078 // SPDX-License-Identifier: MIT
   6079 
   6080 
   6081 
   6082 #include <array> // array
   6083 #include <cstddef> // size_t
   6084 #include <cstring> // strlen
   6085 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
   6086 #include <memory> // shared_ptr, make_shared, addressof
   6087 #include <numeric> // accumulate
   6088 #include <string> // string, char_traits
   6089 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
   6090 #include <utility> // pair, declval
   6091 
   6092 #ifndef JSON_NO_IO
   6093     #include <cstdio>   // FILE *
   6094     #include <istream>  // istream
   6095 #endif                  // JSON_NO_IO
   6096 
   6097 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
   6098 
   6099 // #include <nlohmann/detail/macro_scope.hpp>
   6100 
   6101 
   6102 NLOHMANN_JSON_NAMESPACE_BEGIN
   6103 namespace detail
   6104 {
   6105 
   6106 /// the supported input formats
   6107 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
   6108 
   6109 ////////////////////
   6110 // input adapters //
   6111 ////////////////////
   6112 
   6113 #ifndef JSON_NO_IO
   6114 /*!
   6115 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
   6116  buffer. This adapter is a very low level adapter.
   6117 */
   6118 class file_input_adapter
   6119 {
   6120   public:
   6121     using char_type = char;
   6122 
   6123     JSON_HEDLEY_NON_NULL(2)
   6124     explicit file_input_adapter(std::FILE* f) noexcept
   6125         : m_file(f)
   6126     {
   6127         JSON_ASSERT(m_file != nullptr);
   6128     }
   6129 
   6130     // make class move-only
   6131     file_input_adapter(const file_input_adapter&) = delete;
   6132     file_input_adapter(file_input_adapter&&) noexcept = default;
   6133     file_input_adapter& operator=(const file_input_adapter&) = delete;
   6134     file_input_adapter& operator=(file_input_adapter&&) = delete;
   6135     ~file_input_adapter() = default;
   6136 
   6137     std::char_traits<char>::int_type get_character() noexcept
   6138     {
   6139         return std::fgetc(m_file);
   6140     }
   6141 
   6142   private:
   6143     /// the file pointer to read from
   6144     std::FILE* m_file;
   6145 };
   6146 
   6147 
   6148 /*!
   6149 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
   6150 beginning of input. Does not support changing the underlying std::streambuf
   6151 in mid-input. Maintains underlying std::istream and std::streambuf to support
   6152 subsequent use of standard std::istream operations to process any input
   6153 characters following those used in parsing the JSON input.  Clears the
   6154 std::istream flags; any input errors (e.g., EOF) will be detected by the first
   6155 subsequent call for input from the std::istream.
   6156 */
   6157 class input_stream_adapter
   6158 {
   6159   public:
   6160     using char_type = char;
   6161 
   6162     ~input_stream_adapter()
   6163     {
   6164         // clear stream flags; we use underlying streambuf I/O, do not
   6165         // maintain ifstream flags, except eof
   6166         if (is != nullptr)
   6167         {
   6168             is->clear(is->rdstate() & std::ios::eofbit);
   6169         }
   6170     }
   6171 
   6172     explicit input_stream_adapter(std::istream& i)
   6173         : is(&i), sb(i.rdbuf())
   6174     {}
   6175 
   6176     // delete because of pointer members
   6177     input_stream_adapter(const input_stream_adapter&) = delete;
   6178     input_stream_adapter& operator=(input_stream_adapter&) = delete;
   6179     input_stream_adapter& operator=(input_stream_adapter&&) = delete;
   6180 
   6181     input_stream_adapter(input_stream_adapter&& rhs) noexcept
   6182         : is(rhs.is), sb(rhs.sb)
   6183     {
   6184         rhs.is = nullptr;
   6185         rhs.sb = nullptr;
   6186     }
   6187 
   6188     // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
   6189     // ensure that std::char_traits<char>::eof() and the character 0xFF do not
   6190     // end up as the same value, e.g. 0xFFFFFFFF.
   6191     std::char_traits<char>::int_type get_character()
   6192     {
   6193         auto res = sb->sbumpc();
   6194         // set eof manually, as we don't use the istream interface.
   6195         if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
   6196         {
   6197             is->clear(is->rdstate() | std::ios::eofbit);
   6198         }
   6199         return res;
   6200     }
   6201 
   6202   private:
   6203     /// the associated input stream
   6204     std::istream* is = nullptr;
   6205     std::streambuf* sb = nullptr;
   6206 };
   6207 #endif  // JSON_NO_IO
   6208 
   6209 // General-purpose iterator-based adapter. It might not be as fast as
   6210 // theoretically possible for some containers, but it is extremely versatile.
   6211 template<typename IteratorType>
   6212 class iterator_input_adapter
   6213 {
   6214   public:
   6215     using char_type = typename std::iterator_traits<IteratorType>::value_type;
   6216 
   6217     iterator_input_adapter(IteratorType first, IteratorType last)
   6218         : current(std::move(first)), end(std::move(last))
   6219     {}
   6220 
   6221     typename std::char_traits<char_type>::int_type get_character()
   6222     {
   6223         if (JSON_HEDLEY_LIKELY(current != end))
   6224         {
   6225             auto result = std::char_traits<char_type>::to_int_type(*current);
   6226             std::advance(current, 1);
   6227             return result;
   6228         }
   6229 
   6230         return std::char_traits<char_type>::eof();
   6231     }
   6232 
   6233   private:
   6234     IteratorType current;
   6235     IteratorType end;
   6236 
   6237     template<typename BaseInputAdapter, size_t T>
   6238     friend struct wide_string_input_helper;
   6239 
   6240     bool empty() const
   6241     {
   6242         return current == end;
   6243     }
   6244 };
   6245 
   6246 
   6247 template<typename BaseInputAdapter, size_t T>
   6248 struct wide_string_input_helper;
   6249 
   6250 template<typename BaseInputAdapter>
   6251 struct wide_string_input_helper<BaseInputAdapter, 4>
   6252 {
   6253     // UTF-32
   6254     static void fill_buffer(BaseInputAdapter& input,
   6255                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
   6256                             size_t& utf8_bytes_index,
   6257                             size_t& utf8_bytes_filled)
   6258     {
   6259         utf8_bytes_index = 0;
   6260 
   6261         if (JSON_HEDLEY_UNLIKELY(input.empty()))
   6262         {
   6263             utf8_bytes[0] = std::char_traits<char>::eof();
   6264             utf8_bytes_filled = 1;
   6265         }
   6266         else
   6267         {
   6268             // get the current character
   6269             const auto wc = input.get_character();
   6270 
   6271             // UTF-32 to UTF-8 encoding
   6272             if (wc < 0x80)
   6273             {
   6274                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6275                 utf8_bytes_filled = 1;
   6276             }
   6277             else if (wc <= 0x7FF)
   6278             {
   6279                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
   6280                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6281                 utf8_bytes_filled = 2;
   6282             }
   6283             else if (wc <= 0xFFFF)
   6284             {
   6285                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
   6286                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
   6287                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6288                 utf8_bytes_filled = 3;
   6289             }
   6290             else if (wc <= 0x10FFFF)
   6291             {
   6292                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
   6293                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
   6294                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
   6295                 utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6296                 utf8_bytes_filled = 4;
   6297             }
   6298             else
   6299             {
   6300                 // unknown character
   6301                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6302                 utf8_bytes_filled = 1;
   6303             }
   6304         }
   6305     }
   6306 };
   6307 
   6308 template<typename BaseInputAdapter>
   6309 struct wide_string_input_helper<BaseInputAdapter, 2>
   6310 {
   6311     // UTF-16
   6312     static void fill_buffer(BaseInputAdapter& input,
   6313                             std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
   6314                             size_t& utf8_bytes_index,
   6315                             size_t& utf8_bytes_filled)
   6316     {
   6317         utf8_bytes_index = 0;
   6318 
   6319         if (JSON_HEDLEY_UNLIKELY(input.empty()))
   6320         {
   6321             utf8_bytes[0] = std::char_traits<char>::eof();
   6322             utf8_bytes_filled = 1;
   6323         }
   6324         else
   6325         {
   6326             // get the current character
   6327             const auto wc = input.get_character();
   6328 
   6329             // UTF-16 to UTF-8 encoding
   6330             if (wc < 0x80)
   6331             {
   6332                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6333                 utf8_bytes_filled = 1;
   6334             }
   6335             else if (wc <= 0x7FF)
   6336             {
   6337                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
   6338                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6339                 utf8_bytes_filled = 2;
   6340             }
   6341             else if (0xD800 > wc || wc >= 0xE000)
   6342             {
   6343                 utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
   6344                 utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
   6345                 utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6346                 utf8_bytes_filled = 3;
   6347             }
   6348             else
   6349             {
   6350                 if (JSON_HEDLEY_UNLIKELY(!input.empty()))
   6351                 {
   6352                     const auto wc2 = static_cast<unsigned int>(input.get_character());
   6353                     const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
   6354                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
   6355                     utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
   6356                     utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
   6357                     utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
   6358                     utf8_bytes_filled = 4;
   6359                 }
   6360                 else
   6361                 {
   6362                     utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6363                     utf8_bytes_filled = 1;
   6364                 }
   6365             }
   6366         }
   6367     }
   6368 };
   6369 
   6370 // Wraps another input apdater to convert wide character types into individual bytes.
   6371 template<typename BaseInputAdapter, typename WideCharType>
   6372 class wide_string_input_adapter
   6373 {
   6374   public:
   6375     using char_type = char;
   6376 
   6377     wide_string_input_adapter(BaseInputAdapter base)
   6378         : base_adapter(base) {}
   6379 
   6380     typename std::char_traits<char>::int_type get_character() noexcept
   6381     {
   6382         // check if buffer needs to be filled
   6383         if (utf8_bytes_index == utf8_bytes_filled)
   6384         {
   6385             fill_buffer<sizeof(WideCharType)>();
   6386 
   6387             JSON_ASSERT(utf8_bytes_filled > 0);
   6388             JSON_ASSERT(utf8_bytes_index == 0);
   6389         }
   6390 
   6391         // use buffer
   6392         JSON_ASSERT(utf8_bytes_filled > 0);
   6393         JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
   6394         return utf8_bytes[utf8_bytes_index++];
   6395     }
   6396 
   6397   private:
   6398     BaseInputAdapter base_adapter;
   6399 
   6400     template<size_t T>
   6401     void fill_buffer()
   6402     {
   6403         wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
   6404     }
   6405 
   6406     /// a buffer for UTF-8 bytes
   6407     std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
   6408 
   6409     /// index to the utf8_codes array for the next valid byte
   6410     std::size_t utf8_bytes_index = 0;
   6411     /// number of valid bytes in the utf8_codes array
   6412     std::size_t utf8_bytes_filled = 0;
   6413 };
   6414 
   6415 
   6416 template<typename IteratorType, typename Enable = void>
   6417 struct iterator_input_adapter_factory
   6418 {
   6419     using iterator_type = IteratorType;
   6420     using char_type = typename std::iterator_traits<iterator_type>::value_type;
   6421     using adapter_type = iterator_input_adapter<iterator_type>;
   6422 
   6423     static adapter_type create(IteratorType first, IteratorType last)
   6424     {
   6425         return adapter_type(std::move(first), std::move(last));
   6426     }
   6427 };
   6428 
   6429 template<typename T>
   6430 struct is_iterator_of_multibyte
   6431 {
   6432     using value_type = typename std::iterator_traits<T>::value_type;
   6433     enum
   6434     {
   6435         value = sizeof(value_type) > 1
   6436     };
   6437 };
   6438 
   6439 template<typename IteratorType>
   6440 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
   6441 {
   6442     using iterator_type = IteratorType;
   6443     using char_type = typename std::iterator_traits<iterator_type>::value_type;
   6444     using base_adapter_type = iterator_input_adapter<iterator_type>;
   6445     using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
   6446 
   6447     static adapter_type create(IteratorType first, IteratorType last)
   6448     {
   6449         return adapter_type(base_adapter_type(std::move(first), std::move(last)));
   6450     }
   6451 };
   6452 
   6453 // General purpose iterator-based input
   6454 template<typename IteratorType>
   6455 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
   6456 {
   6457     using factory_type = iterator_input_adapter_factory<IteratorType>;
   6458     return factory_type::create(first, last);
   6459 }
   6460 
   6461 // Convenience shorthand from container to iterator
   6462 // Enables ADL on begin(container) and end(container)
   6463 // Encloses the using declarations in namespace for not to leak them to outside scope
   6464 
   6465 namespace container_input_adapter_factory_impl
   6466 {
   6467 
   6468 using std::begin;
   6469 using std::end;
   6470 
   6471 template<typename ContainerType, typename Enable = void>
   6472 struct container_input_adapter_factory {};
   6473 
   6474 template<typename ContainerType>
   6475 struct container_input_adapter_factory< ContainerType,
   6476        void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
   6477        {
   6478            using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
   6479 
   6480            static adapter_type create(const ContainerType& container)
   6481 {
   6482     return input_adapter(begin(container), end(container));
   6483 }
   6484        };
   6485 
   6486 }  // namespace container_input_adapter_factory_impl
   6487 
   6488 template<typename ContainerType>
   6489 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
   6490 {
   6491     return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
   6492 }
   6493 
   6494 #ifndef JSON_NO_IO
   6495 // Special cases with fast paths
   6496 inline file_input_adapter input_adapter(std::FILE* file)
   6497 {
   6498     return file_input_adapter(file);
   6499 }
   6500 
   6501 inline input_stream_adapter input_adapter(std::istream& stream)
   6502 {
   6503     return input_stream_adapter(stream);
   6504 }
   6505 
   6506 inline input_stream_adapter input_adapter(std::istream&& stream)
   6507 {
   6508     return input_stream_adapter(stream);
   6509 }
   6510 #endif  // JSON_NO_IO
   6511 
   6512 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
   6513 
   6514 // Null-delimited strings, and the like.
   6515 template < typename CharT,
   6516            typename std::enable_if <
   6517                std::is_pointer<CharT>::value&&
   6518                !std::is_array<CharT>::value&&
   6519                std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
   6520                sizeof(typename std::remove_pointer<CharT>::type) == 1,
   6521                int >::type = 0 >
   6522 contiguous_bytes_input_adapter input_adapter(CharT b)
   6523 {
   6524     auto length = std::strlen(reinterpret_cast<const char*>(b));
   6525     const auto* ptr = reinterpret_cast<const char*>(b);
   6526     return input_adapter(ptr, ptr + length);
   6527 }
   6528 
   6529 template<typename T, std::size_t N>
   6530 auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   6531 {
   6532     return input_adapter(array, array + N);
   6533 }
   6534 
   6535 // This class only handles inputs of input_buffer_adapter type.
   6536 // It's required so that expressions like {ptr, len} can be implicitly cast
   6537 // to the correct adapter.
   6538 class span_input_adapter
   6539 {
   6540   public:
   6541     template < typename CharT,
   6542                typename std::enable_if <
   6543                    std::is_pointer<CharT>::value&&
   6544                    std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
   6545                    sizeof(typename std::remove_pointer<CharT>::type) == 1,
   6546                    int >::type = 0 >
   6547     span_input_adapter(CharT b, std::size_t l)
   6548         : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
   6549 
   6550     template<class IteratorType,
   6551              typename std::enable_if<
   6552                  std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
   6553                  int>::type = 0>
   6554     span_input_adapter(IteratorType first, IteratorType last)
   6555         : ia(input_adapter(first, last)) {}
   6556 
   6557     contiguous_bytes_input_adapter&& get()
   6558     {
   6559         return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
   6560     }
   6561 
   6562   private:
   6563     contiguous_bytes_input_adapter ia;
   6564 };
   6565 
   6566 }  // namespace detail
   6567 NLOHMANN_JSON_NAMESPACE_END
   6568 
   6569 // #include <nlohmann/detail/input/json_sax.hpp>
   6570 //     __ _____ _____ _____
   6571 //  __|  |   __|     |   | |  JSON for Modern C++
   6572 // |  |  |__   |  |  | | | |  version 3.11.2
   6573 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6574 //
   6575 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   6576 // SPDX-License-Identifier: MIT
   6577 
   6578 
   6579 
   6580 #include <cstddef>
   6581 #include <string> // string
   6582 #include <utility> // move
   6583 #include <vector> // vector
   6584 
   6585 // #include <nlohmann/detail/exceptions.hpp>
   6586 
   6587 // #include <nlohmann/detail/macro_scope.hpp>
   6588 
   6589 // #include <nlohmann/detail/string_concat.hpp>
   6590 
   6591 
   6592 NLOHMANN_JSON_NAMESPACE_BEGIN
   6593 
   6594 /*!
   6595 @brief SAX interface
   6596 
   6597 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
   6598 Each function is called in different situations while the input is parsed. The
   6599 boolean return value informs the parser whether to continue processing the
   6600 input.
   6601 */
   6602 template<typename BasicJsonType>
   6603 struct json_sax
   6604 {
   6605     using number_integer_t = typename BasicJsonType::number_integer_t;
   6606     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   6607     using number_float_t = typename BasicJsonType::number_float_t;
   6608     using string_t = typename BasicJsonType::string_t;
   6609     using binary_t = typename BasicJsonType::binary_t;
   6610 
   6611     /*!
   6612     @brief a null value was read
   6613     @return whether parsing should proceed
   6614     */
   6615     virtual bool null() = 0;
   6616 
   6617     /*!
   6618     @brief a boolean value was read
   6619     @param[in] val  boolean value
   6620     @return whether parsing should proceed
   6621     */
   6622     virtual bool boolean(bool val) = 0;
   6623 
   6624     /*!
   6625     @brief an integer number was read
   6626     @param[in] val  integer value
   6627     @return whether parsing should proceed
   6628     */
   6629     virtual bool number_integer(number_integer_t val) = 0;
   6630 
   6631     /*!
   6632     @brief an unsigned integer number was read
   6633     @param[in] val  unsigned integer value
   6634     @return whether parsing should proceed
   6635     */
   6636     virtual bool number_unsigned(number_unsigned_t val) = 0;
   6637 
   6638     /*!
   6639     @brief a floating-point number was read
   6640     @param[in] val  floating-point value
   6641     @param[in] s    raw token value
   6642     @return whether parsing should proceed
   6643     */
   6644     virtual bool number_float(number_float_t val, const string_t& s) = 0;
   6645 
   6646     /*!
   6647     @brief a string value was read
   6648     @param[in] val  string value
   6649     @return whether parsing should proceed
   6650     @note It is safe to move the passed string value.
   6651     */
   6652     virtual bool string(string_t& val) = 0;
   6653 
   6654     /*!
   6655     @brief a binary value was read
   6656     @param[in] val  binary value
   6657     @return whether parsing should proceed
   6658     @note It is safe to move the passed binary value.
   6659     */
   6660     virtual bool binary(binary_t& val) = 0;
   6661 
   6662     /*!
   6663     @brief the beginning of an object was read
   6664     @param[in] elements  number of object elements or -1 if unknown
   6665     @return whether parsing should proceed
   6666     @note binary formats may report the number of elements
   6667     */
   6668     virtual bool start_object(std::size_t elements) = 0;
   6669 
   6670     /*!
   6671     @brief an object key was read
   6672     @param[in] val  object key
   6673     @return whether parsing should proceed
   6674     @note It is safe to move the passed string.
   6675     */
   6676     virtual bool key(string_t& val) = 0;
   6677 
   6678     /*!
   6679     @brief the end of an object was read
   6680     @return whether parsing should proceed
   6681     */
   6682     virtual bool end_object() = 0;
   6683 
   6684     /*!
   6685     @brief the beginning of an array was read
   6686     @param[in] elements  number of array elements or -1 if unknown
   6687     @return whether parsing should proceed
   6688     @note binary formats may report the number of elements
   6689     */
   6690     virtual bool start_array(std::size_t elements) = 0;
   6691 
   6692     /*!
   6693     @brief the end of an array was read
   6694     @return whether parsing should proceed
   6695     */
   6696     virtual bool end_array() = 0;
   6697 
   6698     /*!
   6699     @brief a parse error occurred
   6700     @param[in] position    the position in the input where the error occurs
   6701     @param[in] last_token  the last read token
   6702     @param[in] ex          an exception object describing the error
   6703     @return whether parsing should proceed (must return false)
   6704     */
   6705     virtual bool parse_error(std::size_t position,
   6706                              const std::string& last_token,
   6707                              const detail::exception& ex) = 0;
   6708 
   6709     json_sax() = default;
   6710     json_sax(const json_sax&) = default;
   6711     json_sax(json_sax&&) noexcept = default;
   6712     json_sax& operator=(const json_sax&) = default;
   6713     json_sax& operator=(json_sax&&) noexcept = default;
   6714     virtual ~json_sax() = default;
   6715 };
   6716 
   6717 
   6718 namespace detail
   6719 {
   6720 /*!
   6721 @brief SAX implementation to create a JSON value from SAX events
   6722 
   6723 This class implements the @ref json_sax interface and processes the SAX events
   6724 to create a JSON value which makes it basically a DOM parser. The structure or
   6725 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
   6726 a pointer to the respective array or object for each recursion depth.
   6727 
   6728 After successful parsing, the value that is passed by reference to the
   6729 constructor contains the parsed value.
   6730 
   6731 @tparam BasicJsonType  the JSON type
   6732 */
   6733 template<typename BasicJsonType>
   6734 class json_sax_dom_parser
   6735 {
   6736   public:
   6737     using number_integer_t = typename BasicJsonType::number_integer_t;
   6738     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   6739     using number_float_t = typename BasicJsonType::number_float_t;
   6740     using string_t = typename BasicJsonType::string_t;
   6741     using binary_t = typename BasicJsonType::binary_t;
   6742 
   6743     /*!
   6744     @param[in,out] r  reference to a JSON value that is manipulated while
   6745                        parsing
   6746     @param[in] allow_exceptions_  whether parse errors yield exceptions
   6747     */
   6748     explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
   6749         : root(r), allow_exceptions(allow_exceptions_)
   6750     {}
   6751 
   6752     // make class move-only
   6753     json_sax_dom_parser(const json_sax_dom_parser&) = delete;
   6754     json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   6755     json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
   6756     json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   6757     ~json_sax_dom_parser() = default;
   6758 
   6759     bool null()
   6760     {
   6761         handle_value(nullptr);
   6762         return true;
   6763     }
   6764 
   6765     bool boolean(bool val)
   6766     {
   6767         handle_value(val);
   6768         return true;
   6769     }
   6770 
   6771     bool number_integer(number_integer_t val)
   6772     {
   6773         handle_value(val);
   6774         return true;
   6775     }
   6776 
   6777     bool number_unsigned(number_unsigned_t val)
   6778     {
   6779         handle_value(val);
   6780         return true;
   6781     }
   6782 
   6783     bool number_float(number_float_t val, const string_t& /*unused*/)
   6784     {
   6785         handle_value(val);
   6786         return true;
   6787     }
   6788 
   6789     bool string(string_t& val)
   6790     {
   6791         handle_value(val);
   6792         return true;
   6793     }
   6794 
   6795     bool binary(binary_t& val)
   6796     {
   6797         handle_value(std::move(val));
   6798         return true;
   6799     }
   6800 
   6801     bool start_object(std::size_t len)
   6802     {
   6803         ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
   6804 
   6805         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   6806         {
   6807             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
   6808         }
   6809 
   6810         return true;
   6811     }
   6812 
   6813     bool key(string_t& val)
   6814     {
   6815         JSON_ASSERT(!ref_stack.empty());
   6816         JSON_ASSERT(ref_stack.back()->is_object());
   6817 
   6818         // add null at given key and store the reference for later
   6819         object_element = &(ref_stack.back()->m_value.object->operator[](val));
   6820         return true;
   6821     }
   6822 
   6823     bool end_object()
   6824     {
   6825         JSON_ASSERT(!ref_stack.empty());
   6826         JSON_ASSERT(ref_stack.back()->is_object());
   6827 
   6828         ref_stack.back()->set_parents();
   6829         ref_stack.pop_back();
   6830         return true;
   6831     }
   6832 
   6833     bool start_array(std::size_t len)
   6834     {
   6835         ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
   6836 
   6837         if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   6838         {
   6839             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
   6840         }
   6841 
   6842         return true;
   6843     }
   6844 
   6845     bool end_array()
   6846     {
   6847         JSON_ASSERT(!ref_stack.empty());
   6848         JSON_ASSERT(ref_stack.back()->is_array());
   6849 
   6850         ref_stack.back()->set_parents();
   6851         ref_stack.pop_back();
   6852         return true;
   6853     }
   6854 
   6855     template<class Exception>
   6856     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
   6857                      const Exception& ex)
   6858     {
   6859         errored = true;
   6860         static_cast<void>(ex);
   6861         if (allow_exceptions)
   6862         {
   6863             JSON_THROW(ex);
   6864         }
   6865         return false;
   6866     }
   6867 
   6868     constexpr bool is_errored() const
   6869     {
   6870         return errored;
   6871     }
   6872 
   6873   private:
   6874     /*!
   6875     @invariant If the ref stack is empty, then the passed value will be the new
   6876                root.
   6877     @invariant If the ref stack contains a value, then it is an array or an
   6878                object to which we can add elements
   6879     */
   6880     template<typename Value>
   6881     JSON_HEDLEY_RETURNS_NON_NULL
   6882     BasicJsonType* handle_value(Value&& v)
   6883     {
   6884         if (ref_stack.empty())
   6885         {
   6886             root = BasicJsonType(std::forward<Value>(v));
   6887             return &root;
   6888         }
   6889 
   6890         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
   6891 
   6892         if (ref_stack.back()->is_array())
   6893         {
   6894             ref_stack.back()->m_value.array->emplace_back(std::forward<Value>(v));
   6895             return &(ref_stack.back()->m_value.array->back());
   6896         }
   6897 
   6898         JSON_ASSERT(ref_stack.back()->is_object());
   6899         JSON_ASSERT(object_element);
   6900         *object_element = BasicJsonType(std::forward<Value>(v));
   6901         return object_element;
   6902     }
   6903 
   6904     /// the parsed JSON value
   6905     BasicJsonType& root;
   6906     /// stack to model hierarchy of values
   6907     std::vector<BasicJsonType*> ref_stack {};
   6908     /// helper to hold the reference for the next object element
   6909     BasicJsonType* object_element = nullptr;
   6910     /// whether a syntax error occurred
   6911     bool errored = false;
   6912     /// whether to throw exceptions in case of errors
   6913     const bool allow_exceptions = true;
   6914 };
   6915 
   6916 template<typename BasicJsonType>
   6917 class json_sax_dom_callback_parser
   6918 {
   6919   public:
   6920     using number_integer_t = typename BasicJsonType::number_integer_t;
   6921     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   6922     using number_float_t = typename BasicJsonType::number_float_t;
   6923     using string_t = typename BasicJsonType::string_t;
   6924     using binary_t = typename BasicJsonType::binary_t;
   6925     using parser_callback_t = typename BasicJsonType::parser_callback_t;
   6926     using parse_event_t = typename BasicJsonType::parse_event_t;
   6927 
   6928     json_sax_dom_callback_parser(BasicJsonType& r,
   6929                                  const parser_callback_t cb,
   6930                                  const bool allow_exceptions_ = true)
   6931         : root(r), callback(cb), allow_exceptions(allow_exceptions_)
   6932     {
   6933         keep_stack.push_back(true);
   6934     }
   6935 
   6936     // make class move-only
   6937     json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
   6938     json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   6939     json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
   6940     json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   6941     ~json_sax_dom_callback_parser() = default;
   6942 
   6943     bool null()
   6944     {
   6945         handle_value(nullptr);
   6946         return true;
   6947     }
   6948 
   6949     bool boolean(bool val)
   6950     {
   6951         handle_value(val);
   6952         return true;
   6953     }
   6954 
   6955     bool number_integer(number_integer_t val)
   6956     {
   6957         handle_value(val);
   6958         return true;
   6959     }
   6960 
   6961     bool number_unsigned(number_unsigned_t val)
   6962     {
   6963         handle_value(val);
   6964         return true;
   6965     }
   6966 
   6967     bool number_float(number_float_t val, const string_t& /*unused*/)
   6968     {
   6969         handle_value(val);
   6970         return true;
   6971     }
   6972 
   6973     bool string(string_t& val)
   6974     {
   6975         handle_value(val);
   6976         return true;
   6977     }
   6978 
   6979     bool binary(binary_t& val)
   6980     {
   6981         handle_value(std::move(val));
   6982         return true;
   6983     }
   6984 
   6985     bool start_object(std::size_t len)
   6986     {
   6987         // check callback for object start
   6988         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
   6989         keep_stack.push_back(keep);
   6990 
   6991         auto val = handle_value(BasicJsonType::value_t::object, true);
   6992         ref_stack.push_back(val.second);
   6993 
   6994         // check object limit
   6995         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   6996         {
   6997             JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
   6998         }
   6999 
   7000         return true;
   7001     }
   7002 
   7003     bool key(string_t& val)
   7004     {
   7005         BasicJsonType k = BasicJsonType(val);
   7006 
   7007         // check callback for key
   7008         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
   7009         key_keep_stack.push_back(keep);
   7010 
   7011         // add discarded value at given key and store the reference for later
   7012         if (keep && ref_stack.back())
   7013         {
   7014             object_element = &(ref_stack.back()->m_value.object->operator[](val) = discarded);
   7015         }
   7016 
   7017         return true;
   7018     }
   7019 
   7020     bool end_object()
   7021     {
   7022         if (ref_stack.back())
   7023         {
   7024             if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
   7025             {
   7026                 // discard object
   7027                 *ref_stack.back() = discarded;
   7028             }
   7029             else
   7030             {
   7031                 ref_stack.back()->set_parents();
   7032             }
   7033         }
   7034 
   7035         JSON_ASSERT(!ref_stack.empty());
   7036         JSON_ASSERT(!keep_stack.empty());
   7037         ref_stack.pop_back();
   7038         keep_stack.pop_back();
   7039 
   7040         if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
   7041         {
   7042             // remove discarded value
   7043             for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
   7044             {
   7045                 if (it->is_discarded())
   7046                 {
   7047                     ref_stack.back()->erase(it);
   7048                     break;
   7049                 }
   7050             }
   7051         }
   7052 
   7053         return true;
   7054     }
   7055 
   7056     bool start_array(std::size_t len)
   7057     {
   7058         const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
   7059         keep_stack.push_back(keep);
   7060 
   7061         auto val = handle_value(BasicJsonType::value_t::array, true);
   7062         ref_stack.push_back(val.second);
   7063 
   7064         // check array limit
   7065         if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   7066         {
   7067             JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
   7068         }
   7069 
   7070         return true;
   7071     }
   7072 
   7073     bool end_array()
   7074     {
   7075         bool keep = true;
   7076 
   7077         if (ref_stack.back())
   7078         {
   7079             keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
   7080             if (keep)
   7081             {
   7082                 ref_stack.back()->set_parents();
   7083             }
   7084             else
   7085             {
   7086                 // discard array
   7087                 *ref_stack.back() = discarded;
   7088             }
   7089         }
   7090 
   7091         JSON_ASSERT(!ref_stack.empty());
   7092         JSON_ASSERT(!keep_stack.empty());
   7093         ref_stack.pop_back();
   7094         keep_stack.pop_back();
   7095 
   7096         // remove discarded value
   7097         if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
   7098         {
   7099             ref_stack.back()->m_value.array->pop_back();
   7100         }
   7101 
   7102         return true;
   7103     }
   7104 
   7105     template<class Exception>
   7106     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
   7107                      const Exception& ex)
   7108     {
   7109         errored = true;
   7110         static_cast<void>(ex);
   7111         if (allow_exceptions)
   7112         {
   7113             JSON_THROW(ex);
   7114         }
   7115         return false;
   7116     }
   7117 
   7118     constexpr bool is_errored() const
   7119     {
   7120         return errored;
   7121     }
   7122 
   7123   private:
   7124     /*!
   7125     @param[in] v  value to add to the JSON value we build during parsing
   7126     @param[in] skip_callback  whether we should skip calling the callback
   7127                function; this is required after start_array() and
   7128                start_object() SAX events, because otherwise we would call the
   7129                callback function with an empty array or object, respectively.
   7130 
   7131     @invariant If the ref stack is empty, then the passed value will be the new
   7132                root.
   7133     @invariant If the ref stack contains a value, then it is an array or an
   7134                object to which we can add elements
   7135 
   7136     @return pair of boolean (whether value should be kept) and pointer (to the
   7137             passed value in the ref_stack hierarchy; nullptr if not kept)
   7138     */
   7139     template<typename Value>
   7140     std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
   7141     {
   7142         JSON_ASSERT(!keep_stack.empty());
   7143 
   7144         // do not handle this value if we know it would be added to a discarded
   7145         // container
   7146         if (!keep_stack.back())
   7147         {
   7148             return {false, nullptr};
   7149         }
   7150 
   7151         // create value
   7152         auto value = BasicJsonType(std::forward<Value>(v));
   7153 
   7154         // check callback
   7155         const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
   7156 
   7157         // do not handle this value if we just learnt it shall be discarded
   7158         if (!keep)
   7159         {
   7160             return {false, nullptr};
   7161         }
   7162 
   7163         if (ref_stack.empty())
   7164         {
   7165             root = std::move(value);
   7166             return {true, &root};
   7167         }
   7168 
   7169         // skip this value if we already decided to skip the parent
   7170         // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
   7171         if (!ref_stack.back())
   7172         {
   7173             return {false, nullptr};
   7174         }
   7175 
   7176         // we now only expect arrays and objects
   7177         JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
   7178 
   7179         // array
   7180         if (ref_stack.back()->is_array())
   7181         {
   7182             ref_stack.back()->m_value.array->emplace_back(std::move(value));
   7183             return {true, &(ref_stack.back()->m_value.array->back())};
   7184         }
   7185 
   7186         // object
   7187         JSON_ASSERT(ref_stack.back()->is_object());
   7188         // check if we should store an element for the current key
   7189         JSON_ASSERT(!key_keep_stack.empty());
   7190         const bool store_element = key_keep_stack.back();
   7191         key_keep_stack.pop_back();
   7192 
   7193         if (!store_element)
   7194         {
   7195             return {false, nullptr};
   7196         }
   7197 
   7198         JSON_ASSERT(object_element);
   7199         *object_element = std::move(value);
   7200         return {true, object_element};
   7201     }
   7202 
   7203     /// the parsed JSON value
   7204     BasicJsonType& root;
   7205     /// stack to model hierarchy of values
   7206     std::vector<BasicJsonType*> ref_stack {};
   7207     /// stack to manage which values to keep
   7208     std::vector<bool> keep_stack {};
   7209     /// stack to manage which object keys to keep
   7210     std::vector<bool> key_keep_stack {};
   7211     /// helper to hold the reference for the next object element
   7212     BasicJsonType* object_element = nullptr;
   7213     /// whether a syntax error occurred
   7214     bool errored = false;
   7215     /// callback function
   7216     const parser_callback_t callback = nullptr;
   7217     /// whether to throw exceptions in case of errors
   7218     const bool allow_exceptions = true;
   7219     /// a discarded value for the callback
   7220     BasicJsonType discarded = BasicJsonType::value_t::discarded;
   7221 };
   7222 
   7223 template<typename BasicJsonType>
   7224 class json_sax_acceptor
   7225 {
   7226   public:
   7227     using number_integer_t = typename BasicJsonType::number_integer_t;
   7228     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   7229     using number_float_t = typename BasicJsonType::number_float_t;
   7230     using string_t = typename BasicJsonType::string_t;
   7231     using binary_t = typename BasicJsonType::binary_t;
   7232 
   7233     bool null()
   7234     {
   7235         return true;
   7236     }
   7237 
   7238     bool boolean(bool /*unused*/)
   7239     {
   7240         return true;
   7241     }
   7242 
   7243     bool number_integer(number_integer_t /*unused*/)
   7244     {
   7245         return true;
   7246     }
   7247 
   7248     bool number_unsigned(number_unsigned_t /*unused*/)
   7249     {
   7250         return true;
   7251     }
   7252 
   7253     bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
   7254     {
   7255         return true;
   7256     }
   7257 
   7258     bool string(string_t& /*unused*/)
   7259     {
   7260         return true;
   7261     }
   7262 
   7263     bool binary(binary_t& /*unused*/)
   7264     {
   7265         return true;
   7266     }
   7267 
   7268     bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
   7269     {
   7270         return true;
   7271     }
   7272 
   7273     bool key(string_t& /*unused*/)
   7274     {
   7275         return true;
   7276     }
   7277 
   7278     bool end_object()
   7279     {
   7280         return true;
   7281     }
   7282 
   7283     bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
   7284     {
   7285         return true;
   7286     }
   7287 
   7288     bool end_array()
   7289     {
   7290         return true;
   7291     }
   7292 
   7293     bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
   7294     {
   7295         return false;
   7296     }
   7297 };
   7298 
   7299 }  // namespace detail
   7300 NLOHMANN_JSON_NAMESPACE_END
   7301 
   7302 // #include <nlohmann/detail/input/lexer.hpp>
   7303 //     __ _____ _____ _____
   7304 //  __|  |   __|     |   | |  JSON for Modern C++
   7305 // |  |  |__   |  |  | | | |  version 3.11.2
   7306 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   7307 //
   7308 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   7309 // SPDX-License-Identifier: MIT
   7310 
   7311 
   7312 
   7313 #include <array> // array
   7314 #include <clocale> // localeconv
   7315 #include <cstddef> // size_t
   7316 #include <cstdio> // snprintf
   7317 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
   7318 #include <initializer_list> // initializer_list
   7319 #include <string> // char_traits, string
   7320 #include <utility> // move
   7321 #include <vector> // vector
   7322 
   7323 // #include <nlohmann/detail/input/input_adapters.hpp>
   7324 
   7325 // #include <nlohmann/detail/input/position_t.hpp>
   7326 
   7327 // #include <nlohmann/detail/macro_scope.hpp>
   7328 
   7329 
   7330 NLOHMANN_JSON_NAMESPACE_BEGIN
   7331 namespace detail
   7332 {
   7333 
   7334 ///////////
   7335 // lexer //
   7336 ///////////
   7337 
   7338 template<typename BasicJsonType>
   7339 class lexer_base
   7340 {
   7341   public:
   7342     /// token types for the parser
   7343     enum class token_type
   7344     {
   7345         uninitialized,    ///< indicating the scanner is uninitialized
   7346         literal_true,     ///< the `true` literal
   7347         literal_false,    ///< the `false` literal
   7348         literal_null,     ///< the `null` literal
   7349         value_string,     ///< a string -- use get_string() for actual value
   7350         value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
   7351         value_integer,    ///< a signed integer -- use get_number_integer() for actual value
   7352         value_float,      ///< an floating point number -- use get_number_float() for actual value
   7353         begin_array,      ///< the character for array begin `[`
   7354         begin_object,     ///< the character for object begin `{`
   7355         end_array,        ///< the character for array end `]`
   7356         end_object,       ///< the character for object end `}`
   7357         name_separator,   ///< the name separator `:`
   7358         value_separator,  ///< the value separator `,`
   7359         parse_error,      ///< indicating a parse error
   7360         end_of_input,     ///< indicating the end of the input buffer
   7361         literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
   7362     };
   7363 
   7364     /// return name of values of type token_type (only used for errors)
   7365     JSON_HEDLEY_RETURNS_NON_NULL
   7366     JSON_HEDLEY_CONST
   7367     static const char* token_type_name(const token_type t) noexcept
   7368     {
   7369         switch (t)
   7370         {
   7371             case token_type::uninitialized:
   7372                 return "<uninitialized>";
   7373             case token_type::literal_true:
   7374                 return "true literal";
   7375             case token_type::literal_false:
   7376                 return "false literal";
   7377             case token_type::literal_null:
   7378                 return "null literal";
   7379             case token_type::value_string:
   7380                 return "string literal";
   7381             case token_type::value_unsigned:
   7382             case token_type::value_integer:
   7383             case token_type::value_float:
   7384                 return "number literal";
   7385             case token_type::begin_array:
   7386                 return "'['";
   7387             case token_type::begin_object:
   7388                 return "'{'";
   7389             case token_type::end_array:
   7390                 return "']'";
   7391             case token_type::end_object:
   7392                 return "'}'";
   7393             case token_type::name_separator:
   7394                 return "':'";
   7395             case token_type::value_separator:
   7396                 return "','";
   7397             case token_type::parse_error:
   7398                 return "<parse error>";
   7399             case token_type::end_of_input:
   7400                 return "end of input";
   7401             case token_type::literal_or_value:
   7402                 return "'[', '{', or a literal";
   7403             // LCOV_EXCL_START
   7404             default: // catch non-enum values
   7405                 return "unknown token";
   7406                 // LCOV_EXCL_STOP
   7407         }
   7408     }
   7409 };
   7410 /*!
   7411 @brief lexical analysis
   7412 
   7413 This class organizes the lexical analysis during JSON deserialization.
   7414 */
   7415 template<typename BasicJsonType, typename InputAdapterType>
   7416 class lexer : public lexer_base<BasicJsonType>
   7417 {
   7418     using number_integer_t = typename BasicJsonType::number_integer_t;
   7419     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   7420     using number_float_t = typename BasicJsonType::number_float_t;
   7421     using string_t = typename BasicJsonType::string_t;
   7422     using char_type = typename InputAdapterType::char_type;
   7423     using char_int_type = typename std::char_traits<char_type>::int_type;
   7424 
   7425   public:
   7426     using token_type = typename lexer_base<BasicJsonType>::token_type;
   7427 
   7428     explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
   7429         : ia(std::move(adapter))
   7430         , ignore_comments(ignore_comments_)
   7431         , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
   7432     {}
   7433 
   7434     // delete because of pointer members
   7435     lexer(const lexer&) = delete;
   7436     lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   7437     lexer& operator=(lexer&) = delete;
   7438     lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   7439     ~lexer() = default;
   7440 
   7441   private:
   7442     /////////////////////
   7443     // locales
   7444     /////////////////////
   7445 
   7446     /// return the locale-dependent decimal point
   7447     JSON_HEDLEY_PURE
   7448     static char get_decimal_point() noexcept
   7449     {
   7450         const auto* loc = localeconv();
   7451         JSON_ASSERT(loc != nullptr);
   7452         return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
   7453     }
   7454 
   7455     /////////////////////
   7456     // scan functions
   7457     /////////////////////
   7458 
   7459     /*!
   7460     @brief get codepoint from 4 hex characters following `\u`
   7461 
   7462     For input "\u c1 c2 c3 c4" the codepoint is:
   7463       (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
   7464     = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
   7465 
   7466     Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
   7467     must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
   7468     conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
   7469     between the ASCII value of the character and the desired integer value.
   7470 
   7471     @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
   7472             non-hex character)
   7473     */
   7474     int get_codepoint()
   7475     {
   7476         // this function only makes sense after reading `\u`
   7477         JSON_ASSERT(current == 'u');
   7478         int codepoint = 0;
   7479 
   7480         const auto factors = { 12u, 8u, 4u, 0u };
   7481         for (const auto factor : factors)
   7482         {
   7483             get();
   7484 
   7485             if (current >= '0' && current <= '9')
   7486             {
   7487                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
   7488             }
   7489             else if (current >= 'A' && current <= 'F')
   7490             {
   7491                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
   7492             }
   7493             else if (current >= 'a' && current <= 'f')
   7494             {
   7495                 codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
   7496             }
   7497             else
   7498             {
   7499                 return -1;
   7500             }
   7501         }
   7502 
   7503         JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
   7504         return codepoint;
   7505     }
   7506 
   7507     /*!
   7508     @brief check if the next byte(s) are inside a given range
   7509 
   7510     Adds the current byte and, for each passed range, reads a new byte and
   7511     checks if it is inside the range. If a violation was detected, set up an
   7512     error message and return false. Otherwise, return true.
   7513 
   7514     @param[in] ranges  list of integers; interpreted as list of pairs of
   7515                        inclusive lower and upper bound, respectively
   7516 
   7517     @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
   7518          1, 2, or 3 pairs. This precondition is enforced by an assertion.
   7519 
   7520     @return true if and only if no range violation was detected
   7521     */
   7522     bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
   7523     {
   7524         JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
   7525         add(current);
   7526 
   7527         for (auto range = ranges.begin(); range != ranges.end(); ++range)
   7528         {
   7529             get();
   7530             if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range)))
   7531             {
   7532                 add(current);
   7533             }
   7534             else
   7535             {
   7536                 error_message = "invalid string: ill-formed UTF-8 byte";
   7537                 return false;
   7538             }
   7539         }
   7540 
   7541         return true;
   7542     }
   7543 
   7544     /*!
   7545     @brief scan a string literal
   7546 
   7547     This function scans a string according to Sect. 7 of RFC 8259. While
   7548     scanning, bytes are escaped and copied into buffer token_buffer. Then the
   7549     function returns successfully, token_buffer is *not* null-terminated (as it
   7550     may contain \0 bytes), and token_buffer.size() is the number of bytes in the
   7551     string.
   7552 
   7553     @return token_type::value_string if string could be successfully scanned,
   7554             token_type::parse_error otherwise
   7555 
   7556     @note In case of errors, variable error_message contains a textual
   7557           description.
   7558     */
   7559     token_type scan_string()
   7560     {
   7561         // reset token_buffer (ignore opening quote)
   7562         reset();
   7563 
   7564         // we entered the function by reading an open quote
   7565         JSON_ASSERT(current == '\"');
   7566 
   7567         while (true)
   7568         {
   7569             // get next character
   7570             switch (get())
   7571             {
   7572                 // end of file while parsing string
   7573                 case std::char_traits<char_type>::eof():
   7574                 {
   7575                     error_message = "invalid string: missing closing quote";
   7576                     return token_type::parse_error;
   7577                 }
   7578 
   7579                 // closing quote
   7580                 case '\"':
   7581                 {
   7582                     return token_type::value_string;
   7583                 }
   7584 
   7585                 // escapes
   7586                 case '\\':
   7587                 {
   7588                     switch (get())
   7589                     {
   7590                         // quotation mark
   7591                         case '\"':
   7592                             add('\"');
   7593                             break;
   7594                         // reverse solidus
   7595                         case '\\':
   7596                             add('\\');
   7597                             break;
   7598                         // solidus
   7599                         case '/':
   7600                             add('/');
   7601                             break;
   7602                         // backspace
   7603                         case 'b':
   7604                             add('\b');
   7605                             break;
   7606                         // form feed
   7607                         case 'f':
   7608                             add('\f');
   7609                             break;
   7610                         // line feed
   7611                         case 'n':
   7612                             add('\n');
   7613                             break;
   7614                         // carriage return
   7615                         case 'r':
   7616                             add('\r');
   7617                             break;
   7618                         // tab
   7619                         case 't':
   7620                             add('\t');
   7621                             break;
   7622 
   7623                         // unicode escapes
   7624                         case 'u':
   7625                         {
   7626                             const int codepoint1 = get_codepoint();
   7627                             int codepoint = codepoint1; // start with codepoint1
   7628 
   7629                             if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
   7630                             {
   7631                                 error_message = "invalid string: '\\u' must be followed by 4 hex digits";
   7632                                 return token_type::parse_error;
   7633                             }
   7634 
   7635                             // check if code point is a high surrogate
   7636                             if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
   7637                             {
   7638                                 // expect next \uxxxx entry
   7639                                 if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
   7640                                 {
   7641                                     const int codepoint2 = get_codepoint();
   7642 
   7643                                     if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
   7644                                     {
   7645                                         error_message = "invalid string: '\\u' must be followed by 4 hex digits";
   7646                                         return token_type::parse_error;
   7647                                     }
   7648 
   7649                                     // check if codepoint2 is a low surrogate
   7650                                     if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
   7651                                     {
   7652                                         // overwrite codepoint
   7653                                         codepoint = static_cast<int>(
   7654                                                         // high surrogate occupies the most significant 22 bits
   7655                                                         (static_cast<unsigned int>(codepoint1) << 10u)
   7656                                                         // low surrogate occupies the least significant 15 bits
   7657                                                         + static_cast<unsigned int>(codepoint2)
   7658                                                         // there is still the 0xD800, 0xDC00 and 0x10000 noise
   7659                                                         // in the result, so we have to subtract with:
   7660                                                         // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
   7661                                                         - 0x35FDC00u);
   7662                                     }
   7663                                     else
   7664                                     {
   7665                                         error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
   7666                                         return token_type::parse_error;
   7667                                     }
   7668                                 }
   7669                                 else
   7670                                 {
   7671                                     error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
   7672                                     return token_type::parse_error;
   7673                                 }
   7674                             }
   7675                             else
   7676                             {
   7677                                 if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
   7678                                 {
   7679                                     error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
   7680                                     return token_type::parse_error;
   7681                                 }
   7682                             }
   7683 
   7684                             // result of the above calculation yields a proper codepoint
   7685                             JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
   7686 
   7687                             // translate codepoint into bytes
   7688                             if (codepoint < 0x80)
   7689                             {
   7690                                 // 1-byte characters: 0xxxxxxx (ASCII)
   7691                                 add(static_cast<char_int_type>(codepoint));
   7692                             }
   7693                             else if (codepoint <= 0x7FF)
   7694                             {
   7695                                 // 2-byte characters: 110xxxxx 10xxxxxx
   7696                                 add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
   7697                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
   7698                             }
   7699                             else if (codepoint <= 0xFFFF)
   7700                             {
   7701                                 // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
   7702                                 add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
   7703                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
   7704                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
   7705                             }
   7706                             else
   7707                             {
   7708                                 // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   7709                                 add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
   7710                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
   7711                                 add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
   7712                                 add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
   7713                             }
   7714 
   7715                             break;
   7716                         }
   7717 
   7718                         // other characters after escape
   7719                         default:
   7720                             error_message = "invalid string: forbidden character after backslash";
   7721                             return token_type::parse_error;
   7722                     }
   7723 
   7724                     break;
   7725                 }
   7726 
   7727                 // invalid control characters
   7728                 case 0x00:
   7729                 {
   7730                     error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
   7731                     return token_type::parse_error;
   7732                 }
   7733 
   7734                 case 0x01:
   7735                 {
   7736                     error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
   7737                     return token_type::parse_error;
   7738                 }
   7739 
   7740                 case 0x02:
   7741                 {
   7742                     error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
   7743                     return token_type::parse_error;
   7744                 }
   7745 
   7746                 case 0x03:
   7747                 {
   7748                     error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
   7749                     return token_type::parse_error;
   7750                 }
   7751 
   7752                 case 0x04:
   7753                 {
   7754                     error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
   7755                     return token_type::parse_error;
   7756                 }
   7757 
   7758                 case 0x05:
   7759                 {
   7760                     error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
   7761                     return token_type::parse_error;
   7762                 }
   7763 
   7764                 case 0x06:
   7765                 {
   7766                     error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
   7767                     return token_type::parse_error;
   7768                 }
   7769 
   7770                 case 0x07:
   7771                 {
   7772                     error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
   7773                     return token_type::parse_error;
   7774                 }
   7775 
   7776                 case 0x08:
   7777                 {
   7778                     error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
   7779                     return token_type::parse_error;
   7780                 }
   7781 
   7782                 case 0x09:
   7783                 {
   7784                     error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
   7785                     return token_type::parse_error;
   7786                 }
   7787 
   7788                 case 0x0A:
   7789                 {
   7790                     error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
   7791                     return token_type::parse_error;
   7792                 }
   7793 
   7794                 case 0x0B:
   7795                 {
   7796                     error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
   7797                     return token_type::parse_error;
   7798                 }
   7799 
   7800                 case 0x0C:
   7801                 {
   7802                     error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
   7803                     return token_type::parse_error;
   7804                 }
   7805 
   7806                 case 0x0D:
   7807                 {
   7808                     error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
   7809                     return token_type::parse_error;
   7810                 }
   7811 
   7812                 case 0x0E:
   7813                 {
   7814                     error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
   7815                     return token_type::parse_error;
   7816                 }
   7817 
   7818                 case 0x0F:
   7819                 {
   7820                     error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
   7821                     return token_type::parse_error;
   7822                 }
   7823 
   7824                 case 0x10:
   7825                 {
   7826                     error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
   7827                     return token_type::parse_error;
   7828                 }
   7829 
   7830                 case 0x11:
   7831                 {
   7832                     error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
   7833                     return token_type::parse_error;
   7834                 }
   7835 
   7836                 case 0x12:
   7837                 {
   7838                     error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
   7839                     return token_type::parse_error;
   7840                 }
   7841 
   7842                 case 0x13:
   7843                 {
   7844                     error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
   7845                     return token_type::parse_error;
   7846                 }
   7847 
   7848                 case 0x14:
   7849                 {
   7850                     error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
   7851                     return token_type::parse_error;
   7852                 }
   7853 
   7854                 case 0x15:
   7855                 {
   7856                     error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
   7857                     return token_type::parse_error;
   7858                 }
   7859 
   7860                 case 0x16:
   7861                 {
   7862                     error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
   7863                     return token_type::parse_error;
   7864                 }
   7865 
   7866                 case 0x17:
   7867                 {
   7868                     error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
   7869                     return token_type::parse_error;
   7870                 }
   7871 
   7872                 case 0x18:
   7873                 {
   7874                     error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
   7875                     return token_type::parse_error;
   7876                 }
   7877 
   7878                 case 0x19:
   7879                 {
   7880                     error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
   7881                     return token_type::parse_error;
   7882                 }
   7883 
   7884                 case 0x1A:
   7885                 {
   7886                     error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
   7887                     return token_type::parse_error;
   7888                 }
   7889 
   7890                 case 0x1B:
   7891                 {
   7892                     error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
   7893                     return token_type::parse_error;
   7894                 }
   7895 
   7896                 case 0x1C:
   7897                 {
   7898                     error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
   7899                     return token_type::parse_error;
   7900                 }
   7901 
   7902                 case 0x1D:
   7903                 {
   7904                     error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
   7905                     return token_type::parse_error;
   7906                 }
   7907 
   7908                 case 0x1E:
   7909                 {
   7910                     error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
   7911                     return token_type::parse_error;
   7912                 }
   7913 
   7914                 case 0x1F:
   7915                 {
   7916                     error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
   7917                     return token_type::parse_error;
   7918                 }
   7919 
   7920                 // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
   7921                 case 0x20:
   7922                 case 0x21:
   7923                 case 0x23:
   7924                 case 0x24:
   7925                 case 0x25:
   7926                 case 0x26:
   7927                 case 0x27:
   7928                 case 0x28:
   7929                 case 0x29:
   7930                 case 0x2A:
   7931                 case 0x2B:
   7932                 case 0x2C:
   7933                 case 0x2D:
   7934                 case 0x2E:
   7935                 case 0x2F:
   7936                 case 0x30:
   7937                 case 0x31:
   7938                 case 0x32:
   7939                 case 0x33:
   7940                 case 0x34:
   7941                 case 0x35:
   7942                 case 0x36:
   7943                 case 0x37:
   7944                 case 0x38:
   7945                 case 0x39:
   7946                 case 0x3A:
   7947                 case 0x3B:
   7948                 case 0x3C:
   7949                 case 0x3D:
   7950                 case 0x3E:
   7951                 case 0x3F:
   7952                 case 0x40:
   7953                 case 0x41:
   7954                 case 0x42:
   7955                 case 0x43:
   7956                 case 0x44:
   7957                 case 0x45:
   7958                 case 0x46:
   7959                 case 0x47:
   7960                 case 0x48:
   7961                 case 0x49:
   7962                 case 0x4A:
   7963                 case 0x4B:
   7964                 case 0x4C:
   7965                 case 0x4D:
   7966                 case 0x4E:
   7967                 case 0x4F:
   7968                 case 0x50:
   7969                 case 0x51:
   7970                 case 0x52:
   7971                 case 0x53:
   7972                 case 0x54:
   7973                 case 0x55:
   7974                 case 0x56:
   7975                 case 0x57:
   7976                 case 0x58:
   7977                 case 0x59:
   7978                 case 0x5A:
   7979                 case 0x5B:
   7980                 case 0x5D:
   7981                 case 0x5E:
   7982                 case 0x5F:
   7983                 case 0x60:
   7984                 case 0x61:
   7985                 case 0x62:
   7986                 case 0x63:
   7987                 case 0x64:
   7988                 case 0x65:
   7989                 case 0x66:
   7990                 case 0x67:
   7991                 case 0x68:
   7992                 case 0x69:
   7993                 case 0x6A:
   7994                 case 0x6B:
   7995                 case 0x6C:
   7996                 case 0x6D:
   7997                 case 0x6E:
   7998                 case 0x6F:
   7999                 case 0x70:
   8000                 case 0x71:
   8001                 case 0x72:
   8002                 case 0x73:
   8003                 case 0x74:
   8004                 case 0x75:
   8005                 case 0x76:
   8006                 case 0x77:
   8007                 case 0x78:
   8008                 case 0x79:
   8009                 case 0x7A:
   8010                 case 0x7B:
   8011                 case 0x7C:
   8012                 case 0x7D:
   8013                 case 0x7E:
   8014                 case 0x7F:
   8015                 {
   8016                     add(current);
   8017                     break;
   8018                 }
   8019 
   8020                 // U+0080..U+07FF: bytes C2..DF 80..BF
   8021                 case 0xC2:
   8022                 case 0xC3:
   8023                 case 0xC4:
   8024                 case 0xC5:
   8025                 case 0xC6:
   8026                 case 0xC7:
   8027                 case 0xC8:
   8028                 case 0xC9:
   8029                 case 0xCA:
   8030                 case 0xCB:
   8031                 case 0xCC:
   8032                 case 0xCD:
   8033                 case 0xCE:
   8034                 case 0xCF:
   8035                 case 0xD0:
   8036                 case 0xD1:
   8037                 case 0xD2:
   8038                 case 0xD3:
   8039                 case 0xD4:
   8040                 case 0xD5:
   8041                 case 0xD6:
   8042                 case 0xD7:
   8043                 case 0xD8:
   8044                 case 0xD9:
   8045                 case 0xDA:
   8046                 case 0xDB:
   8047                 case 0xDC:
   8048                 case 0xDD:
   8049                 case 0xDE:
   8050                 case 0xDF:
   8051                 {
   8052                     if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
   8053                     {
   8054                         return token_type::parse_error;
   8055                     }
   8056                     break;
   8057                 }
   8058 
   8059                 // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
   8060                 case 0xE0:
   8061                 {
   8062                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
   8063                     {
   8064                         return token_type::parse_error;
   8065                     }
   8066                     break;
   8067                 }
   8068 
   8069                 // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
   8070                 // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
   8071                 case 0xE1:
   8072                 case 0xE2:
   8073                 case 0xE3:
   8074                 case 0xE4:
   8075                 case 0xE5:
   8076                 case 0xE6:
   8077                 case 0xE7:
   8078                 case 0xE8:
   8079                 case 0xE9:
   8080                 case 0xEA:
   8081                 case 0xEB:
   8082                 case 0xEC:
   8083                 case 0xEE:
   8084                 case 0xEF:
   8085                 {
   8086                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
   8087                     {
   8088                         return token_type::parse_error;
   8089                     }
   8090                     break;
   8091                 }
   8092 
   8093                 // U+D000..U+D7FF: bytes ED 80..9F 80..BF
   8094                 case 0xED:
   8095                 {
   8096                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
   8097                     {
   8098                         return token_type::parse_error;
   8099                     }
   8100                     break;
   8101                 }
   8102 
   8103                 // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
   8104                 case 0xF0:
   8105                 {
   8106                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
   8107                     {
   8108                         return token_type::parse_error;
   8109                     }
   8110                     break;
   8111                 }
   8112 
   8113                 // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
   8114                 case 0xF1:
   8115                 case 0xF2:
   8116                 case 0xF3:
   8117                 {
   8118                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
   8119                     {
   8120                         return token_type::parse_error;
   8121                     }
   8122                     break;
   8123                 }
   8124 
   8125                 // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
   8126                 case 0xF4:
   8127                 {
   8128                     if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
   8129                     {
   8130                         return token_type::parse_error;
   8131                     }
   8132                     break;
   8133                 }
   8134 
   8135                 // remaining bytes (80..C1 and F5..FF) are ill-formed
   8136                 default:
   8137                 {
   8138                     error_message = "invalid string: ill-formed UTF-8 byte";
   8139                     return token_type::parse_error;
   8140                 }
   8141             }
   8142         }
   8143     }
   8144 
   8145     /*!
   8146      * @brief scan a comment
   8147      * @return whether comment could be scanned successfully
   8148      */
   8149     bool scan_comment()
   8150     {
   8151         switch (get())
   8152         {
   8153             // single-line comments skip input until a newline or EOF is read
   8154             case '/':
   8155             {
   8156                 while (true)
   8157                 {
   8158                     switch (get())
   8159                     {
   8160                         case '\n':
   8161                         case '\r':
   8162                         case std::char_traits<char_type>::eof():
   8163                         case '\0':
   8164                             return true;
   8165 
   8166                         default:
   8167                             break;
   8168                     }
   8169                 }
   8170             }
   8171 
   8172             // multi-line comments skip input until */ is read
   8173             case '*':
   8174             {
   8175                 while (true)
   8176                 {
   8177                     switch (get())
   8178                     {
   8179                         case std::char_traits<char_type>::eof():
   8180                         case '\0':
   8181                         {
   8182                             error_message = "invalid comment; missing closing '*/'";
   8183                             return false;
   8184                         }
   8185 
   8186                         case '*':
   8187                         {
   8188                             switch (get())
   8189                             {
   8190                                 case '/':
   8191                                     return true;
   8192 
   8193                                 default:
   8194                                 {
   8195                                     unget();
   8196                                     continue;
   8197                                 }
   8198                             }
   8199                         }
   8200 
   8201                         default:
   8202                             continue;
   8203                     }
   8204                 }
   8205             }
   8206 
   8207             // unexpected character after reading '/'
   8208             default:
   8209             {
   8210                 error_message = "invalid comment; expecting '/' or '*' after '/'";
   8211                 return false;
   8212             }
   8213         }
   8214     }
   8215 
   8216     JSON_HEDLEY_NON_NULL(2)
   8217     static void strtof(float& f, const char* str, char** endptr) noexcept
   8218     {
   8219         f = std::strtof(str, endptr);
   8220     }
   8221 
   8222     JSON_HEDLEY_NON_NULL(2)
   8223     static void strtof(double& f, const char* str, char** endptr) noexcept
   8224     {
   8225         f = std::strtod(str, endptr);
   8226     }
   8227 
   8228     JSON_HEDLEY_NON_NULL(2)
   8229     static void strtof(long double& f, const char* str, char** endptr) noexcept
   8230     {
   8231         f = std::strtold(str, endptr);
   8232     }
   8233 
   8234     /*!
   8235     @brief scan a number literal
   8236 
   8237     This function scans a string according to Sect. 6 of RFC 8259.
   8238 
   8239     The function is realized with a deterministic finite state machine derived
   8240     from the grammar described in RFC 8259. Starting in state "init", the
   8241     input is read and used to determined the next state. Only state "done"
   8242     accepts the number. State "error" is a trap state to model errors. In the
   8243     table below, "anything" means any character but the ones listed before.
   8244 
   8245     state    | 0        | 1-9      | e E      | +       | -       | .        | anything
   8246     ---------|----------|----------|----------|---------|---------|----------|-----------
   8247     init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
   8248     minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
   8249     zero     | done     | done     | exponent | done    | done    | decimal1 | done
   8250     any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
   8251     decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error]
   8252     decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
   8253     exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
   8254     sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
   8255     any2     | any2     | any2     | done     | done    | done    | done     | done
   8256 
   8257     The state machine is realized with one label per state (prefixed with
   8258     "scan_number_") and `goto` statements between them. The state machine
   8259     contains cycles, but any cycle can be left when EOF is read. Therefore,
   8260     the function is guaranteed to terminate.
   8261 
   8262     During scanning, the read bytes are stored in token_buffer. This string is
   8263     then converted to a signed integer, an unsigned integer, or a
   8264     floating-point number.
   8265 
   8266     @return token_type::value_unsigned, token_type::value_integer, or
   8267             token_type::value_float if number could be successfully scanned,
   8268             token_type::parse_error otherwise
   8269 
   8270     @note The scanner is independent of the current locale. Internally, the
   8271           locale's decimal point is used instead of `.` to work with the
   8272           locale-dependent converters.
   8273     */
   8274     token_type scan_number()  // lgtm [cpp/use-of-goto]
   8275     {
   8276         // reset token_buffer to store the number's bytes
   8277         reset();
   8278 
   8279         // the type of the parsed number; initially set to unsigned; will be
   8280         // changed if minus sign, decimal point or exponent is read
   8281         token_type number_type = token_type::value_unsigned;
   8282 
   8283         // state (init): we just found out we need to scan a number
   8284         switch (current)
   8285         {
   8286             case '-':
   8287             {
   8288                 add(current);
   8289                 goto scan_number_minus;
   8290             }
   8291 
   8292             case '0':
   8293             {
   8294                 add(current);
   8295                 goto scan_number_zero;
   8296             }
   8297 
   8298             case '1':
   8299             case '2':
   8300             case '3':
   8301             case '4':
   8302             case '5':
   8303             case '6':
   8304             case '7':
   8305             case '8':
   8306             case '9':
   8307             {
   8308                 add(current);
   8309                 goto scan_number_any1;
   8310             }
   8311 
   8312             // all other characters are rejected outside scan_number()
   8313             default:            // LCOV_EXCL_LINE
   8314                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   8315         }
   8316 
   8317 scan_number_minus:
   8318         // state: we just parsed a leading minus sign
   8319         number_type = token_type::value_integer;
   8320         switch (get())
   8321         {
   8322             case '0':
   8323             {
   8324                 add(current);
   8325                 goto scan_number_zero;
   8326             }
   8327 
   8328             case '1':
   8329             case '2':
   8330             case '3':
   8331             case '4':
   8332             case '5':
   8333             case '6':
   8334             case '7':
   8335             case '8':
   8336             case '9':
   8337             {
   8338                 add(current);
   8339                 goto scan_number_any1;
   8340             }
   8341 
   8342             default:
   8343             {
   8344                 error_message = "invalid number; expected digit after '-'";
   8345                 return token_type::parse_error;
   8346             }
   8347         }
   8348 
   8349 scan_number_zero:
   8350         // state: we just parse a zero (maybe with a leading minus sign)
   8351         switch (get())
   8352         {
   8353             case '.':
   8354             {
   8355                 add(decimal_point_char);
   8356                 goto scan_number_decimal1;
   8357             }
   8358 
   8359             case 'e':
   8360             case 'E':
   8361             {
   8362                 add(current);
   8363                 goto scan_number_exponent;
   8364             }
   8365 
   8366             default:
   8367                 goto scan_number_done;
   8368         }
   8369 
   8370 scan_number_any1:
   8371         // state: we just parsed a number 0-9 (maybe with a leading minus sign)
   8372         switch (get())
   8373         {
   8374             case '0':
   8375             case '1':
   8376             case '2':
   8377             case '3':
   8378             case '4':
   8379             case '5':
   8380             case '6':
   8381             case '7':
   8382             case '8':
   8383             case '9':
   8384             {
   8385                 add(current);
   8386                 goto scan_number_any1;
   8387             }
   8388 
   8389             case '.':
   8390             {
   8391                 add(decimal_point_char);
   8392                 goto scan_number_decimal1;
   8393             }
   8394 
   8395             case 'e':
   8396             case 'E':
   8397             {
   8398                 add(current);
   8399                 goto scan_number_exponent;
   8400             }
   8401 
   8402             default:
   8403                 goto scan_number_done;
   8404         }
   8405 
   8406 scan_number_decimal1:
   8407         // state: we just parsed a decimal point
   8408         number_type = token_type::value_float;
   8409         switch (get())
   8410         {
   8411             case '0':
   8412             case '1':
   8413             case '2':
   8414             case '3':
   8415             case '4':
   8416             case '5':
   8417             case '6':
   8418             case '7':
   8419             case '8':
   8420             case '9':
   8421             {
   8422                 add(current);
   8423                 goto scan_number_decimal2;
   8424             }
   8425 
   8426             default:
   8427             {
   8428                 error_message = "invalid number; expected digit after '.'";
   8429                 return token_type::parse_error;
   8430             }
   8431         }
   8432 
   8433 scan_number_decimal2:
   8434         // we just parsed at least one number after a decimal point
   8435         switch (get())
   8436         {
   8437             case '0':
   8438             case '1':
   8439             case '2':
   8440             case '3':
   8441             case '4':
   8442             case '5':
   8443             case '6':
   8444             case '7':
   8445             case '8':
   8446             case '9':
   8447             {
   8448                 add(current);
   8449                 goto scan_number_decimal2;
   8450             }
   8451 
   8452             case 'e':
   8453             case 'E':
   8454             {
   8455                 add(current);
   8456                 goto scan_number_exponent;
   8457             }
   8458 
   8459             default:
   8460                 goto scan_number_done;
   8461         }
   8462 
   8463 scan_number_exponent:
   8464         // we just parsed an exponent
   8465         number_type = token_type::value_float;
   8466         switch (get())
   8467         {
   8468             case '+':
   8469             case '-':
   8470             {
   8471                 add(current);
   8472                 goto scan_number_sign;
   8473             }
   8474 
   8475             case '0':
   8476             case '1':
   8477             case '2':
   8478             case '3':
   8479             case '4':
   8480             case '5':
   8481             case '6':
   8482             case '7':
   8483             case '8':
   8484             case '9':
   8485             {
   8486                 add(current);
   8487                 goto scan_number_any2;
   8488             }
   8489 
   8490             default:
   8491             {
   8492                 error_message =
   8493                     "invalid number; expected '+', '-', or digit after exponent";
   8494                 return token_type::parse_error;
   8495             }
   8496         }
   8497 
   8498 scan_number_sign:
   8499         // we just parsed an exponent sign
   8500         switch (get())
   8501         {
   8502             case '0':
   8503             case '1':
   8504             case '2':
   8505             case '3':
   8506             case '4':
   8507             case '5':
   8508             case '6':
   8509             case '7':
   8510             case '8':
   8511             case '9':
   8512             {
   8513                 add(current);
   8514                 goto scan_number_any2;
   8515             }
   8516 
   8517             default:
   8518             {
   8519                 error_message = "invalid number; expected digit after exponent sign";
   8520                 return token_type::parse_error;
   8521             }
   8522         }
   8523 
   8524 scan_number_any2:
   8525         // we just parsed a number after the exponent or exponent sign
   8526         switch (get())
   8527         {
   8528             case '0':
   8529             case '1':
   8530             case '2':
   8531             case '3':
   8532             case '4':
   8533             case '5':
   8534             case '6':
   8535             case '7':
   8536             case '8':
   8537             case '9':
   8538             {
   8539                 add(current);
   8540                 goto scan_number_any2;
   8541             }
   8542 
   8543             default:
   8544                 goto scan_number_done;
   8545         }
   8546 
   8547 scan_number_done:
   8548         // unget the character after the number (we only read it to know that
   8549         // we are done scanning a number)
   8550         unget();
   8551 
   8552         char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   8553         errno = 0;
   8554 
   8555         // try to parse integers first and fall back to floats
   8556         if (number_type == token_type::value_unsigned)
   8557         {
   8558             const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
   8559 
   8560             // we checked the number format before
   8561             JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
   8562 
   8563             if (errno == 0)
   8564             {
   8565                 value_unsigned = static_cast<number_unsigned_t>(x);
   8566                 if (value_unsigned == x)
   8567                 {
   8568                     return token_type::value_unsigned;
   8569                 }
   8570             }
   8571         }
   8572         else if (number_type == token_type::value_integer)
   8573         {
   8574             const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
   8575 
   8576             // we checked the number format before
   8577             JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
   8578 
   8579             if (errno == 0)
   8580             {
   8581                 value_integer = static_cast<number_integer_t>(x);
   8582                 if (value_integer == x)
   8583                 {
   8584                     return token_type::value_integer;
   8585                 }
   8586             }
   8587         }
   8588 
   8589         // this code is reached if we parse a floating-point number or if an
   8590         // integer conversion above failed
   8591         strtof(value_float, token_buffer.data(), &endptr);
   8592 
   8593         // we checked the number format before
   8594         JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
   8595 
   8596         return token_type::value_float;
   8597     }
   8598 
   8599     /*!
   8600     @param[in] literal_text  the literal text to expect
   8601     @param[in] length        the length of the passed literal text
   8602     @param[in] return_type   the token type to return on success
   8603     */
   8604     JSON_HEDLEY_NON_NULL(2)
   8605     token_type scan_literal(const char_type* literal_text, const std::size_t length,
   8606                             token_type return_type)
   8607     {
   8608         JSON_ASSERT(std::char_traits<char_type>::to_char_type(current) == literal_text[0]);
   8609         for (std::size_t i = 1; i < length; ++i)
   8610         {
   8611             if (JSON_HEDLEY_UNLIKELY(std::char_traits<char_type>::to_char_type(get()) != literal_text[i]))
   8612             {
   8613                 error_message = "invalid literal";
   8614                 return token_type::parse_error;
   8615             }
   8616         }
   8617         return return_type;
   8618     }
   8619 
   8620     /////////////////////
   8621     // input management
   8622     /////////////////////
   8623 
   8624     /// reset token_buffer; current character is beginning of token
   8625     void reset() noexcept
   8626     {
   8627         token_buffer.clear();
   8628         token_string.clear();
   8629         token_string.push_back(std::char_traits<char_type>::to_char_type(current));
   8630     }
   8631 
   8632     /*
   8633     @brief get next character from the input
   8634 
   8635     This function provides the interface to the used input adapter. It does
   8636     not throw in case the input reached EOF, but returns a
   8637     `std::char_traits<char>::eof()` in that case.  Stores the scanned characters
   8638     for use in error messages.
   8639 
   8640     @return character read from the input
   8641     */
   8642     char_int_type get()
   8643     {
   8644         ++position.chars_read_total;
   8645         ++position.chars_read_current_line;
   8646 
   8647         if (next_unget)
   8648         {
   8649             // just reset the next_unget variable and work with current
   8650             next_unget = false;
   8651         }
   8652         else
   8653         {
   8654             current = ia.get_character();
   8655         }
   8656 
   8657         if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
   8658         {
   8659             token_string.push_back(std::char_traits<char_type>::to_char_type(current));
   8660         }
   8661 
   8662         if (current == '\n')
   8663         {
   8664             ++position.lines_read;
   8665             position.chars_read_current_line = 0;
   8666         }
   8667 
   8668         return current;
   8669     }
   8670 
   8671     /*!
   8672     @brief unget current character (read it again on next get)
   8673 
   8674     We implement unget by setting variable next_unget to true. The input is not
   8675     changed - we just simulate ungetting by modifying chars_read_total,
   8676     chars_read_current_line, and token_string. The next call to get() will
   8677     behave as if the unget character is read again.
   8678     */
   8679     void unget()
   8680     {
   8681         next_unget = true;
   8682 
   8683         --position.chars_read_total;
   8684 
   8685         // in case we "unget" a newline, we have to also decrement the lines_read
   8686         if (position.chars_read_current_line == 0)
   8687         {
   8688             if (position.lines_read > 0)
   8689             {
   8690                 --position.lines_read;
   8691             }
   8692         }
   8693         else
   8694         {
   8695             --position.chars_read_current_line;
   8696         }
   8697 
   8698         if (JSON_HEDLEY_LIKELY(current != std::char_traits<char_type>::eof()))
   8699         {
   8700             JSON_ASSERT(!token_string.empty());
   8701             token_string.pop_back();
   8702         }
   8703     }
   8704 
   8705     /// add a character to token_buffer
   8706     void add(char_int_type c)
   8707     {
   8708         token_buffer.push_back(static_cast<typename string_t::value_type>(c));
   8709     }
   8710 
   8711   public:
   8712     /////////////////////
   8713     // value getters
   8714     /////////////////////
   8715 
   8716     /// return integer value
   8717     constexpr number_integer_t get_number_integer() const noexcept
   8718     {
   8719         return value_integer;
   8720     }
   8721 
   8722     /// return unsigned integer value
   8723     constexpr number_unsigned_t get_number_unsigned() const noexcept
   8724     {
   8725         return value_unsigned;
   8726     }
   8727 
   8728     /// return floating-point value
   8729     constexpr number_float_t get_number_float() const noexcept
   8730     {
   8731         return value_float;
   8732     }
   8733 
   8734     /// return current string value (implicitly resets the token; useful only once)
   8735     string_t& get_string()
   8736     {
   8737         return token_buffer;
   8738     }
   8739 
   8740     /////////////////////
   8741     // diagnostics
   8742     /////////////////////
   8743 
   8744     /// return position of last read token
   8745     constexpr position_t get_position() const noexcept
   8746     {
   8747         return position;
   8748     }
   8749 
   8750     /// return the last read token (for errors only).  Will never contain EOF
   8751     /// (an arbitrary value that is not a valid char value, often -1), because
   8752     /// 255 may legitimately occur.  May contain NUL, which should be escaped.
   8753     std::string get_token_string() const
   8754     {
   8755         // escape control characters
   8756         std::string result;
   8757         for (const auto c : token_string)
   8758         {
   8759             if (static_cast<unsigned char>(c) <= '\x1F')
   8760             {
   8761                 // escape control characters
   8762                 std::array<char, 9> cs{{}};
   8763                 static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   8764                 result += cs.data();
   8765             }
   8766             else
   8767             {
   8768                 // add character as is
   8769                 result.push_back(static_cast<std::string::value_type>(c));
   8770             }
   8771         }
   8772 
   8773         return result;
   8774     }
   8775 
   8776     /// return syntax error message
   8777     JSON_HEDLEY_RETURNS_NON_NULL
   8778     constexpr const char* get_error_message() const noexcept
   8779     {
   8780         return error_message;
   8781     }
   8782 
   8783     /////////////////////
   8784     // actual scanner
   8785     /////////////////////
   8786 
   8787     /*!
   8788     @brief skip the UTF-8 byte order mark
   8789     @return true iff there is no BOM or the correct BOM has been skipped
   8790     */
   8791     bool skip_bom()
   8792     {
   8793         if (get() == 0xEF)
   8794         {
   8795             // check if we completely parse the BOM
   8796             return get() == 0xBB && get() == 0xBF;
   8797         }
   8798 
   8799         // the first character is not the beginning of the BOM; unget it to
   8800         // process is later
   8801         unget();
   8802         return true;
   8803     }
   8804 
   8805     void skip_whitespace()
   8806     {
   8807         do
   8808         {
   8809             get();
   8810         }
   8811         while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
   8812     }
   8813 
   8814     token_type scan()
   8815     {
   8816         // initially, skip the BOM
   8817         if (position.chars_read_total == 0 && !skip_bom())
   8818         {
   8819             error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
   8820             return token_type::parse_error;
   8821         }
   8822 
   8823         // read next character and ignore whitespace
   8824         skip_whitespace();
   8825 
   8826         // ignore comments
   8827         while (ignore_comments && current == '/')
   8828         {
   8829             if (!scan_comment())
   8830             {
   8831                 return token_type::parse_error;
   8832             }
   8833 
   8834             // skip following whitespace
   8835             skip_whitespace();
   8836         }
   8837 
   8838         switch (current)
   8839         {
   8840             // structural characters
   8841             case '[':
   8842                 return token_type::begin_array;
   8843             case ']':
   8844                 return token_type::end_array;
   8845             case '{':
   8846                 return token_type::begin_object;
   8847             case '}':
   8848                 return token_type::end_object;
   8849             case ':':
   8850                 return token_type::name_separator;
   8851             case ',':
   8852                 return token_type::value_separator;
   8853 
   8854             // literals
   8855             case 't':
   8856             {
   8857                 std::array<char_type, 4> true_literal = {{static_cast<char_type>('t'), static_cast<char_type>('r'), static_cast<char_type>('u'), static_cast<char_type>('e')}};
   8858                 return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
   8859             }
   8860             case 'f':
   8861             {
   8862                 std::array<char_type, 5> false_literal = {{static_cast<char_type>('f'), static_cast<char_type>('a'), static_cast<char_type>('l'), static_cast<char_type>('s'), static_cast<char_type>('e')}};
   8863                 return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
   8864             }
   8865             case 'n':
   8866             {
   8867                 std::array<char_type, 4> null_literal = {{static_cast<char_type>('n'), static_cast<char_type>('u'), static_cast<char_type>('l'), static_cast<char_type>('l')}};
   8868                 return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
   8869             }
   8870 
   8871             // string
   8872             case '\"':
   8873                 return scan_string();
   8874 
   8875             // number
   8876             case '-':
   8877             case '0':
   8878             case '1':
   8879             case '2':
   8880             case '3':
   8881             case '4':
   8882             case '5':
   8883             case '6':
   8884             case '7':
   8885             case '8':
   8886             case '9':
   8887                 return scan_number();
   8888 
   8889             // end of input (the null byte is needed when parsing from
   8890             // string literals)
   8891             case '\0':
   8892             case std::char_traits<char_type>::eof():
   8893                 return token_type::end_of_input;
   8894 
   8895             // error
   8896             default:
   8897                 error_message = "invalid literal";
   8898                 return token_type::parse_error;
   8899         }
   8900     }
   8901 
   8902   private:
   8903     /// input adapter
   8904     InputAdapterType ia;
   8905 
   8906     /// whether comments should be ignored (true) or signaled as errors (false)
   8907     const bool ignore_comments = false;
   8908 
   8909     /// the current character
   8910     char_int_type current = std::char_traits<char_type>::eof();
   8911 
   8912     /// whether the next get() call should just return current
   8913     bool next_unget = false;
   8914 
   8915     /// the start position of the current token
   8916     position_t position {};
   8917 
   8918     /// raw input token string (for error messages)
   8919     std::vector<char_type> token_string {};
   8920 
   8921     /// buffer for variable-length tokens (numbers, strings)
   8922     string_t token_buffer {};
   8923 
   8924     /// a description of occurred lexer errors
   8925     const char* error_message = "";
   8926 
   8927     // number values
   8928     number_integer_t value_integer = 0;
   8929     number_unsigned_t value_unsigned = 0;
   8930     number_float_t value_float = 0;
   8931 
   8932     /// the decimal point
   8933     const char_int_type decimal_point_char = '.';
   8934 };
   8935 
   8936 }  // namespace detail
   8937 NLOHMANN_JSON_NAMESPACE_END
   8938 
   8939 // #include <nlohmann/detail/macro_scope.hpp>
   8940 
   8941 // #include <nlohmann/detail/meta/is_sax.hpp>
   8942 //     __ _____ _____ _____
   8943 //  __|  |   __|     |   | |  JSON for Modern C++
   8944 // |  |  |__   |  |  | | | |  version 3.11.2
   8945 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   8946 //
   8947 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
   8948 // SPDX-License-Identifier: MIT
   8949 
   8950 
   8951 
   8952 #include <cstdint> // size_t
   8953 #include <utility> // declval
   8954 #include <string> // string
   8955 
   8956 // #include <nlohmann/detail/abi_macros.hpp>
   8957 
   8958 // #include <nlohmann/detail/meta/detected.hpp>
   8959 
   8960 // #include <nlohmann/detail/meta/type_traits.hpp>
   8961 
   8962 
   8963 NLOHMANN_JSON_NAMESPACE_BEGIN
   8964 namespace detail
   8965 {
   8966 
   8967 template<typename T>
   8968 using null_function_t = decltype(std::declval<T&>().null());
   8969 
   8970 template<typename T>
   8971 using boolean_function_t =
   8972     decltype(std::declval<T&>().boolean(std::declval<bool>()));
   8973 
   8974 template<typename T, typename Integer>
   8975 using number_integer_function_t =
   8976     decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
   8977 
   8978 template<typename T, typename Unsigned>
   8979 using number_unsigned_function_t =
   8980     decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
   8981 
   8982 template<typename T, typename Float, typename String>
   8983 using number_float_function_t = decltype(std::declval<T&>().number_float(
   8984                                     std::declval<Float>(), std::declval<const String&>()));
   8985 
   8986 template<typename T, typename String>
   8987 using string_function_t =
   8988     decltype(std::declval<T&>().string(std::declval<String&>()));
   8989 
   8990 template<typename T, typename Binary>
   8991 using binary_function_t =
   8992     decltype(std::declval<T&>().binary(std::declval<Binary&>()));
   8993 
   8994 template<typename T>
   8995 using start_object_function_t =
   8996     decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
   8997 
   8998 template<typename T, typename String>
   8999 using key_function_t =
   9000     decltype(std::declval<T&>().key(std::declval<String&>()));
   9001 
   9002 template<typename T>
   9003 using end_object_function_t = decltype(std::declval<T&>().end_object());
   9004 
   9005 template<typename T>
   9006 using start_array_function_t =
   9007     decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
   9008 
   9009 template<typename T>
   9010 using end_array_function_t = decltype(std::declval<T&>().end_array());
   9011 
   9012 template<typename T, typename Exception>
   9013 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
   9014         std::declval<std::size_t>(), std::declval<const std::string&>(),
   9015         std::declval<const Exception&>()));
   9016 
   9017 template<typename SAX, typename BasicJsonType>
   9018 struct is_sax
   9019 {
   9020   private:
   9021     static_assert(is_basic_json<BasicJsonType>::value,
   9022                   "BasicJsonType must be of type basic_json<...>");
   9023 
   9024     using number_integer_t = typename BasicJsonType::number_integer_t;
   9025     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   9026     using number_float_t = typename BasicJsonType::number_float_t;
   9027     using string_t = typename BasicJsonType::string_t;
   9028     using binary_t = typename BasicJsonType::binary_t;
   9029     using exception_t = typename BasicJsonType::exception;
   9030 
   9031   public:
   9032     static constexpr bool value =
   9033         is_detected_exact<bool, null_function_t, SAX>::value &&
   9034         is_detected_exact<bool, boolean_function_t, SAX>::value &&
   9035         is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
   9036         is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
   9037         is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
   9038         is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
   9039         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
   9040         is_detected_exact<bool, start_object_function_t, SAX>::value &&
   9041         is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
   9042         is_detected_exact<bool, end_object_function_t, SAX>::value &&
   9043         is_detected_exact<bool, start_array_function_t, SAX>::value &&
   9044         is_detected_exact<bool, end_array_function_t, SAX>::value &&
   9045         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
   9046 };
   9047 
   9048 template<typename SAX, typename BasicJsonType>
   9049 struct is_sax_static_asserts
   9050 {
   9051   private:
   9052     static_assert(is_basic_json<BasicJsonType>::value,
   9053                   "BasicJsonType must be of type basic_json<...>");
   9054 
   9055     using number_integer_t = typename BasicJsonType::number_integer_t;
   9056     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   9057     using number_float_t = typename BasicJsonType::number_float_t;
   9058     using string_t = typename BasicJsonType::string_t;
   9059     using binary_t = typename BasicJsonType::binary_t;
   9060     using exception_t = typename BasicJsonType::exception;
   9061 
   9062   public:
   9063     static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
   9064                   "Missing/invalid function: bool null()");
   9065     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
   9066                   "Missing/invalid function: bool boolean(bool)");
   9067     static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
   9068                   "Missing/invalid function: bool boolean(bool)");
   9069     static_assert(
   9070         is_detected_exact<bool, number_integer_function_t, SAX,
   9071         number_integer_t>::value,
   9072         "Missing/invalid function: bool number_integer(number_integer_t)");
   9073     static_assert(
   9074         is_detected_exact<bool, number_unsigned_function_t, SAX,
   9075         number_unsigned_t>::value,
   9076         "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
   9077     static_assert(is_detected_exact<bool, number_float_function_t, SAX,
   9078                   number_float_t, string_t>::value,
   9079                   "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
   9080     static_assert(
   9081         is_detected_exact<bool, string_function_t, SAX, string_t>::value,
   9082         "Missing/invalid function: bool string(string_t&)");
   9083     static_assert(
   9084         is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
   9085         "Missing/invalid function: bool binary(binary_t&)");
   9086     static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
   9087                   "Missing/invalid function: bool start_object(std::size_t)");
   9088     static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
   9089                   "Missing/invalid function: bool key(string_t&)");
   9090     static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
   9091                   "Missing/invalid function: bool end_object()");
   9092     static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
   9093                   "Missing/invalid function: bool start_array(std::size_t)");
   9094     static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
   9095                   "Missing/invalid function: bool end_array()");
   9096     static_assert(
   9097         is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
   9098         "Missing/invalid function: bool parse_error(std::size_t, const "
   9099         "std::string&, const exception&)");
   9100 };
   9101 
   9102 }  // namespace detail
   9103 NLOHMANN_JSON_NAMESPACE_END
   9104 
   9105 // #include <nlohmann/detail/meta/type_traits.hpp>
   9106 
   9107 // #include <nlohmann/detail/string_concat.hpp>
   9108 
   9109 // #include <nlohmann/detail/value_t.hpp>
   9110 
   9111 
   9112 NLOHMANN_JSON_NAMESPACE_BEGIN
   9113 namespace detail
   9114 {
   9115 
   9116 /// how to treat CBOR tags
   9117 enum class cbor_tag_handler_t
   9118 {
   9119     error,   ///< throw a parse_error exception in case of a tag
   9120     ignore,  ///< ignore tags
   9121     store    ///< store tags as binary type
   9122 };
   9123 
   9124 /*!
   9125 @brief determine system byte order
   9126 
   9127 @return true if and only if system's byte order is little endian
   9128 
   9129 @note from https://stackoverflow.com/a/1001328/266378
   9130 */
   9131 static inline bool little_endianness(int num = 1) noexcept
   9132 {
   9133     return *reinterpret_cast<char*>(&num) == 1;
   9134 }
   9135 
   9136 
   9137 ///////////////////
   9138 // binary reader //
   9139 ///////////////////
   9140 
   9141 /*!
   9142 @brief deserialization of CBOR, MessagePack, and UBJSON values
   9143 */
   9144 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
   9145 class binary_reader
   9146 {
   9147     using number_integer_t = typename BasicJsonType::number_integer_t;
   9148     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   9149     using number_float_t = typename BasicJsonType::number_float_t;
   9150     using string_t = typename BasicJsonType::string_t;
   9151     using binary_t = typename BasicJsonType::binary_t;
   9152     using json_sax_t = SAX;
   9153     using char_type = typename InputAdapterType::char_type;
   9154     using char_int_type = typename std::char_traits<char_type>::int_type;
   9155 
   9156   public:
   9157     /*!
   9158     @brief create a binary reader
   9159 
   9160     @param[in] adapter  input adapter to read from
   9161     */
   9162     explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
   9163     {
   9164         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
   9165     }
   9166 
   9167     // make class move-only
   9168     binary_reader(const binary_reader&) = delete;
   9169     binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   9170     binary_reader& operator=(const binary_reader&) = delete;
   9171     binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   9172     ~binary_reader() = default;
   9173 
   9174     /*!
   9175     @param[in] format  the binary format to parse
   9176     @param[in] sax_    a SAX event processor
   9177     @param[in] strict  whether to expect the input to be consumed completed
   9178     @param[in] tag_handler  how to treat CBOR tags
   9179 
   9180     @return whether parsing was successful
   9181     */
   9182     JSON_HEDLEY_NON_NULL(3)
   9183     bool sax_parse(const input_format_t format,
   9184                    json_sax_t* sax_,
   9185                    const bool strict = true,
   9186                    const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
   9187     {
   9188         sax = sax_;
   9189         bool result = false;
   9190 
   9191         switch (format)
   9192         {
   9193             case input_format_t::bson:
   9194                 result = parse_bson_internal();
   9195                 break;
   9196 
   9197             case input_format_t::cbor:
   9198                 result = parse_cbor_internal(true, tag_handler);
   9199                 break;
   9200 
   9201             case input_format_t::msgpack:
   9202                 result = parse_msgpack_internal();
   9203                 break;
   9204 
   9205             case input_format_t::ubjson:
   9206             case input_format_t::bjdata:
   9207                 result = parse_ubjson_internal();
   9208                 break;
   9209 
   9210             case input_format_t::json: // LCOV_EXCL_LINE
   9211             default:            // LCOV_EXCL_LINE
   9212                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   9213         }
   9214 
   9215         // strict mode: next byte must be EOF
   9216         if (result && strict)
   9217         {
   9218             if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
   9219             {
   9220                 get_ignore_noop();
   9221             }
   9222             else
   9223             {
   9224                 get();
   9225             }
   9226 
   9227             if (JSON_HEDLEY_UNLIKELY(current != std::char_traits<char_type>::eof()))
   9228             {
   9229                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
   9230                                         exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
   9231             }
   9232         }
   9233 
   9234         return result;
   9235     }
   9236 
   9237   private:
   9238     //////////
   9239     // BSON //
   9240     //////////
   9241 
   9242     /*!
   9243     @brief Reads in a BSON-object and passes it to the SAX-parser.
   9244     @return whether a valid BSON-value was passed to the SAX parser
   9245     */
   9246     bool parse_bson_internal()
   9247     {
   9248         std::int32_t document_size{};
   9249         get_number<std::int32_t, true>(input_format_t::bson, document_size);
   9250 
   9251         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
   9252         {
   9253             return false;
   9254         }
   9255 
   9256         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
   9257         {
   9258             return false;
   9259         }
   9260 
   9261         return sax->end_object();
   9262     }
   9263 
   9264     /*!
   9265     @brief Parses a C-style string from the BSON input.
   9266     @param[in,out] result  A reference to the string variable where the read
   9267                             string is to be stored.
   9268     @return `true` if the \x00-byte indicating the end of the string was
   9269              encountered before the EOF; false` indicates an unexpected EOF.
   9270     */
   9271     bool get_bson_cstr(string_t& result)
   9272     {
   9273         auto out = std::back_inserter(result);
   9274         while (true)
   9275         {
   9276             get();
   9277             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
   9278             {
   9279                 return false;
   9280             }
   9281             if (current == 0x00)
   9282             {
   9283                 return true;
   9284             }
   9285             *out++ = static_cast<typename string_t::value_type>(current);
   9286         }
   9287     }
   9288 
   9289     /*!
   9290     @brief Parses a zero-terminated string of length @a len from the BSON
   9291            input.
   9292     @param[in] len  The length (including the zero-byte at the end) of the
   9293                     string to be read.
   9294     @param[in,out] result  A reference to the string variable where the read
   9295                             string is to be stored.
   9296     @tparam NumberType The type of the length @a len
   9297     @pre len >= 1
   9298     @return `true` if the string was successfully parsed
   9299     */
   9300     template<typename NumberType>
   9301     bool get_bson_string(const NumberType len, string_t& result)
   9302     {
   9303         if (JSON_HEDLEY_UNLIKELY(len < 1))
   9304         {
   9305             auto last_token = get_token_string();
   9306             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9307                                     exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
   9308         }
   9309 
   9310         return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != std::char_traits<char_type>::eof();
   9311     }
   9312 
   9313     /*!
   9314     @brief Parses a byte array input of length @a len from the BSON input.
   9315     @param[in] len  The length of the byte array to be read.
   9316     @param[in,out] result  A reference to the binary variable where the read
   9317                             array is to be stored.
   9318     @tparam NumberType The type of the length @a len
   9319     @pre len >= 0
   9320     @return `true` if the byte array was successfully parsed
   9321     */
   9322     template<typename NumberType>
   9323     bool get_bson_binary(const NumberType len, binary_t& result)
   9324     {
   9325         if (JSON_HEDLEY_UNLIKELY(len < 0))
   9326         {
   9327             auto last_token = get_token_string();
   9328             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9329                                     exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
   9330         }
   9331 
   9332         // All BSON binary values have a subtype
   9333         std::uint8_t subtype{};
   9334         get_number<std::uint8_t>(input_format_t::bson, subtype);
   9335         result.set_subtype(subtype);
   9336 
   9337         return get_binary(input_format_t::bson, len, result);
   9338     }
   9339 
   9340     /*!
   9341     @brief Read a BSON document element of the given @a element_type.
   9342     @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
   9343     @param[in] element_type_parse_position The position in the input stream,
   9344                where the `element_type` was read.
   9345     @warning Not all BSON element types are supported yet. An unsupported
   9346              @a element_type will give rise to a parse_error.114:
   9347              Unsupported BSON record type 0x...
   9348     @return whether a valid BSON-object/array was passed to the SAX parser
   9349     */
   9350     bool parse_bson_element_internal(const char_int_type element_type,
   9351                                      const std::size_t element_type_parse_position)
   9352     {
   9353         switch (element_type)
   9354         {
   9355             case 0x01: // double
   9356             {
   9357                 double number{};
   9358                 return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
   9359             }
   9360 
   9361             case 0x02: // string
   9362             {
   9363                 std::int32_t len{};
   9364                 string_t value;
   9365                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
   9366             }
   9367 
   9368             case 0x03: // object
   9369             {
   9370                 return parse_bson_internal();
   9371             }
   9372 
   9373             case 0x04: // array
   9374             {
   9375                 return parse_bson_array();
   9376             }
   9377 
   9378             case 0x05: // binary
   9379             {
   9380                 std::int32_t len{};
   9381                 binary_t value;
   9382                 return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
   9383             }
   9384 
   9385             case 0x08: // boolean
   9386             {
   9387                 return sax->boolean(get() != 0);
   9388             }
   9389 
   9390             case 0x0A: // null
   9391             {
   9392                 return sax->null();
   9393             }
   9394 
   9395             case 0x10: // int32
   9396             {
   9397                 std::int32_t value{};
   9398                 return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
   9399             }
   9400 
   9401             case 0x12: // int64
   9402             {
   9403                 std::int64_t value{};
   9404                 return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
   9405             }
   9406 
   9407             default: // anything else not supported (yet)
   9408             {
   9409                 std::array<char, 3> cr{{}};
   9410                 static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   9411                 const std::string cr_str{cr.data()};
   9412                 return sax->parse_error(element_type_parse_position, cr_str,
   9413                                         parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
   9414             }
   9415         }
   9416     }
   9417 
   9418     /*!
   9419     @brief Read a BSON element list (as specified in the BSON-spec)
   9420 
   9421     The same binary layout is used for objects and arrays, hence it must be
   9422     indicated with the argument @a is_array which one is expected
   9423     (true --> array, false --> object).
   9424 
   9425     @param[in] is_array Determines if the element list being read is to be
   9426                         treated as an object (@a is_array == false), or as an
   9427                         array (@a is_array == true).
   9428     @return whether a valid BSON-object/array was passed to the SAX parser
   9429     */
   9430     bool parse_bson_element_list(const bool is_array)
   9431     {
   9432         string_t key;
   9433 
   9434         while (auto element_type = get())
   9435         {
   9436             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
   9437             {
   9438                 return false;
   9439             }
   9440 
   9441             const std::size_t element_type_parse_position = chars_read;
   9442             if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
   9443             {
   9444                 return false;
   9445             }
   9446 
   9447             if (!is_array && !sax->key(key))
   9448             {
   9449                 return false;
   9450             }
   9451 
   9452             if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
   9453             {
   9454                 return false;
   9455             }
   9456 
   9457             // get_bson_cstr only appends
   9458             key.clear();
   9459         }
   9460 
   9461         return true;
   9462     }
   9463 
   9464     /*!
   9465     @brief Reads an array from the BSON input and passes it to the SAX-parser.
   9466     @return whether a valid BSON-array was passed to the SAX parser
   9467     */
   9468     bool parse_bson_array()
   9469     {
   9470         std::int32_t document_size{};
   9471         get_number<std::int32_t, true>(input_format_t::bson, document_size);
   9472 
   9473         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
   9474         {
   9475             return false;
   9476         }
   9477 
   9478         if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
   9479         {
   9480             return false;
   9481         }
   9482 
   9483         return sax->end_array();
   9484     }
   9485 
   9486     //////////
   9487     // CBOR //
   9488     //////////
   9489 
   9490     /*!
   9491     @param[in] get_char  whether a new character should be retrieved from the
   9492                          input (true) or whether the last read character should
   9493                          be considered instead (false)
   9494     @param[in] tag_handler how CBOR tags should be treated
   9495 
   9496     @return whether a valid CBOR value was passed to the SAX parser
   9497     */
   9498     bool parse_cbor_internal(const bool get_char,
   9499                              const cbor_tag_handler_t tag_handler)
   9500     {
   9501         switch (get_char ? get() : current)
   9502         {
   9503             // EOF
   9504             case std::char_traits<char_type>::eof():
   9505                 return unexpect_eof(input_format_t::cbor, "value");
   9506 
   9507             // Integer 0x00..0x17 (0..23)
   9508             case 0x00:
   9509             case 0x01:
   9510             case 0x02:
   9511             case 0x03:
   9512             case 0x04:
   9513             case 0x05:
   9514             case 0x06:
   9515             case 0x07:
   9516             case 0x08:
   9517             case 0x09:
   9518             case 0x0A:
   9519             case 0x0B:
   9520             case 0x0C:
   9521             case 0x0D:
   9522             case 0x0E:
   9523             case 0x0F:
   9524             case 0x10:
   9525             case 0x11:
   9526             case 0x12:
   9527             case 0x13:
   9528             case 0x14:
   9529             case 0x15:
   9530             case 0x16:
   9531             case 0x17:
   9532                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
   9533 
   9534             case 0x18: // Unsigned integer (one-byte uint8_t follows)
   9535             {
   9536                 std::uint8_t number{};
   9537                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9538             }
   9539 
   9540             case 0x19: // Unsigned integer (two-byte uint16_t follows)
   9541             {
   9542                 std::uint16_t number{};
   9543                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9544             }
   9545 
   9546             case 0x1A: // Unsigned integer (four-byte uint32_t follows)
   9547             {
   9548                 std::uint32_t number{};
   9549                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9550             }
   9551 
   9552             case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
   9553             {
   9554                 std::uint64_t number{};
   9555                 return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9556             }
   9557 
   9558             // Negative integer -1-0x00..-1-0x17 (-1..-24)
   9559             case 0x20:
   9560             case 0x21:
   9561             case 0x22:
   9562             case 0x23:
   9563             case 0x24:
   9564             case 0x25:
   9565             case 0x26:
   9566             case 0x27:
   9567             case 0x28:
   9568             case 0x29:
   9569             case 0x2A:
   9570             case 0x2B:
   9571             case 0x2C:
   9572             case 0x2D:
   9573             case 0x2E:
   9574             case 0x2F:
   9575             case 0x30:
   9576             case 0x31:
   9577             case 0x32:
   9578             case 0x33:
   9579             case 0x34:
   9580             case 0x35:
   9581             case 0x36:
   9582             case 0x37:
   9583                 return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
   9584 
   9585             case 0x38: // Negative integer (one-byte uint8_t follows)
   9586             {
   9587                 std::uint8_t number{};
   9588                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
   9589             }
   9590 
   9591             case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
   9592             {
   9593                 std::uint16_t number{};
   9594                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
   9595             }
   9596 
   9597             case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
   9598             {
   9599                 std::uint32_t number{};
   9600                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
   9601             }
   9602 
   9603             case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
   9604             {
   9605                 std::uint64_t number{};
   9606                 return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
   9607                         - static_cast<number_integer_t>(number));
   9608             }
   9609 
   9610             // Binary data (0x00..0x17 bytes follow)
   9611             case 0x40:
   9612             case 0x41:
   9613             case 0x42:
   9614             case 0x43:
   9615             case 0x44:
   9616             case 0x45:
   9617             case 0x46:
   9618             case 0x47:
   9619             case 0x48:
   9620             case 0x49:
   9621             case 0x4A:
   9622             case 0x4B:
   9623             case 0x4C:
   9624             case 0x4D:
   9625             case 0x4E:
   9626             case 0x4F:
   9627             case 0x50:
   9628             case 0x51:
   9629             case 0x52:
   9630             case 0x53:
   9631             case 0x54:
   9632             case 0x55:
   9633             case 0x56:
   9634             case 0x57:
   9635             case 0x58: // Binary data (one-byte uint8_t for n follows)
   9636             case 0x59: // Binary data (two-byte uint16_t for n follow)
   9637             case 0x5A: // Binary data (four-byte uint32_t for n follow)
   9638             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
   9639             case 0x5F: // Binary data (indefinite length)
   9640             {
   9641                 binary_t b;
   9642                 return get_cbor_binary(b) && sax->binary(b);
   9643             }
   9644 
   9645             // UTF-8 string (0x00..0x17 bytes follow)
   9646             case 0x60:
   9647             case 0x61:
   9648             case 0x62:
   9649             case 0x63:
   9650             case 0x64:
   9651             case 0x65:
   9652             case 0x66:
   9653             case 0x67:
   9654             case 0x68:
   9655             case 0x69:
   9656             case 0x6A:
   9657             case 0x6B:
   9658             case 0x6C:
   9659             case 0x6D:
   9660             case 0x6E:
   9661             case 0x6F:
   9662             case 0x70:
   9663             case 0x71:
   9664             case 0x72:
   9665             case 0x73:
   9666             case 0x74:
   9667             case 0x75:
   9668             case 0x76:
   9669             case 0x77:
   9670             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
   9671             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
   9672             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
   9673             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
   9674             case 0x7F: // UTF-8 string (indefinite length)
   9675             {
   9676                 string_t s;
   9677                 return get_cbor_string(s) && sax->string(s);
   9678             }
   9679 
   9680             // array (0x00..0x17 data items follow)
   9681             case 0x80:
   9682             case 0x81:
   9683             case 0x82:
   9684             case 0x83:
   9685             case 0x84:
   9686             case 0x85:
   9687             case 0x86:
   9688             case 0x87:
   9689             case 0x88:
   9690             case 0x89:
   9691             case 0x8A:
   9692             case 0x8B:
   9693             case 0x8C:
   9694             case 0x8D:
   9695             case 0x8E:
   9696             case 0x8F:
   9697             case 0x90:
   9698             case 0x91:
   9699             case 0x92:
   9700             case 0x93:
   9701             case 0x94:
   9702             case 0x95:
   9703             case 0x96:
   9704             case 0x97:
   9705                 return get_cbor_array(
   9706                            conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
   9707 
   9708             case 0x98: // array (one-byte uint8_t for n follows)
   9709             {
   9710                 std::uint8_t len{};
   9711                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
   9712             }
   9713 
   9714             case 0x99: // array (two-byte uint16_t for n follow)
   9715             {
   9716                 std::uint16_t len{};
   9717                 return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
   9718             }
   9719 
   9720             case 0x9A: // array (four-byte uint32_t for n follow)
   9721             {
   9722                 std::uint32_t len{};
   9723                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
   9724             }
   9725 
   9726             case 0x9B: // array (eight-byte uint64_t for n follow)
   9727             {
   9728                 std::uint64_t len{};
   9729                 return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
   9730             }
   9731 
   9732             case 0x9F: // array (indefinite length)
   9733                 return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
   9734 
   9735             // map (0x00..0x17 pairs of data items follow)
   9736             case 0xA0:
   9737             case 0xA1:
   9738             case 0xA2:
   9739             case 0xA3:
   9740             case 0xA4:
   9741             case 0xA5:
   9742             case 0xA6:
   9743             case 0xA7:
   9744             case 0xA8:
   9745             case 0xA9:
   9746             case 0xAA:
   9747             case 0xAB:
   9748             case 0xAC:
   9749             case 0xAD:
   9750             case 0xAE:
   9751             case 0xAF:
   9752             case 0xB0:
   9753             case 0xB1:
   9754             case 0xB2:
   9755             case 0xB3:
   9756             case 0xB4:
   9757             case 0xB5:
   9758             case 0xB6:
   9759             case 0xB7:
   9760                 return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
   9761 
   9762             case 0xB8: // map (one-byte uint8_t for n follows)
   9763             {
   9764                 std::uint8_t len{};
   9765                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
   9766             }
   9767 
   9768             case 0xB9: // map (two-byte uint16_t for n follow)
   9769             {
   9770                 std::uint16_t len{};
   9771                 return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
   9772             }
   9773 
   9774             case 0xBA: // map (four-byte uint32_t for n follow)
   9775             {
   9776                 std::uint32_t len{};
   9777                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
   9778             }
   9779 
   9780             case 0xBB: // map (eight-byte uint64_t for n follow)
   9781             {
   9782                 std::uint64_t len{};
   9783                 return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
   9784             }
   9785 
   9786             case 0xBF: // map (indefinite length)
   9787                 return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
   9788 
   9789             case 0xC6: // tagged item
   9790             case 0xC7:
   9791             case 0xC8:
   9792             case 0xC9:
   9793             case 0xCA:
   9794             case 0xCB:
   9795             case 0xCC:
   9796             case 0xCD:
   9797             case 0xCE:
   9798             case 0xCF:
   9799             case 0xD0:
   9800             case 0xD1:
   9801             case 0xD2:
   9802             case 0xD3:
   9803             case 0xD4:
   9804             case 0xD8: // tagged item (1 bytes follow)
   9805             case 0xD9: // tagged item (2 bytes follow)
   9806             case 0xDA: // tagged item (4 bytes follow)
   9807             case 0xDB: // tagged item (8 bytes follow)
   9808             {
   9809                 switch (tag_handler)
   9810                 {
   9811                     case cbor_tag_handler_t::error:
   9812                     {
   9813                         auto last_token = get_token_string();
   9814                         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9815                                                 exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
   9816                     }
   9817 
   9818                     case cbor_tag_handler_t::ignore:
   9819                     {
   9820                         // ignore binary subtype
   9821                         switch (current)
   9822                         {
   9823                             case 0xD8:
   9824                             {
   9825                                 std::uint8_t subtype_to_ignore{};
   9826                                 get_number(input_format_t::cbor, subtype_to_ignore);
   9827                                 break;
   9828                             }
   9829                             case 0xD9:
   9830                             {
   9831                                 std::uint16_t subtype_to_ignore{};
   9832                                 get_number(input_format_t::cbor, subtype_to_ignore);
   9833                                 break;
   9834                             }
   9835                             case 0xDA:
   9836                             {
   9837                                 std::uint32_t subtype_to_ignore{};
   9838                                 get_number(input_format_t::cbor, subtype_to_ignore);
   9839                                 break;
   9840                             }
   9841                             case 0xDB:
   9842                             {
   9843                                 std::uint64_t subtype_to_ignore{};
   9844                                 get_number(input_format_t::cbor, subtype_to_ignore);
   9845                                 break;
   9846                             }
   9847                             default:
   9848                                 break;
   9849                         }
   9850                         return parse_cbor_internal(true, tag_handler);
   9851                     }
   9852 
   9853                     case cbor_tag_handler_t::store:
   9854                     {
   9855                         binary_t b;
   9856                         // use binary subtype and store in binary container
   9857                         switch (current)
   9858                         {
   9859                             case 0xD8:
   9860                             {
   9861                                 std::uint8_t subtype{};
   9862                                 get_number(input_format_t::cbor, subtype);
   9863                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9864                                 break;
   9865                             }
   9866                             case 0xD9:
   9867                             {
   9868                                 std::uint16_t subtype{};
   9869                                 get_number(input_format_t::cbor, subtype);
   9870                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9871                                 break;
   9872                             }
   9873                             case 0xDA:
   9874                             {
   9875                                 std::uint32_t subtype{};
   9876                                 get_number(input_format_t::cbor, subtype);
   9877                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9878                                 break;
   9879                             }
   9880                             case 0xDB:
   9881                             {
   9882                                 std::uint64_t subtype{};
   9883                                 get_number(input_format_t::cbor, subtype);
   9884                                 b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9885                                 break;
   9886                             }
   9887                             default:
   9888                                 return parse_cbor_internal(true, tag_handler);
   9889                         }
   9890                         get();
   9891                         return get_cbor_binary(b) && sax->binary(b);
   9892                     }
   9893 
   9894                     default:                 // LCOV_EXCL_LINE
   9895                         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   9896                         return false;        // LCOV_EXCL_LINE
   9897                 }
   9898             }
   9899 
   9900             case 0xF4: // false
   9901                 return sax->boolean(false);
   9902 
   9903             case 0xF5: // true
   9904                 return sax->boolean(true);
   9905 
   9906             case 0xF6: // null
   9907                 return sax->null();
   9908 
   9909             case 0xF9: // Half-Precision Float (two-byte IEEE 754)
   9910             {
   9911                 const auto byte1_raw = get();
   9912                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
   9913                 {
   9914                     return false;
   9915                 }
   9916                 const auto byte2_raw = get();
   9917                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
   9918                 {
   9919                     return false;
   9920                 }
   9921 
   9922                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
   9923                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
   9924 
   9925                 // code from RFC 7049, Appendix D, Figure 3:
   9926                 // As half-precision floating-point numbers were only added
   9927                 // to IEEE 754 in 2008, today's programming platforms often
   9928                 // still only have limited support for them. It is very
   9929                 // easy to include at least decoding support for them even
   9930                 // without such support. An example of a small decoder for
   9931                 // half-precision floating-point numbers in the C language
   9932                 // is shown in Fig. 3.
   9933                 const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
   9934                 const double val = [&half]
   9935                 {
   9936                     const int exp = (half >> 10u) & 0x1Fu;
   9937                     const unsigned int mant = half & 0x3FFu;
   9938                     JSON_ASSERT(0 <= exp&& exp <= 32);
   9939                     JSON_ASSERT(mant <= 1024);
   9940                     switch (exp)
   9941                     {
   9942                         case 0:
   9943                             return std::ldexp(mant, -24);
   9944                         case 31:
   9945                             return (mant == 0)
   9946                             ? std::numeric_limits<double>::infinity()
   9947                             : std::numeric_limits<double>::quiet_NaN();
   9948                         default:
   9949                             return std::ldexp(mant + 1024, exp - 25);
   9950                     }
   9951                 }();
   9952                 return sax->number_float((half & 0x8000u) != 0
   9953                                          ? static_cast<number_float_t>(-val)
   9954                                          : static_cast<number_float_t>(val), "");
   9955             }
   9956 
   9957             case 0xFA: // Single-Precision Float (four-byte IEEE 754)
   9958             {
   9959                 float number{};
   9960                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
   9961             }
   9962 
   9963             case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
   9964             {
   9965                 double number{};
   9966                 return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
   9967             }
   9968 
   9969             default: // anything else (0xFF is handled inside the other types)
   9970             {
   9971                 auto last_token = get_token_string();
   9972                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9973                                         exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
   9974             }
   9975         }
   9976     }
   9977 
   9978     /*!
   9979     @brief reads a CBOR string
   9980 
   9981     This function first reads starting bytes to determine the expected
   9982     string length and then copies this number of bytes into a string.
   9983     Additionally, CBOR's strings with indefinite lengths are supported.
   9984 
   9985     @param[out] result  created string
   9986 
   9987     @return whether string creation completed
   9988     */
   9989     bool get_cbor_string(string_t& result)
   9990     {
   9991         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
   9992         {
   9993             return false;
   9994         }
   9995 
   9996         switch (current)
   9997         {
   9998             // UTF-8 string (0x00..0x17 bytes follow)
   9999             case 0x60:
  10000             case 0x61:
  10001             case 0x62:
  10002             case 0x63:
  10003             case 0x64:
  10004             case 0x65:
  10005             case 0x66:
  10006             case 0x67:
  10007             case 0x68:
  10008             case 0x69:
  10009             case 0x6A:
  10010             case 0x6B:
  10011             case 0x6C:
  10012             case 0x6D:
  10013             case 0x6E:
  10014             case 0x6F:
  10015             case 0x70:
  10016             case 0x71:
  10017             case 0x72:
  10018             case 0x73:
  10019             case 0x74:
  10020             case 0x75:
  10021             case 0x76:
  10022             case 0x77:
  10023             {
  10024                 return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
  10025             }
  10026 
  10027             case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
  10028             {
  10029                 std::uint8_t len{};
  10030                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10031             }
  10032 
  10033             case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
  10034             {
  10035                 std::uint16_t len{};
  10036                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10037             }
  10038 
  10039             case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
  10040             {
  10041                 std::uint32_t len{};
  10042                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10043             }
  10044 
  10045             case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
  10046             {
  10047                 std::uint64_t len{};
  10048                 return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10049             }
  10050 
  10051             case 0x7F: // UTF-8 string (indefinite length)
  10052             {
  10053                 while (get() != 0xFF)
  10054                 {
  10055                     string_t chunk;
  10056                     if (!get_cbor_string(chunk))
  10057                     {
  10058                         return false;
  10059                     }
  10060                     result.append(chunk);
  10061                 }
  10062                 return true;
  10063             }
  10064 
  10065             default:
  10066             {
  10067                 auto last_token = get_token_string();
  10068                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  10069                                         exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
  10070             }
  10071         }
  10072     }
  10073 
  10074     /*!
  10075     @brief reads a CBOR byte array
  10076 
  10077     This function first reads starting bytes to determine the expected
  10078     byte array length and then copies this number of bytes into the byte array.
  10079     Additionally, CBOR's byte arrays with indefinite lengths are supported.
  10080 
  10081     @param[out] result  created byte array
  10082 
  10083     @return whether byte array creation completed
  10084     */
  10085     bool get_cbor_binary(binary_t& result)
  10086     {
  10087         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
  10088         {
  10089             return false;
  10090         }
  10091 
  10092         switch (current)
  10093         {
  10094             // Binary data (0x00..0x17 bytes follow)
  10095             case 0x40:
  10096             case 0x41:
  10097             case 0x42:
  10098             case 0x43:
  10099             case 0x44:
  10100             case 0x45:
  10101             case 0x46:
  10102             case 0x47:
  10103             case 0x48:
  10104             case 0x49:
  10105             case 0x4A:
  10106             case 0x4B:
  10107             case 0x4C:
  10108             case 0x4D:
  10109             case 0x4E:
  10110             case 0x4F:
  10111             case 0x50:
  10112             case 0x51:
  10113             case 0x52:
  10114             case 0x53:
  10115             case 0x54:
  10116             case 0x55:
  10117             case 0x56:
  10118             case 0x57:
  10119             {
  10120                 return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
  10121             }
  10122 
  10123             case 0x58: // Binary data (one-byte uint8_t for n follows)
  10124             {
  10125                 std::uint8_t len{};
  10126                 return get_number(input_format_t::cbor, len) &&
  10127                        get_binary(input_format_t::cbor, len, result);
  10128             }
  10129 
  10130             case 0x59: // Binary data (two-byte uint16_t for n follow)
  10131             {
  10132                 std::uint16_t len{};
  10133                 return get_number(input_format_t::cbor, len) &&
  10134                        get_binary(input_format_t::cbor, len, result);
  10135             }
  10136 
  10137             case 0x5A: // Binary data (four-byte uint32_t for n follow)
  10138             {
  10139                 std::uint32_t len{};
  10140                 return get_number(input_format_t::cbor, len) &&
  10141                        get_binary(input_format_t::cbor, len, result);
  10142             }
  10143 
  10144             case 0x5B: // Binary data (eight-byte uint64_t for n follow)
  10145             {
  10146                 std::uint64_t len{};
  10147                 return get_number(input_format_t::cbor, len) &&
  10148                        get_binary(input_format_t::cbor, len, result);
  10149             }
  10150 
  10151             case 0x5F: // Binary data (indefinite length)
  10152             {
  10153                 while (get() != 0xFF)
  10154                 {
  10155                     binary_t chunk;
  10156                     if (!get_cbor_binary(chunk))
  10157                     {
  10158                         return false;
  10159                     }
  10160                     result.insert(result.end(), chunk.begin(), chunk.end());
  10161                 }
  10162                 return true;
  10163             }
  10164 
  10165             default:
  10166             {
  10167                 auto last_token = get_token_string();
  10168                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  10169                                         exception_message(input_format_t::cbor, concat("expected length specification (0x40-0x5B) or indefinite binary array type (0x5F); last byte: 0x", last_token), "binary"), nullptr));
  10170             }
  10171         }
  10172     }
  10173 
  10174     /*!
  10175     @param[in] len  the length of the array or static_cast<std::size_t>(-1) for an
  10176                     array of indefinite size
  10177     @param[in] tag_handler how CBOR tags should be treated
  10178     @return whether array creation completed
  10179     */
  10180     bool get_cbor_array(const std::size_t len,
  10181                         const cbor_tag_handler_t tag_handler)
  10182     {
  10183         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
  10184         {
  10185             return false;
  10186         }
  10187 
  10188         if (len != static_cast<std::size_t>(-1))
  10189         {
  10190             for (std::size_t i = 0; i < len; ++i)
  10191             {
  10192                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
  10193                 {
  10194                     return false;
  10195                 }
  10196             }
  10197         }
  10198         else
  10199         {
  10200             while (get() != 0xFF)
  10201             {
  10202                 if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
  10203                 {
  10204                     return false;
  10205                 }
  10206             }
  10207         }
  10208 
  10209         return sax->end_array();
  10210     }
  10211 
  10212     /*!
  10213     @param[in] len  the length of the object or static_cast<std::size_t>(-1) for an
  10214                     object of indefinite size
  10215     @param[in] tag_handler how CBOR tags should be treated
  10216     @return whether object creation completed
  10217     */
  10218     bool get_cbor_object(const std::size_t len,
  10219                          const cbor_tag_handler_t tag_handler)
  10220     {
  10221         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
  10222         {
  10223             return false;
  10224         }
  10225 
  10226         if (len != 0)
  10227         {
  10228             string_t key;
  10229             if (len != static_cast<std::size_t>(-1))
  10230             {
  10231                 for (std::size_t i = 0; i < len; ++i)
  10232                 {
  10233                     get();
  10234                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
  10235                     {
  10236                         return false;
  10237                     }
  10238 
  10239                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
  10240                     {
  10241                         return false;
  10242                     }
  10243                     key.clear();
  10244                 }
  10245             }
  10246             else
  10247             {
  10248                 while (get() != 0xFF)
  10249                 {
  10250                     if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
  10251                     {
  10252                         return false;
  10253                     }
  10254 
  10255                     if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
  10256                     {
  10257                         return false;
  10258                     }
  10259                     key.clear();
  10260                 }
  10261             }
  10262         }
  10263 
  10264         return sax->end_object();
  10265     }
  10266 
  10267     /////////////
  10268     // MsgPack //
  10269     /////////////
  10270 
  10271     /*!
  10272     @return whether a valid MessagePack value was passed to the SAX parser
  10273     */
  10274     bool parse_msgpack_internal()
  10275     {
  10276         switch (get())
  10277         {
  10278             // EOF
  10279             case std::char_traits<char_type>::eof():
  10280                 return unexpect_eof(input_format_t::msgpack, "value");
  10281 
  10282             // positive fixint
  10283             case 0x00:
  10284             case 0x01:
  10285             case 0x02:
  10286             case 0x03:
  10287             case 0x04:
  10288             case 0x05:
  10289             case 0x06:
  10290             case 0x07:
  10291             case 0x08:
  10292             case 0x09:
  10293             case 0x0A:
  10294             case 0x0B:
  10295             case 0x0C:
  10296             case 0x0D:
  10297             case 0x0E:
  10298             case 0x0F:
  10299             case 0x10:
  10300             case 0x11:
  10301             case 0x12:
  10302             case 0x13:
  10303             case 0x14:
  10304             case 0x15:
  10305             case 0x16:
  10306             case 0x17:
  10307             case 0x18:
  10308             case 0x19:
  10309             case 0x1A:
  10310             case 0x1B:
  10311             case 0x1C:
  10312             case 0x1D:
  10313             case 0x1E:
  10314             case 0x1F:
  10315             case 0x20:
  10316             case 0x21:
  10317             case 0x22:
  10318             case 0x23:
  10319             case 0x24:
  10320             case 0x25:
  10321             case 0x26:
  10322             case 0x27:
  10323             case 0x28:
  10324             case 0x29:
  10325             case 0x2A:
  10326             case 0x2B:
  10327             case 0x2C:
  10328             case 0x2D:
  10329             case 0x2E:
  10330             case 0x2F:
  10331             case 0x30:
  10332             case 0x31:
  10333             case 0x32:
  10334             case 0x33:
  10335             case 0x34:
  10336             case 0x35:
  10337             case 0x36:
  10338             case 0x37:
  10339             case 0x38:
  10340             case 0x39:
  10341             case 0x3A:
  10342             case 0x3B:
  10343             case 0x3C:
  10344             case 0x3D:
  10345             case 0x3E:
  10346             case 0x3F:
  10347             case 0x40:
  10348             case 0x41:
  10349             case 0x42:
  10350             case 0x43:
  10351             case 0x44:
  10352             case 0x45:
  10353             case 0x46:
  10354             case 0x47:
  10355             case 0x48:
  10356             case 0x49:
  10357             case 0x4A:
  10358             case 0x4B:
  10359             case 0x4C:
  10360             case 0x4D:
  10361             case 0x4E:
  10362             case 0x4F:
  10363             case 0x50:
  10364             case 0x51:
  10365             case 0x52:
  10366             case 0x53:
  10367             case 0x54:
  10368             case 0x55:
  10369             case 0x56:
  10370             case 0x57:
  10371             case 0x58:
  10372             case 0x59:
  10373             case 0x5A:
  10374             case 0x5B:
  10375             case 0x5C:
  10376             case 0x5D:
  10377             case 0x5E:
  10378             case 0x5F:
  10379             case 0x60:
  10380             case 0x61:
  10381             case 0x62:
  10382             case 0x63:
  10383             case 0x64:
  10384             case 0x65:
  10385             case 0x66:
  10386             case 0x67:
  10387             case 0x68:
  10388             case 0x69:
  10389             case 0x6A:
  10390             case 0x6B:
  10391             case 0x6C:
  10392             case 0x6D:
  10393             case 0x6E:
  10394             case 0x6F:
  10395             case 0x70:
  10396             case 0x71:
  10397             case 0x72:
  10398             case 0x73:
  10399             case 0x74:
  10400             case 0x75:
  10401             case 0x76:
  10402             case 0x77:
  10403             case 0x78:
  10404             case 0x79:
  10405             case 0x7A:
  10406             case 0x7B:
  10407             case 0x7C:
  10408             case 0x7D:
  10409             case 0x7E:
  10410             case 0x7F:
  10411                 return sax->number_unsigned(static_cast<number_unsigned_t>(current));
  10412 
  10413             // fixmap
  10414             case 0x80:
  10415             case 0x81:
  10416             case 0x82:
  10417             case 0x83:
  10418             case 0x84:
  10419             case 0x85:
  10420             case 0x86:
  10421             case 0x87:
  10422             case 0x88:
  10423             case 0x89:
  10424             case 0x8A:
  10425             case 0x8B:
  10426             case 0x8C:
  10427             case 0x8D:
  10428             case 0x8E:
  10429             case 0x8F:
  10430                 return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
  10431 
  10432             // fixarray
  10433             case 0x90:
  10434             case 0x91:
  10435             case 0x92:
  10436             case 0x93:
  10437             case 0x94:
  10438             case 0x95:
  10439             case 0x96:
  10440             case 0x97:
  10441             case 0x98:
  10442             case 0x99:
  10443             case 0x9A:
  10444             case 0x9B:
  10445             case 0x9C:
  10446             case 0x9D:
  10447             case 0x9E:
  10448             case 0x9F:
  10449                 return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
  10450 
  10451             // fixstr
  10452             case 0xA0:
  10453             case 0xA1:
  10454             case 0xA2:
  10455             case 0xA3:
  10456             case 0xA4:
  10457             case 0xA5:
  10458             case 0xA6:
  10459             case 0xA7:
  10460             case 0xA8:
  10461             case 0xA9:
  10462             case 0xAA:
  10463             case 0xAB:
  10464             case 0xAC:
  10465             case 0xAD:
  10466             case 0xAE:
  10467             case 0xAF:
  10468             case 0xB0:
  10469             case 0xB1:
  10470             case 0xB2:
  10471             case 0xB3:
  10472             case 0xB4:
  10473             case 0xB5:
  10474             case 0xB6:
  10475             case 0xB7:
  10476             case 0xB8:
  10477             case 0xB9:
  10478             case 0xBA:
  10479             case 0xBB:
  10480             case 0xBC:
  10481             case 0xBD:
  10482             case 0xBE:
  10483             case 0xBF:
  10484             case 0xD9: // str 8
  10485             case 0xDA: // str 16
  10486             case 0xDB: // str 32
  10487             {
  10488                 string_t s;
  10489                 return get_msgpack_string(s) && sax->string(s);
  10490             }
  10491 
  10492             case 0xC0: // nil
  10493                 return sax->null();
  10494 
  10495             case 0xC2: // false
  10496                 return sax->boolean(false);
  10497 
  10498             case 0xC3: // true
  10499                 return sax->boolean(true);
  10500 
  10501             case 0xC4: // bin 8
  10502             case 0xC5: // bin 16
  10503             case 0xC6: // bin 32
  10504             case 0xC7: // ext 8
  10505             case 0xC8: // ext 16
  10506             case 0xC9: // ext 32
  10507             case 0xD4: // fixext 1
  10508             case 0xD5: // fixext 2
  10509             case 0xD6: // fixext 4
  10510             case 0xD7: // fixext 8
  10511             case 0xD8: // fixext 16
  10512             {
  10513                 binary_t b;
  10514                 return get_msgpack_binary(b) && sax->binary(b);
  10515             }
  10516 
  10517             case 0xCA: // float 32
  10518             {
  10519                 float number{};
  10520                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
  10521             }
  10522 
  10523             case 0xCB: // float 64
  10524             {
  10525                 double number{};
  10526                 return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
  10527             }
  10528 
  10529             case 0xCC: // uint 8
  10530             {
  10531                 std::uint8_t number{};
  10532                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10533             }
  10534 
  10535             case 0xCD: // uint 16
  10536             {
  10537                 std::uint16_t number{};
  10538                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10539             }
  10540 
  10541             case 0xCE: // uint 32
  10542             {
  10543                 std::uint32_t number{};
  10544                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10545             }
  10546 
  10547             case 0xCF: // uint 64
  10548             {
  10549                 std::uint64_t number{};
  10550                 return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10551             }
  10552 
  10553             case 0xD0: // int 8
  10554             {
  10555                 std::int8_t number{};
  10556                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10557             }
  10558 
  10559             case 0xD1: // int 16
  10560             {
  10561                 std::int16_t number{};
  10562                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10563             }
  10564 
  10565             case 0xD2: // int 32
  10566             {
  10567                 std::int32_t number{};
  10568                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10569             }
  10570 
  10571             case 0xD3: // int 64
  10572             {
  10573                 std::int64_t number{};
  10574                 return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10575             }
  10576 
  10577             case 0xDC: // array 16
  10578             {
  10579                 std::uint16_t len{};
  10580                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
  10581             }
  10582 
  10583             case 0xDD: // array 32
  10584             {
  10585                 std::uint32_t len{};
  10586                 return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
  10587             }
  10588 
  10589             case 0xDE: // map 16
  10590             {
  10591                 std::uint16_t len{};
  10592                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
  10593             }
  10594 
  10595             case 0xDF: // map 32
  10596             {
  10597                 std::uint32_t len{};
  10598                 return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
  10599             }
  10600 
  10601             // negative fixint
  10602             case 0xE0:
  10603             case 0xE1:
  10604             case 0xE2:
  10605             case 0xE3:
  10606             case 0xE4:
  10607             case 0xE5:
  10608             case 0xE6:
  10609             case 0xE7:
  10610             case 0xE8:
  10611             case 0xE9:
  10612             case 0xEA:
  10613             case 0xEB:
  10614             case 0xEC:
  10615             case 0xED:
  10616             case 0xEE:
  10617             case 0xEF:
  10618             case 0xF0:
  10619             case 0xF1:
  10620             case 0xF2:
  10621             case 0xF3:
  10622             case 0xF4:
  10623             case 0xF5:
  10624             case 0xF6:
  10625             case 0xF7:
  10626             case 0xF8:
  10627             case 0xF9:
  10628             case 0xFA:
  10629             case 0xFB:
  10630             case 0xFC:
  10631             case 0xFD:
  10632             case 0xFE:
  10633             case 0xFF:
  10634                 return sax->number_integer(static_cast<std::int8_t>(current));
  10635 
  10636             default: // anything else
  10637             {
  10638                 auto last_token = get_token_string();
  10639                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  10640                                         exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
  10641             }
  10642         }
  10643     }
  10644 
  10645     /*!
  10646     @brief reads a MessagePack string
  10647 
  10648     This function first reads starting bytes to determine the expected
  10649     string length and then copies this number of bytes into a string.
  10650 
  10651     @param[out] result  created string
  10652 
  10653     @return whether string creation completed
  10654     */
  10655     bool get_msgpack_string(string_t& result)
  10656     {
  10657         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
  10658         {
  10659             return false;
  10660         }
  10661 
  10662         switch (current)
  10663         {
  10664             // fixstr
  10665             case 0xA0:
  10666             case 0xA1:
  10667             case 0xA2:
  10668             case 0xA3:
  10669             case 0xA4:
  10670             case 0xA5:
  10671             case 0xA6:
  10672             case 0xA7:
  10673             case 0xA8:
  10674             case 0xA9:
  10675             case 0xAA:
  10676             case 0xAB:
  10677             case 0xAC:
  10678             case 0xAD:
  10679             case 0xAE:
  10680             case 0xAF:
  10681             case 0xB0:
  10682             case 0xB1:
  10683             case 0xB2:
  10684             case 0xB3:
  10685             case 0xB4:
  10686             case 0xB5:
  10687             case 0xB6:
  10688             case 0xB7:
  10689             case 0xB8:
  10690             case 0xB9:
  10691             case 0xBA:
  10692             case 0xBB:
  10693             case 0xBC:
  10694             case 0xBD:
  10695             case 0xBE:
  10696             case 0xBF:
  10697             {
  10698                 return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
  10699             }
  10700 
  10701             case 0xD9: // str 8
  10702             {
  10703                 std::uint8_t len{};
  10704                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
  10705             }
  10706 
  10707             case 0xDA: // str 16
  10708             {
  10709                 std::uint16_t len{};
  10710                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
  10711             }
  10712 
  10713             case 0xDB: // str 32
  10714             {
  10715                 std::uint32_t len{};
  10716                 return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
  10717             }
  10718 
  10719             default:
  10720             {
  10721                 auto last_token = get_token_string();
  10722                 return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  10723                                         exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
  10724             }
  10725         }
  10726     }
  10727 
  10728     /*!
  10729     @brief reads a MessagePack byte array
  10730 
  10731     This function first reads starting bytes to determine the expected
  10732     byte array length and then copies this number of bytes into a byte array.
  10733 
  10734     @param[out] result  created byte array
  10735 
  10736     @return whether byte array creation completed
  10737     */
  10738     bool get_msgpack_binary(binary_t& result)
  10739     {
  10740         // helper function to set the subtype
  10741         auto assign_and_return_true = [&result](std::int8_t subtype)
  10742         {
  10743             result.set_subtype(static_cast<std::uint8_t>(subtype));
  10744             return true;
  10745         };
  10746 
  10747         switch (current)
  10748         {
  10749             case 0xC4: // bin 8
  10750             {
  10751                 std::uint8_t len{};
  10752                 return get_number(input_format_t::msgpack, len) &&
  10753                        get_binary(input_format_t::msgpack, len, result);
  10754             }
  10755 
  10756             case 0xC5: // bin 16
  10757             {
  10758                 std::uint16_t len{};
  10759                 return get_number(input_format_t::msgpack, len) &&
  10760                        get_binary(input_format_t::msgpack, len, result);
  10761             }
  10762 
  10763             case 0xC6: // bin 32
  10764             {
  10765                 std::uint32_t len{};
  10766                 return get_number(input_format_t::msgpack, len) &&
  10767                        get_binary(input_format_t::msgpack, len, result);
  10768             }
  10769 
  10770             case 0xC7: // ext 8
  10771             {
  10772                 std::uint8_t len{};
  10773                 std::int8_t subtype{};
  10774                 return get_number(input_format_t::msgpack, len) &&
  10775                        get_number(input_format_t::msgpack, subtype) &&
  10776                        get_binary(input_format_t::msgpack, len, result) &&
  10777                        assign_and_return_true(subtype);
  10778             }
  10779 
  10780             case 0xC8: // ext 16
  10781             {
  10782                 std::uint16_t len{};
  10783                 std::int8_t subtype{};
  10784                 return get_number(input_format_t::msgpack, len) &&
  10785                        get_number(input_format_t::msgpack, subtype) &&
  10786                        get_binary(input_format_t::msgpack, len, result) &&
  10787                        assign_and_return_true(subtype);
  10788             }
  10789 
  10790             case 0xC9: // ext 32
  10791             {
  10792                 std::uint32_t len{};
  10793                 std::int8_t subtype{};
  10794                 return get_number(input_format_t::msgpack, len) &&
  10795                        get_number(input_format_t::msgpack, subtype) &&
  10796                        get_binary(input_format_t::msgpack, len, result) &&
  10797                        assign_and_return_true(subtype);
  10798             }
  10799 
  10800             case 0xD4: // fixext 1
  10801             {
  10802                 std::int8_t subtype{};
  10803                 return get_number(input_format_t::msgpack, subtype) &&
  10804                        get_binary(input_format_t::msgpack, 1, result) &&
  10805                        assign_and_return_true(subtype);
  10806             }
  10807 
  10808             case 0xD5: // fixext 2
  10809             {
  10810                 std::int8_t subtype{};
  10811                 return get_number(input_format_t::msgpack, subtype) &&
  10812                        get_binary(input_format_t::msgpack, 2, result) &&
  10813                        assign_and_return_true(subtype);
  10814             }
  10815 
  10816             case 0xD6: // fixext 4
  10817             {
  10818                 std::int8_t subtype{};
  10819                 return get_number(input_format_t::msgpack, subtype) &&
  10820                        get_binary(input_format_t::msgpack, 4, result) &&
  10821                        assign_and_return_true(subtype);
  10822             }
  10823 
  10824             case 0xD7: // fixext 8
  10825             {
  10826                 std::int8_t subtype{};
  10827                 return get_number(input_format_t::msgpack, subtype) &&
  10828                        get_binary(input_format_t::msgpack, 8, result) &&
  10829                        assign_and_return_true(subtype);
  10830             }
  10831 
  10832             case 0xD8: // fixext 16
  10833             {
  10834                 std::int8_t subtype{};
  10835                 return get_number(input_format_t::msgpack, subtype) &&
  10836                        get_binary(input_format_t::msgpack, 16, result) &&
  10837                        assign_and_return_true(subtype);
  10838             }
  10839 
  10840             default:           // LCOV_EXCL_LINE
  10841                 return false;  // LCOV_EXCL_LINE
  10842         }
  10843     }
  10844 
  10845     /*!
  10846     @param[in] len  the length of the array
  10847     @return whether array creation completed
  10848     */
  10849     bool get_msgpack_array(const std::size_t len)
  10850     {
  10851         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
  10852         {
  10853             return false;
  10854         }
  10855 
  10856         for (std::size_t i = 0; i < len; ++i)
  10857         {
  10858             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
  10859             {
  10860                 return false;
  10861             }
  10862         }
  10863 
  10864         return sax->end_array();
  10865     }
  10866 
  10867     /*!
  10868     @param[in] len  the length of the object
  10869     @return whether object creation completed
  10870     */
  10871     bool get_msgpack_object(const std::size_t len)
  10872     {
  10873         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
  10874         {
  10875             return false;
  10876         }
  10877 
  10878         string_t key;
  10879         for (std::size_t i = 0; i < len; ++i)
  10880         {
  10881             get();
  10882             if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
  10883             {
  10884                 return false;
  10885             }
  10886 
  10887             if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
  10888             {
  10889                 return false;
  10890             }
  10891             key.clear();
  10892         }
  10893 
  10894         return sax->end_object();
  10895     }
  10896 
  10897     ////////////
  10898     // UBJSON //
  10899     ////////////
  10900 
  10901     /*!
  10902     @param[in] get_char  whether a new character should be retrieved from the
  10903                          input (true, default) or whether the last read
  10904                          character should be considered instead
  10905 
  10906     @return whether a valid UBJSON value was passed to the SAX parser
  10907     */
  10908     bool parse_ubjson_internal(const bool get_char = true)
  10909     {
  10910         return get_ubjson_value(get_char ? get_ignore_noop() : current);
  10911     }
  10912 
  10913     /*!
  10914     @brief reads a UBJSON string
  10915 
  10916     This function is either called after reading the 'S' byte explicitly
  10917     indicating a string, or in case of an object key where the 'S' byte can be
  10918     left out.
  10919 
  10920     @param[out] result   created string
  10921     @param[in] get_char  whether a new character should be retrieved from the
  10922                          input (true, default) or whether the last read
  10923                          character should be considered instead
  10924 
  10925     @return whether string creation completed
  10926     */
  10927     bool get_ubjson_string(string_t& result, const bool get_char = true)
  10928     {
  10929         if (get_char)
  10930         {
  10931             get();  // TODO(niels): may we ignore N here?
  10932         }
  10933 
  10934         if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
  10935         {
  10936             return false;
  10937         }
  10938 
  10939         switch (current)
  10940         {
  10941             case 'U':
  10942             {
  10943                 std::uint8_t len{};
  10944                 return get_number(input_format, len) && get_string(input_format, len, result);
  10945             }
  10946 
  10947             case 'i':
  10948             {
  10949                 std::int8_t len{};
  10950                 return get_number(input_format, len) && get_string(input_format, len, result);
  10951             }
  10952 
  10953             case 'I':
  10954             {
  10955                 std::int16_t len{};
  10956                 return get_number(input_format, len) && get_string(input_format, len, result);
  10957             }
  10958 
  10959             case 'l':
  10960             {
  10961                 std::int32_t len{};
  10962                 return get_number(input_format, len) && get_string(input_format, len, result);
  10963             }
  10964 
  10965             case 'L':
  10966             {
  10967                 std::int64_t len{};
  10968                 return get_number(input_format, len) && get_string(input_format, len, result);
  10969             }
  10970 
  10971             case 'u':
  10972             {
  10973                 if (input_format != input_format_t::bjdata)
  10974                 {
  10975                     break;
  10976                 }
  10977                 std::uint16_t len{};
  10978                 return get_number(input_format, len) && get_string(input_format, len, result);
  10979             }
  10980 
  10981             case 'm':
  10982             {
  10983                 if (input_format != input_format_t::bjdata)
  10984                 {
  10985                     break;
  10986                 }
  10987                 std::uint32_t len{};
  10988                 return get_number(input_format, len) && get_string(input_format, len, result);
  10989             }
  10990 
  10991             case 'M':
  10992             {
  10993                 if (input_format != input_format_t::bjdata)
  10994                 {
  10995                     break;
  10996                 }
  10997                 std::uint64_t len{};
  10998                 return get_number(input_format, len) && get_string(input_format, len, result);
  10999             }
  11000 
  11001             default:
  11002                 break;
  11003         }
  11004         auto last_token = get_token_string();
  11005         std::string message;
  11006 
  11007         if (input_format != input_format_t::bjdata)
  11008         {
  11009             message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
  11010         }
  11011         else
  11012         {
  11013             message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
  11014         }
  11015         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
  11016     }
  11017 
  11018     /*!
  11019     @param[out] dim  an integer vector storing the ND array dimensions
  11020     @return whether reading ND array size vector is successful
  11021     */
  11022     bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
  11023     {
  11024         std::pair<std::size_t, char_int_type> size_and_type;
  11025         size_t dimlen = 0;
  11026         bool no_ndarray = true;
  11027 
  11028         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
  11029         {
  11030             return false;
  11031         }
  11032 
  11033         if (size_and_type.first != npos)
  11034         {
  11035             if (size_and_type.second != 0)
  11036             {
  11037                 if (size_and_type.second != 'N')
  11038                 {
  11039                     for (std::size_t i = 0; i < size_and_type.first; ++i)
  11040                     {
  11041                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
  11042                         {
  11043                             return false;
  11044                         }
  11045                         dim.push_back(dimlen);
  11046                     }
  11047                 }
  11048             }
  11049             else
  11050             {
  11051                 for (std::size_t i = 0; i < size_and_type.first; ++i)
  11052                 {
  11053                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
  11054                     {
  11055                         return false;
  11056                     }
  11057                     dim.push_back(dimlen);
  11058                 }
  11059             }
  11060         }
  11061         else
  11062         {
  11063             while (current != ']')
  11064             {
  11065                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
  11066                 {
  11067                     return false;
  11068                 }
  11069                 dim.push_back(dimlen);
  11070                 get_ignore_noop();
  11071             }
  11072         }
  11073         return true;
  11074     }
  11075 
  11076     /*!
  11077     @param[out] result  determined size
  11078     @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector
  11079                                or ndarray dimension is not allowed; `false` means ndarray
  11080                                is allowed; for output, `true` means an ndarray is found;
  11081                                is_ndarray can only return `true` when its initial value
  11082                                is `false`
  11083     @param[in] prefix  type marker if already read, otherwise set to 0
  11084 
  11085     @return whether size determination completed
  11086     */
  11087     bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
  11088     {
  11089         if (prefix == 0)
  11090         {
  11091             prefix = get_ignore_noop();
  11092         }
  11093 
  11094         switch (prefix)
  11095         {
  11096             case 'U':
  11097             {
  11098                 std::uint8_t number{};
  11099                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11100                 {
  11101                     return false;
  11102                 }
  11103                 result = static_cast<std::size_t>(number);
  11104                 return true;
  11105             }
  11106 
  11107             case 'i':
  11108             {
  11109                 std::int8_t number{};
  11110                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11111                 {
  11112                     return false;
  11113                 }
  11114                 if (number < 0)
  11115                 {
  11116                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11117                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11118                 }
  11119                 result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
  11120                 return true;
  11121             }
  11122 
  11123             case 'I':
  11124             {
  11125                 std::int16_t number{};
  11126                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11127                 {
  11128                     return false;
  11129                 }
  11130                 if (number < 0)
  11131                 {
  11132                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11133                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11134                 }
  11135                 result = static_cast<std::size_t>(number);
  11136                 return true;
  11137             }
  11138 
  11139             case 'l':
  11140             {
  11141                 std::int32_t number{};
  11142                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11143                 {
  11144                     return false;
  11145                 }
  11146                 if (number < 0)
  11147                 {
  11148                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11149                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11150                 }
  11151                 result = static_cast<std::size_t>(number);
  11152                 return true;
  11153             }
  11154 
  11155             case 'L':
  11156             {
  11157                 std::int64_t number{};
  11158                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11159                 {
  11160                     return false;
  11161                 }
  11162                 if (number < 0)
  11163                 {
  11164                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11165                                             exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11166                 }
  11167                 if (!value_in_range_of<std::size_t>(number))
  11168                 {
  11169                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
  11170                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
  11171                 }
  11172                 result = static_cast<std::size_t>(number);
  11173                 return true;
  11174             }
  11175 
  11176             case 'u':
  11177             {
  11178                 if (input_format != input_format_t::bjdata)
  11179                 {
  11180                     break;
  11181                 }
  11182                 std::uint16_t number{};
  11183                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11184                 {
  11185                     return false;
  11186                 }
  11187                 result = static_cast<std::size_t>(number);
  11188                 return true;
  11189             }
  11190 
  11191             case 'm':
  11192             {
  11193                 if (input_format != input_format_t::bjdata)
  11194                 {
  11195                     break;
  11196                 }
  11197                 std::uint32_t number{};
  11198                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11199                 {
  11200                     return false;
  11201                 }
  11202                 result = conditional_static_cast<std::size_t>(number);
  11203                 return true;
  11204             }
  11205 
  11206             case 'M':
  11207             {
  11208                 if (input_format != input_format_t::bjdata)
  11209                 {
  11210                     break;
  11211                 }
  11212                 std::uint64_t number{};
  11213                 if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11214                 {
  11215                     return false;
  11216                 }
  11217                 if (!value_in_range_of<std::size_t>(number))
  11218                 {
  11219                     return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
  11220                                             exception_message(input_format, "integer value overflow", "size"), nullptr));
  11221                 }
  11222                 result = detail::conditional_static_cast<std::size_t>(number);
  11223                 return true;
  11224             }
  11225 
  11226             case '[':
  11227             {
  11228                 if (input_format != input_format_t::bjdata)
  11229                 {
  11230                     break;
  11231                 }
  11232                 if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
  11233                 {
  11234                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read, exception_message(input_format, "ndarray dimensional vector is not allowed", "size"), nullptr));
  11235                 }
  11236                 std::vector<size_t> dim;
  11237                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
  11238                 {
  11239                     return false;
  11240                 }
  11241                 if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
  11242                 {
  11243                     result = dim.at(dim.size() - 1);
  11244                     return true;
  11245                 }
  11246                 if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
  11247                 {
  11248                     for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
  11249                     {
  11250                         if ( i == 0 )
  11251                         {
  11252                             result = 0;
  11253                             return true;
  11254                         }
  11255                     }
  11256 
  11257                     string_t key = "_ArraySize_";
  11258                     if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
  11259                     {
  11260                         return false;
  11261                     }
  11262                     result = 1;
  11263                     for (auto i : dim)
  11264                     {
  11265                         result *= i;
  11266                         if (result == 0 || result == npos) // because dim elements shall not have zeros, result = 0 means overflow happened; it also can't be npos as it is used to initialize size in get_ubjson_size_type()
  11267                         {
  11268                             return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408, exception_message(input_format, "excessive ndarray size caused overflow", "size"), nullptr));
  11269                         }
  11270                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
  11271                         {
  11272                             return false;
  11273                         }
  11274                     }
  11275                     is_ndarray = true;
  11276                     return sax->end_array();
  11277                 }
  11278                 result = 0;
  11279                 return true;
  11280             }
  11281 
  11282             default:
  11283                 break;
  11284         }
  11285         auto last_token = get_token_string();
  11286         std::string message;
  11287 
  11288         if (input_format != input_format_t::bjdata)
  11289         {
  11290             message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
  11291         }
  11292         else
  11293         {
  11294             message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
  11295         }
  11296         return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
  11297     }
  11298 
  11299     /*!
  11300     @brief determine the type and size for a container
  11301 
  11302     In the optimized UBJSON format, a type and a size can be provided to allow
  11303     for a more compact representation.
  11304 
  11305     @param[out] result  pair of the size and the type
  11306     @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector
  11307 
  11308     @return whether pair creation completed
  11309     */
  11310     bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
  11311     {
  11312         result.first = npos; // size
  11313         result.second = 0; // type
  11314         bool is_ndarray = false;
  11315 
  11316         get_ignore_noop();
  11317 
  11318         if (current == '$')
  11319         {
  11320             result.second = get();  // must not ignore 'N', because 'N' maybe the type
  11321             if (input_format == input_format_t::bjdata
  11322                     && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
  11323             {
  11324                 auto last_token = get_token_string();
  11325                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11326                                         exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
  11327             }
  11328 
  11329             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
  11330             {
  11331                 return false;
  11332             }
  11333 
  11334             get_ignore_noop();
  11335             if (JSON_HEDLEY_UNLIKELY(current != '#'))
  11336             {
  11337                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
  11338                 {
  11339                     return false;
  11340                 }
  11341                 auto last_token = get_token_string();
  11342                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11343                                         exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
  11344             }
  11345 
  11346             const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
  11347             if (input_format == input_format_t::bjdata && is_ndarray)
  11348             {
  11349                 if (inside_ndarray)
  11350                 {
  11351                     return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
  11352                                             exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
  11353                 }
  11354                 result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
  11355             }
  11356             return is_error;
  11357         }
  11358 
  11359         if (current == '#')
  11360         {
  11361             const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
  11362             if (input_format == input_format_t::bjdata && is_ndarray)
  11363             {
  11364                 return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
  11365                                         exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
  11366             }
  11367             return is_error;
  11368         }
  11369 
  11370         return true;
  11371     }
  11372 
  11373     /*!
  11374     @param prefix  the previously read or set type prefix
  11375     @return whether value creation completed
  11376     */
  11377     bool get_ubjson_value(const char_int_type prefix)
  11378     {
  11379         switch (prefix)
  11380         {
  11381             case std::char_traits<char_type>::eof():  // EOF
  11382                 return unexpect_eof(input_format, "value");
  11383 
  11384             case 'T':  // true
  11385                 return sax->boolean(true);
  11386             case 'F':  // false
  11387                 return sax->boolean(false);
  11388 
  11389             case 'Z':  // null
  11390                 return sax->null();
  11391 
  11392             case 'U':
  11393             {
  11394                 std::uint8_t number{};
  11395                 return get_number(input_format, number) && sax->number_unsigned(number);
  11396             }
  11397 
  11398             case 'i':
  11399             {
  11400                 std::int8_t number{};
  11401                 return get_number(input_format, number) && sax->number_integer(number);
  11402             }
  11403 
  11404             case 'I':
  11405             {
  11406                 std::int16_t number{};
  11407                 return get_number(input_format, number) && sax->number_integer(number);
  11408             }
  11409 
  11410             case 'l':
  11411             {
  11412                 std::int32_t number{};
  11413                 return get_number(input_format, number) && sax->number_integer(number);
  11414             }
  11415 
  11416             case 'L':
  11417             {
  11418                 std::int64_t number{};
  11419                 return get_number(input_format, number) && sax->number_integer(number);
  11420             }
  11421 
  11422             case 'u':
  11423             {
  11424                 if (input_format != input_format_t::bjdata)
  11425                 {
  11426                     break;
  11427                 }
  11428                 std::uint16_t number{};
  11429                 return get_number(input_format, number) && sax->number_unsigned(number);
  11430             }
  11431 
  11432             case 'm':
  11433             {
  11434                 if (input_format != input_format_t::bjdata)
  11435                 {
  11436                     break;
  11437                 }
  11438                 std::uint32_t number{};
  11439                 return get_number(input_format, number) && sax->number_unsigned(number);
  11440             }
  11441 
  11442             case 'M':
  11443             {
  11444                 if (input_format != input_format_t::bjdata)
  11445                 {
  11446                     break;
  11447                 }
  11448                 std::uint64_t number{};
  11449                 return get_number(input_format, number) && sax->number_unsigned(number);
  11450             }
  11451 
  11452             case 'h':
  11453             {
  11454                 if (input_format != input_format_t::bjdata)
  11455                 {
  11456                     break;
  11457                 }
  11458                 const auto byte1_raw = get();
  11459                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
  11460                 {
  11461                     return false;
  11462                 }
  11463                 const auto byte2_raw = get();
  11464                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
  11465                 {
  11466                     return false;
  11467                 }
  11468 
  11469                 const auto byte1 = static_cast<unsigned char>(byte1_raw);
  11470                 const auto byte2 = static_cast<unsigned char>(byte2_raw);
  11471 
  11472                 // code from RFC 7049, Appendix D, Figure 3:
  11473                 // As half-precision floating-point numbers were only added
  11474                 // to IEEE 754 in 2008, today's programming platforms often
  11475                 // still only have limited support for them. It is very
  11476                 // easy to include at least decoding support for them even
  11477                 // without such support. An example of a small decoder for
  11478                 // half-precision floating-point numbers in the C language
  11479                 // is shown in Fig. 3.
  11480                 const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
  11481                 const double val = [&half]
  11482                 {
  11483                     const int exp = (half >> 10u) & 0x1Fu;
  11484                     const unsigned int mant = half & 0x3FFu;
  11485                     JSON_ASSERT(0 <= exp&& exp <= 32);
  11486                     JSON_ASSERT(mant <= 1024);
  11487                     switch (exp)
  11488                     {
  11489                         case 0:
  11490                             return std::ldexp(mant, -24);
  11491                         case 31:
  11492                             return (mant == 0)
  11493                             ? std::numeric_limits<double>::infinity()
  11494                             : std::numeric_limits<double>::quiet_NaN();
  11495                         default:
  11496                             return std::ldexp(mant + 1024, exp - 25);
  11497                     }
  11498                 }();
  11499                 return sax->number_float((half & 0x8000u) != 0
  11500                                          ? static_cast<number_float_t>(-val)
  11501                                          : static_cast<number_float_t>(val), "");
  11502             }
  11503 
  11504             case 'd':
  11505             {
  11506                 float number{};
  11507                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
  11508             }
  11509 
  11510             case 'D':
  11511             {
  11512                 double number{};
  11513                 return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
  11514             }
  11515 
  11516             case 'H':
  11517             {
  11518                 return get_ubjson_high_precision_number();
  11519             }
  11520 
  11521             case 'C':  // char
  11522             {
  11523                 get();
  11524                 if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
  11525                 {
  11526                     return false;
  11527                 }
  11528                 if (JSON_HEDLEY_UNLIKELY(current > 127))
  11529                 {
  11530                     auto last_token = get_token_string();
  11531                     return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  11532                                             exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
  11533                 }
  11534                 string_t s(1, static_cast<typename string_t::value_type>(current));
  11535                 return sax->string(s);
  11536             }
  11537 
  11538             case 'S':  // string
  11539             {
  11540                 string_t s;
  11541                 return get_ubjson_string(s) && sax->string(s);
  11542             }
  11543 
  11544             case '[':  // array
  11545                 return get_ubjson_array();
  11546 
  11547             case '{':  // object
  11548                 return get_ubjson_object();
  11549 
  11550             default: // anything else
  11551                 break;
  11552         }
  11553         auto last_token = get_token_string();
  11554         return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read, exception_message(input_format, "invalid byte: 0x" + last_token, "value"), nullptr));
  11555     }
  11556 
  11557     /*!
  11558     @return whether array creation completed
  11559     */
  11560     bool get_ubjson_array()
  11561     {
  11562         std::pair<std::size_t, char_int_type> size_and_type;
  11563         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
  11564         {
  11565             return false;
  11566         }
  11567 
  11568         // if bit-8 of size_and_type.second is set to 1, encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata):
  11569         // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
  11570 
  11571         if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
  11572         {
  11573             size_and_type.second &= ~(static_cast<char_int_type>(1) << 8);  // use bit 8 to indicate ndarray, here we remove the bit to restore the type marker
  11574             auto it = std::lower_bound(bjd_types_map.begin(), bjd_types_map.end(), size_and_type.second, [](const bjd_type & p, char_int_type t)
  11575             {
  11576                 return p.first < t;
  11577             });
  11578             string_t key = "_ArrayType_";
  11579             if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
  11580             {
  11581                 auto last_token = get_token_string();
  11582                 return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11583                                         exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
  11584             }
  11585 
  11586             string_t type = it->second; // sax->string() takes a reference
  11587             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
  11588             {
  11589                 return false;
  11590             }
  11591 
  11592             if (size_and_type.second == 'C')
  11593             {
  11594                 size_and_type.second = 'U';
  11595             }
  11596 
  11597             key = "_ArrayData_";
  11598             if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
  11599             {
  11600                 return false;
  11601             }
  11602 
  11603             for (std::size_t i = 0; i < size_and_type.first; ++i)
  11604             {
  11605                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
  11606                 {
  11607                     return false;
  11608                 }
  11609             }
  11610 
  11611             return (sax->end_array() && sax->end_object());
  11612         }
  11613 
  11614         if (size_and_type.first != npos)
  11615         {
  11616             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
  11617             {
  11618                 return false;
  11619             }
  11620 
  11621             if (size_and_type.second != 0)
  11622             {
  11623                 if (size_and_type.second != 'N')
  11624                 {
  11625                     for (std::size_t i = 0; i < size_and_type.first; ++i)
  11626                     {
  11627                         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
  11628                         {
  11629                             return false;
  11630                         }
  11631                     }
  11632                 }
  11633             }
  11634             else
  11635             {
  11636                 for (std::size_t i = 0; i < size_and_type.first; ++i)
  11637                 {
  11638                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
  11639                     {
  11640                         return false;
  11641                     }
  11642                 }
  11643             }
  11644         }
  11645         else
  11646         {
  11647             if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
  11648             {
  11649                 return false;
  11650             }
  11651 
  11652             while (current != ']')
  11653             {
  11654                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
  11655                 {
  11656                     return false;
  11657                 }
  11658                 get_ignore_noop();
  11659             }
  11660         }
  11661 
  11662         return sax->end_array();
  11663     }
  11664 
  11665     /*!
  11666     @return whether object creation completed
  11667     */
  11668     bool get_ubjson_object()
  11669     {
  11670         std::pair<std::size_t, char_int_type> size_and_type;
  11671         if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
  11672         {
  11673             return false;
  11674         }
  11675 
  11676         // do not accept ND-array size in objects in BJData
  11677         if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
  11678         {
  11679             auto last_token = get_token_string();
  11680             return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11681                                     exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
  11682         }
  11683 
  11684         string_t key;
  11685         if (size_and_type.first != npos)
  11686         {
  11687             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
  11688             {
  11689                 return false;
  11690             }
  11691 
  11692             if (size_and_type.second != 0)
  11693             {
  11694                 for (std::size_t i = 0; i < size_and_type.first; ++i)
  11695                 {
  11696                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
  11697                     {
  11698                         return false;
  11699                     }
  11700                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
  11701                     {
  11702                         return false;
  11703                     }
  11704                     key.clear();
  11705                 }
  11706             }
  11707             else
  11708             {
  11709                 for (std::size_t i = 0; i < size_and_type.first; ++i)
  11710                 {
  11711                     if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
  11712                     {
  11713                         return false;
  11714                     }
  11715                     if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
  11716                     {
  11717                         return false;
  11718                     }
  11719                     key.clear();
  11720                 }
  11721             }
  11722         }
  11723         else
  11724         {
  11725             if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
  11726             {
  11727                 return false;
  11728             }
  11729 
  11730             while (current != '}')
  11731             {
  11732                 if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
  11733                 {
  11734                     return false;
  11735                 }
  11736                 if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
  11737                 {
  11738                     return false;
  11739                 }
  11740                 get_ignore_noop();
  11741                 key.clear();
  11742             }
  11743         }
  11744 
  11745         return sax->end_object();
  11746     }
  11747 
  11748     // Note, no reader for UBJSON binary types is implemented because they do
  11749     // not exist
  11750 
  11751     bool get_ubjson_high_precision_number()
  11752     {
  11753         // get size of following number string
  11754         std::size_t size{};
  11755         bool no_ndarray = true;
  11756         auto res = get_ubjson_size_value(size, no_ndarray);
  11757         if (JSON_HEDLEY_UNLIKELY(!res))
  11758         {
  11759             return res;
  11760         }
  11761 
  11762         // get number string
  11763         std::vector<char> number_vector;
  11764         for (std::size_t i = 0; i < size; ++i)
  11765         {
  11766             get();
  11767             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
  11768             {
  11769                 return false;
  11770             }
  11771             number_vector.push_back(static_cast<char>(current));
  11772         }
  11773 
  11774         // parse number string
  11775         using ia_type = decltype(detail::input_adapter(number_vector));
  11776         auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
  11777         const auto result_number = number_lexer.scan();
  11778         const auto number_string = number_lexer.get_token_string();
  11779         const auto result_remainder = number_lexer.scan();
  11780 
  11781         using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
  11782 
  11783         if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
  11784         {
  11785             return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
  11786                                     exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
  11787         }
  11788 
  11789         switch (result_number)
  11790         {
  11791             case token_type::value_integer:
  11792                 return sax->number_integer(number_lexer.get_number_integer());
  11793             case token_type::value_unsigned:
  11794                 return sax->number_unsigned(number_lexer.get_number_unsigned());
  11795             case token_type::value_float:
  11796                 return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
  11797             case token_type::uninitialized:
  11798             case token_type::literal_true:
  11799             case token_type::literal_false:
  11800             case token_type::literal_null:
  11801             case token_type::value_string:
  11802             case token_type::begin_array:
  11803             case token_type::begin_object:
  11804             case token_type::end_array:
  11805             case token_type::end_object:
  11806             case token_type::name_separator:
  11807             case token_type::value_separator:
  11808             case token_type::parse_error:
  11809             case token_type::end_of_input:
  11810             case token_type::literal_or_value:
  11811             default:
  11812                 return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
  11813                                         exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
  11814         }
  11815     }
  11816 
  11817     ///////////////////////
  11818     // Utility functions //
  11819     ///////////////////////
  11820 
  11821     /*!
  11822     @brief get next character from the input
  11823 
  11824     This function provides the interface to the used input adapter. It does
  11825     not throw in case the input reached EOF, but returns a -'ve valued
  11826     `std::char_traits<char_type>::eof()` in that case.
  11827 
  11828     @return character read from the input
  11829     */
  11830     char_int_type get()
  11831     {
  11832         ++chars_read;
  11833         return current = ia.get_character();
  11834     }
  11835 
  11836     /*!
  11837     @return character read from the input after ignoring all 'N' entries
  11838     */
  11839     char_int_type get_ignore_noop()
  11840     {
  11841         do
  11842         {
  11843             get();
  11844         }
  11845         while (current == 'N');
  11846 
  11847         return current;
  11848     }
  11849 
  11850     /*
  11851     @brief read a number from the input
  11852 
  11853     @tparam NumberType the type of the number
  11854     @param[in] format   the current format (for diagnostics)
  11855     @param[out] result  number of type @a NumberType
  11856 
  11857     @return whether conversion completed
  11858 
  11859     @note This function needs to respect the system's endianness, because
  11860           bytes in CBOR, MessagePack, and UBJSON are stored in network order
  11861           (big endian) and therefore need reordering on little endian systems.
  11862           On the other hand, BSON and BJData use little endian and should reorder
  11863           on big endian systems.
  11864     */
  11865     template<typename NumberType, bool InputIsLittleEndian = false>
  11866     bool get_number(const input_format_t format, NumberType& result)
  11867     {
  11868         // step 1: read input into array with system's byte order
  11869         std::array<std::uint8_t, sizeof(NumberType)> vec{};
  11870         for (std::size_t i = 0; i < sizeof(NumberType); ++i)
  11871         {
  11872             get();
  11873             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
  11874             {
  11875                 return false;
  11876             }
  11877 
  11878             // reverse byte order prior to conversion if necessary
  11879             if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
  11880             {
  11881                 vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
  11882             }
  11883             else
  11884             {
  11885                 vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
  11886             }
  11887         }
  11888 
  11889         // step 2: convert array into number of type T and return
  11890         std::memcpy(&result, vec.data(), sizeof(NumberType));
  11891         return true;
  11892     }
  11893 
  11894     /*!
  11895     @brief create a string by reading characters from the input
  11896 
  11897     @tparam NumberType the type of the number
  11898     @param[in] format the current format (for diagnostics)
  11899     @param[in] len number of characters to read
  11900     @param[out] result string created by reading @a len bytes
  11901 
  11902     @return whether string creation completed
  11903 
  11904     @note We can not reserve @a len bytes for the result, because @a len
  11905           may be too large. Usually, @ref unexpect_eof() detects the end of
  11906           the input before we run out of string memory.
  11907     */
  11908     template<typename NumberType>
  11909     bool get_string(const input_format_t format,
  11910                     const NumberType len,
  11911                     string_t& result)
  11912     {
  11913         bool success = true;
  11914         for (NumberType i = 0; i < len; i++)
  11915         {
  11916             get();
  11917             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
  11918             {
  11919                 success = false;
  11920                 break;
  11921             }
  11922             result.push_back(static_cast<typename string_t::value_type>(current));
  11923         }
  11924         return success;
  11925     }
  11926 
  11927     /*!
  11928     @brief create a byte array by reading bytes from the input
  11929 
  11930     @tparam NumberType the type of the number
  11931     @param[in] format the current format (for diagnostics)
  11932     @param[in] len number of bytes to read
  11933     @param[out] result byte array created by reading @a len bytes
  11934 
  11935     @return whether byte array creation completed
  11936 
  11937     @note We can not reserve @a len bytes for the result, because @a len
  11938           may be too large. Usually, @ref unexpect_eof() detects the end of
  11939           the input before we run out of memory.
  11940     */
  11941     template<typename NumberType>
  11942     bool get_binary(const input_format_t format,
  11943                     const NumberType len,
  11944                     binary_t& result)
  11945     {
  11946         bool success = true;
  11947         for (NumberType i = 0; i < len; i++)
  11948         {
  11949             get();
  11950             if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
  11951             {
  11952                 success = false;
  11953                 break;
  11954             }
  11955             result.push_back(static_cast<std::uint8_t>(current));
  11956         }
  11957         return success;
  11958     }
  11959 
  11960     /*!
  11961     @param[in] format   the current format (for diagnostics)
  11962     @param[in] context  further context information (for diagnostics)
  11963     @return whether the last read character is not EOF
  11964     */
  11965     JSON_HEDLEY_NON_NULL(3)
  11966     bool unexpect_eof(const input_format_t format, const char* context) const
  11967     {
  11968         if (JSON_HEDLEY_UNLIKELY(current == std::char_traits<char_type>::eof()))
  11969         {
  11970             return sax->parse_error(chars_read, "<end of file>",
  11971                                     parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
  11972         }
  11973         return true;
  11974     }
  11975 
  11976     /*!
  11977     @return a string representation of the last read byte
  11978     */
  11979     std::string get_token_string() const
  11980     {
  11981         std::array<char, 3> cr{{}};
  11982         static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  11983         return std::string{cr.data()};
  11984     }
  11985 
  11986     /*!
  11987     @param[in] format   the current format
  11988     @param[in] detail   a detailed error message
  11989     @param[in] context  further context information
  11990     @return a message string to use in the parse_error exceptions
  11991     */
  11992     std::string exception_message(const input_format_t format,
  11993                                   const std::string& detail,
  11994                                   const std::string& context) const
  11995     {
  11996         std::string error_msg = "syntax error while parsing ";
  11997 
  11998         switch (format)
  11999         {
  12000             case input_format_t::cbor:
  12001                 error_msg += "CBOR";
  12002                 break;
  12003 
  12004             case input_format_t::msgpack:
  12005                 error_msg += "MessagePack";
  12006                 break;
  12007 
  12008             case input_format_t::ubjson:
  12009                 error_msg += "UBJSON";
  12010                 break;
  12011 
  12012             case input_format_t::bson:
  12013                 error_msg += "BSON";
  12014                 break;
  12015 
  12016             case input_format_t::bjdata:
  12017                 error_msg += "BJData";
  12018                 break;
  12019 
  12020             case input_format_t::json: // LCOV_EXCL_LINE
  12021             default:            // LCOV_EXCL_LINE
  12022                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  12023         }
  12024 
  12025         return concat(error_msg, ' ', context, ": ", detail);
  12026     }
  12027 
  12028   private:
  12029     static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
  12030 
  12031     /// input adapter
  12032     InputAdapterType ia;
  12033 
  12034     /// the current character
  12035     char_int_type current = std::char_traits<char_type>::eof();
  12036 
  12037     /// the number of characters read
  12038     std::size_t chars_read = 0;
  12039 
  12040     /// whether we can assume little endianness
  12041     const bool is_little_endian = little_endianness();
  12042 
  12043     /// input format
  12044     const input_format_t input_format = input_format_t::json;
  12045 
  12046     /// the SAX parser
  12047     json_sax_t* sax = nullptr;
  12048 
  12049     // excluded markers in bjdata optimized type
  12050 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
  12051     make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
  12052 
  12053 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
  12054     make_array<bjd_type>(                      \
  12055     bjd_type{'C', "char"},                     \
  12056     bjd_type{'D', "double"},                   \
  12057     bjd_type{'I', "int16"},                    \
  12058     bjd_type{'L', "int64"},                    \
  12059     bjd_type{'M', "uint64"},                   \
  12060     bjd_type{'U', "uint8"},                    \
  12061     bjd_type{'d', "single"},                   \
  12062     bjd_type{'i', "int8"},                     \
  12063     bjd_type{'l', "int32"},                    \
  12064     bjd_type{'m', "uint32"},                   \
  12065     bjd_type{'u', "uint16"})
  12066 
  12067   JSON_PRIVATE_UNLESS_TESTED:
  12068     // lookup tables
  12069     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
  12070     const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
  12071         JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
  12072 
  12073     using bjd_type = std::pair<char_int_type, string_t>;
  12074     // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
  12075     const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
  12076         JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
  12077 
  12078 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
  12079 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
  12080 };
  12081 
  12082 #ifndef JSON_HAS_CPP_17
  12083     template<typename BasicJsonType, typename InputAdapterType, typename SAX>
  12084     constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
  12085 #endif
  12086 
  12087 }  // namespace detail
  12088 NLOHMANN_JSON_NAMESPACE_END
  12089 
  12090 // #include <nlohmann/detail/input/input_adapters.hpp>
  12091 
  12092 // #include <nlohmann/detail/input/lexer.hpp>
  12093 
  12094 // #include <nlohmann/detail/input/parser.hpp>
  12095 //     __ _____ _____ _____
  12096 //  __|  |   __|     |   | |  JSON for Modern C++
  12097 // |  |  |__   |  |  | | | |  version 3.11.2
  12098 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12099 //
  12100 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  12101 // SPDX-License-Identifier: MIT
  12102 
  12103 
  12104 
  12105 #include <cmath> // isfinite
  12106 #include <cstdint> // uint8_t
  12107 #include <functional> // function
  12108 #include <string> // string
  12109 #include <utility> // move
  12110 #include <vector> // vector
  12111 
  12112 // #include <nlohmann/detail/exceptions.hpp>
  12113 
  12114 // #include <nlohmann/detail/input/input_adapters.hpp>
  12115 
  12116 // #include <nlohmann/detail/input/json_sax.hpp>
  12117 
  12118 // #include <nlohmann/detail/input/lexer.hpp>
  12119 
  12120 // #include <nlohmann/detail/macro_scope.hpp>
  12121 
  12122 // #include <nlohmann/detail/meta/is_sax.hpp>
  12123 
  12124 // #include <nlohmann/detail/string_concat.hpp>
  12125 
  12126 // #include <nlohmann/detail/value_t.hpp>
  12127 
  12128 
  12129 NLOHMANN_JSON_NAMESPACE_BEGIN
  12130 namespace detail
  12131 {
  12132 ////////////
  12133 // parser //
  12134 ////////////
  12135 
  12136 enum class parse_event_t : std::uint8_t
  12137 {
  12138     /// the parser read `{` and started to process a JSON object
  12139     object_start,
  12140     /// the parser read `}` and finished processing a JSON object
  12141     object_end,
  12142     /// the parser read `[` and started to process a JSON array
  12143     array_start,
  12144     /// the parser read `]` and finished processing a JSON array
  12145     array_end,
  12146     /// the parser read a key of a value in an object
  12147     key,
  12148     /// the parser finished reading a JSON value
  12149     value
  12150 };
  12151 
  12152 template<typename BasicJsonType>
  12153 using parser_callback_t =
  12154     std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
  12155 
  12156 /*!
  12157 @brief syntax analysis
  12158 
  12159 This class implements a recursive descent parser.
  12160 */
  12161 template<typename BasicJsonType, typename InputAdapterType>
  12162 class parser
  12163 {
  12164     using number_integer_t = typename BasicJsonType::number_integer_t;
  12165     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  12166     using number_float_t = typename BasicJsonType::number_float_t;
  12167     using string_t = typename BasicJsonType::string_t;
  12168     using lexer_t = lexer<BasicJsonType, InputAdapterType>;
  12169     using token_type = typename lexer_t::token_type;
  12170 
  12171   public:
  12172     /// a parser reading from an input adapter
  12173     explicit parser(InputAdapterType&& adapter,
  12174                     const parser_callback_t<BasicJsonType> cb = nullptr,
  12175                     const bool allow_exceptions_ = true,
  12176                     const bool skip_comments = false)
  12177         : callback(cb)
  12178         , m_lexer(std::move(adapter), skip_comments)
  12179         , allow_exceptions(allow_exceptions_)
  12180     {
  12181         // read first token
  12182         get_token();
  12183     }
  12184 
  12185     /*!
  12186     @brief public parser interface
  12187 
  12188     @param[in] strict      whether to expect the last token to be EOF
  12189     @param[in,out] result  parsed JSON value
  12190 
  12191     @throw parse_error.101 in case of an unexpected token
  12192     @throw parse_error.102 if to_unicode fails or surrogate error
  12193     @throw parse_error.103 if to_unicode fails
  12194     */
  12195     void parse(const bool strict, BasicJsonType& result)
  12196     {
  12197         if (callback)
  12198         {
  12199             json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
  12200             sax_parse_internal(&sdp);
  12201 
  12202             // in strict mode, input must be completely read
  12203             if (strict && (get_token() != token_type::end_of_input))
  12204             {
  12205                 sdp.parse_error(m_lexer.get_position(),
  12206                                 m_lexer.get_token_string(),
  12207                                 parse_error::create(101, m_lexer.get_position(),
  12208                                                     exception_message(token_type::end_of_input, "value"), nullptr));
  12209             }
  12210 
  12211             // in case of an error, return discarded value
  12212             if (sdp.is_errored())
  12213             {
  12214                 result = value_t::discarded;
  12215                 return;
  12216             }
  12217 
  12218             // set top-level value to null if it was discarded by the callback
  12219             // function
  12220             if (result.is_discarded())
  12221             {
  12222                 result = nullptr;
  12223             }
  12224         }
  12225         else
  12226         {
  12227             json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
  12228             sax_parse_internal(&sdp);
  12229 
  12230             // in strict mode, input must be completely read
  12231             if (strict && (get_token() != token_type::end_of_input))
  12232             {
  12233                 sdp.parse_error(m_lexer.get_position(),
  12234                                 m_lexer.get_token_string(),
  12235                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
  12236             }
  12237 
  12238             // in case of an error, return discarded value
  12239             if (sdp.is_errored())
  12240             {
  12241                 result = value_t::discarded;
  12242                 return;
  12243             }
  12244         }
  12245 
  12246         result.assert_invariant();
  12247     }
  12248 
  12249     /*!
  12250     @brief public accept interface
  12251 
  12252     @param[in] strict  whether to expect the last token to be EOF
  12253     @return whether the input is a proper JSON text
  12254     */
  12255     bool accept(const bool strict = true)
  12256     {
  12257         json_sax_acceptor<BasicJsonType> sax_acceptor;
  12258         return sax_parse(&sax_acceptor, strict);
  12259     }
  12260 
  12261     template<typename SAX>
  12262     JSON_HEDLEY_NON_NULL(2)
  12263     bool sax_parse(SAX* sax, const bool strict = true)
  12264     {
  12265         (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
  12266         const bool result = sax_parse_internal(sax);
  12267 
  12268         // strict mode: next byte must be EOF
  12269         if (result && strict && (get_token() != token_type::end_of_input))
  12270         {
  12271             return sax->parse_error(m_lexer.get_position(),
  12272                                     m_lexer.get_token_string(),
  12273                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
  12274         }
  12275 
  12276         return result;
  12277     }
  12278 
  12279   private:
  12280     template<typename SAX>
  12281     JSON_HEDLEY_NON_NULL(2)
  12282     bool sax_parse_internal(SAX* sax)
  12283     {
  12284         // stack to remember the hierarchy of structured values we are parsing
  12285         // true = array; false = object
  12286         std::vector<bool> states;
  12287         // value to avoid a goto (see comment where set to true)
  12288         bool skip_to_state_evaluation = false;
  12289 
  12290         while (true)
  12291         {
  12292             if (!skip_to_state_evaluation)
  12293             {
  12294                 // invariant: get_token() was called before each iteration
  12295                 switch (last_token)
  12296                 {
  12297                     case token_type::begin_object:
  12298                     {
  12299                         if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
  12300                         {
  12301                             return false;
  12302                         }
  12303 
  12304                         // closing } -> we are done
  12305                         if (get_token() == token_type::end_object)
  12306                         {
  12307                             if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
  12308                             {
  12309                                 return false;
  12310                             }
  12311                             break;
  12312                         }
  12313 
  12314                         // parse key
  12315                         if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
  12316                         {
  12317                             return sax->parse_error(m_lexer.get_position(),
  12318                                                     m_lexer.get_token_string(),
  12319                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
  12320                         }
  12321                         if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
  12322                         {
  12323                             return false;
  12324                         }
  12325 
  12326                         // parse separator (:)
  12327                         if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
  12328                         {
  12329                             return sax->parse_error(m_lexer.get_position(),
  12330                                                     m_lexer.get_token_string(),
  12331                                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
  12332                         }
  12333 
  12334                         // remember we are now inside an object
  12335                         states.push_back(false);
  12336 
  12337                         // parse values
  12338                         get_token();
  12339                         continue;
  12340                     }
  12341 
  12342                     case token_type::begin_array:
  12343                     {
  12344                         if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
  12345                         {
  12346                             return false;
  12347                         }
  12348 
  12349                         // closing ] -> we are done
  12350                         if (get_token() == token_type::end_array)
  12351                         {
  12352                             if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
  12353                             {
  12354                                 return false;
  12355                             }
  12356                             break;
  12357                         }
  12358 
  12359                         // remember we are now inside an array
  12360                         states.push_back(true);
  12361 
  12362                         // parse values (no need to call get_token)
  12363                         continue;
  12364                     }
  12365 
  12366                     case token_type::value_float:
  12367                     {
  12368                         const auto res = m_lexer.get_number_float();
  12369 
  12370                         if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
  12371                         {
  12372                             return sax->parse_error(m_lexer.get_position(),
  12373                                                     m_lexer.get_token_string(),
  12374                                                     out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
  12375                         }
  12376 
  12377                         if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
  12378                         {
  12379                             return false;
  12380                         }
  12381 
  12382                         break;
  12383                     }
  12384 
  12385                     case token_type::literal_false:
  12386                     {
  12387                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
  12388                         {
  12389                             return false;
  12390                         }
  12391                         break;
  12392                     }
  12393 
  12394                     case token_type::literal_null:
  12395                     {
  12396                         if (JSON_HEDLEY_UNLIKELY(!sax->null()))
  12397                         {
  12398                             return false;
  12399                         }
  12400                         break;
  12401                     }
  12402 
  12403                     case token_type::literal_true:
  12404                     {
  12405                         if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
  12406                         {
  12407                             return false;
  12408                         }
  12409                         break;
  12410                     }
  12411 
  12412                     case token_type::value_integer:
  12413                     {
  12414                         if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
  12415                         {
  12416                             return false;
  12417                         }
  12418                         break;
  12419                     }
  12420 
  12421                     case token_type::value_string:
  12422                     {
  12423                         if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
  12424                         {
  12425                             return false;
  12426                         }
  12427                         break;
  12428                     }
  12429 
  12430                     case token_type::value_unsigned:
  12431                     {
  12432                         if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
  12433                         {
  12434                             return false;
  12435                         }
  12436                         break;
  12437                     }
  12438 
  12439                     case token_type::parse_error:
  12440                     {
  12441                         // using "uninitialized" to avoid "expected" message
  12442                         return sax->parse_error(m_lexer.get_position(),
  12443                                                 m_lexer.get_token_string(),
  12444                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
  12445                     }
  12446 
  12447                     case token_type::uninitialized:
  12448                     case token_type::end_array:
  12449                     case token_type::end_object:
  12450                     case token_type::name_separator:
  12451                     case token_type::value_separator:
  12452                     case token_type::end_of_input:
  12453                     case token_type::literal_or_value:
  12454                     default: // the last token was unexpected
  12455                     {
  12456                         return sax->parse_error(m_lexer.get_position(),
  12457                                                 m_lexer.get_token_string(),
  12458                                                 parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
  12459                     }
  12460                 }
  12461             }
  12462             else
  12463             {
  12464                 skip_to_state_evaluation = false;
  12465             }
  12466 
  12467             // we reached this line after we successfully parsed a value
  12468             if (states.empty())
  12469             {
  12470                 // empty stack: we reached the end of the hierarchy: done
  12471                 return true;
  12472             }
  12473 
  12474             if (states.back())  // array
  12475             {
  12476                 // comma -> next value
  12477                 if (get_token() == token_type::value_separator)
  12478                 {
  12479                     // parse a new value
  12480                     get_token();
  12481                     continue;
  12482                 }
  12483 
  12484                 // closing ]
  12485                 if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
  12486                 {
  12487                     if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
  12488                     {
  12489                         return false;
  12490                     }
  12491 
  12492                     // We are done with this array. Before we can parse a
  12493                     // new value, we need to evaluate the new state first.
  12494                     // By setting skip_to_state_evaluation to false, we
  12495                     // are effectively jumping to the beginning of this if.
  12496                     JSON_ASSERT(!states.empty());
  12497                     states.pop_back();
  12498                     skip_to_state_evaluation = true;
  12499                     continue;
  12500                 }
  12501 
  12502                 return sax->parse_error(m_lexer.get_position(),
  12503                                         m_lexer.get_token_string(),
  12504                                         parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
  12505             }
  12506 
  12507             // states.back() is false -> object
  12508 
  12509             // comma -> next value
  12510             if (get_token() == token_type::value_separator)
  12511             {
  12512                 // parse key
  12513                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
  12514                 {
  12515                     return sax->parse_error(m_lexer.get_position(),
  12516                                             m_lexer.get_token_string(),
  12517                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
  12518                 }
  12519 
  12520                 if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
  12521                 {
  12522                     return false;
  12523                 }
  12524 
  12525                 // parse separator (:)
  12526                 if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
  12527                 {
  12528                     return sax->parse_error(m_lexer.get_position(),
  12529                                             m_lexer.get_token_string(),
  12530                                             parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
  12531                 }
  12532 
  12533                 // parse values
  12534                 get_token();
  12535                 continue;
  12536             }
  12537 
  12538             // closing }
  12539             if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
  12540             {
  12541                 if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
  12542                 {
  12543                     return false;
  12544                 }
  12545 
  12546                 // We are done with this object. Before we can parse a
  12547                 // new value, we need to evaluate the new state first.
  12548                 // By setting skip_to_state_evaluation to false, we
  12549                 // are effectively jumping to the beginning of this if.
  12550                 JSON_ASSERT(!states.empty());
  12551                 states.pop_back();
  12552                 skip_to_state_evaluation = true;
  12553                 continue;
  12554             }
  12555 
  12556             return sax->parse_error(m_lexer.get_position(),
  12557                                     m_lexer.get_token_string(),
  12558                                     parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
  12559         }
  12560     }
  12561 
  12562     /// get next token from lexer
  12563     token_type get_token()
  12564     {
  12565         return last_token = m_lexer.scan();
  12566     }
  12567 
  12568     std::string exception_message(const token_type expected, const std::string& context)
  12569     {
  12570         std::string error_msg = "syntax error ";
  12571 
  12572         if (!context.empty())
  12573         {
  12574             error_msg += concat("while parsing ", context, ' ');
  12575         }
  12576 
  12577         error_msg += "- ";
  12578 
  12579         if (last_token == token_type::parse_error)
  12580         {
  12581             error_msg += concat(m_lexer.get_error_message(), "; last read: '",
  12582                                 m_lexer.get_token_string(), '\'');
  12583         }
  12584         else
  12585         {
  12586             error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
  12587         }
  12588 
  12589         if (expected != token_type::uninitialized)
  12590         {
  12591             error_msg += concat("; expected ", lexer_t::token_type_name(expected));
  12592         }
  12593 
  12594         return error_msg;
  12595     }
  12596 
  12597   private:
  12598     /// callback function
  12599     const parser_callback_t<BasicJsonType> callback = nullptr;
  12600     /// the type of the last read token
  12601     token_type last_token = token_type::uninitialized;
  12602     /// the lexer
  12603     lexer_t m_lexer;
  12604     /// whether to throw exceptions in case of errors
  12605     const bool allow_exceptions = true;
  12606 };
  12607 
  12608 }  // namespace detail
  12609 NLOHMANN_JSON_NAMESPACE_END
  12610 
  12611 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
  12612 //     __ _____ _____ _____
  12613 //  __|  |   __|     |   | |  JSON for Modern C++
  12614 // |  |  |__   |  |  | | | |  version 3.11.2
  12615 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12616 //
  12617 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  12618 // SPDX-License-Identifier: MIT
  12619 
  12620 
  12621 
  12622 // #include <nlohmann/detail/abi_macros.hpp>
  12623 
  12624 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  12625 //     __ _____ _____ _____
  12626 //  __|  |   __|     |   | |  JSON for Modern C++
  12627 // |  |  |__   |  |  | | | |  version 3.11.2
  12628 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12629 //
  12630 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  12631 // SPDX-License-Identifier: MIT
  12632 
  12633 
  12634 
  12635 #include <cstddef> // ptrdiff_t
  12636 #include <limits>  // numeric_limits
  12637 
  12638 // #include <nlohmann/detail/macro_scope.hpp>
  12639 
  12640 
  12641 NLOHMANN_JSON_NAMESPACE_BEGIN
  12642 namespace detail
  12643 {
  12644 
  12645 /*
  12646 @brief an iterator for primitive JSON types
  12647 
  12648 This class models an iterator for primitive JSON types (boolean, number,
  12649 string). It's only purpose is to allow the iterator/const_iterator classes
  12650 to "iterate" over primitive values. Internally, the iterator is modeled by
  12651 a `difference_type` variable. Value begin_value (`0`) models the begin,
  12652 end_value (`1`) models past the end.
  12653 */
  12654 class primitive_iterator_t
  12655 {
  12656   private:
  12657     using difference_type = std::ptrdiff_t;
  12658     static constexpr difference_type begin_value = 0;
  12659     static constexpr difference_type end_value = begin_value + 1;
  12660 
  12661   JSON_PRIVATE_UNLESS_TESTED:
  12662     /// iterator as signed integer type
  12663     difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
  12664 
  12665   public:
  12666     constexpr difference_type get_value() const noexcept
  12667     {
  12668         return m_it;
  12669     }
  12670 
  12671     /// set iterator to a defined beginning
  12672     void set_begin() noexcept
  12673     {
  12674         m_it = begin_value;
  12675     }
  12676 
  12677     /// set iterator to a defined past the end
  12678     void set_end() noexcept
  12679     {
  12680         m_it = end_value;
  12681     }
  12682 
  12683     /// return whether the iterator can be dereferenced
  12684     constexpr bool is_begin() const noexcept
  12685     {
  12686         return m_it == begin_value;
  12687     }
  12688 
  12689     /// return whether the iterator is at end
  12690     constexpr bool is_end() const noexcept
  12691     {
  12692         return m_it == end_value;
  12693     }
  12694 
  12695     friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
  12696     {
  12697         return lhs.m_it == rhs.m_it;
  12698     }
  12699 
  12700     friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
  12701     {
  12702         return lhs.m_it < rhs.m_it;
  12703     }
  12704 
  12705     primitive_iterator_t operator+(difference_type n) noexcept
  12706     {
  12707         auto result = *this;
  12708         result += n;
  12709         return result;
  12710     }
  12711 
  12712     friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
  12713     {
  12714         return lhs.m_it - rhs.m_it;
  12715     }
  12716 
  12717     primitive_iterator_t& operator++() noexcept
  12718     {
  12719         ++m_it;
  12720         return *this;
  12721     }
  12722 
  12723     primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
  12724     {
  12725         auto result = *this;
  12726         ++m_it;
  12727         return result;
  12728     }
  12729 
  12730     primitive_iterator_t& operator--() noexcept
  12731     {
  12732         --m_it;
  12733         return *this;
  12734     }
  12735 
  12736     primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
  12737     {
  12738         auto result = *this;
  12739         --m_it;
  12740         return result;
  12741     }
  12742 
  12743     primitive_iterator_t& operator+=(difference_type n) noexcept
  12744     {
  12745         m_it += n;
  12746         return *this;
  12747     }
  12748 
  12749     primitive_iterator_t& operator-=(difference_type n) noexcept
  12750     {
  12751         m_it -= n;
  12752         return *this;
  12753     }
  12754 };
  12755 
  12756 }  // namespace detail
  12757 NLOHMANN_JSON_NAMESPACE_END
  12758 
  12759 
  12760 NLOHMANN_JSON_NAMESPACE_BEGIN
  12761 namespace detail
  12762 {
  12763 
  12764 /*!
  12765 @brief an iterator value
  12766 
  12767 @note This structure could easily be a union, but MSVC currently does not allow
  12768 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
  12769 */
  12770 template<typename BasicJsonType> struct internal_iterator
  12771 {
  12772     /// iterator for JSON objects
  12773     typename BasicJsonType::object_t::iterator object_iterator {};
  12774     /// iterator for JSON arrays
  12775     typename BasicJsonType::array_t::iterator array_iterator {};
  12776     /// generic iterator for all other types
  12777     primitive_iterator_t primitive_iterator {};
  12778 };
  12779 
  12780 }  // namespace detail
  12781 NLOHMANN_JSON_NAMESPACE_END
  12782 
  12783 // #include <nlohmann/detail/iterators/iter_impl.hpp>
  12784 //     __ _____ _____ _____
  12785 //  __|  |   __|     |   | |  JSON for Modern C++
  12786 // |  |  |__   |  |  | | | |  version 3.11.2
  12787 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12788 //
  12789 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  12790 // SPDX-License-Identifier: MIT
  12791 
  12792 
  12793 
  12794 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
  12795 #include <type_traits> // conditional, is_const, remove_const
  12796 
  12797 // #include <nlohmann/detail/exceptions.hpp>
  12798 
  12799 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
  12800 
  12801 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  12802 
  12803 // #include <nlohmann/detail/macro_scope.hpp>
  12804 
  12805 // #include <nlohmann/detail/meta/cpp_future.hpp>
  12806 
  12807 // #include <nlohmann/detail/meta/type_traits.hpp>
  12808 
  12809 // #include <nlohmann/detail/value_t.hpp>
  12810 
  12811 
  12812 NLOHMANN_JSON_NAMESPACE_BEGIN
  12813 namespace detail
  12814 {
  12815 
  12816 // forward declare, to be able to friend it later on
  12817 template<typename IteratorType> class iteration_proxy;
  12818 template<typename IteratorType> class iteration_proxy_value;
  12819 
  12820 /*!
  12821 @brief a template for a bidirectional iterator for the @ref basic_json class
  12822 This class implements a both iterators (iterator and const_iterator) for the
  12823 @ref basic_json class.
  12824 @note An iterator is called *initialized* when a pointer to a JSON value has
  12825       been set (e.g., by a constructor or a copy assignment). If the iterator is
  12826       default-constructed, it is *uninitialized* and most methods are undefined.
  12827       **The library uses assertions to detect calls on uninitialized iterators.**
  12828 @requirement The class satisfies the following concept requirements:
  12829 -
  12830 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
  12831   The iterator that can be moved can be moved in both directions (i.e.
  12832   incremented and decremented).
  12833 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
  12834        iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
  12835 */
  12836 template<typename BasicJsonType>
  12837 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
  12838 {
  12839     /// the iterator with BasicJsonType of different const-ness
  12840     using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
  12841     /// allow basic_json to access private members
  12842     friend other_iter_impl;
  12843     friend BasicJsonType;
  12844     friend iteration_proxy<iter_impl>;
  12845     friend iteration_proxy_value<iter_impl>;
  12846 
  12847     using object_t = typename BasicJsonType::object_t;
  12848     using array_t = typename BasicJsonType::array_t;
  12849     // make sure BasicJsonType is basic_json or const basic_json
  12850     static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
  12851                   "iter_impl only accepts (const) basic_json");
  12852     // superficial check for the LegacyBidirectionalIterator named requirement
  12853     static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
  12854                   &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
  12855                   "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
  12856 
  12857   public:
  12858     /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
  12859     /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
  12860     /// A user-defined iterator should provide publicly accessible typedefs named
  12861     /// iterator_category, value_type, difference_type, pointer, and reference.
  12862     /// Note that value_type is required to be non-const, even for constant iterators.
  12863     using iterator_category = std::bidirectional_iterator_tag;
  12864 
  12865     /// the type of the values when the iterator is dereferenced
  12866     using value_type = typename BasicJsonType::value_type;
  12867     /// a type to represent differences between iterators
  12868     using difference_type = typename BasicJsonType::difference_type;
  12869     /// defines a pointer to the type iterated over (value_type)
  12870     using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
  12871           typename BasicJsonType::const_pointer,
  12872           typename BasicJsonType::pointer>::type;
  12873     /// defines a reference to the type iterated over (value_type)
  12874     using reference =
  12875         typename std::conditional<std::is_const<BasicJsonType>::value,
  12876         typename BasicJsonType::const_reference,
  12877         typename BasicJsonType::reference>::type;
  12878 
  12879     iter_impl() = default;
  12880     ~iter_impl() = default;
  12881     iter_impl(iter_impl&&) noexcept = default;
  12882     iter_impl& operator=(iter_impl&&) noexcept = default;
  12883 
  12884     /*!
  12885     @brief constructor for a given JSON instance
  12886     @param[in] object  pointer to a JSON object for this iterator
  12887     @pre object != nullptr
  12888     @post The iterator is initialized; i.e. `m_object != nullptr`.
  12889     */
  12890     explicit iter_impl(pointer object) noexcept : m_object(object)
  12891     {
  12892         JSON_ASSERT(m_object != nullptr);
  12893 
  12894         switch (m_object->m_type)
  12895         {
  12896             case value_t::object:
  12897             {
  12898                 m_it.object_iterator = typename object_t::iterator();
  12899                 break;
  12900             }
  12901 
  12902             case value_t::array:
  12903             {
  12904                 m_it.array_iterator = typename array_t::iterator();
  12905                 break;
  12906             }
  12907 
  12908             case value_t::null:
  12909             case value_t::string:
  12910             case value_t::boolean:
  12911             case value_t::number_integer:
  12912             case value_t::number_unsigned:
  12913             case value_t::number_float:
  12914             case value_t::binary:
  12915             case value_t::discarded:
  12916             default:
  12917             {
  12918                 m_it.primitive_iterator = primitive_iterator_t();
  12919                 break;
  12920             }
  12921         }
  12922     }
  12923 
  12924     /*!
  12925     @note The conventional copy constructor and copy assignment are implicitly
  12926           defined. Combined with the following converting constructor and
  12927           assignment, they support: (1) copy from iterator to iterator, (2)
  12928           copy from const iterator to const iterator, and (3) conversion from
  12929           iterator to const iterator. However conversion from const iterator
  12930           to iterator is not defined.
  12931     */
  12932 
  12933     /*!
  12934     @brief const copy constructor
  12935     @param[in] other const iterator to copy from
  12936     @note This copy constructor had to be defined explicitly to circumvent a bug
  12937           occurring on msvc v19.0 compiler (VS 2015) debug build. For more
  12938           information refer to: https://github.com/nlohmann/json/issues/1608
  12939     */
  12940     iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
  12941         : m_object(other.m_object), m_it(other.m_it)
  12942     {}
  12943 
  12944     /*!
  12945     @brief converting assignment
  12946     @param[in] other const iterator to copy from
  12947     @return const/non-const iterator
  12948     @note It is not checked whether @a other is initialized.
  12949     */
  12950     iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
  12951     {
  12952         if (&other != this)
  12953         {
  12954             m_object = other.m_object;
  12955             m_it = other.m_it;
  12956         }
  12957         return *this;
  12958     }
  12959 
  12960     /*!
  12961     @brief converting constructor
  12962     @param[in] other  non-const iterator to copy from
  12963     @note It is not checked whether @a other is initialized.
  12964     */
  12965     iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
  12966         : m_object(other.m_object), m_it(other.m_it)
  12967     {}
  12968 
  12969     /*!
  12970     @brief converting assignment
  12971     @param[in] other  non-const iterator to copy from
  12972     @return const/non-const iterator
  12973     @note It is not checked whether @a other is initialized.
  12974     */
  12975     iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
  12976     {
  12977         m_object = other.m_object;
  12978         m_it = other.m_it;
  12979         return *this;
  12980     }
  12981 
  12982   JSON_PRIVATE_UNLESS_TESTED:
  12983     /*!
  12984     @brief set the iterator to the first value
  12985     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  12986     */
  12987     void set_begin() noexcept
  12988     {
  12989         JSON_ASSERT(m_object != nullptr);
  12990 
  12991         switch (m_object->m_type)
  12992         {
  12993             case value_t::object:
  12994             {
  12995                 m_it.object_iterator = m_object->m_value.object->begin();
  12996                 break;
  12997             }
  12998 
  12999             case value_t::array:
  13000             {
  13001                 m_it.array_iterator = m_object->m_value.array->begin();
  13002                 break;
  13003             }
  13004 
  13005             case value_t::null:
  13006             {
  13007                 // set to end so begin()==end() is true: null is empty
  13008                 m_it.primitive_iterator.set_end();
  13009                 break;
  13010             }
  13011 
  13012             case value_t::string:
  13013             case value_t::boolean:
  13014             case value_t::number_integer:
  13015             case value_t::number_unsigned:
  13016             case value_t::number_float:
  13017             case value_t::binary:
  13018             case value_t::discarded:
  13019             default:
  13020             {
  13021                 m_it.primitive_iterator.set_begin();
  13022                 break;
  13023             }
  13024         }
  13025     }
  13026 
  13027     /*!
  13028     @brief set the iterator past the last value
  13029     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13030     */
  13031     void set_end() noexcept
  13032     {
  13033         JSON_ASSERT(m_object != nullptr);
  13034 
  13035         switch (m_object->m_type)
  13036         {
  13037             case value_t::object:
  13038             {
  13039                 m_it.object_iterator = m_object->m_value.object->end();
  13040                 break;
  13041             }
  13042 
  13043             case value_t::array:
  13044             {
  13045                 m_it.array_iterator = m_object->m_value.array->end();
  13046                 break;
  13047             }
  13048 
  13049             case value_t::null:
  13050             case value_t::string:
  13051             case value_t::boolean:
  13052             case value_t::number_integer:
  13053             case value_t::number_unsigned:
  13054             case value_t::number_float:
  13055             case value_t::binary:
  13056             case value_t::discarded:
  13057             default:
  13058             {
  13059                 m_it.primitive_iterator.set_end();
  13060                 break;
  13061             }
  13062         }
  13063     }
  13064 
  13065   public:
  13066     /*!
  13067     @brief return a reference to the value pointed to by the iterator
  13068     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13069     */
  13070     reference operator*() const
  13071     {
  13072         JSON_ASSERT(m_object != nullptr);
  13073 
  13074         switch (m_object->m_type)
  13075         {
  13076             case value_t::object:
  13077             {
  13078                 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
  13079                 return m_it.object_iterator->second;
  13080             }
  13081 
  13082             case value_t::array:
  13083             {
  13084                 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
  13085                 return *m_it.array_iterator;
  13086             }
  13087 
  13088             case value_t::null:
  13089                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13090 
  13091             case value_t::string:
  13092             case value_t::boolean:
  13093             case value_t::number_integer:
  13094             case value_t::number_unsigned:
  13095             case value_t::number_float:
  13096             case value_t::binary:
  13097             case value_t::discarded:
  13098             default:
  13099             {
  13100                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
  13101                 {
  13102                     return *m_object;
  13103                 }
  13104 
  13105                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13106             }
  13107         }
  13108     }
  13109 
  13110     /*!
  13111     @brief dereference the iterator
  13112     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13113     */
  13114     pointer operator->() const
  13115     {
  13116         JSON_ASSERT(m_object != nullptr);
  13117 
  13118         switch (m_object->m_type)
  13119         {
  13120             case value_t::object:
  13121             {
  13122                 JSON_ASSERT(m_it.object_iterator != m_object->m_value.object->end());
  13123                 return &(m_it.object_iterator->second);
  13124             }
  13125 
  13126             case value_t::array:
  13127             {
  13128                 JSON_ASSERT(m_it.array_iterator != m_object->m_value.array->end());
  13129                 return &*m_it.array_iterator;
  13130             }
  13131 
  13132             case value_t::null:
  13133             case value_t::string:
  13134             case value_t::boolean:
  13135             case value_t::number_integer:
  13136             case value_t::number_unsigned:
  13137             case value_t::number_float:
  13138             case value_t::binary:
  13139             case value_t::discarded:
  13140             default:
  13141             {
  13142                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
  13143                 {
  13144                     return m_object;
  13145                 }
  13146 
  13147                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13148             }
  13149         }
  13150     }
  13151 
  13152     /*!
  13153     @brief post-increment (it++)
  13154     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13155     */
  13156     iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
  13157     {
  13158         auto result = *this;
  13159         ++(*this);
  13160         return result;
  13161     }
  13162 
  13163     /*!
  13164     @brief pre-increment (++it)
  13165     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13166     */
  13167     iter_impl& operator++()
  13168     {
  13169         JSON_ASSERT(m_object != nullptr);
  13170 
  13171         switch (m_object->m_type)
  13172         {
  13173             case value_t::object:
  13174             {
  13175                 std::advance(m_it.object_iterator, 1);
  13176                 break;
  13177             }
  13178 
  13179             case value_t::array:
  13180             {
  13181                 std::advance(m_it.array_iterator, 1);
  13182                 break;
  13183             }
  13184 
  13185             case value_t::null:
  13186             case value_t::string:
  13187             case value_t::boolean:
  13188             case value_t::number_integer:
  13189             case value_t::number_unsigned:
  13190             case value_t::number_float:
  13191             case value_t::binary:
  13192             case value_t::discarded:
  13193             default:
  13194             {
  13195                 ++m_it.primitive_iterator;
  13196                 break;
  13197             }
  13198         }
  13199 
  13200         return *this;
  13201     }
  13202 
  13203     /*!
  13204     @brief post-decrement (it--)
  13205     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13206     */
  13207     iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
  13208     {
  13209         auto result = *this;
  13210         --(*this);
  13211         return result;
  13212     }
  13213 
  13214     /*!
  13215     @brief pre-decrement (--it)
  13216     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13217     */
  13218     iter_impl& operator--()
  13219     {
  13220         JSON_ASSERT(m_object != nullptr);
  13221 
  13222         switch (m_object->m_type)
  13223         {
  13224             case value_t::object:
  13225             {
  13226                 std::advance(m_it.object_iterator, -1);
  13227                 break;
  13228             }
  13229 
  13230             case value_t::array:
  13231             {
  13232                 std::advance(m_it.array_iterator, -1);
  13233                 break;
  13234             }
  13235 
  13236             case value_t::null:
  13237             case value_t::string:
  13238             case value_t::boolean:
  13239             case value_t::number_integer:
  13240             case value_t::number_unsigned:
  13241             case value_t::number_float:
  13242             case value_t::binary:
  13243             case value_t::discarded:
  13244             default:
  13245             {
  13246                 --m_it.primitive_iterator;
  13247                 break;
  13248             }
  13249         }
  13250 
  13251         return *this;
  13252     }
  13253 
  13254     /*!
  13255     @brief comparison: equal
  13256     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13257     */
  13258     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
  13259     bool operator==(const IterImpl& other) const
  13260     {
  13261         // if objects are not the same, the comparison is undefined
  13262         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
  13263         {
  13264             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
  13265         }
  13266 
  13267         JSON_ASSERT(m_object != nullptr);
  13268 
  13269         switch (m_object->m_type)
  13270         {
  13271             case value_t::object:
  13272                 return (m_it.object_iterator == other.m_it.object_iterator);
  13273 
  13274             case value_t::array:
  13275                 return (m_it.array_iterator == other.m_it.array_iterator);
  13276 
  13277             case value_t::null:
  13278             case value_t::string:
  13279             case value_t::boolean:
  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                 return (m_it.primitive_iterator == other.m_it.primitive_iterator);
  13287         }
  13288     }
  13289 
  13290     /*!
  13291     @brief comparison: not equal
  13292     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13293     */
  13294     template < typename IterImpl, detail::enable_if_t < (std::is_same<IterImpl, iter_impl>::value || std::is_same<IterImpl, other_iter_impl>::value), std::nullptr_t > = nullptr >
  13295     bool operator!=(const IterImpl& other) const
  13296     {
  13297         return !operator==(other);
  13298     }
  13299 
  13300     /*!
  13301     @brief comparison: smaller
  13302     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13303     */
  13304     bool operator<(const iter_impl& other) const
  13305     {
  13306         // if objects are not the same, the comparison is undefined
  13307         if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
  13308         {
  13309             JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
  13310         }
  13311 
  13312         JSON_ASSERT(m_object != nullptr);
  13313 
  13314         switch (m_object->m_type)
  13315         {
  13316             case value_t::object:
  13317                 JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
  13318 
  13319             case value_t::array:
  13320                 return (m_it.array_iterator < other.m_it.array_iterator);
  13321 
  13322             case value_t::null:
  13323             case value_t::string:
  13324             case value_t::boolean:
  13325             case value_t::number_integer:
  13326             case value_t::number_unsigned:
  13327             case value_t::number_float:
  13328             case value_t::binary:
  13329             case value_t::discarded:
  13330             default:
  13331                 return (m_it.primitive_iterator < other.m_it.primitive_iterator);
  13332         }
  13333     }
  13334 
  13335     /*!
  13336     @brief comparison: less than or equal
  13337     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13338     */
  13339     bool operator<=(const iter_impl& other) const
  13340     {
  13341         return !other.operator < (*this);
  13342     }
  13343 
  13344     /*!
  13345     @brief comparison: greater than
  13346     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13347     */
  13348     bool operator>(const iter_impl& other) const
  13349     {
  13350         return !operator<=(other);
  13351     }
  13352 
  13353     /*!
  13354     @brief comparison: greater than or equal
  13355     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13356     */
  13357     bool operator>=(const iter_impl& other) const
  13358     {
  13359         return !operator<(other);
  13360     }
  13361 
  13362     /*!
  13363     @brief add to iterator
  13364     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13365     */
  13366     iter_impl& operator+=(difference_type i)
  13367     {
  13368         JSON_ASSERT(m_object != nullptr);
  13369 
  13370         switch (m_object->m_type)
  13371         {
  13372             case value_t::object:
  13373                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
  13374 
  13375             case value_t::array:
  13376             {
  13377                 std::advance(m_it.array_iterator, i);
  13378                 break;
  13379             }
  13380 
  13381             case value_t::null:
  13382             case value_t::string:
  13383             case value_t::boolean:
  13384             case value_t::number_integer:
  13385             case value_t::number_unsigned:
  13386             case value_t::number_float:
  13387             case value_t::binary:
  13388             case value_t::discarded:
  13389             default:
  13390             {
  13391                 m_it.primitive_iterator += i;
  13392                 break;
  13393             }
  13394         }
  13395 
  13396         return *this;
  13397     }
  13398 
  13399     /*!
  13400     @brief subtract from iterator
  13401     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13402     */
  13403     iter_impl& operator-=(difference_type i)
  13404     {
  13405         return operator+=(-i);
  13406     }
  13407 
  13408     /*!
  13409     @brief add to iterator
  13410     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13411     */
  13412     iter_impl operator+(difference_type i) const
  13413     {
  13414         auto result = *this;
  13415         result += i;
  13416         return result;
  13417     }
  13418 
  13419     /*!
  13420     @brief addition of distance and iterator
  13421     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13422     */
  13423     friend iter_impl operator+(difference_type i, const iter_impl& it)
  13424     {
  13425         auto result = it;
  13426         result += i;
  13427         return result;
  13428     }
  13429 
  13430     /*!
  13431     @brief subtract from iterator
  13432     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13433     */
  13434     iter_impl operator-(difference_type i) const
  13435     {
  13436         auto result = *this;
  13437         result -= i;
  13438         return result;
  13439     }
  13440 
  13441     /*!
  13442     @brief return difference
  13443     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13444     */
  13445     difference_type operator-(const iter_impl& other) const
  13446     {
  13447         JSON_ASSERT(m_object != nullptr);
  13448 
  13449         switch (m_object->m_type)
  13450         {
  13451             case value_t::object:
  13452                 JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
  13453 
  13454             case value_t::array:
  13455                 return m_it.array_iterator - other.m_it.array_iterator;
  13456 
  13457             case value_t::null:
  13458             case value_t::string:
  13459             case value_t::boolean:
  13460             case value_t::number_integer:
  13461             case value_t::number_unsigned:
  13462             case value_t::number_float:
  13463             case value_t::binary:
  13464             case value_t::discarded:
  13465             default:
  13466                 return m_it.primitive_iterator - other.m_it.primitive_iterator;
  13467         }
  13468     }
  13469 
  13470     /*!
  13471     @brief access to successor
  13472     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13473     */
  13474     reference operator[](difference_type n) const
  13475     {
  13476         JSON_ASSERT(m_object != nullptr);
  13477 
  13478         switch (m_object->m_type)
  13479         {
  13480             case value_t::object:
  13481                 JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
  13482 
  13483             case value_t::array:
  13484                 return *std::next(m_it.array_iterator, n);
  13485 
  13486             case value_t::null:
  13487                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13488 
  13489             case value_t::string:
  13490             case value_t::boolean:
  13491             case value_t::number_integer:
  13492             case value_t::number_unsigned:
  13493             case value_t::number_float:
  13494             case value_t::binary:
  13495             case value_t::discarded:
  13496             default:
  13497             {
  13498                 if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
  13499                 {
  13500                     return *m_object;
  13501                 }
  13502 
  13503                 JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13504             }
  13505         }
  13506     }
  13507 
  13508     /*!
  13509     @brief return the key of an object iterator
  13510     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13511     */
  13512     const typename object_t::key_type& key() const
  13513     {
  13514         JSON_ASSERT(m_object != nullptr);
  13515 
  13516         if (JSON_HEDLEY_LIKELY(m_object->is_object()))
  13517         {
  13518             return m_it.object_iterator->first;
  13519         }
  13520 
  13521         JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
  13522     }
  13523 
  13524     /*!
  13525     @brief return the value of an iterator
  13526     @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13527     */
  13528     reference value() const
  13529     {
  13530         return operator*();
  13531     }
  13532 
  13533   JSON_PRIVATE_UNLESS_TESTED:
  13534     /// associated JSON instance
  13535     pointer m_object = nullptr;
  13536     /// the actual iterator of the associated instance
  13537     internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
  13538 };
  13539 
  13540 }  // namespace detail
  13541 NLOHMANN_JSON_NAMESPACE_END
  13542 
  13543 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
  13544 
  13545 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
  13546 //     __ _____ _____ _____
  13547 //  __|  |   __|     |   | |  JSON for Modern C++
  13548 // |  |  |__   |  |  | | | |  version 3.11.2
  13549 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  13550 //
  13551 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  13552 // SPDX-License-Identifier: MIT
  13553 
  13554 
  13555 
  13556 #include <cstddef> // ptrdiff_t
  13557 #include <iterator> // reverse_iterator
  13558 #include <utility> // declval
  13559 
  13560 // #include <nlohmann/detail/abi_macros.hpp>
  13561 
  13562 
  13563 NLOHMANN_JSON_NAMESPACE_BEGIN
  13564 namespace detail
  13565 {
  13566 
  13567 //////////////////////
  13568 // reverse_iterator //
  13569 //////////////////////
  13570 
  13571 /*!
  13572 @brief a template for a reverse iterator class
  13573 
  13574 @tparam Base the base iterator type to reverse. Valid types are @ref
  13575 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
  13576 create @ref const_reverse_iterator).
  13577 
  13578 @requirement The class satisfies the following concept requirements:
  13579 -
  13580 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
  13581   The iterator that can be moved can be moved in both directions (i.e.
  13582   incremented and decremented).
  13583 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
  13584   It is possible to write to the pointed-to element (only if @a Base is
  13585   @ref iterator).
  13586 
  13587 @since version 1.0.0
  13588 */
  13589 template<typename Base>
  13590 class json_reverse_iterator : public std::reverse_iterator<Base>
  13591 {
  13592   public:
  13593     using difference_type = std::ptrdiff_t;
  13594     /// shortcut to the reverse iterator adapter
  13595     using base_iterator = std::reverse_iterator<Base>;
  13596     /// the reference type for the pointed-to element
  13597     using reference = typename Base::reference;
  13598 
  13599     /// create reverse iterator from iterator
  13600     explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
  13601         : base_iterator(it) {}
  13602 
  13603     /// create reverse iterator from base class
  13604     explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
  13605 
  13606     /// post-increment (it++)
  13607     json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
  13608     {
  13609         return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
  13610     }
  13611 
  13612     /// pre-increment (++it)
  13613     json_reverse_iterator& operator++()
  13614     {
  13615         return static_cast<json_reverse_iterator&>(base_iterator::operator++());
  13616     }
  13617 
  13618     /// post-decrement (it--)
  13619     json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
  13620     {
  13621         return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
  13622     }
  13623 
  13624     /// pre-decrement (--it)
  13625     json_reverse_iterator& operator--()
  13626     {
  13627         return static_cast<json_reverse_iterator&>(base_iterator::operator--());
  13628     }
  13629 
  13630     /// add to iterator
  13631     json_reverse_iterator& operator+=(difference_type i)
  13632     {
  13633         return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
  13634     }
  13635 
  13636     /// add to iterator
  13637     json_reverse_iterator operator+(difference_type i) const
  13638     {
  13639         return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
  13640     }
  13641 
  13642     /// subtract from iterator
  13643     json_reverse_iterator operator-(difference_type i) const
  13644     {
  13645         return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
  13646     }
  13647 
  13648     /// return difference
  13649     difference_type operator-(const json_reverse_iterator& other) const
  13650     {
  13651         return base_iterator(*this) - base_iterator(other);
  13652     }
  13653 
  13654     /// access to successor
  13655     reference operator[](difference_type n) const
  13656     {
  13657         return *(this->operator+(n));
  13658     }
  13659 
  13660     /// return the key of an object iterator
  13661     auto key() const -> decltype(std::declval<Base>().key())
  13662     {
  13663         auto it = --this->base();
  13664         return it.key();
  13665     }
  13666 
  13667     /// return the value of an iterator
  13668     reference value() const
  13669     {
  13670         auto it = --this->base();
  13671         return it.operator * ();
  13672     }
  13673 };
  13674 
  13675 }  // namespace detail
  13676 NLOHMANN_JSON_NAMESPACE_END
  13677 
  13678 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  13679 
  13680 // #include <nlohmann/detail/json_custom_base_class.hpp>
  13681 
  13682 
  13683 #include <type_traits> // conditional, is_same
  13684 
  13685 // #include <nlohmann/detail/abi_macros.hpp>
  13686 
  13687 
  13688 NLOHMANN_JSON_NAMESPACE_BEGIN
  13689 namespace detail
  13690 {
  13691 
  13692 /*!
  13693 @brief Default base class of the @ref basic_json class.
  13694 
  13695 So that the correct implementations of the copy / move ctors / assign operators
  13696 of @ref basic_json do not require complex case distinctions
  13697 (no base class / custom base class used as customization point),
  13698 @ref basic_json always has a base class.
  13699 By default, this class is used because it is empty and thus has no effect
  13700 on the behavior of @ref basic_json.
  13701 */
  13702 struct json_default_base {};
  13703 
  13704 template<class T>
  13705 using json_base_class = typename std::conditional <
  13706                         std::is_same<T, void>::value,
  13707                         json_default_base,
  13708                         T
  13709                         >::type;
  13710 
  13711 }  // namespace detail
  13712 NLOHMANN_JSON_NAMESPACE_END
  13713 
  13714 // #include <nlohmann/detail/json_pointer.hpp>
  13715 //     __ _____ _____ _____
  13716 //  __|  |   __|     |   | |  JSON for Modern C++
  13717 // |  |  |__   |  |  | | | |  version 3.11.2
  13718 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  13719 //
  13720 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  13721 // SPDX-License-Identifier: MIT
  13722 
  13723 
  13724 
  13725 #include <algorithm> // all_of
  13726 #include <cctype> // isdigit
  13727 #include <cerrno> // errno, ERANGE
  13728 #include <cstdlib> // strtoull
  13729 #ifndef JSON_NO_IO
  13730     #include <iosfwd> // ostream
  13731 #endif  // JSON_NO_IO
  13732 #include <limits> // max
  13733 #include <numeric> // accumulate
  13734 #include <string> // string
  13735 #include <utility> // move
  13736 #include <vector> // vector
  13737 
  13738 // #include <nlohmann/detail/exceptions.hpp>
  13739 
  13740 // #include <nlohmann/detail/macro_scope.hpp>
  13741 
  13742 // #include <nlohmann/detail/string_concat.hpp>
  13743 
  13744 // #include <nlohmann/detail/string_escape.hpp>
  13745 
  13746 // #include <nlohmann/detail/value_t.hpp>
  13747 
  13748 
  13749 NLOHMANN_JSON_NAMESPACE_BEGIN
  13750 
  13751 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
  13752 /// @sa https://json.nlohmann.me/api/json_pointer/
  13753 template<typename RefStringType>
  13754 class json_pointer
  13755 {
  13756     // allow basic_json to access private members
  13757     NLOHMANN_BASIC_JSON_TPL_DECLARATION
  13758     friend class basic_json;
  13759 
  13760     template<typename>
  13761     friend class json_pointer;
  13762 
  13763     template<typename T>
  13764     struct string_t_helper
  13765     {
  13766         using type = T;
  13767     };
  13768 
  13769     NLOHMANN_BASIC_JSON_TPL_DECLARATION
  13770     struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
  13771     {
  13772         using type = StringType;
  13773     };
  13774 
  13775   public:
  13776     // for backwards compatibility accept BasicJsonType
  13777     using string_t = typename string_t_helper<RefStringType>::type;
  13778 
  13779     /// @brief create JSON pointer
  13780     /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
  13781     explicit json_pointer(const string_t& s = "")
  13782         : reference_tokens(split(s))
  13783     {}
  13784 
  13785     /// @brief return a string representation of the JSON pointer
  13786     /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
  13787     string_t to_string() const
  13788     {
  13789         return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
  13790                                string_t{},
  13791                                [](const string_t& a, const string_t& b)
  13792         {
  13793             return detail::concat(a, '/', detail::escape(b));
  13794         });
  13795     }
  13796 
  13797     /// @brief return a string representation of the JSON pointer
  13798     /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
  13799     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
  13800     operator string_t() const
  13801     {
  13802         return to_string();
  13803     }
  13804 
  13805 #ifndef JSON_NO_IO
  13806     /// @brief write string representation of the JSON pointer to stream
  13807     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
  13808     friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
  13809     {
  13810         o << ptr.to_string();
  13811         return o;
  13812     }
  13813 #endif
  13814 
  13815     /// @brief append another JSON pointer at the end of this JSON pointer
  13816     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
  13817     json_pointer& operator/=(const json_pointer& ptr)
  13818     {
  13819         reference_tokens.insert(reference_tokens.end(),
  13820                                 ptr.reference_tokens.begin(),
  13821                                 ptr.reference_tokens.end());
  13822         return *this;
  13823     }
  13824 
  13825     /// @brief append an unescaped reference token at the end of this JSON pointer
  13826     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
  13827     json_pointer& operator/=(string_t token)
  13828     {
  13829         push_back(std::move(token));
  13830         return *this;
  13831     }
  13832 
  13833     /// @brief append an array index at the end of this JSON pointer
  13834     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
  13835     json_pointer& operator/=(std::size_t array_idx)
  13836     {
  13837         return *this /= std::to_string(array_idx);
  13838     }
  13839 
  13840     /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
  13841     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
  13842     friend json_pointer operator/(const json_pointer& lhs,
  13843                                   const json_pointer& rhs)
  13844     {
  13845         return json_pointer(lhs) /= rhs;
  13846     }
  13847 
  13848     /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
  13849     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
  13850     friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
  13851     {
  13852         return json_pointer(lhs) /= std::move(token);
  13853     }
  13854 
  13855     /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
  13856     /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
  13857     friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
  13858     {
  13859         return json_pointer(lhs) /= array_idx;
  13860     }
  13861 
  13862     /// @brief returns the parent of this JSON pointer
  13863     /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
  13864     json_pointer parent_pointer() const
  13865     {
  13866         if (empty())
  13867         {
  13868             return *this;
  13869         }
  13870 
  13871         json_pointer res = *this;
  13872         res.pop_back();
  13873         return res;
  13874     }
  13875 
  13876     /// @brief remove last reference token
  13877     /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
  13878     void pop_back()
  13879     {
  13880         if (JSON_HEDLEY_UNLIKELY(empty()))
  13881         {
  13882             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
  13883         }
  13884 
  13885         reference_tokens.pop_back();
  13886     }
  13887 
  13888     /// @brief return last reference token
  13889     /// @sa https://json.nlohmann.me/api/json_pointer/back/
  13890     const string_t& back() const
  13891     {
  13892         if (JSON_HEDLEY_UNLIKELY(empty()))
  13893         {
  13894             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
  13895         }
  13896 
  13897         return reference_tokens.back();
  13898     }
  13899 
  13900     /// @brief append an unescaped token at the end of the reference pointer
  13901     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
  13902     void push_back(const string_t& token)
  13903     {
  13904         reference_tokens.push_back(token);
  13905     }
  13906 
  13907     /// @brief append an unescaped token at the end of the reference pointer
  13908     /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
  13909     void push_back(string_t&& token)
  13910     {
  13911         reference_tokens.push_back(std::move(token));
  13912     }
  13913 
  13914     /// @brief return whether pointer points to the root document
  13915     /// @sa https://json.nlohmann.me/api/json_pointer/empty/
  13916     bool empty() const noexcept
  13917     {
  13918         return reference_tokens.empty();
  13919     }
  13920 
  13921   private:
  13922     /*!
  13923     @param[in] s  reference token to be converted into an array index
  13924 
  13925     @return integer representation of @a s
  13926 
  13927     @throw parse_error.106  if an array index begins with '0'
  13928     @throw parse_error.109  if an array index begins not with a digit
  13929     @throw out_of_range.404 if string @a s could not be converted to an integer
  13930     @throw out_of_range.410 if an array index exceeds size_type
  13931     */
  13932     template<typename BasicJsonType>
  13933     static typename BasicJsonType::size_type array_index(const string_t& s)
  13934     {
  13935         using size_type = typename BasicJsonType::size_type;
  13936 
  13937         // error condition (cf. RFC 6901, Sect. 4)
  13938         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
  13939         {
  13940             JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
  13941         }
  13942 
  13943         // error condition (cf. RFC 6901, Sect. 4)
  13944         if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
  13945         {
  13946             JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
  13947         }
  13948 
  13949         const char* p = s.c_str();
  13950         char* p_end = nullptr;
  13951         errno = 0; // strtoull doesn't reset errno
  13952         const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
  13953         if (p == p_end // invalid input or empty string
  13954                 || errno == ERANGE // out of range
  13955                 || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
  13956         {
  13957             JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
  13958         }
  13959 
  13960         // only triggered on special platforms (like 32bit), see also
  13961         // https://github.com/nlohmann/json/pull/2203
  13962         if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
  13963         {
  13964             JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
  13965         }
  13966 
  13967         return static_cast<size_type>(res);
  13968     }
  13969 
  13970   JSON_PRIVATE_UNLESS_TESTED:
  13971     json_pointer top() const
  13972     {
  13973         if (JSON_HEDLEY_UNLIKELY(empty()))
  13974         {
  13975             JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
  13976         }
  13977 
  13978         json_pointer result = *this;
  13979         result.reference_tokens = {reference_tokens[0]};
  13980         return result;
  13981     }
  13982 
  13983   private:
  13984     /*!
  13985     @brief create and return a reference to the pointed to value
  13986 
  13987     @complexity Linear in the number of reference tokens.
  13988 
  13989     @throw parse_error.109 if array index is not a number
  13990     @throw type_error.313 if value cannot be unflattened
  13991     */
  13992     template<typename BasicJsonType>
  13993     BasicJsonType& get_and_create(BasicJsonType& j) const
  13994     {
  13995         auto* result = &j;
  13996 
  13997         // in case no reference tokens exist, return a reference to the JSON value
  13998         // j which will be overwritten by a primitive value
  13999         for (const auto& reference_token : reference_tokens)
  14000         {
  14001             switch (result->type())
  14002             {
  14003                 case detail::value_t::null:
  14004                 {
  14005                     if (reference_token == "0")
  14006                     {
  14007                         // start a new array if reference token is 0
  14008                         result = &result->operator[](0);
  14009                     }
  14010                     else
  14011                     {
  14012                         // start a new object otherwise
  14013                         result = &result->operator[](reference_token);
  14014                     }
  14015                     break;
  14016                 }
  14017 
  14018                 case detail::value_t::object:
  14019                 {
  14020                     // create an entry in the object
  14021                     result = &result->operator[](reference_token);
  14022                     break;
  14023                 }
  14024 
  14025                 case detail::value_t::array:
  14026                 {
  14027                     // create an entry in the array
  14028                     result = &result->operator[](array_index<BasicJsonType>(reference_token));
  14029                     break;
  14030                 }
  14031 
  14032                 /*
  14033                 The following code is only reached if there exists a reference
  14034                 token _and_ the current value is primitive. In this case, we have
  14035                 an error situation, because primitive values may only occur as
  14036                 single value; that is, with an empty list of reference tokens.
  14037                 */
  14038                 case detail::value_t::string:
  14039                 case detail::value_t::boolean:
  14040                 case detail::value_t::number_integer:
  14041                 case detail::value_t::number_unsigned:
  14042                 case detail::value_t::number_float:
  14043                 case detail::value_t::binary:
  14044                 case detail::value_t::discarded:
  14045                 default:
  14046                     JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
  14047             }
  14048         }
  14049 
  14050         return *result;
  14051     }
  14052 
  14053     /*!
  14054     @brief return a reference to the pointed to value
  14055 
  14056     @note This version does not throw if a value is not present, but tries to
  14057           create nested values instead. For instance, calling this function
  14058           with pointer `"/this/that"` on a null value is equivalent to calling
  14059           `operator[]("this").operator[]("that")` on that value, effectively
  14060           changing the null value to an object.
  14061 
  14062     @param[in] ptr  a JSON value
  14063 
  14064     @return reference to the JSON value pointed to by the JSON pointer
  14065 
  14066     @complexity Linear in the length of the JSON pointer.
  14067 
  14068     @throw parse_error.106   if an array index begins with '0'
  14069     @throw parse_error.109   if an array index was not a number
  14070     @throw out_of_range.404  if the JSON pointer can not be resolved
  14071     */
  14072     template<typename BasicJsonType>
  14073     BasicJsonType& get_unchecked(BasicJsonType* ptr) const
  14074     {
  14075         for (const auto& reference_token : reference_tokens)
  14076         {
  14077             // convert null values to arrays or objects before continuing
  14078             if (ptr->is_null())
  14079             {
  14080                 // check if reference token is a number
  14081                 const bool nums =
  14082                     std::all_of(reference_token.begin(), reference_token.end(),
  14083                                 [](const unsigned char x)
  14084                 {
  14085                     return std::isdigit(x);
  14086                 });
  14087 
  14088                 // change value to array for numbers or "-" or to object otherwise
  14089                 *ptr = (nums || reference_token == "-")
  14090                        ? detail::value_t::array
  14091                        : detail::value_t::object;
  14092             }
  14093 
  14094             switch (ptr->type())
  14095             {
  14096                 case detail::value_t::object:
  14097                 {
  14098                     // use unchecked object access
  14099                     ptr = &ptr->operator[](reference_token);
  14100                     break;
  14101                 }
  14102 
  14103                 case detail::value_t::array:
  14104                 {
  14105                     if (reference_token == "-")
  14106                     {
  14107                         // explicitly treat "-" as index beyond the end
  14108                         ptr = &ptr->operator[](ptr->m_value.array->size());
  14109                     }
  14110                     else
  14111                     {
  14112                         // convert array index to number; unchecked access
  14113                         ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
  14114                     }
  14115                     break;
  14116                 }
  14117 
  14118                 case detail::value_t::null:
  14119                 case detail::value_t::string:
  14120                 case detail::value_t::boolean:
  14121                 case detail::value_t::number_integer:
  14122                 case detail::value_t::number_unsigned:
  14123                 case detail::value_t::number_float:
  14124                 case detail::value_t::binary:
  14125                 case detail::value_t::discarded:
  14126                 default:
  14127                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14128             }
  14129         }
  14130 
  14131         return *ptr;
  14132     }
  14133 
  14134     /*!
  14135     @throw parse_error.106   if an array index begins with '0'
  14136     @throw parse_error.109   if an array index was not a number
  14137     @throw out_of_range.402  if the array index '-' is used
  14138     @throw out_of_range.404  if the JSON pointer can not be resolved
  14139     */
  14140     template<typename BasicJsonType>
  14141     BasicJsonType& get_checked(BasicJsonType* ptr) const
  14142     {
  14143         for (const auto& reference_token : reference_tokens)
  14144         {
  14145             switch (ptr->type())
  14146             {
  14147                 case detail::value_t::object:
  14148                 {
  14149                     // note: at performs range check
  14150                     ptr = &ptr->at(reference_token);
  14151                     break;
  14152                 }
  14153 
  14154                 case detail::value_t::array:
  14155                 {
  14156                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14157                     {
  14158                         // "-" always fails the range check
  14159                         JSON_THROW(detail::out_of_range::create(402, detail::concat(
  14160                                 "array index '-' (", std::to_string(ptr->m_value.array->size()),
  14161                                 ") is out of range"), ptr));
  14162                     }
  14163 
  14164                     // note: at performs range check
  14165                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
  14166                     break;
  14167                 }
  14168 
  14169                 case detail::value_t::null:
  14170                 case detail::value_t::string:
  14171                 case detail::value_t::boolean:
  14172                 case detail::value_t::number_integer:
  14173                 case detail::value_t::number_unsigned:
  14174                 case detail::value_t::number_float:
  14175                 case detail::value_t::binary:
  14176                 case detail::value_t::discarded:
  14177                 default:
  14178                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14179             }
  14180         }
  14181 
  14182         return *ptr;
  14183     }
  14184 
  14185     /*!
  14186     @brief return a const reference to the pointed to value
  14187 
  14188     @param[in] ptr  a JSON value
  14189 
  14190     @return const reference to the JSON value pointed to by the JSON
  14191     pointer
  14192 
  14193     @throw parse_error.106   if an array index begins with '0'
  14194     @throw parse_error.109   if an array index was not a number
  14195     @throw out_of_range.402  if the array index '-' is used
  14196     @throw out_of_range.404  if the JSON pointer can not be resolved
  14197     */
  14198     template<typename BasicJsonType>
  14199     const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
  14200     {
  14201         for (const auto& reference_token : reference_tokens)
  14202         {
  14203             switch (ptr->type())
  14204             {
  14205                 case detail::value_t::object:
  14206                 {
  14207                     // use unchecked object access
  14208                     ptr = &ptr->operator[](reference_token);
  14209                     break;
  14210                 }
  14211 
  14212                 case detail::value_t::array:
  14213                 {
  14214                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14215                     {
  14216                         // "-" cannot be used for const access
  14217                         JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_value.array->size()), ") is out of range"), ptr));
  14218                     }
  14219 
  14220                     // use unchecked array access
  14221                     ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
  14222                     break;
  14223                 }
  14224 
  14225                 case detail::value_t::null:
  14226                 case detail::value_t::string:
  14227                 case detail::value_t::boolean:
  14228                 case detail::value_t::number_integer:
  14229                 case detail::value_t::number_unsigned:
  14230                 case detail::value_t::number_float:
  14231                 case detail::value_t::binary:
  14232                 case detail::value_t::discarded:
  14233                 default:
  14234                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14235             }
  14236         }
  14237 
  14238         return *ptr;
  14239     }
  14240 
  14241     /*!
  14242     @throw parse_error.106   if an array index begins with '0'
  14243     @throw parse_error.109   if an array index was not a number
  14244     @throw out_of_range.402  if the array index '-' is used
  14245     @throw out_of_range.404  if the JSON pointer can not be resolved
  14246     */
  14247     template<typename BasicJsonType>
  14248     const BasicJsonType& get_checked(const BasicJsonType* ptr) const
  14249     {
  14250         for (const auto& reference_token : reference_tokens)
  14251         {
  14252             switch (ptr->type())
  14253             {
  14254                 case detail::value_t::object:
  14255                 {
  14256                     // note: at performs range check
  14257                     ptr = &ptr->at(reference_token);
  14258                     break;
  14259                 }
  14260 
  14261                 case detail::value_t::array:
  14262                 {
  14263                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14264                     {
  14265                         // "-" always fails the range check
  14266                         JSON_THROW(detail::out_of_range::create(402, detail::concat(
  14267                                 "array index '-' (", std::to_string(ptr->m_value.array->size()),
  14268                                 ") is out of range"), ptr));
  14269                     }
  14270 
  14271                     // note: at performs range check
  14272                     ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
  14273                     break;
  14274                 }
  14275 
  14276                 case detail::value_t::null:
  14277                 case detail::value_t::string:
  14278                 case detail::value_t::boolean:
  14279                 case detail::value_t::number_integer:
  14280                 case detail::value_t::number_unsigned:
  14281                 case detail::value_t::number_float:
  14282                 case detail::value_t::binary:
  14283                 case detail::value_t::discarded:
  14284                 default:
  14285                     JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14286             }
  14287         }
  14288 
  14289         return *ptr;
  14290     }
  14291 
  14292     /*!
  14293     @throw parse_error.106   if an array index begins with '0'
  14294     @throw parse_error.109   if an array index was not a number
  14295     */
  14296     template<typename BasicJsonType>
  14297     bool contains(const BasicJsonType* ptr) const
  14298     {
  14299         for (const auto& reference_token : reference_tokens)
  14300         {
  14301             switch (ptr->type())
  14302             {
  14303                 case detail::value_t::object:
  14304                 {
  14305                     if (!ptr->contains(reference_token))
  14306                     {
  14307                         // we did not find the key in the object
  14308                         return false;
  14309                     }
  14310 
  14311                     ptr = &ptr->operator[](reference_token);
  14312                     break;
  14313                 }
  14314 
  14315                 case detail::value_t::array:
  14316                 {
  14317                     if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14318                     {
  14319                         // "-" always fails the range check
  14320                         return false;
  14321                     }
  14322                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
  14323                     {
  14324                         // invalid char
  14325                         return false;
  14326                     }
  14327                     if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
  14328                     {
  14329                         if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
  14330                         {
  14331                             // first char should be between '1' and '9'
  14332                             return false;
  14333                         }
  14334                         for (std::size_t i = 1; i < reference_token.size(); i++)
  14335                         {
  14336                             if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
  14337                             {
  14338                                 // other char should be between '0' and '9'
  14339                                 return false;
  14340                             }
  14341                         }
  14342                     }
  14343 
  14344                     const auto idx = array_index<BasicJsonType>(reference_token);
  14345                     if (idx >= ptr->size())
  14346                     {
  14347                         // index out of range
  14348                         return false;
  14349                     }
  14350 
  14351                     ptr = &ptr->operator[](idx);
  14352                     break;
  14353                 }
  14354 
  14355                 case detail::value_t::null:
  14356                 case detail::value_t::string:
  14357                 case detail::value_t::boolean:
  14358                 case detail::value_t::number_integer:
  14359                 case detail::value_t::number_unsigned:
  14360                 case detail::value_t::number_float:
  14361                 case detail::value_t::binary:
  14362                 case detail::value_t::discarded:
  14363                 default:
  14364                 {
  14365                     // we do not expect primitive values if there is still a
  14366                     // reference token to process
  14367                     return false;
  14368                 }
  14369             }
  14370         }
  14371 
  14372         // no reference token left means we found a primitive value
  14373         return true;
  14374     }
  14375 
  14376     /*!
  14377     @brief split the string input to reference tokens
  14378 
  14379     @note This function is only called by the json_pointer constructor.
  14380           All exceptions below are documented there.
  14381 
  14382     @throw parse_error.107  if the pointer is not empty or begins with '/'
  14383     @throw parse_error.108  if character '~' is not followed by '0' or '1'
  14384     */
  14385     static std::vector<string_t> split(const string_t& reference_string)
  14386     {
  14387         std::vector<string_t> result;
  14388 
  14389         // special case: empty reference string -> no reference tokens
  14390         if (reference_string.empty())
  14391         {
  14392             return result;
  14393         }
  14394 
  14395         // check if nonempty reference string begins with slash
  14396         if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
  14397         {
  14398             JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
  14399         }
  14400 
  14401         // extract the reference tokens:
  14402         // - slash: position of the last read slash (or end of string)
  14403         // - start: position after the previous slash
  14404         for (
  14405             // search for the first slash after the first character
  14406             std::size_t slash = reference_string.find_first_of('/', 1),
  14407             // set the beginning of the first reference token
  14408             start = 1;
  14409             // we can stop if start == 0 (if slash == string_t::npos)
  14410             start != 0;
  14411             // set the beginning of the next reference token
  14412             // (will eventually be 0 if slash == string_t::npos)
  14413             start = (slash == string_t::npos) ? 0 : slash + 1,
  14414             // find next slash
  14415             slash = reference_string.find_first_of('/', start))
  14416         {
  14417             // use the text between the beginning of the reference token
  14418             // (start) and the last slash (slash).
  14419             auto reference_token = reference_string.substr(start, slash - start);
  14420 
  14421             // check reference tokens are properly escaped
  14422             for (std::size_t pos = reference_token.find_first_of('~');
  14423                     pos != string_t::npos;
  14424                     pos = reference_token.find_first_of('~', pos + 1))
  14425             {
  14426                 JSON_ASSERT(reference_token[pos] == '~');
  14427 
  14428                 // ~ must be followed by 0 or 1
  14429                 if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
  14430                                          (reference_token[pos + 1] != '0' &&
  14431                                           reference_token[pos + 1] != '1')))
  14432                 {
  14433                     JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
  14434                 }
  14435             }
  14436 
  14437             // finally, store the reference token
  14438             detail::unescape(reference_token);
  14439             result.push_back(reference_token);
  14440         }
  14441 
  14442         return result;
  14443     }
  14444 
  14445   private:
  14446     /*!
  14447     @param[in] reference_string  the reference string to the current value
  14448     @param[in] value             the value to consider
  14449     @param[in,out] result        the result object to insert values to
  14450 
  14451     @note Empty objects or arrays are flattened to `null`.
  14452     */
  14453     template<typename BasicJsonType>
  14454     static void flatten(const string_t& reference_string,
  14455                         const BasicJsonType& value,
  14456                         BasicJsonType& result)
  14457     {
  14458         switch (value.type())
  14459         {
  14460             case detail::value_t::array:
  14461             {
  14462                 if (value.m_value.array->empty())
  14463                 {
  14464                     // flatten empty array as null
  14465                     result[reference_string] = nullptr;
  14466                 }
  14467                 else
  14468                 {
  14469                     // iterate array and use index as reference string
  14470                     for (std::size_t i = 0; i < value.m_value.array->size(); ++i)
  14471                     {
  14472                         flatten(detail::concat(reference_string, '/', std::to_string(i)),
  14473                                 value.m_value.array->operator[](i), result);
  14474                     }
  14475                 }
  14476                 break;
  14477             }
  14478 
  14479             case detail::value_t::object:
  14480             {
  14481                 if (value.m_value.object->empty())
  14482                 {
  14483                     // flatten empty object as null
  14484                     result[reference_string] = nullptr;
  14485                 }
  14486                 else
  14487                 {
  14488                     // iterate object and use keys as reference string
  14489                     for (const auto& element : *value.m_value.object)
  14490                     {
  14491                         flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
  14492                     }
  14493                 }
  14494                 break;
  14495             }
  14496 
  14497             case detail::value_t::null:
  14498             case detail::value_t::string:
  14499             case detail::value_t::boolean:
  14500             case detail::value_t::number_integer:
  14501             case detail::value_t::number_unsigned:
  14502             case detail::value_t::number_float:
  14503             case detail::value_t::binary:
  14504             case detail::value_t::discarded:
  14505             default:
  14506             {
  14507                 // add primitive value with its reference string
  14508                 result[reference_string] = value;
  14509                 break;
  14510             }
  14511         }
  14512     }
  14513 
  14514     /*!
  14515     @param[in] value  flattened JSON
  14516 
  14517     @return unflattened JSON
  14518 
  14519     @throw parse_error.109 if array index is not a number
  14520     @throw type_error.314  if value is not an object
  14521     @throw type_error.315  if object values are not primitive
  14522     @throw type_error.313  if value cannot be unflattened
  14523     */
  14524     template<typename BasicJsonType>
  14525     static BasicJsonType
  14526     unflatten(const BasicJsonType& value)
  14527     {
  14528         if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
  14529         {
  14530             JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
  14531         }
  14532 
  14533         BasicJsonType result;
  14534 
  14535         // iterate the JSON object values
  14536         for (const auto& element : *value.m_value.object)
  14537         {
  14538             if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
  14539             {
  14540                 JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
  14541             }
  14542 
  14543             // assign value to reference pointed to by JSON pointer; Note that if
  14544             // the JSON pointer is "" (i.e., points to the whole value), function
  14545             // get_and_create returns a reference to result itself. An assignment
  14546             // will then create a primitive value.
  14547             json_pointer(element.first).get_and_create(result) = element.second;
  14548         }
  14549 
  14550         return result;
  14551     }
  14552 
  14553     // can't use conversion operator because of ambiguity
  14554     json_pointer<string_t> convert() const&
  14555     {
  14556         json_pointer<string_t> result;
  14557         result.reference_tokens = reference_tokens;
  14558         return result;
  14559     }
  14560 
  14561     json_pointer<string_t> convert()&&
  14562     {
  14563         json_pointer<string_t> result;
  14564         result.reference_tokens = std::move(reference_tokens);
  14565         return result;
  14566     }
  14567 
  14568   public:
  14569 #if JSON_HAS_THREE_WAY_COMPARISON
  14570     /// @brief compares two JSON pointers for equality
  14571     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14572     template<typename RefStringTypeRhs>
  14573     bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
  14574     {
  14575         return reference_tokens == rhs.reference_tokens;
  14576     }
  14577 
  14578     /// @brief compares JSON pointer and string for equality
  14579     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14580     JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
  14581     bool operator==(const string_t& rhs) const
  14582     {
  14583         return *this == json_pointer(rhs);
  14584     }
  14585 
  14586     /// @brief 3-way compares two JSON pointers
  14587     template<typename RefStringTypeRhs>
  14588     std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
  14589     {
  14590         return  reference_tokens <=> rhs.reference_tokens; // *NOPAD*
  14591     }
  14592 #else
  14593     /// @brief compares two JSON pointers for equality
  14594     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14595     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14596     // NOLINTNEXTLINE(readability-redundant-declaration)
  14597     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14598                            const json_pointer<RefStringTypeRhs>& rhs) noexcept;
  14599 
  14600     /// @brief compares JSON pointer and string for equality
  14601     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14602     template<typename RefStringTypeLhs, typename StringType>
  14603     // NOLINTNEXTLINE(readability-redundant-declaration)
  14604     friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14605                            const StringType& rhs);
  14606 
  14607     /// @brief compares string and JSON pointer for equality
  14608     /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14609     template<typename RefStringTypeRhs, typename StringType>
  14610     // NOLINTNEXTLINE(readability-redundant-declaration)
  14611     friend bool operator==(const StringType& lhs,
  14612                            const json_pointer<RefStringTypeRhs>& rhs);
  14613 
  14614     /// @brief compares two JSON pointers for inequality
  14615     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
  14616     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14617     // NOLINTNEXTLINE(readability-redundant-declaration)
  14618     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14619                            const json_pointer<RefStringTypeRhs>& rhs) noexcept;
  14620 
  14621     /// @brief compares JSON pointer and string for inequality
  14622     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
  14623     template<typename RefStringTypeLhs, typename StringType>
  14624     // NOLINTNEXTLINE(readability-redundant-declaration)
  14625     friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14626                            const StringType& rhs);
  14627 
  14628     /// @brief compares string and JSON pointer for inequality
  14629     /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
  14630     template<typename RefStringTypeRhs, typename StringType>
  14631     // NOLINTNEXTLINE(readability-redundant-declaration)
  14632     friend bool operator!=(const StringType& lhs,
  14633                            const json_pointer<RefStringTypeRhs>& rhs);
  14634 
  14635     /// @brief compares two JSON pointer for less-than
  14636     template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14637     // NOLINTNEXTLINE(readability-redundant-declaration)
  14638     friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
  14639                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
  14640 #endif
  14641 
  14642   private:
  14643     /// the reference tokens
  14644     std::vector<string_t> reference_tokens;
  14645 };
  14646 
  14647 #if !JSON_HAS_THREE_WAY_COMPARISON
  14648 // functions cannot be defined inside class due to ODR violations
  14649 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14650 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14651                        const json_pointer<RefStringTypeRhs>& rhs) noexcept
  14652 {
  14653     return lhs.reference_tokens == rhs.reference_tokens;
  14654 }
  14655 
  14656 template<typename RefStringTypeLhs,
  14657          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
  14658 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
  14659 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14660                        const StringType& rhs)
  14661 {
  14662     return lhs == json_pointer<RefStringTypeLhs>(rhs);
  14663 }
  14664 
  14665 template<typename RefStringTypeRhs,
  14666          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
  14667 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
  14668 inline bool operator==(const StringType& lhs,
  14669                        const json_pointer<RefStringTypeRhs>& rhs)
  14670 {
  14671     return json_pointer<RefStringTypeRhs>(lhs) == rhs;
  14672 }
  14673 
  14674 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14675 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14676                        const json_pointer<RefStringTypeRhs>& rhs) noexcept
  14677 {
  14678     return !(lhs == rhs);
  14679 }
  14680 
  14681 template<typename RefStringTypeLhs,
  14682          typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
  14683 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
  14684 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14685                        const StringType& rhs)
  14686 {
  14687     return !(lhs == rhs);
  14688 }
  14689 
  14690 template<typename RefStringTypeRhs,
  14691          typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
  14692 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
  14693 inline bool operator!=(const StringType& lhs,
  14694                        const json_pointer<RefStringTypeRhs>& rhs)
  14695 {
  14696     return !(lhs == rhs);
  14697 }
  14698 
  14699 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14700 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
  14701                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
  14702 {
  14703     return lhs.reference_tokens < rhs.reference_tokens;
  14704 }
  14705 #endif
  14706 
  14707 NLOHMANN_JSON_NAMESPACE_END
  14708 
  14709 // #include <nlohmann/detail/json_ref.hpp>
  14710 //     __ _____ _____ _____
  14711 //  __|  |   __|     |   | |  JSON for Modern C++
  14712 // |  |  |__   |  |  | | | |  version 3.11.2
  14713 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  14714 //
  14715 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  14716 // SPDX-License-Identifier: MIT
  14717 
  14718 
  14719 
  14720 #include <initializer_list>
  14721 #include <utility>
  14722 
  14723 // #include <nlohmann/detail/abi_macros.hpp>
  14724 
  14725 // #include <nlohmann/detail/meta/type_traits.hpp>
  14726 
  14727 
  14728 NLOHMANN_JSON_NAMESPACE_BEGIN
  14729 namespace detail
  14730 {
  14731 
  14732 template<typename BasicJsonType>
  14733 class json_ref
  14734 {
  14735   public:
  14736     using value_type = BasicJsonType;
  14737 
  14738     json_ref(value_type&& value)
  14739         : owned_value(std::move(value))
  14740     {}
  14741 
  14742     json_ref(const value_type& value)
  14743         : value_ref(&value)
  14744     {}
  14745 
  14746     json_ref(std::initializer_list<json_ref> init)
  14747         : owned_value(init)
  14748     {}
  14749 
  14750     template <
  14751         class... Args,
  14752         enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
  14753     json_ref(Args && ... args)
  14754         : owned_value(std::forward<Args>(args)...)
  14755     {}
  14756 
  14757     // class should be movable only
  14758     json_ref(json_ref&&) noexcept = default;
  14759     json_ref(const json_ref&) = delete;
  14760     json_ref& operator=(const json_ref&) = delete;
  14761     json_ref& operator=(json_ref&&) = delete;
  14762     ~json_ref() = default;
  14763 
  14764     value_type moved_or_copied() const
  14765     {
  14766         if (value_ref == nullptr)
  14767         {
  14768             return std::move(owned_value);
  14769         }
  14770         return *value_ref;
  14771     }
  14772 
  14773     value_type const& operator*() const
  14774     {
  14775         return value_ref ? *value_ref : owned_value;
  14776     }
  14777 
  14778     value_type const* operator->() const
  14779     {
  14780         return &** this;
  14781     }
  14782 
  14783   private:
  14784     mutable value_type owned_value = nullptr;
  14785     value_type const* value_ref = nullptr;
  14786 };
  14787 
  14788 }  // namespace detail
  14789 NLOHMANN_JSON_NAMESPACE_END
  14790 
  14791 // #include <nlohmann/detail/macro_scope.hpp>
  14792 
  14793 // #include <nlohmann/detail/string_concat.hpp>
  14794 
  14795 // #include <nlohmann/detail/string_escape.hpp>
  14796 
  14797 // #include <nlohmann/detail/meta/cpp_future.hpp>
  14798 
  14799 // #include <nlohmann/detail/meta/type_traits.hpp>
  14800 
  14801 // #include <nlohmann/detail/output/binary_writer.hpp>
  14802 //     __ _____ _____ _____
  14803 //  __|  |   __|     |   | |  JSON for Modern C++
  14804 // |  |  |__   |  |  | | | |  version 3.11.2
  14805 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  14806 //
  14807 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  14808 // SPDX-License-Identifier: MIT
  14809 
  14810 
  14811 
  14812 #include <algorithm> // reverse
  14813 #include <array> // array
  14814 #include <map> // map
  14815 #include <cmath> // isnan, isinf
  14816 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
  14817 #include <cstring> // memcpy
  14818 #include <limits> // numeric_limits
  14819 #include <string> // string
  14820 #include <utility> // move
  14821 #include <vector> // vector
  14822 
  14823 // #include <nlohmann/detail/input/binary_reader.hpp>
  14824 
  14825 // #include <nlohmann/detail/macro_scope.hpp>
  14826 
  14827 // #include <nlohmann/detail/output/output_adapters.hpp>
  14828 //     __ _____ _____ _____
  14829 //  __|  |   __|     |   | |  JSON for Modern C++
  14830 // |  |  |__   |  |  | | | |  version 3.11.2
  14831 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  14832 //
  14833 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  14834 // SPDX-License-Identifier: MIT
  14835 
  14836 
  14837 
  14838 #include <algorithm> // copy
  14839 #include <cstddef> // size_t
  14840 #include <iterator> // back_inserter
  14841 #include <memory> // shared_ptr, make_shared
  14842 #include <string> // basic_string
  14843 #include <vector> // vector
  14844 
  14845 #ifndef JSON_NO_IO
  14846     #include <ios>      // streamsize
  14847     #include <ostream>  // basic_ostream
  14848 #endif  // JSON_NO_IO
  14849 
  14850 // #include <nlohmann/detail/macro_scope.hpp>
  14851 
  14852 
  14853 NLOHMANN_JSON_NAMESPACE_BEGIN
  14854 namespace detail
  14855 {
  14856 
  14857 /// abstract output adapter interface
  14858 template<typename CharType> struct output_adapter_protocol
  14859 {
  14860     virtual void write_character(CharType c) = 0;
  14861     virtual void write_characters(const CharType* s, std::size_t length) = 0;
  14862     virtual ~output_adapter_protocol() = default;
  14863 
  14864     output_adapter_protocol() = default;
  14865     output_adapter_protocol(const output_adapter_protocol&) = default;
  14866     output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
  14867     output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
  14868     output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
  14869 };
  14870 
  14871 /// a type to simplify interfaces
  14872 template<typename CharType>
  14873 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
  14874 
  14875 /// output adapter for byte vectors
  14876 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
  14877 class output_vector_adapter : public output_adapter_protocol<CharType>
  14878 {
  14879   public:
  14880     explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
  14881         : v(vec)
  14882     {}
  14883 
  14884     void write_character(CharType c) override
  14885     {
  14886         v.push_back(c);
  14887     }
  14888 
  14889     JSON_HEDLEY_NON_NULL(2)
  14890     void write_characters(const CharType* s, std::size_t length) override
  14891     {
  14892         v.insert(v.end(), s, s + length);
  14893     }
  14894 
  14895   private:
  14896     std::vector<CharType, AllocatorType>& v;
  14897 };
  14898 
  14899 #ifndef JSON_NO_IO
  14900 /// output adapter for output streams
  14901 template<typename CharType>
  14902 class output_stream_adapter : public output_adapter_protocol<CharType>
  14903 {
  14904   public:
  14905     explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
  14906         : stream(s)
  14907     {}
  14908 
  14909     void write_character(CharType c) override
  14910     {
  14911         stream.put(c);
  14912     }
  14913 
  14914     JSON_HEDLEY_NON_NULL(2)
  14915     void write_characters(const CharType* s, std::size_t length) override
  14916     {
  14917         stream.write(s, static_cast<std::streamsize>(length));
  14918     }
  14919 
  14920   private:
  14921     std::basic_ostream<CharType>& stream;
  14922 };
  14923 #endif  // JSON_NO_IO
  14924 
  14925 /// output adapter for basic_string
  14926 template<typename CharType, typename StringType = std::basic_string<CharType>>
  14927 class output_string_adapter : public output_adapter_protocol<CharType>
  14928 {
  14929   public:
  14930     explicit output_string_adapter(StringType& s) noexcept
  14931         : str(s)
  14932     {}
  14933 
  14934     void write_character(CharType c) override
  14935     {
  14936         str.push_back(c);
  14937     }
  14938 
  14939     JSON_HEDLEY_NON_NULL(2)
  14940     void write_characters(const CharType* s, std::size_t length) override
  14941     {
  14942         str.append(s, length);
  14943     }
  14944 
  14945   private:
  14946     StringType& str;
  14947 };
  14948 
  14949 template<typename CharType, typename StringType = std::basic_string<CharType>>
  14950 class output_adapter
  14951 {
  14952   public:
  14953     template<typename AllocatorType = std::allocator<CharType>>
  14954     output_adapter(std::vector<CharType, AllocatorType>& vec)
  14955         : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
  14956 
  14957 #ifndef JSON_NO_IO
  14958     output_adapter(std::basic_ostream<CharType>& s)
  14959         : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
  14960 #endif  // JSON_NO_IO
  14961 
  14962     output_adapter(StringType& s)
  14963         : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
  14964 
  14965     operator output_adapter_t<CharType>()
  14966     {
  14967         return oa;
  14968     }
  14969 
  14970   private:
  14971     output_adapter_t<CharType> oa = nullptr;
  14972 };
  14973 
  14974 }  // namespace detail
  14975 NLOHMANN_JSON_NAMESPACE_END
  14976 
  14977 // #include <nlohmann/detail/string_concat.hpp>
  14978 
  14979 
  14980 NLOHMANN_JSON_NAMESPACE_BEGIN
  14981 namespace detail
  14982 {
  14983 
  14984 ///////////////////
  14985 // binary writer //
  14986 ///////////////////
  14987 
  14988 /*!
  14989 @brief serialization to CBOR and MessagePack values
  14990 */
  14991 template<typename BasicJsonType, typename CharType>
  14992 class binary_writer
  14993 {
  14994     using string_t = typename BasicJsonType::string_t;
  14995     using binary_t = typename BasicJsonType::binary_t;
  14996     using number_float_t = typename BasicJsonType::number_float_t;
  14997 
  14998   public:
  14999     /*!
  15000     @brief create a binary writer
  15001 
  15002     @param[in] adapter  output adapter to write to
  15003     */
  15004     explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
  15005     {
  15006         JSON_ASSERT(oa);
  15007     }
  15008 
  15009     /*!
  15010     @param[in] j  JSON value to serialize
  15011     @pre       j.type() == value_t::object
  15012     */
  15013     void write_bson(const BasicJsonType& j)
  15014     {
  15015         switch (j.type())
  15016         {
  15017             case value_t::object:
  15018             {
  15019                 write_bson_object(*j.m_value.object);
  15020                 break;
  15021             }
  15022 
  15023             case value_t::null:
  15024             case value_t::array:
  15025             case value_t::string:
  15026             case value_t::boolean:
  15027             case value_t::number_integer:
  15028             case value_t::number_unsigned:
  15029             case value_t::number_float:
  15030             case value_t::binary:
  15031             case value_t::discarded:
  15032             default:
  15033             {
  15034                 JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
  15035             }
  15036         }
  15037     }
  15038 
  15039     /*!
  15040     @param[in] j  JSON value to serialize
  15041     */
  15042     void write_cbor(const BasicJsonType& j)
  15043     {
  15044         switch (j.type())
  15045         {
  15046             case value_t::null:
  15047             {
  15048                 oa->write_character(to_char_type(0xF6));
  15049                 break;
  15050             }
  15051 
  15052             case value_t::boolean:
  15053             {
  15054                 oa->write_character(j.m_value.boolean
  15055                                     ? to_char_type(0xF5)
  15056                                     : to_char_type(0xF4));
  15057                 break;
  15058             }
  15059 
  15060             case value_t::number_integer:
  15061             {
  15062                 if (j.m_value.number_integer >= 0)
  15063                 {
  15064                     // CBOR does not differentiate between positive signed
  15065                     // integers and unsigned integers. Therefore, we used the
  15066                     // code from the value_t::number_unsigned case here.
  15067                     if (j.m_value.number_integer <= 0x17)
  15068                     {
  15069                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  15070                     }
  15071                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
  15072                     {
  15073                         oa->write_character(to_char_type(0x18));
  15074                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  15075                     }
  15076                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
  15077                     {
  15078                         oa->write_character(to_char_type(0x19));
  15079                         write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
  15080                     }
  15081                     else if (j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
  15082                     {
  15083                         oa->write_character(to_char_type(0x1A));
  15084                         write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
  15085                     }
  15086                     else
  15087                     {
  15088                         oa->write_character(to_char_type(0x1B));
  15089                         write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
  15090                     }
  15091                 }
  15092                 else
  15093                 {
  15094                     // The conversions below encode the sign in the first
  15095                     // byte, and the value is converted to a positive number.
  15096                     const auto positive_number = -1 - j.m_value.number_integer;
  15097                     if (j.m_value.number_integer >= -24)
  15098                     {
  15099                         write_number(static_cast<std::uint8_t>(0x20 + positive_number));
  15100                     }
  15101                     else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
  15102                     {
  15103                         oa->write_character(to_char_type(0x38));
  15104                         write_number(static_cast<std::uint8_t>(positive_number));
  15105                     }
  15106                     else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
  15107                     {
  15108                         oa->write_character(to_char_type(0x39));
  15109                         write_number(static_cast<std::uint16_t>(positive_number));
  15110                     }
  15111                     else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
  15112                     {
  15113                         oa->write_character(to_char_type(0x3A));
  15114                         write_number(static_cast<std::uint32_t>(positive_number));
  15115                     }
  15116                     else
  15117                     {
  15118                         oa->write_character(to_char_type(0x3B));
  15119                         write_number(static_cast<std::uint64_t>(positive_number));
  15120                     }
  15121                 }
  15122                 break;
  15123             }
  15124 
  15125             case value_t::number_unsigned:
  15126             {
  15127                 if (j.m_value.number_unsigned <= 0x17)
  15128                 {
  15129                     write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
  15130                 }
  15131                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  15132                 {
  15133                     oa->write_character(to_char_type(0x18));
  15134                     write_number(static_cast<std::uint8_t>(j.m_value.number_unsigned));
  15135                 }
  15136                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  15137                 {
  15138                     oa->write_character(to_char_type(0x19));
  15139                     write_number(static_cast<std::uint16_t>(j.m_value.number_unsigned));
  15140                 }
  15141                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  15142                 {
  15143                     oa->write_character(to_char_type(0x1A));
  15144                     write_number(static_cast<std::uint32_t>(j.m_value.number_unsigned));
  15145                 }
  15146                 else
  15147                 {
  15148                     oa->write_character(to_char_type(0x1B));
  15149                     write_number(static_cast<std::uint64_t>(j.m_value.number_unsigned));
  15150                 }
  15151                 break;
  15152             }
  15153 
  15154             case value_t::number_float:
  15155             {
  15156                 if (std::isnan(j.m_value.number_float))
  15157                 {
  15158                     // NaN is 0xf97e00 in CBOR
  15159                     oa->write_character(to_char_type(0xF9));
  15160                     oa->write_character(to_char_type(0x7E));
  15161                     oa->write_character(to_char_type(0x00));
  15162                 }
  15163                 else if (std::isinf(j.m_value.number_float))
  15164                 {
  15165                     // Infinity is 0xf97c00, -Infinity is 0xf9fc00
  15166                     oa->write_character(to_char_type(0xf9));
  15167                     oa->write_character(j.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
  15168                     oa->write_character(to_char_type(0x00));
  15169                 }
  15170                 else
  15171                 {
  15172                     write_compact_float(j.m_value.number_float, detail::input_format_t::cbor);
  15173                 }
  15174                 break;
  15175             }
  15176 
  15177             case value_t::string:
  15178             {
  15179                 // step 1: write control byte and the string length
  15180                 const auto N = j.m_value.string->size();
  15181                 if (N <= 0x17)
  15182                 {
  15183                     write_number(static_cast<std::uint8_t>(0x60 + N));
  15184                 }
  15185                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15186                 {
  15187                     oa->write_character(to_char_type(0x78));
  15188                     write_number(static_cast<std::uint8_t>(N));
  15189                 }
  15190                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15191                 {
  15192                     oa->write_character(to_char_type(0x79));
  15193                     write_number(static_cast<std::uint16_t>(N));
  15194                 }
  15195                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15196                 {
  15197                     oa->write_character(to_char_type(0x7A));
  15198                     write_number(static_cast<std::uint32_t>(N));
  15199                 }
  15200                 // LCOV_EXCL_START
  15201                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15202                 {
  15203                     oa->write_character(to_char_type(0x7B));
  15204                     write_number(static_cast<std::uint64_t>(N));
  15205                 }
  15206                 // LCOV_EXCL_STOP
  15207 
  15208                 // step 2: write the string
  15209                 oa->write_characters(
  15210                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  15211                     j.m_value.string->size());
  15212                 break;
  15213             }
  15214 
  15215             case value_t::array:
  15216             {
  15217                 // step 1: write control byte and the array size
  15218                 const auto N = j.m_value.array->size();
  15219                 if (N <= 0x17)
  15220                 {
  15221                     write_number(static_cast<std::uint8_t>(0x80 + N));
  15222                 }
  15223                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15224                 {
  15225                     oa->write_character(to_char_type(0x98));
  15226                     write_number(static_cast<std::uint8_t>(N));
  15227                 }
  15228                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15229                 {
  15230                     oa->write_character(to_char_type(0x99));
  15231                     write_number(static_cast<std::uint16_t>(N));
  15232                 }
  15233                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15234                 {
  15235                     oa->write_character(to_char_type(0x9A));
  15236                     write_number(static_cast<std::uint32_t>(N));
  15237                 }
  15238                 // LCOV_EXCL_START
  15239                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15240                 {
  15241                     oa->write_character(to_char_type(0x9B));
  15242                     write_number(static_cast<std::uint64_t>(N));
  15243                 }
  15244                 // LCOV_EXCL_STOP
  15245 
  15246                 // step 2: write each element
  15247                 for (const auto& el : *j.m_value.array)
  15248                 {
  15249                     write_cbor(el);
  15250                 }
  15251                 break;
  15252             }
  15253 
  15254             case value_t::binary:
  15255             {
  15256                 if (j.m_value.binary->has_subtype())
  15257                 {
  15258                     if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
  15259                     {
  15260                         write_number(static_cast<std::uint8_t>(0xd8));
  15261                         write_number(static_cast<std::uint8_t>(j.m_value.binary->subtype()));
  15262                     }
  15263                     else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
  15264                     {
  15265                         write_number(static_cast<std::uint8_t>(0xd9));
  15266                         write_number(static_cast<std::uint16_t>(j.m_value.binary->subtype()));
  15267                     }
  15268                     else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
  15269                     {
  15270                         write_number(static_cast<std::uint8_t>(0xda));
  15271                         write_number(static_cast<std::uint32_t>(j.m_value.binary->subtype()));
  15272                     }
  15273                     else if (j.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
  15274                     {
  15275                         write_number(static_cast<std::uint8_t>(0xdb));
  15276                         write_number(static_cast<std::uint64_t>(j.m_value.binary->subtype()));
  15277                     }
  15278                 }
  15279 
  15280                 // step 1: write control byte and the binary array size
  15281                 const auto N = j.m_value.binary->size();
  15282                 if (N <= 0x17)
  15283                 {
  15284                     write_number(static_cast<std::uint8_t>(0x40 + N));
  15285                 }
  15286                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15287                 {
  15288                     oa->write_character(to_char_type(0x58));
  15289                     write_number(static_cast<std::uint8_t>(N));
  15290                 }
  15291                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15292                 {
  15293                     oa->write_character(to_char_type(0x59));
  15294                     write_number(static_cast<std::uint16_t>(N));
  15295                 }
  15296                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15297                 {
  15298                     oa->write_character(to_char_type(0x5A));
  15299                     write_number(static_cast<std::uint32_t>(N));
  15300                 }
  15301                 // LCOV_EXCL_START
  15302                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15303                 {
  15304                     oa->write_character(to_char_type(0x5B));
  15305                     write_number(static_cast<std::uint64_t>(N));
  15306                 }
  15307                 // LCOV_EXCL_STOP
  15308 
  15309                 // step 2: write each element
  15310                 oa->write_characters(
  15311                     reinterpret_cast<const CharType*>(j.m_value.binary->data()),
  15312                     N);
  15313 
  15314                 break;
  15315             }
  15316 
  15317             case value_t::object:
  15318             {
  15319                 // step 1: write control byte and the object size
  15320                 const auto N = j.m_value.object->size();
  15321                 if (N <= 0x17)
  15322                 {
  15323                     write_number(static_cast<std::uint8_t>(0xA0 + N));
  15324                 }
  15325                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15326                 {
  15327                     oa->write_character(to_char_type(0xB8));
  15328                     write_number(static_cast<std::uint8_t>(N));
  15329                 }
  15330                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15331                 {
  15332                     oa->write_character(to_char_type(0xB9));
  15333                     write_number(static_cast<std::uint16_t>(N));
  15334                 }
  15335                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15336                 {
  15337                     oa->write_character(to_char_type(0xBA));
  15338                     write_number(static_cast<std::uint32_t>(N));
  15339                 }
  15340                 // LCOV_EXCL_START
  15341                 else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15342                 {
  15343                     oa->write_character(to_char_type(0xBB));
  15344                     write_number(static_cast<std::uint64_t>(N));
  15345                 }
  15346                 // LCOV_EXCL_STOP
  15347 
  15348                 // step 2: write each element
  15349                 for (const auto& el : *j.m_value.object)
  15350                 {
  15351                     write_cbor(el.first);
  15352                     write_cbor(el.second);
  15353                 }
  15354                 break;
  15355             }
  15356 
  15357             case value_t::discarded:
  15358             default:
  15359                 break;
  15360         }
  15361     }
  15362 
  15363     /*!
  15364     @param[in] j  JSON value to serialize
  15365     */
  15366     void write_msgpack(const BasicJsonType& j)
  15367     {
  15368         switch (j.type())
  15369         {
  15370             case value_t::null: // nil
  15371             {
  15372                 oa->write_character(to_char_type(0xC0));
  15373                 break;
  15374             }
  15375 
  15376             case value_t::boolean: // true and false
  15377             {
  15378                 oa->write_character(j.m_value.boolean
  15379                                     ? to_char_type(0xC3)
  15380                                     : to_char_type(0xC2));
  15381                 break;
  15382             }
  15383 
  15384             case value_t::number_integer:
  15385             {
  15386                 if (j.m_value.number_integer >= 0)
  15387                 {
  15388                     // MessagePack does not differentiate between positive
  15389                     // signed integers and unsigned integers. Therefore, we used
  15390                     // the code from the value_t::number_unsigned case here.
  15391                     if (j.m_value.number_unsigned < 128)
  15392                     {
  15393                         // positive fixnum
  15394                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  15395                     }
  15396                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  15397                     {
  15398                         // uint 8
  15399                         oa->write_character(to_char_type(0xCC));
  15400                         write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  15401                     }
  15402                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  15403                     {
  15404                         // uint 16
  15405                         oa->write_character(to_char_type(0xCD));
  15406                         write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
  15407                     }
  15408                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  15409                     {
  15410                         // uint 32
  15411                         oa->write_character(to_char_type(0xCE));
  15412                         write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
  15413                     }
  15414                     else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  15415                     {
  15416                         // uint 64
  15417                         oa->write_character(to_char_type(0xCF));
  15418                         write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
  15419                     }
  15420                 }
  15421                 else
  15422                 {
  15423                     if (j.m_value.number_integer >= -32)
  15424                     {
  15425                         // negative fixnum
  15426                         write_number(static_cast<std::int8_t>(j.m_value.number_integer));
  15427                     }
  15428                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
  15429                              j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
  15430                     {
  15431                         // int 8
  15432                         oa->write_character(to_char_type(0xD0));
  15433                         write_number(static_cast<std::int8_t>(j.m_value.number_integer));
  15434                     }
  15435                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
  15436                              j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
  15437                     {
  15438                         // int 16
  15439                         oa->write_character(to_char_type(0xD1));
  15440                         write_number(static_cast<std::int16_t>(j.m_value.number_integer));
  15441                     }
  15442                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
  15443                              j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
  15444                     {
  15445                         // int 32
  15446                         oa->write_character(to_char_type(0xD2));
  15447                         write_number(static_cast<std::int32_t>(j.m_value.number_integer));
  15448                     }
  15449                     else if (j.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
  15450                              j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
  15451                     {
  15452                         // int 64
  15453                         oa->write_character(to_char_type(0xD3));
  15454                         write_number(static_cast<std::int64_t>(j.m_value.number_integer));
  15455                     }
  15456                 }
  15457                 break;
  15458             }
  15459 
  15460             case value_t::number_unsigned:
  15461             {
  15462                 if (j.m_value.number_unsigned < 128)
  15463                 {
  15464                     // positive fixnum
  15465                     write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  15466                 }
  15467                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  15468                 {
  15469                     // uint 8
  15470                     oa->write_character(to_char_type(0xCC));
  15471                     write_number(static_cast<std::uint8_t>(j.m_value.number_integer));
  15472                 }
  15473                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  15474                 {
  15475                     // uint 16
  15476                     oa->write_character(to_char_type(0xCD));
  15477                     write_number(static_cast<std::uint16_t>(j.m_value.number_integer));
  15478                 }
  15479                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  15480                 {
  15481                     // uint 32
  15482                     oa->write_character(to_char_type(0xCE));
  15483                     write_number(static_cast<std::uint32_t>(j.m_value.number_integer));
  15484                 }
  15485                 else if (j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  15486                 {
  15487                     // uint 64
  15488                     oa->write_character(to_char_type(0xCF));
  15489                     write_number(static_cast<std::uint64_t>(j.m_value.number_integer));
  15490                 }
  15491                 break;
  15492             }
  15493 
  15494             case value_t::number_float:
  15495             {
  15496                 write_compact_float(j.m_value.number_float, detail::input_format_t::msgpack);
  15497                 break;
  15498             }
  15499 
  15500             case value_t::string:
  15501             {
  15502                 // step 1: write control byte and the string length
  15503                 const auto N = j.m_value.string->size();
  15504                 if (N <= 31)
  15505                 {
  15506                     // fixstr
  15507                     write_number(static_cast<std::uint8_t>(0xA0 | N));
  15508                 }
  15509                 else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15510                 {
  15511                     // str 8
  15512                     oa->write_character(to_char_type(0xD9));
  15513                     write_number(static_cast<std::uint8_t>(N));
  15514                 }
  15515                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15516                 {
  15517                     // str 16
  15518                     oa->write_character(to_char_type(0xDA));
  15519                     write_number(static_cast<std::uint16_t>(N));
  15520                 }
  15521                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15522                 {
  15523                     // str 32
  15524                     oa->write_character(to_char_type(0xDB));
  15525                     write_number(static_cast<std::uint32_t>(N));
  15526                 }
  15527 
  15528                 // step 2: write the string
  15529                 oa->write_characters(
  15530                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  15531                     j.m_value.string->size());
  15532                 break;
  15533             }
  15534 
  15535             case value_t::array:
  15536             {
  15537                 // step 1: write control byte and the array size
  15538                 const auto N = j.m_value.array->size();
  15539                 if (N <= 15)
  15540                 {
  15541                     // fixarray
  15542                     write_number(static_cast<std::uint8_t>(0x90 | N));
  15543                 }
  15544                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15545                 {
  15546                     // array 16
  15547                     oa->write_character(to_char_type(0xDC));
  15548                     write_number(static_cast<std::uint16_t>(N));
  15549                 }
  15550                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15551                 {
  15552                     // array 32
  15553                     oa->write_character(to_char_type(0xDD));
  15554                     write_number(static_cast<std::uint32_t>(N));
  15555                 }
  15556 
  15557                 // step 2: write each element
  15558                 for (const auto& el : *j.m_value.array)
  15559                 {
  15560                     write_msgpack(el);
  15561                 }
  15562                 break;
  15563             }
  15564 
  15565             case value_t::binary:
  15566             {
  15567                 // step 0: determine if the binary type has a set subtype to
  15568                 // determine whether or not to use the ext or fixext types
  15569                 const bool use_ext = j.m_value.binary->has_subtype();
  15570 
  15571                 // step 1: write control byte and the byte string length
  15572                 const auto N = j.m_value.binary->size();
  15573                 if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15574                 {
  15575                     std::uint8_t output_type{};
  15576                     bool fixed = true;
  15577                     if (use_ext)
  15578                     {
  15579                         switch (N)
  15580                         {
  15581                             case 1:
  15582                                 output_type = 0xD4; // fixext 1
  15583                                 break;
  15584                             case 2:
  15585                                 output_type = 0xD5; // fixext 2
  15586                                 break;
  15587                             case 4:
  15588                                 output_type = 0xD6; // fixext 4
  15589                                 break;
  15590                             case 8:
  15591                                 output_type = 0xD7; // fixext 8
  15592                                 break;
  15593                             case 16:
  15594                                 output_type = 0xD8; // fixext 16
  15595                                 break;
  15596                             default:
  15597                                 output_type = 0xC7; // ext 8
  15598                                 fixed = false;
  15599                                 break;
  15600                         }
  15601 
  15602                     }
  15603                     else
  15604                     {
  15605                         output_type = 0xC4; // bin 8
  15606                         fixed = false;
  15607                     }
  15608 
  15609                     oa->write_character(to_char_type(output_type));
  15610                     if (!fixed)
  15611                     {
  15612                         write_number(static_cast<std::uint8_t>(N));
  15613                     }
  15614                 }
  15615                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15616                 {
  15617                     const std::uint8_t output_type = use_ext
  15618                                                      ? 0xC8 // ext 16
  15619                                                      : 0xC5; // bin 16
  15620 
  15621                     oa->write_character(to_char_type(output_type));
  15622                     write_number(static_cast<std::uint16_t>(N));
  15623                 }
  15624                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15625                 {
  15626                     const std::uint8_t output_type = use_ext
  15627                                                      ? 0xC9 // ext 32
  15628                                                      : 0xC6; // bin 32
  15629 
  15630                     oa->write_character(to_char_type(output_type));
  15631                     write_number(static_cast<std::uint32_t>(N));
  15632                 }
  15633 
  15634                 // step 1.5: if this is an ext type, write the subtype
  15635                 if (use_ext)
  15636                 {
  15637                     write_number(static_cast<std::int8_t>(j.m_value.binary->subtype()));
  15638                 }
  15639 
  15640                 // step 2: write the byte string
  15641                 oa->write_characters(
  15642                     reinterpret_cast<const CharType*>(j.m_value.binary->data()),
  15643                     N);
  15644 
  15645                 break;
  15646             }
  15647 
  15648             case value_t::object:
  15649             {
  15650                 // step 1: write control byte and the object size
  15651                 const auto N = j.m_value.object->size();
  15652                 if (N <= 15)
  15653                 {
  15654                     // fixmap
  15655                     write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
  15656                 }
  15657                 else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15658                 {
  15659                     // map 16
  15660                     oa->write_character(to_char_type(0xDE));
  15661                     write_number(static_cast<std::uint16_t>(N));
  15662                 }
  15663                 else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15664                 {
  15665                     // map 32
  15666                     oa->write_character(to_char_type(0xDF));
  15667                     write_number(static_cast<std::uint32_t>(N));
  15668                 }
  15669 
  15670                 // step 2: write each element
  15671                 for (const auto& el : *j.m_value.object)
  15672                 {
  15673                     write_msgpack(el.first);
  15674                     write_msgpack(el.second);
  15675                 }
  15676                 break;
  15677             }
  15678 
  15679             case value_t::discarded:
  15680             default:
  15681                 break;
  15682         }
  15683     }
  15684 
  15685     /*!
  15686     @param[in] j  JSON value to serialize
  15687     @param[in] use_count   whether to use '#' prefixes (optimized format)
  15688     @param[in] use_type    whether to use '$' prefixes (optimized format)
  15689     @param[in] add_prefix  whether prefixes need to be used for this value
  15690     @param[in] use_bjdata  whether write in BJData format, default is false
  15691     */
  15692     void write_ubjson(const BasicJsonType& j, const bool use_count,
  15693                       const bool use_type, const bool add_prefix = true,
  15694                       const bool use_bjdata = false)
  15695     {
  15696         switch (j.type())
  15697         {
  15698             case value_t::null:
  15699             {
  15700                 if (add_prefix)
  15701                 {
  15702                     oa->write_character(to_char_type('Z'));
  15703                 }
  15704                 break;
  15705             }
  15706 
  15707             case value_t::boolean:
  15708             {
  15709                 if (add_prefix)
  15710                 {
  15711                     oa->write_character(j.m_value.boolean
  15712                                         ? to_char_type('T')
  15713                                         : to_char_type('F'));
  15714                 }
  15715                 break;
  15716             }
  15717 
  15718             case value_t::number_integer:
  15719             {
  15720                 write_number_with_ubjson_prefix(j.m_value.number_integer, add_prefix, use_bjdata);
  15721                 break;
  15722             }
  15723 
  15724             case value_t::number_unsigned:
  15725             {
  15726                 write_number_with_ubjson_prefix(j.m_value.number_unsigned, add_prefix, use_bjdata);
  15727                 break;
  15728             }
  15729 
  15730             case value_t::number_float:
  15731             {
  15732                 write_number_with_ubjson_prefix(j.m_value.number_float, add_prefix, use_bjdata);
  15733                 break;
  15734             }
  15735 
  15736             case value_t::string:
  15737             {
  15738                 if (add_prefix)
  15739                 {
  15740                     oa->write_character(to_char_type('S'));
  15741                 }
  15742                 write_number_with_ubjson_prefix(j.m_value.string->size(), true, use_bjdata);
  15743                 oa->write_characters(
  15744                     reinterpret_cast<const CharType*>(j.m_value.string->c_str()),
  15745                     j.m_value.string->size());
  15746                 break;
  15747             }
  15748 
  15749             case value_t::array:
  15750             {
  15751                 if (add_prefix)
  15752                 {
  15753                     oa->write_character(to_char_type('['));
  15754                 }
  15755 
  15756                 bool prefix_required = true;
  15757                 if (use_type && !j.m_value.array->empty())
  15758                 {
  15759                     JSON_ASSERT(use_count);
  15760                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
  15761                     const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
  15762                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
  15763                     {
  15764                         return ubjson_prefix(v, use_bjdata) == first_prefix;
  15765                     });
  15766 
  15767                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
  15768 
  15769                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
  15770                     {
  15771                         prefix_required = false;
  15772                         oa->write_character(to_char_type('$'));
  15773                         oa->write_character(first_prefix);
  15774                     }
  15775                 }
  15776 
  15777                 if (use_count)
  15778                 {
  15779                     oa->write_character(to_char_type('#'));
  15780                     write_number_with_ubjson_prefix(j.m_value.array->size(), true, use_bjdata);
  15781                 }
  15782 
  15783                 for (const auto& el : *j.m_value.array)
  15784                 {
  15785                     write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
  15786                 }
  15787 
  15788                 if (!use_count)
  15789                 {
  15790                     oa->write_character(to_char_type(']'));
  15791                 }
  15792 
  15793                 break;
  15794             }
  15795 
  15796             case value_t::binary:
  15797             {
  15798                 if (add_prefix)
  15799                 {
  15800                     oa->write_character(to_char_type('['));
  15801                 }
  15802 
  15803                 if (use_type && !j.m_value.binary->empty())
  15804                 {
  15805                     JSON_ASSERT(use_count);
  15806                     oa->write_character(to_char_type('$'));
  15807                     oa->write_character('U');
  15808                 }
  15809 
  15810                 if (use_count)
  15811                 {
  15812                     oa->write_character(to_char_type('#'));
  15813                     write_number_with_ubjson_prefix(j.m_value.binary->size(), true, use_bjdata);
  15814                 }
  15815 
  15816                 if (use_type)
  15817                 {
  15818                     oa->write_characters(
  15819                         reinterpret_cast<const CharType*>(j.m_value.binary->data()),
  15820                         j.m_value.binary->size());
  15821                 }
  15822                 else
  15823                 {
  15824                     for (size_t i = 0; i < j.m_value.binary->size(); ++i)
  15825                     {
  15826                         oa->write_character(to_char_type('U'));
  15827                         oa->write_character(j.m_value.binary->data()[i]);
  15828                     }
  15829                 }
  15830 
  15831                 if (!use_count)
  15832                 {
  15833                     oa->write_character(to_char_type(']'));
  15834                 }
  15835 
  15836                 break;
  15837             }
  15838 
  15839             case value_t::object:
  15840             {
  15841                 if (use_bjdata && j.m_value.object->size() == 3 && j.m_value.object->find("_ArrayType_") != j.m_value.object->end() && j.m_value.object->find("_ArraySize_") != j.m_value.object->end() && j.m_value.object->find("_ArrayData_") != j.m_value.object->end())
  15842                 {
  15843                     if (!write_bjdata_ndarray(*j.m_value.object, use_count, use_type))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
  15844                     {
  15845                         break;
  15846                     }
  15847                 }
  15848 
  15849                 if (add_prefix)
  15850                 {
  15851                     oa->write_character(to_char_type('{'));
  15852                 }
  15853 
  15854                 bool prefix_required = true;
  15855                 if (use_type && !j.m_value.object->empty())
  15856                 {
  15857                     JSON_ASSERT(use_count);
  15858                     const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
  15859                     const bool same_prefix = std::all_of(j.begin(), j.end(),
  15860                                                          [this, first_prefix, use_bjdata](const BasicJsonType & v)
  15861                     {
  15862                         return ubjson_prefix(v, use_bjdata) == first_prefix;
  15863                     });
  15864 
  15865                     std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
  15866 
  15867                     if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
  15868                     {
  15869                         prefix_required = false;
  15870                         oa->write_character(to_char_type('$'));
  15871                         oa->write_character(first_prefix);
  15872                     }
  15873                 }
  15874 
  15875                 if (use_count)
  15876                 {
  15877                     oa->write_character(to_char_type('#'));
  15878                     write_number_with_ubjson_prefix(j.m_value.object->size(), true, use_bjdata);
  15879                 }
  15880 
  15881                 for (const auto& el : *j.m_value.object)
  15882                 {
  15883                     write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
  15884                     oa->write_characters(
  15885                         reinterpret_cast<const CharType*>(el.first.c_str()),
  15886                         el.first.size());
  15887                     write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
  15888                 }
  15889 
  15890                 if (!use_count)
  15891                 {
  15892                     oa->write_character(to_char_type('}'));
  15893                 }
  15894 
  15895                 break;
  15896             }
  15897 
  15898             case value_t::discarded:
  15899             default:
  15900                 break;
  15901         }
  15902     }
  15903 
  15904   private:
  15905     //////////
  15906     // BSON //
  15907     //////////
  15908 
  15909     /*!
  15910     @return The size of a BSON document entry header, including the id marker
  15911             and the entry name size (and its null-terminator).
  15912     */
  15913     static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
  15914     {
  15915         const auto it = name.find(static_cast<typename string_t::value_type>(0));
  15916         if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
  15917         {
  15918             JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
  15919             static_cast<void>(j);
  15920         }
  15921 
  15922         return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
  15923     }
  15924 
  15925     /*!
  15926     @brief Writes the given @a element_type and @a name to the output adapter
  15927     */
  15928     void write_bson_entry_header(const string_t& name,
  15929                                  const std::uint8_t element_type)
  15930     {
  15931         oa->write_character(to_char_type(element_type)); // boolean
  15932         oa->write_characters(
  15933             reinterpret_cast<const CharType*>(name.c_str()),
  15934             name.size() + 1u);
  15935     }
  15936 
  15937     /*!
  15938     @brief Writes a BSON element with key @a name and boolean value @a value
  15939     */
  15940     void write_bson_boolean(const string_t& name,
  15941                             const bool value)
  15942     {
  15943         write_bson_entry_header(name, 0x08);
  15944         oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
  15945     }
  15946 
  15947     /*!
  15948     @brief Writes a BSON element with key @a name and double value @a value
  15949     */
  15950     void write_bson_double(const string_t& name,
  15951                            const double value)
  15952     {
  15953         write_bson_entry_header(name, 0x01);
  15954         write_number<double>(value, true);
  15955     }
  15956 
  15957     /*!
  15958     @return The size of the BSON-encoded string in @a value
  15959     */
  15960     static std::size_t calc_bson_string_size(const string_t& value)
  15961     {
  15962         return sizeof(std::int32_t) + value.size() + 1ul;
  15963     }
  15964 
  15965     /*!
  15966     @brief Writes a BSON element with key @a name and string value @a value
  15967     */
  15968     void write_bson_string(const string_t& name,
  15969                            const string_t& value)
  15970     {
  15971         write_bson_entry_header(name, 0x02);
  15972 
  15973         write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
  15974         oa->write_characters(
  15975             reinterpret_cast<const CharType*>(value.c_str()),
  15976             value.size() + 1);
  15977     }
  15978 
  15979     /*!
  15980     @brief Writes a BSON element with key @a name and null value
  15981     */
  15982     void write_bson_null(const string_t& name)
  15983     {
  15984         write_bson_entry_header(name, 0x0A);
  15985     }
  15986 
  15987     /*!
  15988     @return The size of the BSON-encoded integer @a value
  15989     */
  15990     static std::size_t calc_bson_integer_size(const std::int64_t value)
  15991     {
  15992         return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
  15993                ? sizeof(std::int32_t)
  15994                : sizeof(std::int64_t);
  15995     }
  15996 
  15997     /*!
  15998     @brief Writes a BSON element with key @a name and integer @a value
  15999     */
  16000     void write_bson_integer(const string_t& name,
  16001                             const std::int64_t value)
  16002     {
  16003         if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
  16004         {
  16005             write_bson_entry_header(name, 0x10); // int32
  16006             write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
  16007         }
  16008         else
  16009         {
  16010             write_bson_entry_header(name, 0x12); // int64
  16011             write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
  16012         }
  16013     }
  16014 
  16015     /*!
  16016     @return The size of the BSON-encoded unsigned integer in @a j
  16017     */
  16018     static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
  16019     {
  16020         return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16021                ? sizeof(std::int32_t)
  16022                : sizeof(std::int64_t);
  16023     }
  16024 
  16025     /*!
  16026     @brief Writes a BSON element with key @a name and unsigned @a value
  16027     */
  16028     void write_bson_unsigned(const string_t& name,
  16029                              const BasicJsonType& j)
  16030     {
  16031         if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16032         {
  16033             write_bson_entry_header(name, 0x10 /* int32 */);
  16034             write_number<std::int32_t>(static_cast<std::int32_t>(j.m_value.number_unsigned), true);
  16035         }
  16036         else if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  16037         {
  16038             write_bson_entry_header(name, 0x12 /* int64 */);
  16039             write_number<std::int64_t>(static_cast<std::int64_t>(j.m_value.number_unsigned), true);
  16040         }
  16041         else
  16042         {
  16043             JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
  16044         }
  16045     }
  16046 
  16047     /*!
  16048     @brief Writes a BSON element with key @a name and object @a value
  16049     */
  16050     void write_bson_object_entry(const string_t& name,
  16051                                  const typename BasicJsonType::object_t& value)
  16052     {
  16053         write_bson_entry_header(name, 0x03); // object
  16054         write_bson_object(value);
  16055     }
  16056 
  16057     /*!
  16058     @return The size of the BSON-encoded array @a value
  16059     */
  16060     static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
  16061     {
  16062         std::size_t array_index = 0ul;
  16063 
  16064         const std::size_t embedded_document_size = std::accumulate(std::begin(value), std::end(value), static_cast<std::size_t>(0), [&array_index](std::size_t result, const typename BasicJsonType::array_t::value_type & el)
  16065         {
  16066             return result + calc_bson_element_size(std::to_string(array_index++), el);
  16067         });
  16068 
  16069         return sizeof(std::int32_t) + embedded_document_size + 1ul;
  16070     }
  16071 
  16072     /*!
  16073     @return The size of the BSON-encoded binary array @a value
  16074     */
  16075     static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
  16076     {
  16077         return sizeof(std::int32_t) + value.size() + 1ul;
  16078     }
  16079 
  16080     /*!
  16081     @brief Writes a BSON element with key @a name and array @a value
  16082     */
  16083     void write_bson_array(const string_t& name,
  16084                           const typename BasicJsonType::array_t& value)
  16085     {
  16086         write_bson_entry_header(name, 0x04); // array
  16087         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
  16088 
  16089         std::size_t array_index = 0ul;
  16090 
  16091         for (const auto& el : value)
  16092         {
  16093             write_bson_element(std::to_string(array_index++), el);
  16094         }
  16095 
  16096         oa->write_character(to_char_type(0x00));
  16097     }
  16098 
  16099     /*!
  16100     @brief Writes a BSON element with key @a name and binary value @a value
  16101     */
  16102     void write_bson_binary(const string_t& name,
  16103                            const binary_t& value)
  16104     {
  16105         write_bson_entry_header(name, 0x05);
  16106 
  16107         write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
  16108         write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
  16109 
  16110         oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
  16111     }
  16112 
  16113     /*!
  16114     @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
  16115     @return The calculated size for the BSON document entry for @a j with the given @a name.
  16116     */
  16117     static std::size_t calc_bson_element_size(const string_t& name,
  16118             const BasicJsonType& j)
  16119     {
  16120         const auto header_size = calc_bson_entry_header_size(name, j);
  16121         switch (j.type())
  16122         {
  16123             case value_t::object:
  16124                 return header_size + calc_bson_object_size(*j.m_value.object);
  16125 
  16126             case value_t::array:
  16127                 return header_size + calc_bson_array_size(*j.m_value.array);
  16128 
  16129             case value_t::binary:
  16130                 return header_size + calc_bson_binary_size(*j.m_value.binary);
  16131 
  16132             case value_t::boolean:
  16133                 return header_size + 1ul;
  16134 
  16135             case value_t::number_float:
  16136                 return header_size + 8ul;
  16137 
  16138             case value_t::number_integer:
  16139                 return header_size + calc_bson_integer_size(j.m_value.number_integer);
  16140 
  16141             case value_t::number_unsigned:
  16142                 return header_size + calc_bson_unsigned_size(j.m_value.number_unsigned);
  16143 
  16144             case value_t::string:
  16145                 return header_size + calc_bson_string_size(*j.m_value.string);
  16146 
  16147             case value_t::null:
  16148                 return header_size + 0ul;
  16149 
  16150             // LCOV_EXCL_START
  16151             case value_t::discarded:
  16152             default:
  16153                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
  16154                 return 0ul;
  16155                 // LCOV_EXCL_STOP
  16156         }
  16157     }
  16158 
  16159     /*!
  16160     @brief Serializes the JSON value @a j to BSON and associates it with the
  16161            key @a name.
  16162     @param name The name to associate with the JSON entity @a j within the
  16163                 current BSON document
  16164     */
  16165     void write_bson_element(const string_t& name,
  16166                             const BasicJsonType& j)
  16167     {
  16168         switch (j.type())
  16169         {
  16170             case value_t::object:
  16171                 return write_bson_object_entry(name, *j.m_value.object);
  16172 
  16173             case value_t::array:
  16174                 return write_bson_array(name, *j.m_value.array);
  16175 
  16176             case value_t::binary:
  16177                 return write_bson_binary(name, *j.m_value.binary);
  16178 
  16179             case value_t::boolean:
  16180                 return write_bson_boolean(name, j.m_value.boolean);
  16181 
  16182             case value_t::number_float:
  16183                 return write_bson_double(name, j.m_value.number_float);
  16184 
  16185             case value_t::number_integer:
  16186                 return write_bson_integer(name, j.m_value.number_integer);
  16187 
  16188             case value_t::number_unsigned:
  16189                 return write_bson_unsigned(name, j);
  16190 
  16191             case value_t::string:
  16192                 return write_bson_string(name, *j.m_value.string);
  16193 
  16194             case value_t::null:
  16195                 return write_bson_null(name);
  16196 
  16197             // LCOV_EXCL_START
  16198             case value_t::discarded:
  16199             default:
  16200                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
  16201                 return;
  16202                 // LCOV_EXCL_STOP
  16203         }
  16204     }
  16205 
  16206     /*!
  16207     @brief Calculates the size of the BSON serialization of the given
  16208            JSON-object @a j.
  16209     @param[in] value  JSON value to serialize
  16210     @pre       value.type() == value_t::object
  16211     */
  16212     static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
  16213     {
  16214         const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
  16215                                           [](size_t result, const typename BasicJsonType::object_t::value_type & el)
  16216         {
  16217             return result += calc_bson_element_size(el.first, el.second);
  16218         });
  16219 
  16220         return sizeof(std::int32_t) + document_size + 1ul;
  16221     }
  16222 
  16223     /*!
  16224     @param[in] value  JSON value to serialize
  16225     @pre       value.type() == value_t::object
  16226     */
  16227     void write_bson_object(const typename BasicJsonType::object_t& value)
  16228     {
  16229         write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
  16230 
  16231         for (const auto& el : value)
  16232         {
  16233             write_bson_element(el.first, el.second);
  16234         }
  16235 
  16236         oa->write_character(to_char_type(0x00));
  16237     }
  16238 
  16239     //////////
  16240     // CBOR //
  16241     //////////
  16242 
  16243     static constexpr CharType get_cbor_float_prefix(float /*unused*/)
  16244     {
  16245         return to_char_type(0xFA);  // Single-Precision Float
  16246     }
  16247 
  16248     static constexpr CharType get_cbor_float_prefix(double /*unused*/)
  16249     {
  16250         return to_char_type(0xFB);  // Double-Precision Float
  16251     }
  16252 
  16253     /////////////
  16254     // MsgPack //
  16255     /////////////
  16256 
  16257     static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
  16258     {
  16259         return to_char_type(0xCA);  // float 32
  16260     }
  16261 
  16262     static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
  16263     {
  16264         return to_char_type(0xCB);  // float 64
  16265     }
  16266 
  16267     ////////////
  16268     // UBJSON //
  16269     ////////////
  16270 
  16271     // UBJSON: write number (floating point)
  16272     template<typename NumberType, typename std::enable_if<
  16273                  std::is_floating_point<NumberType>::value, int>::type = 0>
  16274     void write_number_with_ubjson_prefix(const NumberType n,
  16275                                          const bool add_prefix,
  16276                                          const bool use_bjdata)
  16277     {
  16278         if (add_prefix)
  16279         {
  16280             oa->write_character(get_ubjson_float_prefix(n));
  16281         }
  16282         write_number(n, use_bjdata);
  16283     }
  16284 
  16285     // UBJSON: write number (unsigned integer)
  16286     template<typename NumberType, typename std::enable_if<
  16287                  std::is_unsigned<NumberType>::value, int>::type = 0>
  16288     void write_number_with_ubjson_prefix(const NumberType n,
  16289                                          const bool add_prefix,
  16290                                          const bool use_bjdata)
  16291     {
  16292         if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
  16293         {
  16294             if (add_prefix)
  16295             {
  16296                 oa->write_character(to_char_type('i'));  // int8
  16297             }
  16298             write_number(static_cast<std::uint8_t>(n), use_bjdata);
  16299         }
  16300         else if (n <= (std::numeric_limits<std::uint8_t>::max)())
  16301         {
  16302             if (add_prefix)
  16303             {
  16304                 oa->write_character(to_char_type('U'));  // uint8
  16305             }
  16306             write_number(static_cast<std::uint8_t>(n), use_bjdata);
  16307         }
  16308         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
  16309         {
  16310             if (add_prefix)
  16311             {
  16312                 oa->write_character(to_char_type('I'));  // int16
  16313             }
  16314             write_number(static_cast<std::int16_t>(n), use_bjdata);
  16315         }
  16316         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
  16317         {
  16318             if (add_prefix)
  16319             {
  16320                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
  16321             }
  16322             write_number(static_cast<std::uint16_t>(n), use_bjdata);
  16323         }
  16324         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16325         {
  16326             if (add_prefix)
  16327             {
  16328                 oa->write_character(to_char_type('l'));  // int32
  16329             }
  16330             write_number(static_cast<std::int32_t>(n), use_bjdata);
  16331         }
  16332         else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
  16333         {
  16334             if (add_prefix)
  16335             {
  16336                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
  16337             }
  16338             write_number(static_cast<std::uint32_t>(n), use_bjdata);
  16339         }
  16340         else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  16341         {
  16342             if (add_prefix)
  16343             {
  16344                 oa->write_character(to_char_type('L'));  // int64
  16345             }
  16346             write_number(static_cast<std::int64_t>(n), use_bjdata);
  16347         }
  16348         else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
  16349         {
  16350             if (add_prefix)
  16351             {
  16352                 oa->write_character(to_char_type('M'));  // uint64 - bjdata only
  16353             }
  16354             write_number(static_cast<std::uint64_t>(n), use_bjdata);
  16355         }
  16356         else
  16357         {
  16358             if (add_prefix)
  16359             {
  16360                 oa->write_character(to_char_type('H'));  // high-precision number
  16361             }
  16362 
  16363             const auto number = BasicJsonType(n).dump();
  16364             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
  16365             for (std::size_t i = 0; i < number.size(); ++i)
  16366             {
  16367                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
  16368             }
  16369         }
  16370     }
  16371 
  16372     // UBJSON: write number (signed integer)
  16373     template < typename NumberType, typename std::enable_if <
  16374                    std::is_signed<NumberType>::value&&
  16375                    !std::is_floating_point<NumberType>::value, int >::type = 0 >
  16376     void write_number_with_ubjson_prefix(const NumberType n,
  16377                                          const bool add_prefix,
  16378                                          const bool use_bjdata)
  16379     {
  16380         if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
  16381         {
  16382             if (add_prefix)
  16383             {
  16384                 oa->write_character(to_char_type('i'));  // int8
  16385             }
  16386             write_number(static_cast<std::int8_t>(n), use_bjdata);
  16387         }
  16388         else if (static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint8_t>::max)()))
  16389         {
  16390             if (add_prefix)
  16391             {
  16392                 oa->write_character(to_char_type('U'));  // uint8
  16393             }
  16394             write_number(static_cast<std::uint8_t>(n), use_bjdata);
  16395         }
  16396         else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
  16397         {
  16398             if (add_prefix)
  16399             {
  16400                 oa->write_character(to_char_type('I'));  // int16
  16401             }
  16402             write_number(static_cast<std::int16_t>(n), use_bjdata);
  16403         }
  16404         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint16_t>::max)())))
  16405         {
  16406             if (add_prefix)
  16407             {
  16408                 oa->write_character(to_char_type('u'));  // uint16 - bjdata only
  16409             }
  16410             write_number(static_cast<uint16_t>(n), use_bjdata);
  16411         }
  16412         else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
  16413         {
  16414             if (add_prefix)
  16415             {
  16416                 oa->write_character(to_char_type('l'));  // int32
  16417             }
  16418             write_number(static_cast<std::int32_t>(n), use_bjdata);
  16419         }
  16420         else if (use_bjdata && (static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::min)()) <= n && n <= static_cast<std::int64_t>((std::numeric_limits<std::uint32_t>::max)())))
  16421         {
  16422             if (add_prefix)
  16423             {
  16424                 oa->write_character(to_char_type('m'));  // uint32 - bjdata only
  16425             }
  16426             write_number(static_cast<uint32_t>(n), use_bjdata);
  16427         }
  16428         else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
  16429         {
  16430             if (add_prefix)
  16431             {
  16432                 oa->write_character(to_char_type('L'));  // int64
  16433             }
  16434             write_number(static_cast<std::int64_t>(n), use_bjdata);
  16435         }
  16436         // LCOV_EXCL_START
  16437         else
  16438         {
  16439             if (add_prefix)
  16440             {
  16441                 oa->write_character(to_char_type('H'));  // high-precision number
  16442             }
  16443 
  16444             const auto number = BasicJsonType(n).dump();
  16445             write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
  16446             for (std::size_t i = 0; i < number.size(); ++i)
  16447             {
  16448                 oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
  16449             }
  16450         }
  16451         // LCOV_EXCL_STOP
  16452     }
  16453 
  16454     /*!
  16455     @brief determine the type prefix of container values
  16456     */
  16457     CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
  16458     {
  16459         switch (j.type())
  16460         {
  16461             case value_t::null:
  16462                 return 'Z';
  16463 
  16464             case value_t::boolean:
  16465                 return j.m_value.boolean ? 'T' : 'F';
  16466 
  16467             case value_t::number_integer:
  16468             {
  16469                 if ((std::numeric_limits<std::int8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
  16470                 {
  16471                     return 'i';
  16472                 }
  16473                 if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
  16474                 {
  16475                     return 'U';
  16476                 }
  16477                 if ((std::numeric_limits<std::int16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
  16478                 {
  16479                     return 'I';
  16480                 }
  16481                 if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
  16482                 {
  16483                     return 'u';
  16484                 }
  16485                 if ((std::numeric_limits<std::int32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
  16486                 {
  16487                     return 'l';
  16488                 }
  16489                 if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
  16490                 {
  16491                     return 'm';
  16492                 }
  16493                 if ((std::numeric_limits<std::int64_t>::min)() <= j.m_value.number_integer && j.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
  16494                 {
  16495                     return 'L';
  16496                 }
  16497                 // anything else is treated as high-precision number
  16498                 return 'H'; // LCOV_EXCL_LINE
  16499             }
  16500 
  16501             case value_t::number_unsigned:
  16502             {
  16503                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
  16504                 {
  16505                     return 'i';
  16506                 }
  16507                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
  16508                 {
  16509                     return 'U';
  16510                 }
  16511                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
  16512                 {
  16513                     return 'I';
  16514                 }
  16515                 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
  16516                 {
  16517                     return 'u';
  16518                 }
  16519                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16520                 {
  16521                     return 'l';
  16522                 }
  16523                 if (use_bjdata && j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
  16524                 {
  16525                     return 'm';
  16526                 }
  16527                 if (j.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  16528                 {
  16529                     return 'L';
  16530                 }
  16531                 if (use_bjdata && j.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  16532                 {
  16533                     return 'M';
  16534                 }
  16535                 // anything else is treated as high-precision number
  16536                 return 'H'; // LCOV_EXCL_LINE
  16537             }
  16538 
  16539             case value_t::number_float:
  16540                 return get_ubjson_float_prefix(j.m_value.number_float);
  16541 
  16542             case value_t::string:
  16543                 return 'S';
  16544 
  16545             case value_t::array: // fallthrough
  16546             case value_t::binary:
  16547                 return '[';
  16548 
  16549             case value_t::object:
  16550                 return '{';
  16551 
  16552             case value_t::discarded:
  16553             default:  // discarded values
  16554                 return 'N';
  16555         }
  16556     }
  16557 
  16558     static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
  16559     {
  16560         return 'd';  // float 32
  16561     }
  16562 
  16563     static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
  16564     {
  16565         return 'D';  // float 64
  16566     }
  16567 
  16568     /*!
  16569     @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
  16570     */
  16571     bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
  16572     {
  16573         std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
  16574             {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
  16575         };
  16576 
  16577         string_t key = "_ArrayType_";
  16578         auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
  16579         if (it == bjdtype.end())
  16580         {
  16581             return true;
  16582         }
  16583         CharType dtype = it->second;
  16584 
  16585         key = "_ArraySize_";
  16586         std::size_t len = (value.at(key).empty() ? 0 : 1);
  16587         for (const auto& el : value.at(key))
  16588         {
  16589             len *= static_cast<std::size_t>(el.m_value.number_unsigned);
  16590         }
  16591 
  16592         key = "_ArrayData_";
  16593         if (value.at(key).size() != len)
  16594         {
  16595             return true;
  16596         }
  16597 
  16598         oa->write_character('[');
  16599         oa->write_character('$');
  16600         oa->write_character(dtype);
  16601         oa->write_character('#');
  16602 
  16603         key = "_ArraySize_";
  16604         write_ubjson(value.at(key), use_count, use_type, true,  true);
  16605 
  16606         key = "_ArrayData_";
  16607         if (dtype == 'U' || dtype == 'C')
  16608         {
  16609             for (const auto& el : value.at(key))
  16610             {
  16611                 write_number(static_cast<std::uint8_t>(el.m_value.number_unsigned), true);
  16612             }
  16613         }
  16614         else if (dtype == 'i')
  16615         {
  16616             for (const auto& el : value.at(key))
  16617             {
  16618                 write_number(static_cast<std::int8_t>(el.m_value.number_integer), true);
  16619             }
  16620         }
  16621         else if (dtype == 'u')
  16622         {
  16623             for (const auto& el : value.at(key))
  16624             {
  16625                 write_number(static_cast<std::uint16_t>(el.m_value.number_unsigned), true);
  16626             }
  16627         }
  16628         else if (dtype == 'I')
  16629         {
  16630             for (const auto& el : value.at(key))
  16631             {
  16632                 write_number(static_cast<std::int16_t>(el.m_value.number_integer), true);
  16633             }
  16634         }
  16635         else if (dtype == 'm')
  16636         {
  16637             for (const auto& el : value.at(key))
  16638             {
  16639                 write_number(static_cast<std::uint32_t>(el.m_value.number_unsigned), true);
  16640             }
  16641         }
  16642         else if (dtype == 'l')
  16643         {
  16644             for (const auto& el : value.at(key))
  16645             {
  16646                 write_number(static_cast<std::int32_t>(el.m_value.number_integer), true);
  16647             }
  16648         }
  16649         else if (dtype == 'M')
  16650         {
  16651             for (const auto& el : value.at(key))
  16652             {
  16653                 write_number(static_cast<std::uint64_t>(el.m_value.number_unsigned), true);
  16654             }
  16655         }
  16656         else if (dtype == 'L')
  16657         {
  16658             for (const auto& el : value.at(key))
  16659             {
  16660                 write_number(static_cast<std::int64_t>(el.m_value.number_integer), true);
  16661             }
  16662         }
  16663         else if (dtype == 'd')
  16664         {
  16665             for (const auto& el : value.at(key))
  16666             {
  16667                 write_number(static_cast<float>(el.m_value.number_float), true);
  16668             }
  16669         }
  16670         else if (dtype == 'D')
  16671         {
  16672             for (const auto& el : value.at(key))
  16673             {
  16674                 write_number(static_cast<double>(el.m_value.number_float), true);
  16675             }
  16676         }
  16677         return false;
  16678     }
  16679 
  16680     ///////////////////////
  16681     // Utility functions //
  16682     ///////////////////////
  16683 
  16684     /*
  16685     @brief write a number to output input
  16686     @param[in] n number of type @a NumberType
  16687     @param[in] OutputIsLittleEndian Set to true if output data is
  16688                                  required to be little endian
  16689     @tparam NumberType the type of the number
  16690 
  16691     @note This function needs to respect the system's endianness, because bytes
  16692           in CBOR, MessagePack, and UBJSON are stored in network order (big
  16693           endian) and therefore need reordering on little endian systems.
  16694           On the other hand, BSON and BJData use little endian and should reorder
  16695           on big endian systems.
  16696     */
  16697     template<typename NumberType>
  16698     void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
  16699     {
  16700         // step 1: write number to array of length NumberType
  16701         std::array<CharType, sizeof(NumberType)> vec{};
  16702         std::memcpy(vec.data(), &n, sizeof(NumberType));
  16703 
  16704         // step 2: write array to output (with possible reordering)
  16705         if (is_little_endian != OutputIsLittleEndian)
  16706         {
  16707             // reverse byte order prior to conversion if necessary
  16708             std::reverse(vec.begin(), vec.end());
  16709         }
  16710 
  16711         oa->write_characters(vec.data(), sizeof(NumberType));
  16712     }
  16713 
  16714     void write_compact_float(const number_float_t n, detail::input_format_t format)
  16715     {
  16716 #ifdef __GNUC__
  16717 #pragma GCC diagnostic push
  16718 #pragma GCC diagnostic ignored "-Wfloat-equal"
  16719 #endif
  16720         if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
  16721                 static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
  16722                 static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
  16723         {
  16724             oa->write_character(format == detail::input_format_t::cbor
  16725                                 ? get_cbor_float_prefix(static_cast<float>(n))
  16726                                 : get_msgpack_float_prefix(static_cast<float>(n)));
  16727             write_number(static_cast<float>(n));
  16728         }
  16729         else
  16730         {
  16731             oa->write_character(format == detail::input_format_t::cbor
  16732                                 ? get_cbor_float_prefix(n)
  16733                                 : get_msgpack_float_prefix(n));
  16734             write_number(n);
  16735         }
  16736 #ifdef __GNUC__
  16737 #pragma GCC diagnostic pop
  16738 #endif
  16739     }
  16740 
  16741   public:
  16742     // The following to_char_type functions are implement the conversion
  16743     // between uint8_t and CharType. In case CharType is not unsigned,
  16744     // such a conversion is required to allow values greater than 128.
  16745     // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
  16746     template < typename C = CharType,
  16747                enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
  16748     static constexpr CharType to_char_type(std::uint8_t x) noexcept
  16749     {
  16750         return *reinterpret_cast<char*>(&x);
  16751     }
  16752 
  16753     template < typename C = CharType,
  16754                enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
  16755     static CharType to_char_type(std::uint8_t x) noexcept
  16756     {
  16757         static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
  16758         static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
  16759         CharType result;
  16760         std::memcpy(&result, &x, sizeof(x));
  16761         return result;
  16762     }
  16763 
  16764     template<typename C = CharType,
  16765              enable_if_t<std::is_unsigned<C>::value>* = nullptr>
  16766     static constexpr CharType to_char_type(std::uint8_t x) noexcept
  16767     {
  16768         return x;
  16769     }
  16770 
  16771     template < typename InputCharType, typename C = CharType,
  16772                enable_if_t <
  16773                    std::is_signed<C>::value &&
  16774                    std::is_signed<char>::value &&
  16775                    std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
  16776                    > * = nullptr >
  16777     static constexpr CharType to_char_type(InputCharType x) noexcept
  16778     {
  16779         return x;
  16780     }
  16781 
  16782   private:
  16783     /// whether we can assume little endianness
  16784     const bool is_little_endian = little_endianness();
  16785 
  16786     /// the output
  16787     output_adapter_t<CharType> oa = nullptr;
  16788 };
  16789 
  16790 }  // namespace detail
  16791 NLOHMANN_JSON_NAMESPACE_END
  16792 
  16793 // #include <nlohmann/detail/output/output_adapters.hpp>
  16794 
  16795 // #include <nlohmann/detail/output/serializer.hpp>
  16796 //     __ _____ _____ _____
  16797 //  __|  |   __|     |   | |  JSON for Modern C++
  16798 // |  |  |__   |  |  | | | |  version 3.11.2
  16799 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  16800 //
  16801 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
  16802 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  16803 // SPDX-License-Identifier: MIT
  16804 
  16805 
  16806 
  16807 #include <algorithm> // reverse, remove, fill, find, none_of
  16808 #include <array> // array
  16809 #include <clocale> // localeconv, lconv
  16810 #include <cmath> // labs, isfinite, isnan, signbit
  16811 #include <cstddef> // size_t, ptrdiff_t
  16812 #include <cstdint> // uint8_t
  16813 #include <cstdio> // snprintf
  16814 #include <limits> // numeric_limits
  16815 #include <string> // string, char_traits
  16816 #include <iomanip> // setfill, setw
  16817 #include <type_traits> // is_same
  16818 #include <utility> // move
  16819 
  16820 // #include <nlohmann/detail/conversions/to_chars.hpp>
  16821 //     __ _____ _____ _____
  16822 //  __|  |   __|     |   | |  JSON for Modern C++
  16823 // |  |  |__   |  |  | | | |  version 3.11.2
  16824 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  16825 //
  16826 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
  16827 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  16828 // SPDX-License-Identifier: MIT
  16829 
  16830 
  16831 
  16832 #include <array> // array
  16833 #include <cmath>   // signbit, isfinite
  16834 #include <cstdint> // intN_t, uintN_t
  16835 #include <cstring> // memcpy, memmove
  16836 #include <limits> // numeric_limits
  16837 #include <type_traits> // conditional
  16838 
  16839 // #include <nlohmann/detail/macro_scope.hpp>
  16840 
  16841 
  16842 NLOHMANN_JSON_NAMESPACE_BEGIN
  16843 namespace detail
  16844 {
  16845 
  16846 /*!
  16847 @brief implements the Grisu2 algorithm for binary to decimal floating-point
  16848 conversion.
  16849 
  16850 This implementation is a slightly modified version of the reference
  16851 implementation which may be obtained from
  16852 http://florian.loitsch.com/publications (bench.tar.gz).
  16853 
  16854 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
  16855 
  16856 For a detailed description of the algorithm see:
  16857 
  16858 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
  16859     Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
  16860     Language Design and Implementation, PLDI 2010
  16861 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
  16862     Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
  16863     Design and Implementation, PLDI 1996
  16864 */
  16865 namespace dtoa_impl
  16866 {
  16867 
  16868 template<typename Target, typename Source>
  16869 Target reinterpret_bits(const Source source)
  16870 {
  16871     static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
  16872 
  16873     Target target;
  16874     std::memcpy(&target, &source, sizeof(Source));
  16875     return target;
  16876 }
  16877 
  16878 struct diyfp // f * 2^e
  16879 {
  16880     static constexpr int kPrecision = 64; // = q
  16881 
  16882     std::uint64_t f = 0;
  16883     int e = 0;
  16884 
  16885     constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
  16886 
  16887     /*!
  16888     @brief returns x - y
  16889     @pre x.e == y.e and x.f >= y.f
  16890     */
  16891     static diyfp sub(const diyfp& x, const diyfp& y) noexcept
  16892     {
  16893         JSON_ASSERT(x.e == y.e);
  16894         JSON_ASSERT(x.f >= y.f);
  16895 
  16896         return {x.f - y.f, x.e};
  16897     }
  16898 
  16899     /*!
  16900     @brief returns x * y
  16901     @note The result is rounded. (Only the upper q bits are returned.)
  16902     */
  16903     static diyfp mul(const diyfp& x, const diyfp& y) noexcept
  16904     {
  16905         static_assert(kPrecision == 64, "internal error");
  16906 
  16907         // Computes:
  16908         //  f = round((x.f * y.f) / 2^q)
  16909         //  e = x.e + y.e + q
  16910 
  16911         // Emulate the 64-bit * 64-bit multiplication:
  16912         //
  16913         // p = u * v
  16914         //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
  16915         //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
  16916         //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
  16917         //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
  16918         //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
  16919         //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
  16920         //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
  16921         //
  16922         // (Since Q might be larger than 2^32 - 1)
  16923         //
  16924         //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
  16925         //
  16926         // (Q_hi + H does not overflow a 64-bit int)
  16927         //
  16928         //   = p_lo + 2^64 p_hi
  16929 
  16930         const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
  16931         const std::uint64_t u_hi = x.f >> 32u;
  16932         const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
  16933         const std::uint64_t v_hi = y.f >> 32u;
  16934 
  16935         const std::uint64_t p0 = u_lo * v_lo;
  16936         const std::uint64_t p1 = u_lo * v_hi;
  16937         const std::uint64_t p2 = u_hi * v_lo;
  16938         const std::uint64_t p3 = u_hi * v_hi;
  16939 
  16940         const std::uint64_t p0_hi = p0 >> 32u;
  16941         const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
  16942         const std::uint64_t p1_hi = p1 >> 32u;
  16943         const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
  16944         const std::uint64_t p2_hi = p2 >> 32u;
  16945 
  16946         std::uint64_t Q = p0_hi + p1_lo + p2_lo;
  16947 
  16948         // The full product might now be computed as
  16949         //
  16950         // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
  16951         // p_lo = p0_lo + (Q << 32)
  16952         //
  16953         // But in this particular case here, the full p_lo is not required.
  16954         // Effectively we only need to add the highest bit in p_lo to p_hi (and
  16955         // Q_hi + 1 does not overflow).
  16956 
  16957         Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
  16958 
  16959         const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
  16960 
  16961         return {h, x.e + y.e + 64};
  16962     }
  16963 
  16964     /*!
  16965     @brief normalize x such that the significand is >= 2^(q-1)
  16966     @pre x.f != 0
  16967     */
  16968     static diyfp normalize(diyfp x) noexcept
  16969     {
  16970         JSON_ASSERT(x.f != 0);
  16971 
  16972         while ((x.f >> 63u) == 0)
  16973         {
  16974             x.f <<= 1u;
  16975             x.e--;
  16976         }
  16977 
  16978         return x;
  16979     }
  16980 
  16981     /*!
  16982     @brief normalize x such that the result has the exponent E
  16983     @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
  16984     */
  16985     static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
  16986     {
  16987         const int delta = x.e - target_exponent;
  16988 
  16989         JSON_ASSERT(delta >= 0);
  16990         JSON_ASSERT(((x.f << delta) >> delta) == x.f);
  16991 
  16992         return {x.f << delta, target_exponent};
  16993     }
  16994 };
  16995 
  16996 struct boundaries
  16997 {
  16998     diyfp w;
  16999     diyfp minus;
  17000     diyfp plus;
  17001 };
  17002 
  17003 /*!
  17004 Compute the (normalized) diyfp representing the input number 'value' and its
  17005 boundaries.
  17006 
  17007 @pre value must be finite and positive
  17008 */
  17009 template<typename FloatType>
  17010 boundaries compute_boundaries(FloatType value)
  17011 {
  17012     JSON_ASSERT(std::isfinite(value));
  17013     JSON_ASSERT(value > 0);
  17014 
  17015     // Convert the IEEE representation into a diyfp.
  17016     //
  17017     // If v is denormal:
  17018     //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
  17019     // If v is normalized:
  17020     //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
  17021 
  17022     static_assert(std::numeric_limits<FloatType>::is_iec559,
  17023                   "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
  17024 
  17025     constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
  17026     constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
  17027     constexpr int      kMinExp    = 1 - kBias;
  17028     constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
  17029 
  17030     using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
  17031 
  17032     const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
  17033     const std::uint64_t E = bits >> (kPrecision - 1);
  17034     const std::uint64_t F = bits & (kHiddenBit - 1);
  17035 
  17036     const bool is_denormal = E == 0;
  17037     const diyfp v = is_denormal
  17038                     ? diyfp(F, kMinExp)
  17039                     : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
  17040 
  17041     // Compute the boundaries m- and m+ of the floating-point value
  17042     // v = f * 2^e.
  17043     //
  17044     // Determine v- and v+, the floating-point predecessor and successor if v,
  17045     // respectively.
  17046     //
  17047     //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
  17048     //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
  17049     //
  17050     //      v+ = v + 2^e
  17051     //
  17052     // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
  17053     // between m- and m+ round to v, regardless of how the input rounding
  17054     // algorithm breaks ties.
  17055     //
  17056     //      ---+-------------+-------------+-------------+-------------+---  (A)
  17057     //         v-            m-            v             m+            v+
  17058     //
  17059     //      -----------------+------+------+-------------+-------------+---  (B)
  17060     //                       v-     m-     v             m+            v+
  17061 
  17062     const bool lower_boundary_is_closer = F == 0 && E > 1;
  17063     const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
  17064     const diyfp m_minus = lower_boundary_is_closer
  17065                           ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
  17066                           : diyfp(2 * v.f - 1, v.e - 1); // (A)
  17067 
  17068     // Determine the normalized w+ = m+.
  17069     const diyfp w_plus = diyfp::normalize(m_plus);
  17070 
  17071     // Determine w- = m- such that e_(w-) = e_(w+).
  17072     const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
  17073 
  17074     return {diyfp::normalize(v), w_minus, w_plus};
  17075 }
  17076 
  17077 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
  17078 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
  17079 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
  17080 //
  17081 //      alpha <= e = e_c + e_w + q <= gamma
  17082 //
  17083 // or
  17084 //
  17085 //      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
  17086 //                          <= f_c * f_w * 2^gamma
  17087 //
  17088 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
  17089 //
  17090 //      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
  17091 //
  17092 // or
  17093 //
  17094 //      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
  17095 //
  17096 // The choice of (alpha,gamma) determines the size of the table and the form of
  17097 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
  17098 // in practice:
  17099 //
  17100 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
  17101 // processed independently: An integral part p1, and a fractional part p2:
  17102 //
  17103 //      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
  17104 //              = (f div 2^-e) + (f mod 2^-e) * 2^e
  17105 //              = p1 + p2 * 2^e
  17106 //
  17107 // The conversion of p1 into decimal form requires a series of divisions and
  17108 // modulos by (a power of) 10. These operations are faster for 32-bit than for
  17109 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
  17110 // achieved by choosing
  17111 //
  17112 //      -e >= 32   or   e <= -32 := gamma
  17113 //
  17114 // In order to convert the fractional part
  17115 //
  17116 //      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
  17117 //
  17118 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
  17119 // d[-i] are extracted in order:
  17120 //
  17121 //      (10 * p2) div 2^-e = d[-1]
  17122 //      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
  17123 //
  17124 // The multiplication by 10 must not overflow. It is sufficient to choose
  17125 //
  17126 //      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
  17127 //
  17128 // Since p2 = f mod 2^-e < 2^-e,
  17129 //
  17130 //      -e <= 60   or   e >= -60 := alpha
  17131 
  17132 constexpr int kAlpha = -60;
  17133 constexpr int kGamma = -32;
  17134 
  17135 struct cached_power // c = f * 2^e ~= 10^k
  17136 {
  17137     std::uint64_t f;
  17138     int e;
  17139     int k;
  17140 };
  17141 
  17142 /*!
  17143 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
  17144 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
  17145 satisfies (Definition 3.2 from [1])
  17146 
  17147      alpha <= e_c + e + q <= gamma.
  17148 */
  17149 inline cached_power get_cached_power_for_binary_exponent(int e)
  17150 {
  17151     // Now
  17152     //
  17153     //      alpha <= e_c + e + q <= gamma                                    (1)
  17154     //      ==> f_c * 2^alpha <= c * 2^e * 2^q
  17155     //
  17156     // and since the c's are normalized, 2^(q-1) <= f_c,
  17157     //
  17158     //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
  17159     //      ==> 2^(alpha - e - 1) <= c
  17160     //
  17161     // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
  17162     //
  17163     //      k = ceil( log_10( 2^(alpha - e - 1) ) )
  17164     //        = ceil( (alpha - e - 1) * log_10(2) )
  17165     //
  17166     // From the paper:
  17167     // "In theory the result of the procedure could be wrong since c is rounded,
  17168     //  and the computation itself is approximated [...]. In practice, however,
  17169     //  this simple function is sufficient."
  17170     //
  17171     // For IEEE double precision floating-point numbers converted into
  17172     // normalized diyfp's w = f * 2^e, with q = 64,
  17173     //
  17174     //      e >= -1022      (min IEEE exponent)
  17175     //           -52        (p - 1)
  17176     //           -52        (p - 1, possibly normalize denormal IEEE numbers)
  17177     //           -11        (normalize the diyfp)
  17178     //         = -1137
  17179     //
  17180     // and
  17181     //
  17182     //      e <= +1023      (max IEEE exponent)
  17183     //           -52        (p - 1)
  17184     //           -11        (normalize the diyfp)
  17185     //         = 960
  17186     //
  17187     // This binary exponent range [-1137,960] results in a decimal exponent
  17188     // range [-307,324]. One does not need to store a cached power for each
  17189     // k in this range. For each such k it suffices to find a cached power
  17190     // such that the exponent of the product lies in [alpha,gamma].
  17191     // This implies that the difference of the decimal exponents of adjacent
  17192     // table entries must be less than or equal to
  17193     //
  17194     //      floor( (gamma - alpha) * log_10(2) ) = 8.
  17195     //
  17196     // (A smaller distance gamma-alpha would require a larger table.)
  17197 
  17198     // NB:
  17199     // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
  17200 
  17201     constexpr int kCachedPowersMinDecExp = -300;
  17202     constexpr int kCachedPowersDecStep = 8;
  17203 
  17204     static constexpr std::array<cached_power, 79> kCachedPowers =
  17205     {
  17206         {
  17207             { 0xAB70FE17C79AC6CA, -1060, -300 },
  17208             { 0xFF77B1FCBEBCDC4F, -1034, -292 },
  17209             { 0xBE5691EF416BD60C, -1007, -284 },
  17210             { 0x8DD01FAD907FFC3C,  -980, -276 },
  17211             { 0xD3515C2831559A83,  -954, -268 },
  17212             { 0x9D71AC8FADA6C9B5,  -927, -260 },
  17213             { 0xEA9C227723EE8BCB,  -901, -252 },
  17214             { 0xAECC49914078536D,  -874, -244 },
  17215             { 0x823C12795DB6CE57,  -847, -236 },
  17216             { 0xC21094364DFB5637,  -821, -228 },
  17217             { 0x9096EA6F3848984F,  -794, -220 },
  17218             { 0xD77485CB25823AC7,  -768, -212 },
  17219             { 0xA086CFCD97BF97F4,  -741, -204 },
  17220             { 0xEF340A98172AACE5,  -715, -196 },
  17221             { 0xB23867FB2A35B28E,  -688, -188 },
  17222             { 0x84C8D4DFD2C63F3B,  -661, -180 },
  17223             { 0xC5DD44271AD3CDBA,  -635, -172 },
  17224             { 0x936B9FCEBB25C996,  -608, -164 },
  17225             { 0xDBAC6C247D62A584,  -582, -156 },
  17226             { 0xA3AB66580D5FDAF6,  -555, -148 },
  17227             { 0xF3E2F893DEC3F126,  -529, -140 },
  17228             { 0xB5B5ADA8AAFF80B8,  -502, -132 },
  17229             { 0x87625F056C7C4A8B,  -475, -124 },
  17230             { 0xC9BCFF6034C13053,  -449, -116 },
  17231             { 0x964E858C91BA2655,  -422, -108 },
  17232             { 0xDFF9772470297EBD,  -396, -100 },
  17233             { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
  17234             { 0xF8A95FCF88747D94,  -343,  -84 },
  17235             { 0xB94470938FA89BCF,  -316,  -76 },
  17236             { 0x8A08F0F8BF0F156B,  -289,  -68 },
  17237             { 0xCDB02555653131B6,  -263,  -60 },
  17238             { 0x993FE2C6D07B7FAC,  -236,  -52 },
  17239             { 0xE45C10C42A2B3B06,  -210,  -44 },
  17240             { 0xAA242499697392D3,  -183,  -36 },
  17241             { 0xFD87B5F28300CA0E,  -157,  -28 },
  17242             { 0xBCE5086492111AEB,  -130,  -20 },
  17243             { 0x8CBCCC096F5088CC,  -103,  -12 },
  17244             { 0xD1B71758E219652C,   -77,   -4 },
  17245             { 0x9C40000000000000,   -50,    4 },
  17246             { 0xE8D4A51000000000,   -24,   12 },
  17247             { 0xAD78EBC5AC620000,     3,   20 },
  17248             { 0x813F3978F8940984,    30,   28 },
  17249             { 0xC097CE7BC90715B3,    56,   36 },
  17250             { 0x8F7E32CE7BEA5C70,    83,   44 },
  17251             { 0xD5D238A4ABE98068,   109,   52 },
  17252             { 0x9F4F2726179A2245,   136,   60 },
  17253             { 0xED63A231D4C4FB27,   162,   68 },
  17254             { 0xB0DE65388CC8ADA8,   189,   76 },
  17255             { 0x83C7088E1AAB65DB,   216,   84 },
  17256             { 0xC45D1DF942711D9A,   242,   92 },
  17257             { 0x924D692CA61BE758,   269,  100 },
  17258             { 0xDA01EE641A708DEA,   295,  108 },
  17259             { 0xA26DA3999AEF774A,   322,  116 },
  17260             { 0xF209787BB47D6B85,   348,  124 },
  17261             { 0xB454E4A179DD1877,   375,  132 },
  17262             { 0x865B86925B9BC5C2,   402,  140 },
  17263             { 0xC83553C5C8965D3D,   428,  148 },
  17264             { 0x952AB45CFA97A0B3,   455,  156 },
  17265             { 0xDE469FBD99A05FE3,   481,  164 },
  17266             { 0xA59BC234DB398C25,   508,  172 },
  17267             { 0xF6C69A72A3989F5C,   534,  180 },
  17268             { 0xB7DCBF5354E9BECE,   561,  188 },
  17269             { 0x88FCF317F22241E2,   588,  196 },
  17270             { 0xCC20CE9BD35C78A5,   614,  204 },
  17271             { 0x98165AF37B2153DF,   641,  212 },
  17272             { 0xE2A0B5DC971F303A,   667,  220 },
  17273             { 0xA8D9D1535CE3B396,   694,  228 },
  17274             { 0xFB9B7CD9A4A7443C,   720,  236 },
  17275             { 0xBB764C4CA7A44410,   747,  244 },
  17276             { 0x8BAB8EEFB6409C1A,   774,  252 },
  17277             { 0xD01FEF10A657842C,   800,  260 },
  17278             { 0x9B10A4E5E9913129,   827,  268 },
  17279             { 0xE7109BFBA19C0C9D,   853,  276 },
  17280             { 0xAC2820D9623BF429,   880,  284 },
  17281             { 0x80444B5E7AA7CF85,   907,  292 },
  17282             { 0xBF21E44003ACDD2D,   933,  300 },
  17283             { 0x8E679C2F5E44FF8F,   960,  308 },
  17284             { 0xD433179D9C8CB841,   986,  316 },
  17285             { 0x9E19DB92B4E31BA9,  1013,  324 },
  17286         }
  17287     };
  17288 
  17289     // This computation gives exactly the same results for k as
  17290     //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
  17291     // for |e| <= 1500, but doesn't require floating-point operations.
  17292     // NB: log_10(2) ~= 78913 / 2^18
  17293     JSON_ASSERT(e >= -1500);
  17294     JSON_ASSERT(e <=  1500);
  17295     const int f = kAlpha - e - 1;
  17296     const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
  17297 
  17298     const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
  17299     JSON_ASSERT(index >= 0);
  17300     JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
  17301 
  17302     const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
  17303     JSON_ASSERT(kAlpha <= cached.e + e + 64);
  17304     JSON_ASSERT(kGamma >= cached.e + e + 64);
  17305 
  17306     return cached;
  17307 }
  17308 
  17309 /*!
  17310 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
  17311 For n == 0, returns 1 and sets pow10 := 1.
  17312 */
  17313 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
  17314 {
  17315     // LCOV_EXCL_START
  17316     if (n >= 1000000000)
  17317     {
  17318         pow10 = 1000000000;
  17319         return 10;
  17320     }
  17321     // LCOV_EXCL_STOP
  17322     if (n >= 100000000)
  17323     {
  17324         pow10 = 100000000;
  17325         return  9;
  17326     }
  17327     if (n >= 10000000)
  17328     {
  17329         pow10 = 10000000;
  17330         return  8;
  17331     }
  17332     if (n >= 1000000)
  17333     {
  17334         pow10 = 1000000;
  17335         return  7;
  17336     }
  17337     if (n >= 100000)
  17338     {
  17339         pow10 = 100000;
  17340         return  6;
  17341     }
  17342     if (n >= 10000)
  17343     {
  17344         pow10 = 10000;
  17345         return  5;
  17346     }
  17347     if (n >= 1000)
  17348     {
  17349         pow10 = 1000;
  17350         return  4;
  17351     }
  17352     if (n >= 100)
  17353     {
  17354         pow10 = 100;
  17355         return  3;
  17356     }
  17357     if (n >= 10)
  17358     {
  17359         pow10 = 10;
  17360         return  2;
  17361     }
  17362 
  17363     pow10 = 1;
  17364     return 1;
  17365 }
  17366 
  17367 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
  17368                          std::uint64_t rest, std::uint64_t ten_k)
  17369 {
  17370     JSON_ASSERT(len >= 1);
  17371     JSON_ASSERT(dist <= delta);
  17372     JSON_ASSERT(rest <= delta);
  17373     JSON_ASSERT(ten_k > 0);
  17374 
  17375     //               <--------------------------- delta ---->
  17376     //                                  <---- dist --------->
  17377     // --------------[------------------+-------------------]--------------
  17378     //               M-                 w                   M+
  17379     //
  17380     //                                  ten_k
  17381     //                                <------>
  17382     //                                       <---- rest ---->
  17383     // --------------[------------------+----+--------------]--------------
  17384     //                                  w    V
  17385     //                                       = buf * 10^k
  17386     //
  17387     // ten_k represents a unit-in-the-last-place in the decimal representation
  17388     // stored in buf.
  17389     // Decrement buf by ten_k while this takes buf closer to w.
  17390 
  17391     // The tests are written in this order to avoid overflow in unsigned
  17392     // integer arithmetic.
  17393 
  17394     while (rest < dist
  17395             && delta - rest >= ten_k
  17396             && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
  17397     {
  17398         JSON_ASSERT(buf[len - 1] != '0');
  17399         buf[len - 1]--;
  17400         rest += ten_k;
  17401     }
  17402 }
  17403 
  17404 /*!
  17405 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
  17406 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
  17407 */
  17408 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
  17409                              diyfp M_minus, diyfp w, diyfp M_plus)
  17410 {
  17411     static_assert(kAlpha >= -60, "internal error");
  17412     static_assert(kGamma <= -32, "internal error");
  17413 
  17414     // Generates the digits (and the exponent) of a decimal floating-point
  17415     // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
  17416     // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
  17417     //
  17418     //               <--------------------------- delta ---->
  17419     //                                  <---- dist --------->
  17420     // --------------[------------------+-------------------]--------------
  17421     //               M-                 w                   M+
  17422     //
  17423     // Grisu2 generates the digits of M+ from left to right and stops as soon as
  17424     // V is in [M-,M+].
  17425 
  17426     JSON_ASSERT(M_plus.e >= kAlpha);
  17427     JSON_ASSERT(M_plus.e <= kGamma);
  17428 
  17429     std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
  17430     std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
  17431 
  17432     // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
  17433     //
  17434     //      M+ = f * 2^e
  17435     //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
  17436     //         = ((p1        ) * 2^-e + (p2        )) * 2^e
  17437     //         = p1 + p2 * 2^e
  17438 
  17439     const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
  17440 
  17441     auto p1 = static_cast<std::uint32_t>(M_plus.f >> -one.e); // p1 = f div 2^-e (Since -e >= 32, p1 fits into a 32-bit int.)
  17442     std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
  17443 
  17444     // 1)
  17445     //
  17446     // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
  17447 
  17448     JSON_ASSERT(p1 > 0);
  17449 
  17450     std::uint32_t pow10{};
  17451     const int k = find_largest_pow10(p1, pow10);
  17452 
  17453     //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
  17454     //
  17455     //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
  17456     //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
  17457     //
  17458     //      M+ = p1                                             + p2 * 2^e
  17459     //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
  17460     //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
  17461     //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
  17462     //
  17463     // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
  17464     //
  17465     //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
  17466     //
  17467     // but stop as soon as
  17468     //
  17469     //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
  17470 
  17471     int n = k;
  17472     while (n > 0)
  17473     {
  17474         // Invariants:
  17475         //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
  17476         //      pow10 = 10^(n-1) <= p1 < 10^n
  17477         //
  17478         const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
  17479         const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
  17480         //
  17481         //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
  17482         //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
  17483         //
  17484         JSON_ASSERT(d <= 9);
  17485         buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
  17486         //
  17487         //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
  17488         //
  17489         p1 = r;
  17490         n--;
  17491         //
  17492         //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
  17493         //      pow10 = 10^n
  17494         //
  17495 
  17496         // Now check if enough digits have been generated.
  17497         // Compute
  17498         //
  17499         //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
  17500         //
  17501         // Note:
  17502         // Since rest and delta share the same exponent e, it suffices to
  17503         // compare the significands.
  17504         const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
  17505         if (rest <= delta)
  17506         {
  17507             // V = buffer * 10^n, with M- <= V <= M+.
  17508 
  17509             decimal_exponent += n;
  17510 
  17511             // We may now just stop. But instead look if the buffer could be
  17512             // decremented to bring V closer to w.
  17513             //
  17514             // pow10 = 10^n is now 1 ulp in the decimal representation V.
  17515             // The rounding procedure works with diyfp's with an implicit
  17516             // exponent of e.
  17517             //
  17518             //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
  17519             //
  17520             const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
  17521             grisu2_round(buffer, length, dist, delta, rest, ten_n);
  17522 
  17523             return;
  17524         }
  17525 
  17526         pow10 /= 10;
  17527         //
  17528         //      pow10 = 10^(n-1) <= p1 < 10^n
  17529         // Invariants restored.
  17530     }
  17531 
  17532     // 2)
  17533     //
  17534     // The digits of the integral part have been generated:
  17535     //
  17536     //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
  17537     //         = buffer            + p2 * 2^e
  17538     //
  17539     // Now generate the digits of the fractional part p2 * 2^e.
  17540     //
  17541     // Note:
  17542     // No decimal point is generated: the exponent is adjusted instead.
  17543     //
  17544     // p2 actually represents the fraction
  17545     //
  17546     //      p2 * 2^e
  17547     //          = p2 / 2^-e
  17548     //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
  17549     //
  17550     // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
  17551     //
  17552     //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
  17553     //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
  17554     //
  17555     // using
  17556     //
  17557     //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
  17558     //                = (                   d) * 2^-e + (                   r)
  17559     //
  17560     // or
  17561     //      10^m * p2 * 2^e = d + r * 2^e
  17562     //
  17563     // i.e.
  17564     //
  17565     //      M+ = buffer + p2 * 2^e
  17566     //         = buffer + 10^-m * (d + r * 2^e)
  17567     //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
  17568     //
  17569     // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
  17570 
  17571     JSON_ASSERT(p2 > delta);
  17572 
  17573     int m = 0;
  17574     for (;;)
  17575     {
  17576         // Invariant:
  17577         //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
  17578         //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
  17579         //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
  17580         //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
  17581         //
  17582         JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
  17583         p2 *= 10;
  17584         const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
  17585         const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
  17586         //
  17587         //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
  17588         //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
  17589         //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
  17590         //
  17591         JSON_ASSERT(d <= 9);
  17592         buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
  17593         //
  17594         //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
  17595         //
  17596         p2 = r;
  17597         m++;
  17598         //
  17599         //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
  17600         // Invariant restored.
  17601 
  17602         // Check if enough digits have been generated.
  17603         //
  17604         //      10^-m * p2 * 2^e <= delta * 2^e
  17605         //              p2 * 2^e <= 10^m * delta * 2^e
  17606         //                    p2 <= 10^m * delta
  17607         delta *= 10;
  17608         dist  *= 10;
  17609         if (p2 <= delta)
  17610         {
  17611             break;
  17612         }
  17613     }
  17614 
  17615     // V = buffer * 10^-m, with M- <= V <= M+.
  17616 
  17617     decimal_exponent -= m;
  17618 
  17619     // 1 ulp in the decimal representation is now 10^-m.
  17620     // Since delta and dist are now scaled by 10^m, we need to do the
  17621     // same with ulp in order to keep the units in sync.
  17622     //
  17623     //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
  17624     //
  17625     const std::uint64_t ten_m = one.f;
  17626     grisu2_round(buffer, length, dist, delta, p2, ten_m);
  17627 
  17628     // By construction this algorithm generates the shortest possible decimal
  17629     // number (Loitsch, Theorem 6.2) which rounds back to w.
  17630     // For an input number of precision p, at least
  17631     //
  17632     //      N = 1 + ceil(p * log_10(2))
  17633     //
  17634     // decimal digits are sufficient to identify all binary floating-point
  17635     // numbers (Matula, "In-and-Out conversions").
  17636     // This implies that the algorithm does not produce more than N decimal
  17637     // digits.
  17638     //
  17639     //      N = 17 for p = 53 (IEEE double precision)
  17640     //      N = 9  for p = 24 (IEEE single precision)
  17641 }
  17642 
  17643 /*!
  17644 v = buf * 10^decimal_exponent
  17645 len is the length of the buffer (number of decimal digits)
  17646 The buffer must be large enough, i.e. >= max_digits10.
  17647 */
  17648 JSON_HEDLEY_NON_NULL(1)
  17649 inline void grisu2(char* buf, int& len, int& decimal_exponent,
  17650                    diyfp m_minus, diyfp v, diyfp m_plus)
  17651 {
  17652     JSON_ASSERT(m_plus.e == m_minus.e);
  17653     JSON_ASSERT(m_plus.e == v.e);
  17654 
  17655     //  --------(-----------------------+-----------------------)--------    (A)
  17656     //          m-                      v                       m+
  17657     //
  17658     //  --------------------(-----------+-----------------------)--------    (B)
  17659     //                      m-          v                       m+
  17660     //
  17661     // First scale v (and m- and m+) such that the exponent is in the range
  17662     // [alpha, gamma].
  17663 
  17664     const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
  17665 
  17666     const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
  17667 
  17668     // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
  17669     const diyfp w       = diyfp::mul(v,       c_minus_k);
  17670     const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
  17671     const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
  17672 
  17673     //  ----(---+---)---------------(---+---)---------------(---+---)----
  17674     //          w-                      w                       w+
  17675     //          = c*m-                  = c*v                   = c*m+
  17676     //
  17677     // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
  17678     // w+ are now off by a small amount.
  17679     // In fact:
  17680     //
  17681     //      w - v * 10^k < 1 ulp
  17682     //
  17683     // To account for this inaccuracy, add resp. subtract 1 ulp.
  17684     //
  17685     //  --------+---[---------------(---+---)---------------]---+--------
  17686     //          w-  M-                  w                   M+  w+
  17687     //
  17688     // Now any number in [M-, M+] (bounds included) will round to w when input,
  17689     // regardless of how the input rounding algorithm breaks ties.
  17690     //
  17691     // And digit_gen generates the shortest possible such number in [M-, M+].
  17692     // Note that this does not mean that Grisu2 always generates the shortest
  17693     // possible number in the interval (m-, m+).
  17694     const diyfp M_minus(w_minus.f + 1, w_minus.e);
  17695     const diyfp M_plus (w_plus.f  - 1, w_plus.e );
  17696 
  17697     decimal_exponent = -cached.k; // = -(-k) = k
  17698 
  17699     grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
  17700 }
  17701 
  17702 /*!
  17703 v = buf * 10^decimal_exponent
  17704 len is the length of the buffer (number of decimal digits)
  17705 The buffer must be large enough, i.e. >= max_digits10.
  17706 */
  17707 template<typename FloatType>
  17708 JSON_HEDLEY_NON_NULL(1)
  17709 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
  17710 {
  17711     static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
  17712                   "internal error: not enough precision");
  17713 
  17714     JSON_ASSERT(std::isfinite(value));
  17715     JSON_ASSERT(value > 0);
  17716 
  17717     // If the neighbors (and boundaries) of 'value' are always computed for double-precision
  17718     // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
  17719     // decimal representations are not exactly "short".
  17720     //
  17721     // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
  17722     // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
  17723     // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
  17724     // does.
  17725     // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
  17726     // representation using the corresponding std::from_chars function recovers value exactly". That
  17727     // indicates that single precision floating-point numbers should be recovered using
  17728     // 'std::strtof'.
  17729     //
  17730     // NB: If the neighbors are computed for single-precision numbers, there is a single float
  17731     //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
  17732     //     value is off by 1 ulp.
  17733 #if 0
  17734     const boundaries w = compute_boundaries(static_cast<double>(value));
  17735 #else
  17736     const boundaries w = compute_boundaries(value);
  17737 #endif
  17738 
  17739     grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
  17740 }
  17741 
  17742 /*!
  17743 @brief appends a decimal representation of e to buf
  17744 @return a pointer to the element following the exponent.
  17745 @pre -1000 < e < 1000
  17746 */
  17747 JSON_HEDLEY_NON_NULL(1)
  17748 JSON_HEDLEY_RETURNS_NON_NULL
  17749 inline char* append_exponent(char* buf, int e)
  17750 {
  17751     JSON_ASSERT(e > -1000);
  17752     JSON_ASSERT(e <  1000);
  17753 
  17754     if (e < 0)
  17755     {
  17756         e = -e;
  17757         *buf++ = '-';
  17758     }
  17759     else
  17760     {
  17761         *buf++ = '+';
  17762     }
  17763 
  17764     auto k = static_cast<std::uint32_t>(e);
  17765     if (k < 10)
  17766     {
  17767         // Always print at least two digits in the exponent.
  17768         // This is for compatibility with printf("%g").
  17769         *buf++ = '0';
  17770         *buf++ = static_cast<char>('0' + k);
  17771     }
  17772     else if (k < 100)
  17773     {
  17774         *buf++ = static_cast<char>('0' + k / 10);
  17775         k %= 10;
  17776         *buf++ = static_cast<char>('0' + k);
  17777     }
  17778     else
  17779     {
  17780         *buf++ = static_cast<char>('0' + k / 100);
  17781         k %= 100;
  17782         *buf++ = static_cast<char>('0' + k / 10);
  17783         k %= 10;
  17784         *buf++ = static_cast<char>('0' + k);
  17785     }
  17786 
  17787     return buf;
  17788 }
  17789 
  17790 /*!
  17791 @brief prettify v = buf * 10^decimal_exponent
  17792 
  17793 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
  17794 notation. Otherwise it will be printed in exponential notation.
  17795 
  17796 @pre min_exp < 0
  17797 @pre max_exp > 0
  17798 */
  17799 JSON_HEDLEY_NON_NULL(1)
  17800 JSON_HEDLEY_RETURNS_NON_NULL
  17801 inline char* format_buffer(char* buf, int len, int decimal_exponent,
  17802                            int min_exp, int max_exp)
  17803 {
  17804     JSON_ASSERT(min_exp < 0);
  17805     JSON_ASSERT(max_exp > 0);
  17806 
  17807     const int k = len;
  17808     const int n = len + decimal_exponent;
  17809 
  17810     // v = buf * 10^(n-k)
  17811     // k is the length of the buffer (number of decimal digits)
  17812     // n is the position of the decimal point relative to the start of the buffer.
  17813 
  17814     if (k <= n && n <= max_exp)
  17815     {
  17816         // digits[000]
  17817         // len <= max_exp + 2
  17818 
  17819         std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
  17820         // Make it look like a floating-point number (#362, #378)
  17821         buf[n + 0] = '.';
  17822         buf[n + 1] = '0';
  17823         return buf + (static_cast<size_t>(n) + 2);
  17824     }
  17825 
  17826     if (0 < n && n <= max_exp)
  17827     {
  17828         // dig.its
  17829         // len <= max_digits10 + 1
  17830 
  17831         JSON_ASSERT(k > n);
  17832 
  17833         std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
  17834         buf[n] = '.';
  17835         return buf + (static_cast<size_t>(k) + 1U);
  17836     }
  17837 
  17838     if (min_exp < n && n <= 0)
  17839     {
  17840         // 0.[000]digits
  17841         // len <= 2 + (-min_exp - 1) + max_digits10
  17842 
  17843         std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
  17844         buf[0] = '0';
  17845         buf[1] = '.';
  17846         std::memset(buf + 2, '0', static_cast<size_t>(-n));
  17847         return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
  17848     }
  17849 
  17850     if (k == 1)
  17851     {
  17852         // dE+123
  17853         // len <= 1 + 5
  17854 
  17855         buf += 1;
  17856     }
  17857     else
  17858     {
  17859         // d.igitsE+123
  17860         // len <= max_digits10 + 1 + 5
  17861 
  17862         std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
  17863         buf[1] = '.';
  17864         buf += 1 + static_cast<size_t>(k);
  17865     }
  17866 
  17867     *buf++ = 'e';
  17868     return append_exponent(buf, n - 1);
  17869 }
  17870 
  17871 }  // namespace dtoa_impl
  17872 
  17873 /*!
  17874 @brief generates a decimal representation of the floating-point number value in [first, last).
  17875 
  17876 The format of the resulting decimal representation is similar to printf's %g
  17877 format. Returns an iterator pointing past-the-end of the decimal representation.
  17878 
  17879 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
  17880 @note The buffer must be large enough.
  17881 @note The result is NOT null-terminated.
  17882 */
  17883 template<typename FloatType>
  17884 JSON_HEDLEY_NON_NULL(1, 2)
  17885 JSON_HEDLEY_RETURNS_NON_NULL
  17886 char* to_chars(char* first, const char* last, FloatType value)
  17887 {
  17888     static_cast<void>(last); // maybe unused - fix warning
  17889     JSON_ASSERT(std::isfinite(value));
  17890 
  17891     // Use signbit(value) instead of (value < 0) since signbit works for -0.
  17892     if (std::signbit(value))
  17893     {
  17894         value = -value;
  17895         *first++ = '-';
  17896     }
  17897 
  17898 #ifdef __GNUC__
  17899 #pragma GCC diagnostic push
  17900 #pragma GCC diagnostic ignored "-Wfloat-equal"
  17901 #endif
  17902     if (value == 0) // +-0
  17903     {
  17904         *first++ = '0';
  17905         // Make it look like a floating-point number (#362, #378)
  17906         *first++ = '.';
  17907         *first++ = '0';
  17908         return first;
  17909     }
  17910 #ifdef __GNUC__
  17911 #pragma GCC diagnostic pop
  17912 #endif
  17913 
  17914     JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
  17915 
  17916     // Compute v = buffer * 10^decimal_exponent.
  17917     // The decimal digits are stored in the buffer, which needs to be interpreted
  17918     // as an unsigned decimal integer.
  17919     // len is the length of the buffer, i.e. the number of decimal digits.
  17920     int len = 0;
  17921     int decimal_exponent = 0;
  17922     dtoa_impl::grisu2(first, len, decimal_exponent, value);
  17923 
  17924     JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
  17925 
  17926     // Format the buffer like printf("%.*g", prec, value)
  17927     constexpr int kMinExp = -4;
  17928     // Use digits10 here to increase compatibility with version 2.
  17929     constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
  17930 
  17931     JSON_ASSERT(last - first >= kMaxExp + 2);
  17932     JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
  17933     JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
  17934 
  17935     return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
  17936 }
  17937 
  17938 }  // namespace detail
  17939 NLOHMANN_JSON_NAMESPACE_END
  17940 
  17941 // #include <nlohmann/detail/exceptions.hpp>
  17942 
  17943 // #include <nlohmann/detail/macro_scope.hpp>
  17944 
  17945 // #include <nlohmann/detail/meta/cpp_future.hpp>
  17946 
  17947 // #include <nlohmann/detail/output/binary_writer.hpp>
  17948 
  17949 // #include <nlohmann/detail/output/output_adapters.hpp>
  17950 
  17951 // #include <nlohmann/detail/string_concat.hpp>
  17952 
  17953 // #include <nlohmann/detail/value_t.hpp>
  17954 
  17955 
  17956 NLOHMANN_JSON_NAMESPACE_BEGIN
  17957 namespace detail
  17958 {
  17959 
  17960 ///////////////////
  17961 // serialization //
  17962 ///////////////////
  17963 
  17964 /// how to treat decoding errors
  17965 enum class error_handler_t
  17966 {
  17967     strict,  ///< throw a type_error exception in case of invalid UTF-8
  17968     replace, ///< replace invalid UTF-8 sequences with U+FFFD
  17969     ignore   ///< ignore invalid UTF-8 sequences
  17970 };
  17971 
  17972 template<typename BasicJsonType>
  17973 class serializer
  17974 {
  17975     using string_t = typename BasicJsonType::string_t;
  17976     using number_float_t = typename BasicJsonType::number_float_t;
  17977     using number_integer_t = typename BasicJsonType::number_integer_t;
  17978     using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  17979     using binary_char_t = typename BasicJsonType::binary_t::value_type;
  17980     static constexpr std::uint8_t UTF8_ACCEPT = 0;
  17981     static constexpr std::uint8_t UTF8_REJECT = 1;
  17982 
  17983   public:
  17984     /*!
  17985     @param[in] s  output stream to serialize to
  17986     @param[in] ichar  indentation character to use
  17987     @param[in] error_handler_  how to react on decoding errors
  17988     */
  17989     serializer(output_adapter_t<char> s, const char ichar,
  17990                error_handler_t error_handler_ = error_handler_t::strict)
  17991         : o(std::move(s))
  17992         , loc(std::localeconv())
  17993         , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
  17994         , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
  17995         , indent_char(ichar)
  17996         , indent_string(512, indent_char)
  17997         , error_handler(error_handler_)
  17998     {}
  17999 
  18000     // delete because of pointer members
  18001     serializer(const serializer&) = delete;
  18002     serializer& operator=(const serializer&) = delete;
  18003     serializer(serializer&&) = delete;
  18004     serializer& operator=(serializer&&) = delete;
  18005     ~serializer() = default;
  18006 
  18007     /*!
  18008     @brief internal implementation of the serialization function
  18009 
  18010     This function is called by the public member function dump and organizes
  18011     the serialization internally. The indentation level is propagated as
  18012     additional parameter. In case of arrays and objects, the function is
  18013     called recursively.
  18014 
  18015     - strings and object keys are escaped using `escape_string()`
  18016     - integer numbers are converted implicitly via `operator<<`
  18017     - floating-point numbers are converted to a string using `"%g"` format
  18018     - binary values are serialized as objects containing the subtype and the
  18019       byte array
  18020 
  18021     @param[in] val               value to serialize
  18022     @param[in] pretty_print      whether the output shall be pretty-printed
  18023     @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
  18024     in the output are escaped with `\uXXXX` sequences, and the result consists
  18025     of ASCII characters only.
  18026     @param[in] indent_step       the indent level
  18027     @param[in] current_indent    the current indent level (only used internally)
  18028     */
  18029     void dump(const BasicJsonType& val,
  18030               const bool pretty_print,
  18031               const bool ensure_ascii,
  18032               const unsigned int indent_step,
  18033               const unsigned int current_indent = 0)
  18034     {
  18035         switch (val.m_type)
  18036         {
  18037             case value_t::object:
  18038             {
  18039                 if (val.m_value.object->empty())
  18040                 {
  18041                     o->write_characters("{}", 2);
  18042                     return;
  18043                 }
  18044 
  18045                 if (pretty_print)
  18046                 {
  18047                     o->write_characters("{\n", 2);
  18048 
  18049                     // variable to hold indentation for recursive calls
  18050                     const auto new_indent = current_indent + indent_step;
  18051                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  18052                     {
  18053                         indent_string.resize(indent_string.size() * 2, ' ');
  18054                     }
  18055 
  18056                     // first n-1 elements
  18057                     auto i = val.m_value.object->cbegin();
  18058                     for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
  18059                     {
  18060                         o->write_characters(indent_string.c_str(), new_indent);
  18061                         o->write_character('\"');
  18062                         dump_escaped(i->first, ensure_ascii);
  18063                         o->write_characters("\": ", 3);
  18064                         dump(i->second, true, ensure_ascii, indent_step, new_indent);
  18065                         o->write_characters(",\n", 2);
  18066                     }
  18067 
  18068                     // last element
  18069                     JSON_ASSERT(i != val.m_value.object->cend());
  18070                     JSON_ASSERT(std::next(i) == val.m_value.object->cend());
  18071                     o->write_characters(indent_string.c_str(), new_indent);
  18072                     o->write_character('\"');
  18073                     dump_escaped(i->first, ensure_ascii);
  18074                     o->write_characters("\": ", 3);
  18075                     dump(i->second, true, ensure_ascii, indent_step, new_indent);
  18076 
  18077                     o->write_character('\n');
  18078                     o->write_characters(indent_string.c_str(), current_indent);
  18079                     o->write_character('}');
  18080                 }
  18081                 else
  18082                 {
  18083                     o->write_character('{');
  18084 
  18085                     // first n-1 elements
  18086                     auto i = val.m_value.object->cbegin();
  18087                     for (std::size_t cnt = 0; cnt < val.m_value.object->size() - 1; ++cnt, ++i)
  18088                     {
  18089                         o->write_character('\"');
  18090                         dump_escaped(i->first, ensure_ascii);
  18091                         o->write_characters("\":", 2);
  18092                         dump(i->second, false, ensure_ascii, indent_step, current_indent);
  18093                         o->write_character(',');
  18094                     }
  18095 
  18096                     // last element
  18097                     JSON_ASSERT(i != val.m_value.object->cend());
  18098                     JSON_ASSERT(std::next(i) == val.m_value.object->cend());
  18099                     o->write_character('\"');
  18100                     dump_escaped(i->first, ensure_ascii);
  18101                     o->write_characters("\":", 2);
  18102                     dump(i->second, false, ensure_ascii, indent_step, current_indent);
  18103 
  18104                     o->write_character('}');
  18105                 }
  18106 
  18107                 return;
  18108             }
  18109 
  18110             case value_t::array:
  18111             {
  18112                 if (val.m_value.array->empty())
  18113                 {
  18114                     o->write_characters("[]", 2);
  18115                     return;
  18116                 }
  18117 
  18118                 if (pretty_print)
  18119                 {
  18120                     o->write_characters("[\n", 2);
  18121 
  18122                     // variable to hold indentation for recursive calls
  18123                     const auto new_indent = current_indent + indent_step;
  18124                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  18125                     {
  18126                         indent_string.resize(indent_string.size() * 2, ' ');
  18127                     }
  18128 
  18129                     // first n-1 elements
  18130                     for (auto i = val.m_value.array->cbegin();
  18131                             i != val.m_value.array->cend() - 1; ++i)
  18132                     {
  18133                         o->write_characters(indent_string.c_str(), new_indent);
  18134                         dump(*i, true, ensure_ascii, indent_step, new_indent);
  18135                         o->write_characters(",\n", 2);
  18136                     }
  18137 
  18138                     // last element
  18139                     JSON_ASSERT(!val.m_value.array->empty());
  18140                     o->write_characters(indent_string.c_str(), new_indent);
  18141                     dump(val.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
  18142 
  18143                     o->write_character('\n');
  18144                     o->write_characters(indent_string.c_str(), current_indent);
  18145                     o->write_character(']');
  18146                 }
  18147                 else
  18148                 {
  18149                     o->write_character('[');
  18150 
  18151                     // first n-1 elements
  18152                     for (auto i = val.m_value.array->cbegin();
  18153                             i != val.m_value.array->cend() - 1; ++i)
  18154                     {
  18155                         dump(*i, false, ensure_ascii, indent_step, current_indent);
  18156                         o->write_character(',');
  18157                     }
  18158 
  18159                     // last element
  18160                     JSON_ASSERT(!val.m_value.array->empty());
  18161                     dump(val.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
  18162 
  18163                     o->write_character(']');
  18164                 }
  18165 
  18166                 return;
  18167             }
  18168 
  18169             case value_t::string:
  18170             {
  18171                 o->write_character('\"');
  18172                 dump_escaped(*val.m_value.string, ensure_ascii);
  18173                 o->write_character('\"');
  18174                 return;
  18175             }
  18176 
  18177             case value_t::binary:
  18178             {
  18179                 if (pretty_print)
  18180                 {
  18181                     o->write_characters("{\n", 2);
  18182 
  18183                     // variable to hold indentation for recursive calls
  18184                     const auto new_indent = current_indent + indent_step;
  18185                     if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  18186                     {
  18187                         indent_string.resize(indent_string.size() * 2, ' ');
  18188                     }
  18189 
  18190                     o->write_characters(indent_string.c_str(), new_indent);
  18191 
  18192                     o->write_characters("\"bytes\": [", 10);
  18193 
  18194                     if (!val.m_value.binary->empty())
  18195                     {
  18196                         for (auto i = val.m_value.binary->cbegin();
  18197                                 i != val.m_value.binary->cend() - 1; ++i)
  18198                         {
  18199                             dump_integer(*i);
  18200                             o->write_characters(", ", 2);
  18201                         }
  18202                         dump_integer(val.m_value.binary->back());
  18203                     }
  18204 
  18205                     o->write_characters("],\n", 3);
  18206                     o->write_characters(indent_string.c_str(), new_indent);
  18207 
  18208                     o->write_characters("\"subtype\": ", 11);
  18209                     if (val.m_value.binary->has_subtype())
  18210                     {
  18211                         dump_integer(val.m_value.binary->subtype());
  18212                     }
  18213                     else
  18214                     {
  18215                         o->write_characters("null", 4);
  18216                     }
  18217                     o->write_character('\n');
  18218                     o->write_characters(indent_string.c_str(), current_indent);
  18219                     o->write_character('}');
  18220                 }
  18221                 else
  18222                 {
  18223                     o->write_characters("{\"bytes\":[", 10);
  18224 
  18225                     if (!val.m_value.binary->empty())
  18226                     {
  18227                         for (auto i = val.m_value.binary->cbegin();
  18228                                 i != val.m_value.binary->cend() - 1; ++i)
  18229                         {
  18230                             dump_integer(*i);
  18231                             o->write_character(',');
  18232                         }
  18233                         dump_integer(val.m_value.binary->back());
  18234                     }
  18235 
  18236                     o->write_characters("],\"subtype\":", 12);
  18237                     if (val.m_value.binary->has_subtype())
  18238                     {
  18239                         dump_integer(val.m_value.binary->subtype());
  18240                         o->write_character('}');
  18241                     }
  18242                     else
  18243                     {
  18244                         o->write_characters("null}", 5);
  18245                     }
  18246                 }
  18247                 return;
  18248             }
  18249 
  18250             case value_t::boolean:
  18251             {
  18252                 if (val.m_value.boolean)
  18253                 {
  18254                     o->write_characters("true", 4);
  18255                 }
  18256                 else
  18257                 {
  18258                     o->write_characters("false", 5);
  18259                 }
  18260                 return;
  18261             }
  18262 
  18263             case value_t::number_integer:
  18264             {
  18265                 dump_integer(val.m_value.number_integer);
  18266                 return;
  18267             }
  18268 
  18269             case value_t::number_unsigned:
  18270             {
  18271                 dump_integer(val.m_value.number_unsigned);
  18272                 return;
  18273             }
  18274 
  18275             case value_t::number_float:
  18276             {
  18277                 dump_float(val.m_value.number_float);
  18278                 return;
  18279             }
  18280 
  18281             case value_t::discarded:
  18282             {
  18283                 o->write_characters("<discarded>", 11);
  18284                 return;
  18285             }
  18286 
  18287             case value_t::null:
  18288             {
  18289                 o->write_characters("null", 4);
  18290                 return;
  18291             }
  18292 
  18293             default:            // LCOV_EXCL_LINE
  18294                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18295         }
  18296     }
  18297 
  18298   JSON_PRIVATE_UNLESS_TESTED:
  18299     /*!
  18300     @brief dump escaped string
  18301 
  18302     Escape a string by replacing certain special characters by a sequence of an
  18303     escape character (backslash) and another character and other control
  18304     characters by a sequence of "\u" followed by a four-digit hex
  18305     representation. The escaped string is written to output stream @a o.
  18306 
  18307     @param[in] s  the string to escape
  18308     @param[in] ensure_ascii  whether to escape non-ASCII characters with
  18309                              \uXXXX sequences
  18310 
  18311     @complexity Linear in the length of string @a s.
  18312     */
  18313     void dump_escaped(const string_t& s, const bool ensure_ascii)
  18314     {
  18315         std::uint32_t codepoint{};
  18316         std::uint8_t state = UTF8_ACCEPT;
  18317         std::size_t bytes = 0;  // number of bytes written to string_buffer
  18318 
  18319         // number of bytes written at the point of the last valid byte
  18320         std::size_t bytes_after_last_accept = 0;
  18321         std::size_t undumped_chars = 0;
  18322 
  18323         for (std::size_t i = 0; i < s.size(); ++i)
  18324         {
  18325             const auto byte = static_cast<std::uint8_t>(s[i]);
  18326 
  18327             switch (decode(state, codepoint, byte))
  18328             {
  18329                 case UTF8_ACCEPT:  // decode found a new code point
  18330                 {
  18331                     switch (codepoint)
  18332                     {
  18333                         case 0x08: // backspace
  18334                         {
  18335                             string_buffer[bytes++] = '\\';
  18336                             string_buffer[bytes++] = 'b';
  18337                             break;
  18338                         }
  18339 
  18340                         case 0x09: // horizontal tab
  18341                         {
  18342                             string_buffer[bytes++] = '\\';
  18343                             string_buffer[bytes++] = 't';
  18344                             break;
  18345                         }
  18346 
  18347                         case 0x0A: // newline
  18348                         {
  18349                             string_buffer[bytes++] = '\\';
  18350                             string_buffer[bytes++] = 'n';
  18351                             break;
  18352                         }
  18353 
  18354                         case 0x0C: // formfeed
  18355                         {
  18356                             string_buffer[bytes++] = '\\';
  18357                             string_buffer[bytes++] = 'f';
  18358                             break;
  18359                         }
  18360 
  18361                         case 0x0D: // carriage return
  18362                         {
  18363                             string_buffer[bytes++] = '\\';
  18364                             string_buffer[bytes++] = 'r';
  18365                             break;
  18366                         }
  18367 
  18368                         case 0x22: // quotation mark
  18369                         {
  18370                             string_buffer[bytes++] = '\\';
  18371                             string_buffer[bytes++] = '\"';
  18372                             break;
  18373                         }
  18374 
  18375                         case 0x5C: // reverse solidus
  18376                         {
  18377                             string_buffer[bytes++] = '\\';
  18378                             string_buffer[bytes++] = '\\';
  18379                             break;
  18380                         }
  18381 
  18382                         default:
  18383                         {
  18384                             // escape control characters (0x00..0x1F) or, if
  18385                             // ensure_ascii parameter is used, non-ASCII characters
  18386                             if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
  18387                             {
  18388                                 if (codepoint <= 0xFFFF)
  18389                                 {
  18390                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18391                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
  18392                                                                       static_cast<std::uint16_t>(codepoint)));
  18393                                     bytes += 6;
  18394                                 }
  18395                                 else
  18396                                 {
  18397                                     // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18398                                     static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
  18399                                                                       static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
  18400                                                                       static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
  18401                                     bytes += 12;
  18402                                 }
  18403                             }
  18404                             else
  18405                             {
  18406                                 // copy byte to buffer (all previous bytes
  18407                                 // been copied have in default case above)
  18408                                 string_buffer[bytes++] = s[i];
  18409                             }
  18410                             break;
  18411                         }
  18412                     }
  18413 
  18414                     // write buffer and reset index; there must be 13 bytes
  18415                     // left, as this is the maximal number of bytes to be
  18416                     // written ("\uxxxx\uxxxx\0") for one code point
  18417                     if (string_buffer.size() - bytes < 13)
  18418                     {
  18419                         o->write_characters(string_buffer.data(), bytes);
  18420                         bytes = 0;
  18421                     }
  18422 
  18423                     // remember the byte position of this accept
  18424                     bytes_after_last_accept = bytes;
  18425                     undumped_chars = 0;
  18426                     break;
  18427                 }
  18428 
  18429                 case UTF8_REJECT:  // decode found invalid UTF-8 byte
  18430                 {
  18431                     switch (error_handler)
  18432                     {
  18433                         case error_handler_t::strict:
  18434                         {
  18435                             JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
  18436                         }
  18437 
  18438                         case error_handler_t::ignore:
  18439                         case error_handler_t::replace:
  18440                         {
  18441                             // in case we saw this character the first time, we
  18442                             // would like to read it again, because the byte
  18443                             // may be OK for itself, but just not OK for the
  18444                             // previous sequence
  18445                             if (undumped_chars > 0)
  18446                             {
  18447                                 --i;
  18448                             }
  18449 
  18450                             // reset length buffer to the last accepted index;
  18451                             // thus removing/ignoring the invalid characters
  18452                             bytes = bytes_after_last_accept;
  18453 
  18454                             if (error_handler == error_handler_t::replace)
  18455                             {
  18456                                 // add a replacement character
  18457                                 if (ensure_ascii)
  18458                                 {
  18459                                     string_buffer[bytes++] = '\\';
  18460                                     string_buffer[bytes++] = 'u';
  18461                                     string_buffer[bytes++] = 'f';
  18462                                     string_buffer[bytes++] = 'f';
  18463                                     string_buffer[bytes++] = 'f';
  18464                                     string_buffer[bytes++] = 'd';
  18465                                 }
  18466                                 else
  18467                                 {
  18468                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
  18469                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
  18470                                     string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
  18471                                 }
  18472 
  18473                                 // write buffer and reset index; there must be 13 bytes
  18474                                 // left, as this is the maximal number of bytes to be
  18475                                 // written ("\uxxxx\uxxxx\0") for one code point
  18476                                 if (string_buffer.size() - bytes < 13)
  18477                                 {
  18478                                     o->write_characters(string_buffer.data(), bytes);
  18479                                     bytes = 0;
  18480                                 }
  18481 
  18482                                 bytes_after_last_accept = bytes;
  18483                             }
  18484 
  18485                             undumped_chars = 0;
  18486 
  18487                             // continue processing the string
  18488                             state = UTF8_ACCEPT;
  18489                             break;
  18490                         }
  18491 
  18492                         default:            // LCOV_EXCL_LINE
  18493                             JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18494                     }
  18495                     break;
  18496                 }
  18497 
  18498                 default:  // decode found yet incomplete multi-byte code point
  18499                 {
  18500                     if (!ensure_ascii)
  18501                     {
  18502                         // code point will not be escaped - copy byte to buffer
  18503                         string_buffer[bytes++] = s[i];
  18504                     }
  18505                     ++undumped_chars;
  18506                     break;
  18507                 }
  18508             }
  18509         }
  18510 
  18511         // we finished processing the string
  18512         if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
  18513         {
  18514             // write buffer
  18515             if (bytes > 0)
  18516             {
  18517                 o->write_characters(string_buffer.data(), bytes);
  18518             }
  18519         }
  18520         else
  18521         {
  18522             // we finish reading, but do not accept: string was incomplete
  18523             switch (error_handler)
  18524             {
  18525                 case error_handler_t::strict:
  18526                 {
  18527                     JSON_THROW(type_error::create(316, concat("incomplete UTF-8 string; last byte: 0x", hex_bytes(static_cast<std::uint8_t>(s.back() | 0))), nullptr));
  18528                 }
  18529 
  18530                 case error_handler_t::ignore:
  18531                 {
  18532                     // write all accepted bytes
  18533                     o->write_characters(string_buffer.data(), bytes_after_last_accept);
  18534                     break;
  18535                 }
  18536 
  18537                 case error_handler_t::replace:
  18538                 {
  18539                     // write all accepted bytes
  18540                     o->write_characters(string_buffer.data(), bytes_after_last_accept);
  18541                     // add a replacement character
  18542                     if (ensure_ascii)
  18543                     {
  18544                         o->write_characters("\\ufffd", 6);
  18545                     }
  18546                     else
  18547                     {
  18548                         o->write_characters("\xEF\xBF\xBD", 3);
  18549                     }
  18550                     break;
  18551                 }
  18552 
  18553                 default:            // LCOV_EXCL_LINE
  18554                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18555             }
  18556         }
  18557     }
  18558 
  18559   private:
  18560     /*!
  18561     @brief count digits
  18562 
  18563     Count the number of decimal (base 10) digits for an input unsigned integer.
  18564 
  18565     @param[in] x  unsigned integer number to count its digits
  18566     @return    number of decimal digits
  18567     */
  18568     inline unsigned int count_digits(number_unsigned_t x) noexcept
  18569     {
  18570         unsigned int n_digits = 1;
  18571         for (;;)
  18572         {
  18573             if (x < 10)
  18574             {
  18575                 return n_digits;
  18576             }
  18577             if (x < 100)
  18578             {
  18579                 return n_digits + 1;
  18580             }
  18581             if (x < 1000)
  18582             {
  18583                 return n_digits + 2;
  18584             }
  18585             if (x < 10000)
  18586             {
  18587                 return n_digits + 3;
  18588             }
  18589             x = x / 10000u;
  18590             n_digits += 4;
  18591         }
  18592     }
  18593 
  18594     /*!
  18595      * @brief convert a byte to a uppercase hex representation
  18596      * @param[in] byte byte to represent
  18597      * @return representation ("00".."FF")
  18598      */
  18599     static std::string hex_bytes(std::uint8_t byte)
  18600     {
  18601         std::string result = "FF";
  18602         constexpr const char* nibble_to_hex = "0123456789ABCDEF";
  18603         result[0] = nibble_to_hex[byte / 16];
  18604         result[1] = nibble_to_hex[byte % 16];
  18605         return result;
  18606     }
  18607 
  18608     // templates to avoid warnings about useless casts
  18609     template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
  18610     bool is_negative_number(NumberType x)
  18611     {
  18612         return x < 0;
  18613     }
  18614 
  18615     template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
  18616     bool is_negative_number(NumberType /*unused*/)
  18617     {
  18618         return false;
  18619     }
  18620 
  18621     /*!
  18622     @brief dump an integer
  18623 
  18624     Dump a given integer to output stream @a o. Works internally with
  18625     @a number_buffer.
  18626 
  18627     @param[in] x  integer number (signed or unsigned) to dump
  18628     @tparam NumberType either @a number_integer_t or @a number_unsigned_t
  18629     */
  18630     template < typename NumberType, detail::enable_if_t <
  18631                    std::is_integral<NumberType>::value ||
  18632                    std::is_same<NumberType, number_unsigned_t>::value ||
  18633                    std::is_same<NumberType, number_integer_t>::value ||
  18634                    std::is_same<NumberType, binary_char_t>::value,
  18635                    int > = 0 >
  18636     void dump_integer(NumberType x)
  18637     {
  18638         static constexpr std::array<std::array<char, 2>, 100> digits_to_99
  18639         {
  18640             {
  18641                 {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
  18642                 {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
  18643                 {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
  18644                 {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
  18645                 {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
  18646                 {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
  18647                 {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
  18648                 {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
  18649                 {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
  18650                 {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
  18651             }
  18652         };
  18653 
  18654         // special case for "0"
  18655         if (x == 0)
  18656         {
  18657             o->write_character('0');
  18658             return;
  18659         }
  18660 
  18661         // use a pointer to fill the buffer
  18662         auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18663 
  18664         number_unsigned_t abs_value;
  18665 
  18666         unsigned int n_chars{};
  18667 
  18668         if (is_negative_number(x))
  18669         {
  18670             *buffer_ptr = '-';
  18671             abs_value = remove_sign(static_cast<number_integer_t>(x));
  18672 
  18673             // account one more byte for the minus sign
  18674             n_chars = 1 + count_digits(abs_value);
  18675         }
  18676         else
  18677         {
  18678             abs_value = static_cast<number_unsigned_t>(x);
  18679             n_chars = count_digits(abs_value);
  18680         }
  18681 
  18682         // spare 1 byte for '\0'
  18683         JSON_ASSERT(n_chars < number_buffer.size() - 1);
  18684 
  18685         // jump to the end to generate the string from backward,
  18686         // so we later avoid reversing the result
  18687         buffer_ptr += n_chars;
  18688 
  18689         // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
  18690         // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
  18691         while (abs_value >= 100)
  18692         {
  18693             const auto digits_index = static_cast<unsigned>((abs_value % 100));
  18694             abs_value /= 100;
  18695             *(--buffer_ptr) = digits_to_99[digits_index][1];
  18696             *(--buffer_ptr) = digits_to_99[digits_index][0];
  18697         }
  18698 
  18699         if (abs_value >= 10)
  18700         {
  18701             const auto digits_index = static_cast<unsigned>(abs_value);
  18702             *(--buffer_ptr) = digits_to_99[digits_index][1];
  18703             *(--buffer_ptr) = digits_to_99[digits_index][0];
  18704         }
  18705         else
  18706         {
  18707             *(--buffer_ptr) = static_cast<char>('0' + abs_value);
  18708         }
  18709 
  18710         o->write_characters(number_buffer.data(), n_chars);
  18711     }
  18712 
  18713     /*!
  18714     @brief dump a floating-point number
  18715 
  18716     Dump a given floating-point number to output stream @a o. Works internally
  18717     with @a number_buffer.
  18718 
  18719     @param[in] x  floating-point number to dump
  18720     */
  18721     void dump_float(number_float_t x)
  18722     {
  18723         // NaN / inf
  18724         if (!std::isfinite(x))
  18725         {
  18726             o->write_characters("null", 4);
  18727             return;
  18728         }
  18729 
  18730         // If number_float_t is an IEEE-754 single or double precision number,
  18731         // use the Grisu2 algorithm to produce short numbers which are
  18732         // guaranteed to round-trip, using strtof and strtod, resp.
  18733         //
  18734         // NB: The test below works if <long double> == <double>.
  18735         static constexpr bool is_ieee_single_or_double
  18736             = (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 24 && std::numeric_limits<number_float_t>::max_exponent == 128) ||
  18737               (std::numeric_limits<number_float_t>::is_iec559 && std::numeric_limits<number_float_t>::digits == 53 && std::numeric_limits<number_float_t>::max_exponent == 1024);
  18738 
  18739         dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
  18740     }
  18741 
  18742     void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
  18743     {
  18744         auto* begin = number_buffer.data();
  18745         auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
  18746 
  18747         o->write_characters(begin, static_cast<size_t>(end - begin));
  18748     }
  18749 
  18750     void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
  18751     {
  18752         // get number of digits for a float -> text -> float round-trip
  18753         static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
  18754 
  18755         // the actual conversion
  18756         // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18757         std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
  18758 
  18759         // negative value indicates an error
  18760         JSON_ASSERT(len > 0);
  18761         // check if buffer was large enough
  18762         JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
  18763 
  18764         // erase thousands separator
  18765         if (thousands_sep != '\0')
  18766         {
  18767             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
  18768             const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
  18769             std::fill(end, number_buffer.end(), '\0');
  18770             JSON_ASSERT((end - number_buffer.begin()) <= len);
  18771             len = (end - number_buffer.begin());
  18772         }
  18773 
  18774         // convert decimal point to '.'
  18775         if (decimal_point != '\0' && decimal_point != '.')
  18776         {
  18777             // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
  18778             const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
  18779             if (dec_pos != number_buffer.end())
  18780             {
  18781                 *dec_pos = '.';
  18782             }
  18783         }
  18784 
  18785         o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
  18786 
  18787         // determine if we need to append ".0"
  18788         const bool value_is_int_like =
  18789             std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
  18790                          [](char c)
  18791         {
  18792             return c == '.' || c == 'e';
  18793         });
  18794 
  18795         if (value_is_int_like)
  18796         {
  18797             o->write_characters(".0", 2);
  18798         }
  18799     }
  18800 
  18801     /*!
  18802     @brief check whether a string is UTF-8 encoded
  18803 
  18804     The function checks each byte of a string whether it is UTF-8 encoded. The
  18805     result of the check is stored in the @a state parameter. The function must
  18806     be called initially with state 0 (accept). State 1 means the string must
  18807     be rejected, because the current byte is not allowed. If the string is
  18808     completely processed, but the state is non-zero, the string ended
  18809     prematurely; that is, the last byte indicated more bytes should have
  18810     followed.
  18811 
  18812     @param[in,out] state  the state of the decoding
  18813     @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
  18814     @param[in] byte       next byte to decode
  18815     @return               new state
  18816 
  18817     @note The function has been edited: a std::array is used.
  18818 
  18819     @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  18820     @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
  18821     */
  18822     static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
  18823     {
  18824         static const std::array<std::uint8_t, 400> utf8d =
  18825         {
  18826             {
  18827                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 00..1F
  18828                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 20..3F
  18829                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40..5F
  18830                 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60..7F
  18831                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, 9, // 80..9F
  18832                 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, 7, // A0..BF
  18833                 8, 8, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, 2, // C0..DF
  18834                 0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
  18835                 0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
  18836                 0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
  18837                 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, // s1..s2
  18838                 1, 2, 1, 1, 1, 1, 1, 2, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, // s3..s4
  18839                 1, 2, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, // s5..s6
  18840                 1, 3, 1, 1, 1, 1, 1, 3, 1, 3, 1, 1, 1, 1, 1, 1, 1, 3, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1 // s7..s8
  18841             }
  18842         };
  18843 
  18844         JSON_ASSERT(byte < utf8d.size());
  18845         const std::uint8_t type = utf8d[byte];
  18846 
  18847         codep = (state != UTF8_ACCEPT)
  18848                 ? (byte & 0x3fu) | (codep << 6u)
  18849                 : (0xFFu >> type) & (byte);
  18850 
  18851         const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
  18852         JSON_ASSERT(index < utf8d.size());
  18853         state = utf8d[index];
  18854         return state;
  18855     }
  18856 
  18857     /*
  18858      * Overload to make the compiler happy while it is instantiating
  18859      * dump_integer for number_unsigned_t.
  18860      * Must never be called.
  18861      */
  18862     number_unsigned_t remove_sign(number_unsigned_t x)
  18863     {
  18864         JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18865         return x; // LCOV_EXCL_LINE
  18866     }
  18867 
  18868     /*
  18869      * Helper function for dump_integer
  18870      *
  18871      * This function takes a negative signed integer and returns its absolute
  18872      * value as unsigned integer. The plus/minus shuffling is necessary as we can
  18873      * not directly remove the sign of an arbitrary signed integer as the
  18874      * absolute values of INT_MIN and INT_MAX are usually not the same. See
  18875      * #1708 for details.
  18876      */
  18877     inline number_unsigned_t remove_sign(number_integer_t x) noexcept
  18878     {
  18879         JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
  18880         return static_cast<number_unsigned_t>(-(x + 1)) + 1;
  18881     }
  18882 
  18883   private:
  18884     /// the output of the serializer
  18885     output_adapter_t<char> o = nullptr;
  18886 
  18887     /// a (hopefully) large enough character buffer
  18888     std::array<char, 64> number_buffer{{}};
  18889 
  18890     /// the locale
  18891     const std::lconv* loc = nullptr;
  18892     /// the locale's thousand separator character
  18893     const char thousands_sep = '\0';
  18894     /// the locale's decimal point character
  18895     const char decimal_point = '\0';
  18896 
  18897     /// string buffer
  18898     std::array<char, 512> string_buffer{{}};
  18899 
  18900     /// the indentation character
  18901     const char indent_char;
  18902     /// the indentation string
  18903     string_t indent_string;
  18904 
  18905     /// error_handler how to react on decoding errors
  18906     const error_handler_t error_handler;
  18907 };
  18908 
  18909 }  // namespace detail
  18910 NLOHMANN_JSON_NAMESPACE_END
  18911 
  18912 // #include <nlohmann/detail/value_t.hpp>
  18913 
  18914 // #include <nlohmann/json_fwd.hpp>
  18915 
  18916 // #include <nlohmann/ordered_map.hpp>
  18917 //     __ _____ _____ _____
  18918 //  __|  |   __|     |   | |  JSON for Modern C++
  18919 // |  |  |__   |  |  | | | |  version 3.11.2
  18920 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  18921 //
  18922 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  18923 // SPDX-License-Identifier: MIT
  18924 
  18925 
  18926 
  18927 #include <functional> // equal_to, less
  18928 #include <initializer_list> // initializer_list
  18929 #include <iterator> // input_iterator_tag, iterator_traits
  18930 #include <memory> // allocator
  18931 #include <stdexcept> // for out_of_range
  18932 #include <type_traits> // enable_if, is_convertible
  18933 #include <utility> // pair
  18934 #include <vector> // vector
  18935 
  18936 // #include <nlohmann/detail/macro_scope.hpp>
  18937 
  18938 // #include <nlohmann/detail/meta/type_traits.hpp>
  18939 
  18940 
  18941 NLOHMANN_JSON_NAMESPACE_BEGIN
  18942 
  18943 /// ordered_map: a minimal map-like container that preserves insertion order
  18944 /// for use within nlohmann::basic_json<ordered_map>
  18945 template <class Key, class T, class IgnoredLess = std::less<Key>,
  18946           class Allocator = std::allocator<std::pair<const Key, T>>>
  18947                   struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
  18948 {
  18949     using key_type = Key;
  18950     using mapped_type = T;
  18951     using Container = std::vector<std::pair<const Key, T>, Allocator>;
  18952     using iterator = typename Container::iterator;
  18953     using const_iterator = typename Container::const_iterator;
  18954     using size_type = typename Container::size_type;
  18955     using value_type = typename Container::value_type;
  18956 #ifdef JSON_HAS_CPP_14
  18957     using key_compare = std::equal_to<>;
  18958 #else
  18959     using key_compare = std::equal_to<Key>;
  18960 #endif
  18961 
  18962     // Explicit constructors instead of `using Container::Container`
  18963     // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
  18964     ordered_map() noexcept(noexcept(Container())) : Container{} {}
  18965     explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
  18966     template <class It>
  18967     ordered_map(It first, It last, const Allocator& alloc = Allocator())
  18968         : Container{first, last, alloc} {}
  18969     ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
  18970         : Container{init, alloc} {}
  18971 
  18972     std::pair<iterator, bool> emplace(const key_type& key, T&& t)
  18973     {
  18974         for (auto it = this->begin(); it != this->end(); ++it)
  18975         {
  18976             if (m_compare(it->first, key))
  18977             {
  18978                 return {it, false};
  18979             }
  18980         }
  18981         Container::emplace_back(key, std::forward<T>(t));
  18982         return {std::prev(this->end()), true};
  18983     }
  18984 
  18985     template<class KeyType, detail::enable_if_t<
  18986                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  18987     std::pair<iterator, bool> emplace(KeyType && key, T && t)
  18988     {
  18989         for (auto it = this->begin(); it != this->end(); ++it)
  18990         {
  18991             if (m_compare(it->first, key))
  18992             {
  18993                 return {it, false};
  18994             }
  18995         }
  18996         Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
  18997         return {std::prev(this->end()), true};
  18998     }
  18999 
  19000     T& operator[](const key_type& key)
  19001     {
  19002         return emplace(key, T{}).first->second;
  19003     }
  19004 
  19005     template<class KeyType, detail::enable_if_t<
  19006                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19007     T & operator[](KeyType && key)
  19008     {
  19009         return emplace(std::forward<KeyType>(key), T{}).first->second;
  19010     }
  19011 
  19012     const T& operator[](const key_type& key) const
  19013     {
  19014         return at(key);
  19015     }
  19016 
  19017     template<class KeyType, detail::enable_if_t<
  19018                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19019     const T & operator[](KeyType && key) const
  19020     {
  19021         return at(std::forward<KeyType>(key));
  19022     }
  19023 
  19024     T& at(const key_type& key)
  19025     {
  19026         for (auto it = this->begin(); it != this->end(); ++it)
  19027         {
  19028             if (m_compare(it->first, key))
  19029             {
  19030                 return it->second;
  19031             }
  19032         }
  19033 
  19034         JSON_THROW(std::out_of_range("key not found"));
  19035     }
  19036 
  19037     template<class KeyType, detail::enable_if_t<
  19038                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19039     T & at(KeyType && key)
  19040     {
  19041         for (auto it = this->begin(); it != this->end(); ++it)
  19042         {
  19043             if (m_compare(it->first, key))
  19044             {
  19045                 return it->second;
  19046             }
  19047         }
  19048 
  19049         JSON_THROW(std::out_of_range("key not found"));
  19050     }
  19051 
  19052     const T& at(const key_type& key) const
  19053     {
  19054         for (auto it = this->begin(); it != this->end(); ++it)
  19055         {
  19056             if (m_compare(it->first, key))
  19057             {
  19058                 return it->second;
  19059             }
  19060         }
  19061 
  19062         JSON_THROW(std::out_of_range("key not found"));
  19063     }
  19064 
  19065     template<class KeyType, detail::enable_if_t<
  19066                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19067     const T & at(KeyType && key) const
  19068     {
  19069         for (auto it = this->begin(); it != this->end(); ++it)
  19070         {
  19071             if (m_compare(it->first, key))
  19072             {
  19073                 return it->second;
  19074             }
  19075         }
  19076 
  19077         JSON_THROW(std::out_of_range("key not found"));
  19078     }
  19079 
  19080     size_type erase(const key_type& key)
  19081     {
  19082         for (auto it = this->begin(); it != this->end(); ++it)
  19083         {
  19084             if (m_compare(it->first, key))
  19085             {
  19086                 // Since we cannot move const Keys, re-construct them in place
  19087                 for (auto next = it; ++next != this->end(); ++it)
  19088                 {
  19089                     it->~value_type(); // Destroy but keep allocation
  19090                     new (&*it) value_type{std::move(*next)};
  19091                 }
  19092                 Container::pop_back();
  19093                 return 1;
  19094             }
  19095         }
  19096         return 0;
  19097     }
  19098 
  19099     template<class KeyType, detail::enable_if_t<
  19100                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19101     size_type erase(KeyType && key)
  19102     {
  19103         for (auto it = this->begin(); it != this->end(); ++it)
  19104         {
  19105             if (m_compare(it->first, key))
  19106             {
  19107                 // Since we cannot move const Keys, re-construct them in place
  19108                 for (auto next = it; ++next != this->end(); ++it)
  19109                 {
  19110                     it->~value_type(); // Destroy but keep allocation
  19111                     new (&*it) value_type{std::move(*next)};
  19112                 }
  19113                 Container::pop_back();
  19114                 return 1;
  19115             }
  19116         }
  19117         return 0;
  19118     }
  19119 
  19120     iterator erase(iterator pos)
  19121     {
  19122         return erase(pos, std::next(pos));
  19123     }
  19124 
  19125     iterator erase(iterator first, iterator last)
  19126     {
  19127         if (first == last)
  19128         {
  19129             return first;
  19130         }
  19131 
  19132         const auto elements_affected = std::distance(first, last);
  19133         const auto offset = std::distance(Container::begin(), first);
  19134 
  19135         // This is the start situation. We need to delete elements_affected
  19136         // elements (3 in this example: e, f, g), and need to return an
  19137         // iterator past the last deleted element (h in this example).
  19138         // Note that offset is the distance from the start of the vector
  19139         // to first. We will need this later.
  19140 
  19141         // [ a, b, c, d, e, f, g, h, i, j ]
  19142         //               ^        ^
  19143         //             first    last
  19144 
  19145         // Since we cannot move const Keys, we re-construct them in place.
  19146         // We start at first and re-construct (viz. copy) the elements from
  19147         // the back of the vector. Example for first iteration:
  19148 
  19149         //               ,--------.
  19150         //               v        |   destroy e and re-construct with h
  19151         // [ a, b, c, d, e, f, g, h, i, j ]
  19152         //               ^        ^
  19153         //               it       it + elements_affected
  19154 
  19155         for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
  19156         {
  19157             it->~value_type(); // destroy but keep allocation
  19158             new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
  19159         }
  19160 
  19161         // [ a, b, c, d, h, i, j, h, i, j ]
  19162         //               ^        ^
  19163         //             first    last
  19164 
  19165         // remove the unneeded elements at the end of the vector
  19166         Container::resize(this->size() - static_cast<size_type>(elements_affected));
  19167 
  19168         // [ a, b, c, d, h, i, j ]
  19169         //               ^        ^
  19170         //             first    last
  19171 
  19172         // first is now pointing past the last deleted element, but we cannot
  19173         // use this iterator, because it may have been invalidated by the
  19174         // resize call. Instead, we can return begin() + offset.
  19175         return Container::begin() + offset;
  19176     }
  19177 
  19178     size_type count(const key_type& key) const
  19179     {
  19180         for (auto it = this->begin(); it != this->end(); ++it)
  19181         {
  19182             if (m_compare(it->first, key))
  19183             {
  19184                 return 1;
  19185             }
  19186         }
  19187         return 0;
  19188     }
  19189 
  19190     template<class KeyType, detail::enable_if_t<
  19191                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19192     size_type count(KeyType && key) const
  19193     {
  19194         for (auto it = this->begin(); it != this->end(); ++it)
  19195         {
  19196             if (m_compare(it->first, key))
  19197             {
  19198                 return 1;
  19199             }
  19200         }
  19201         return 0;
  19202     }
  19203 
  19204     iterator find(const key_type& key)
  19205     {
  19206         for (auto it = this->begin(); it != this->end(); ++it)
  19207         {
  19208             if (m_compare(it->first, key))
  19209             {
  19210                 return it;
  19211             }
  19212         }
  19213         return Container::end();
  19214     }
  19215 
  19216     template<class KeyType, detail::enable_if_t<
  19217                  detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19218     iterator find(KeyType && key)
  19219     {
  19220         for (auto it = this->begin(); it != this->end(); ++it)
  19221         {
  19222             if (m_compare(it->first, key))
  19223             {
  19224                 return it;
  19225             }
  19226         }
  19227         return Container::end();
  19228     }
  19229 
  19230     const_iterator find(const key_type& key) const
  19231     {
  19232         for (auto it = this->begin(); it != this->end(); ++it)
  19233         {
  19234             if (m_compare(it->first, key))
  19235             {
  19236                 return it;
  19237             }
  19238         }
  19239         return Container::end();
  19240     }
  19241 
  19242     std::pair<iterator, bool> insert( value_type&& value )
  19243     {
  19244         return emplace(value.first, std::move(value.second));
  19245     }
  19246 
  19247     std::pair<iterator, bool> insert( const value_type& value )
  19248     {
  19249         for (auto it = this->begin(); it != this->end(); ++it)
  19250         {
  19251             if (m_compare(it->first, value.first))
  19252             {
  19253                 return {it, false};
  19254             }
  19255         }
  19256         Container::push_back(value);
  19257         return {--this->end(), true};
  19258     }
  19259 
  19260     template<typename InputIt>
  19261     using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
  19262             std::input_iterator_tag>::value>::type;
  19263 
  19264     template<typename InputIt, typename = require_input_iter<InputIt>>
  19265     void insert(InputIt first, InputIt last)
  19266     {
  19267         for (auto it = first; it != last; ++it)
  19268         {
  19269             insert(*it);
  19270         }
  19271     }
  19272 
  19273 private:
  19274     JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
  19275 };
  19276 
  19277 NLOHMANN_JSON_NAMESPACE_END
  19278 
  19279 
  19280 #if defined(JSON_HAS_CPP_17)
  19281     #include <any>
  19282     #include <string_view>
  19283 #endif
  19284 
  19285 /*!
  19286 @brief namespace for Niels Lohmann
  19287 @see https://github.com/nlohmann
  19288 @since version 1.0.0
  19289 */
  19290 NLOHMANN_JSON_NAMESPACE_BEGIN
  19291 
  19292 /*!
  19293 @brief a class to store JSON values
  19294 
  19295 @internal
  19296 @invariant The member variables @a m_value and @a m_type have the following
  19297 relationship:
  19298 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
  19299 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
  19300 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
  19301 The invariants are checked by member function assert_invariant().
  19302 
  19303 @note ObjectType trick from https://stackoverflow.com/a/9860911
  19304 @endinternal
  19305 
  19306 @since version 1.0.0
  19307 
  19308 @nosubgrouping
  19309 */
  19310 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  19311 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
  19312     : public ::nlohmann::detail::json_base_class<CustomBaseClass>
  19313 {
  19314   private:
  19315     template<detail::value_t> friend struct detail::external_constructor;
  19316 
  19317     template<typename>
  19318     friend class ::nlohmann::json_pointer;
  19319     // can be restored when json_pointer backwards compatibility is removed
  19320     // friend ::nlohmann::json_pointer<StringType>;
  19321 
  19322     template<typename BasicJsonType, typename InputType>
  19323     friend class ::nlohmann::detail::parser;
  19324     friend ::nlohmann::detail::serializer<basic_json>;
  19325     template<typename BasicJsonType>
  19326     friend class ::nlohmann::detail::iter_impl;
  19327     template<typename BasicJsonType, typename CharType>
  19328     friend class ::nlohmann::detail::binary_writer;
  19329     template<typename BasicJsonType, typename InputType, typename SAX>
  19330     friend class ::nlohmann::detail::binary_reader;
  19331     template<typename BasicJsonType>
  19332     friend class ::nlohmann::detail::json_sax_dom_parser;
  19333     template<typename BasicJsonType>
  19334     friend class ::nlohmann::detail::json_sax_dom_callback_parser;
  19335     friend class ::nlohmann::detail::exception;
  19336 
  19337     /// workaround type for MSVC
  19338     using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
  19339     using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
  19340 
  19341   JSON_PRIVATE_UNLESS_TESTED:
  19342     // convenience aliases for types residing in namespace detail;
  19343     using lexer = ::nlohmann::detail::lexer_base<basic_json>;
  19344 
  19345     template<typename InputAdapterType>
  19346     static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
  19347         InputAdapterType adapter,
  19348         detail::parser_callback_t<basic_json>cb = nullptr,
  19349         const bool allow_exceptions = true,
  19350         const bool ignore_comments = false
  19351                                  )
  19352     {
  19353         return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
  19354                 std::move(cb), allow_exceptions, ignore_comments);
  19355     }
  19356 
  19357   private:
  19358     using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
  19359     template<typename BasicJsonType>
  19360     using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
  19361     template<typename BasicJsonType>
  19362     using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
  19363     template<typename Iterator>
  19364     using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
  19365     template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
  19366 
  19367     template<typename CharType>
  19368     using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
  19369 
  19370     template<typename InputType>
  19371     using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
  19372     template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
  19373 
  19374   JSON_PRIVATE_UNLESS_TESTED:
  19375     using serializer = ::nlohmann::detail::serializer<basic_json>;
  19376 
  19377   public:
  19378     using value_t = detail::value_t;
  19379     /// JSON Pointer, see @ref nlohmann::json_pointer
  19380     using json_pointer = ::nlohmann::json_pointer<StringType>;
  19381     template<typename T, typename SFINAE>
  19382     using json_serializer = JSONSerializer<T, SFINAE>;
  19383     /// how to treat decoding errors
  19384     using error_handler_t = detail::error_handler_t;
  19385     /// how to treat CBOR tags
  19386     using cbor_tag_handler_t = detail::cbor_tag_handler_t;
  19387     /// helper type for initializer lists of basic_json values
  19388     using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
  19389 
  19390     using input_format_t = detail::input_format_t;
  19391     /// SAX interface type, see @ref nlohmann::json_sax
  19392     using json_sax_t = json_sax<basic_json>;
  19393 
  19394     ////////////////
  19395     // exceptions //
  19396     ////////////////
  19397 
  19398     /// @name exceptions
  19399     /// Classes to implement user-defined exceptions.
  19400     /// @{
  19401 
  19402     using exception = detail::exception;
  19403     using parse_error = detail::parse_error;
  19404     using invalid_iterator = detail::invalid_iterator;
  19405     using type_error = detail::type_error;
  19406     using out_of_range = detail::out_of_range;
  19407     using other_error = detail::other_error;
  19408 
  19409     /// @}
  19410 
  19411 
  19412     /////////////////////
  19413     // container types //
  19414     /////////////////////
  19415 
  19416     /// @name container types
  19417     /// The canonic container types to use @ref basic_json like any other STL
  19418     /// container.
  19419     /// @{
  19420 
  19421     /// the type of elements in a basic_json container
  19422     using value_type = basic_json;
  19423 
  19424     /// the type of an element reference
  19425     using reference = value_type&;
  19426     /// the type of an element const reference
  19427     using const_reference = const value_type&;
  19428 
  19429     /// a type to represent differences between iterators
  19430     using difference_type = std::ptrdiff_t;
  19431     /// a type to represent container sizes
  19432     using size_type = std::size_t;
  19433 
  19434     /// the allocator type
  19435     using allocator_type = AllocatorType<basic_json>;
  19436 
  19437     /// the type of an element pointer
  19438     using pointer = typename std::allocator_traits<allocator_type>::pointer;
  19439     /// the type of an element const pointer
  19440     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
  19441 
  19442     /// an iterator for a basic_json container
  19443     using iterator = iter_impl<basic_json>;
  19444     /// a const iterator for a basic_json container
  19445     using const_iterator = iter_impl<const basic_json>;
  19446     /// a reverse iterator for a basic_json container
  19447     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
  19448     /// a const reverse iterator for a basic_json container
  19449     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
  19450 
  19451     /// @}
  19452 
  19453 
  19454     /// @brief returns the allocator associated with the container
  19455     /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
  19456     static allocator_type get_allocator()
  19457     {
  19458         return allocator_type();
  19459     }
  19460 
  19461     /// @brief returns version information on the library
  19462     /// @sa https://json.nlohmann.me/api/basic_json/meta/
  19463     JSON_HEDLEY_WARN_UNUSED_RESULT
  19464     static basic_json meta()
  19465     {
  19466         basic_json result;
  19467 
  19468         result["copyright"] = "(C) 2013-2022 Niels Lohmann";
  19469         result["name"] = "JSON for Modern C++";
  19470         result["url"] = "https://github.com/nlohmann/json";
  19471         result["version"]["string"] =
  19472             detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
  19473                            std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
  19474                            std::to_string(NLOHMANN_JSON_VERSION_PATCH));
  19475         result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
  19476         result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
  19477         result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
  19478 
  19479 #ifdef _WIN32
  19480         result["platform"] = "win32";
  19481 #elif defined __linux__
  19482         result["platform"] = "linux";
  19483 #elif defined __APPLE__
  19484         result["platform"] = "apple";
  19485 #elif defined __unix__
  19486         result["platform"] = "unix";
  19487 #else
  19488         result["platform"] = "unknown";
  19489 #endif
  19490 
  19491 #if defined(__ICC) || defined(__INTEL_COMPILER)
  19492         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
  19493 #elif defined(__clang__)
  19494         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
  19495 #elif defined(__GNUC__) || defined(__GNUG__)
  19496         result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
  19497                     std::to_string(__GNUC__), '.',
  19498                     std::to_string(__GNUC_MINOR__), '.',
  19499                     std::to_string(__GNUC_PATCHLEVEL__))
  19500             }
  19501         };
  19502 #elif defined(__HP_cc) || defined(__HP_aCC)
  19503         result["compiler"] = "hp"
  19504 #elif defined(__IBMCPP__)
  19505         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
  19506 #elif defined(_MSC_VER)
  19507         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
  19508 #elif defined(__PGI)
  19509         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
  19510 #elif defined(__SUNPRO_CC)
  19511         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
  19512 #else
  19513         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
  19514 #endif
  19515 
  19516 
  19517 #if defined(_MSVC_LANG)
  19518         result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
  19519 #elif defined(__cplusplus)
  19520         result["compiler"]["c++"] = std::to_string(__cplusplus);
  19521 #else
  19522         result["compiler"]["c++"] = "unknown";
  19523 #endif
  19524         return result;
  19525     }
  19526 
  19527 
  19528     ///////////////////////////
  19529     // JSON value data types //
  19530     ///////////////////////////
  19531 
  19532     /// @name JSON value data types
  19533     /// The data types to store a JSON value. These types are derived from
  19534     /// the template arguments passed to class @ref basic_json.
  19535     /// @{
  19536 
  19537     /// @brief default object key comparator type
  19538     /// The actual object key comparator type (@ref object_comparator_t) may be
  19539     /// different.
  19540     /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
  19541 #if defined(JSON_HAS_CPP_14)
  19542     // use of transparent comparator avoids unnecessary repeated construction of temporaries
  19543     // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
  19544     using default_object_comparator_t = std::less<>;
  19545 #else
  19546     using default_object_comparator_t = std::less<StringType>;
  19547 #endif
  19548 
  19549     /// @brief a type for an object
  19550     /// @sa https://json.nlohmann.me/api/basic_json/object_t/
  19551     using object_t = ObjectType<StringType,
  19552           basic_json,
  19553           default_object_comparator_t,
  19554           AllocatorType<std::pair<const StringType,
  19555           basic_json>>>;
  19556 
  19557     /// @brief a type for an array
  19558     /// @sa https://json.nlohmann.me/api/basic_json/array_t/
  19559     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
  19560 
  19561     /// @brief a type for a string
  19562     /// @sa https://json.nlohmann.me/api/basic_json/string_t/
  19563     using string_t = StringType;
  19564 
  19565     /// @brief a type for a boolean
  19566     /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
  19567     using boolean_t = BooleanType;
  19568 
  19569     /// @brief a type for a number (integer)
  19570     /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
  19571     using number_integer_t = NumberIntegerType;
  19572 
  19573     /// @brief a type for a number (unsigned)
  19574     /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
  19575     using number_unsigned_t = NumberUnsignedType;
  19576 
  19577     /// @brief a type for a number (floating-point)
  19578     /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
  19579     using number_float_t = NumberFloatType;
  19580 
  19581     /// @brief a type for a packed binary type
  19582     /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
  19583     using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
  19584 
  19585     /// @brief object key comparator type
  19586     /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
  19587     using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
  19588 
  19589     /// @}
  19590 
  19591   private:
  19592 
  19593     /// helper for exception-safe object creation
  19594     template<typename T, typename... Args>
  19595     JSON_HEDLEY_RETURNS_NON_NULL
  19596     static T* create(Args&& ... args)
  19597     {
  19598         AllocatorType<T> alloc;
  19599         using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
  19600 
  19601         auto deleter = [&](T * obj)
  19602         {
  19603             AllocatorTraits::deallocate(alloc, obj, 1);
  19604         };
  19605         std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
  19606         AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
  19607         JSON_ASSERT(obj != nullptr);
  19608         return obj.release();
  19609     }
  19610 
  19611     ////////////////////////
  19612     // JSON value storage //
  19613     ////////////////////////
  19614 
  19615   JSON_PRIVATE_UNLESS_TESTED:
  19616     /*!
  19617     @brief a JSON value
  19618 
  19619     The actual storage for a JSON value of the @ref basic_json class. This
  19620     union combines the different storage types for the JSON value types
  19621     defined in @ref value_t.
  19622 
  19623     JSON type | value_t type    | used type
  19624     --------- | --------------- | ------------------------
  19625     object    | object          | pointer to @ref object_t
  19626     array     | array           | pointer to @ref array_t
  19627     string    | string          | pointer to @ref string_t
  19628     boolean   | boolean         | @ref boolean_t
  19629     number    | number_integer  | @ref number_integer_t
  19630     number    | number_unsigned | @ref number_unsigned_t
  19631     number    | number_float    | @ref number_float_t
  19632     binary    | binary          | pointer to @ref binary_t
  19633     null      | null            | *no value is stored*
  19634 
  19635     @note Variable-length types (objects, arrays, and strings) are stored as
  19636     pointers. The size of the union should not exceed 64 bits if the default
  19637     value types are used.
  19638 
  19639     @since version 1.0.0
  19640     */
  19641     union json_value
  19642     {
  19643         /// object (stored with pointer to save storage)
  19644         object_t* object;
  19645         /// array (stored with pointer to save storage)
  19646         array_t* array;
  19647         /// string (stored with pointer to save storage)
  19648         string_t* string;
  19649         /// binary (stored with pointer to save storage)
  19650         binary_t* binary;
  19651         /// boolean
  19652         boolean_t boolean;
  19653         /// number (integer)
  19654         number_integer_t number_integer;
  19655         /// number (unsigned integer)
  19656         number_unsigned_t number_unsigned;
  19657         /// number (floating-point)
  19658         number_float_t number_float;
  19659 
  19660         /// default constructor (for null values)
  19661         json_value() = default;
  19662         /// constructor for booleans
  19663         json_value(boolean_t v) noexcept : boolean(v) {}
  19664         /// constructor for numbers (integer)
  19665         json_value(number_integer_t v) noexcept : number_integer(v) {}
  19666         /// constructor for numbers (unsigned)
  19667         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
  19668         /// constructor for numbers (floating-point)
  19669         json_value(number_float_t v) noexcept : number_float(v) {}
  19670         /// constructor for empty values of a given type
  19671         json_value(value_t t)
  19672         {
  19673             switch (t)
  19674             {
  19675                 case value_t::object:
  19676                 {
  19677                     object = create<object_t>();
  19678                     break;
  19679                 }
  19680 
  19681                 case value_t::array:
  19682                 {
  19683                     array = create<array_t>();
  19684                     break;
  19685                 }
  19686 
  19687                 case value_t::string:
  19688                 {
  19689                     string = create<string_t>("");
  19690                     break;
  19691                 }
  19692 
  19693                 case value_t::binary:
  19694                 {
  19695                     binary = create<binary_t>();
  19696                     break;
  19697                 }
  19698 
  19699                 case value_t::boolean:
  19700                 {
  19701                     boolean = static_cast<boolean_t>(false);
  19702                     break;
  19703                 }
  19704 
  19705                 case value_t::number_integer:
  19706                 {
  19707                     number_integer = static_cast<number_integer_t>(0);
  19708                     break;
  19709                 }
  19710 
  19711                 case value_t::number_unsigned:
  19712                 {
  19713                     number_unsigned = static_cast<number_unsigned_t>(0);
  19714                     break;
  19715                 }
  19716 
  19717                 case value_t::number_float:
  19718                 {
  19719                     number_float = static_cast<number_float_t>(0.0);
  19720                     break;
  19721                 }
  19722 
  19723                 case value_t::null:
  19724                 {
  19725                     object = nullptr;  // silence warning, see #821
  19726                     break;
  19727                 }
  19728 
  19729                 case value_t::discarded:
  19730                 default:
  19731                 {
  19732                     object = nullptr;  // silence warning, see #821
  19733                     if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
  19734                     {
  19735                         JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.2", nullptr)); // LCOV_EXCL_LINE
  19736                     }
  19737                     break;
  19738                 }
  19739             }
  19740         }
  19741 
  19742         /// constructor for strings
  19743         json_value(const string_t& value) : string(create<string_t>(value)) {}
  19744 
  19745         /// constructor for rvalue strings
  19746         json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
  19747 
  19748         /// constructor for objects
  19749         json_value(const object_t& value) : object(create<object_t>(value)) {}
  19750 
  19751         /// constructor for rvalue objects
  19752         json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
  19753 
  19754         /// constructor for arrays
  19755         json_value(const array_t& value) : array(create<array_t>(value)) {}
  19756 
  19757         /// constructor for rvalue arrays
  19758         json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
  19759 
  19760         /// constructor for binary arrays
  19761         json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
  19762 
  19763         /// constructor for rvalue binary arrays
  19764         json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
  19765 
  19766         /// constructor for binary arrays (internal type)
  19767         json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
  19768 
  19769         /// constructor for rvalue binary arrays (internal type)
  19770         json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
  19771 
  19772         void destroy(value_t t)
  19773         {
  19774             if (t == value_t::array || t == value_t::object)
  19775             {
  19776                 // flatten the current json_value to a heap-allocated stack
  19777                 std::vector<basic_json> stack;
  19778 
  19779                 // move the top-level items to stack
  19780                 if (t == value_t::array)
  19781                 {
  19782                     stack.reserve(array->size());
  19783                     std::move(array->begin(), array->end(), std::back_inserter(stack));
  19784                 }
  19785                 else
  19786                 {
  19787                     stack.reserve(object->size());
  19788                     for (auto&& it : *object)
  19789                     {
  19790                         stack.push_back(std::move(it.second));
  19791                     }
  19792                 }
  19793 
  19794                 while (!stack.empty())
  19795                 {
  19796                     // move the last item to local variable to be processed
  19797                     basic_json current_item(std::move(stack.back()));
  19798                     stack.pop_back();
  19799 
  19800                     // if current_item is array/object, move
  19801                     // its children to the stack to be processed later
  19802                     if (current_item.is_array())
  19803                     {
  19804                         std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
  19805 
  19806                         current_item.m_value.array->clear();
  19807                     }
  19808                     else if (current_item.is_object())
  19809                     {
  19810                         for (auto&& it : *current_item.m_value.object)
  19811                         {
  19812                             stack.push_back(std::move(it.second));
  19813                         }
  19814 
  19815                         current_item.m_value.object->clear();
  19816                     }
  19817 
  19818                     // it's now safe that current_item get destructed
  19819                     // since it doesn't have any children
  19820                 }
  19821             }
  19822 
  19823             switch (t)
  19824             {
  19825                 case value_t::object:
  19826                 {
  19827                     AllocatorType<object_t> alloc;
  19828                     std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
  19829                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
  19830                     break;
  19831                 }
  19832 
  19833                 case value_t::array:
  19834                 {
  19835                     AllocatorType<array_t> alloc;
  19836                     std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
  19837                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
  19838                     break;
  19839                 }
  19840 
  19841                 case value_t::string:
  19842                 {
  19843                     AllocatorType<string_t> alloc;
  19844                     std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
  19845                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
  19846                     break;
  19847                 }
  19848 
  19849                 case value_t::binary:
  19850                 {
  19851                     AllocatorType<binary_t> alloc;
  19852                     std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
  19853                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
  19854                     break;
  19855                 }
  19856 
  19857                 case value_t::null:
  19858                 case value_t::boolean:
  19859                 case value_t::number_integer:
  19860                 case value_t::number_unsigned:
  19861                 case value_t::number_float:
  19862                 case value_t::discarded:
  19863                 default:
  19864                 {
  19865                     break;
  19866                 }
  19867             }
  19868         }
  19869     };
  19870 
  19871   private:
  19872     /*!
  19873     @brief checks the class invariants
  19874 
  19875     This function asserts the class invariants. It needs to be called at the
  19876     end of every constructor to make sure that created objects respect the
  19877     invariant. Furthermore, it has to be called each time the type of a JSON
  19878     value is changed, because the invariant expresses a relationship between
  19879     @a m_type and @a m_value.
  19880 
  19881     Furthermore, the parent relation is checked for arrays and objects: If
  19882     @a check_parents true and the value is an array or object, then the
  19883     container's elements must have the current value as parent.
  19884 
  19885     @param[in] check_parents  whether the parent relation should be checked.
  19886                The value is true by default and should only be set to false
  19887                during destruction of objects when the invariant does not
  19888                need to hold.
  19889     */
  19890     void assert_invariant(bool check_parents = true) const noexcept
  19891     {
  19892         JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
  19893         JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
  19894         JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
  19895         JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
  19896 
  19897 #if JSON_DIAGNOSTICS
  19898         JSON_TRY
  19899         {
  19900             // cppcheck-suppress assertWithSideEffect
  19901             JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
  19902             {
  19903                 return j.m_parent == this;
  19904             }));
  19905         }
  19906         JSON_CATCH(...) {} // LCOV_EXCL_LINE
  19907 #endif
  19908         static_cast<void>(check_parents);
  19909     }
  19910 
  19911     void set_parents()
  19912     {
  19913 #if JSON_DIAGNOSTICS
  19914         switch (m_type)
  19915         {
  19916             case value_t::array:
  19917             {
  19918                 for (auto& element : *m_value.array)
  19919                 {
  19920                     element.m_parent = this;
  19921                 }
  19922                 break;
  19923             }
  19924 
  19925             case value_t::object:
  19926             {
  19927                 for (auto& element : *m_value.object)
  19928                 {
  19929                     element.second.m_parent = this;
  19930                 }
  19931                 break;
  19932             }
  19933 
  19934             case value_t::null:
  19935             case value_t::string:
  19936             case value_t::boolean:
  19937             case value_t::number_integer:
  19938             case value_t::number_unsigned:
  19939             case value_t::number_float:
  19940             case value_t::binary:
  19941             case value_t::discarded:
  19942             default:
  19943                 break;
  19944         }
  19945 #endif
  19946     }
  19947 
  19948     iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
  19949     {
  19950 #if JSON_DIAGNOSTICS
  19951         for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
  19952         {
  19953             (it + i)->m_parent = this;
  19954         }
  19955 #else
  19956         static_cast<void>(count_set_parents);
  19957 #endif
  19958         return it;
  19959     }
  19960 
  19961     reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
  19962     {
  19963 #if JSON_DIAGNOSTICS
  19964         if (old_capacity != static_cast<std::size_t>(-1))
  19965         {
  19966             // see https://github.com/nlohmann/json/issues/2838
  19967             JSON_ASSERT(type() == value_t::array);
  19968             if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
  19969             {
  19970                 // capacity has changed: update all parents
  19971                 set_parents();
  19972                 return j;
  19973             }
  19974         }
  19975 
  19976         // ordered_json uses a vector internally, so pointers could have
  19977         // been invalidated; see https://github.com/nlohmann/json/issues/2962
  19978 #ifdef JSON_HEDLEY_MSVC_VERSION
  19979 #pragma warning(push )
  19980 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
  19981 #endif
  19982         if (detail::is_ordered_map<object_t>::value)
  19983         {
  19984             set_parents();
  19985             return j;
  19986         }
  19987 #ifdef JSON_HEDLEY_MSVC_VERSION
  19988 #pragma warning( pop )
  19989 #endif
  19990 
  19991         j.m_parent = this;
  19992 #else
  19993         static_cast<void>(j);
  19994         static_cast<void>(old_capacity);
  19995 #endif
  19996         return j;
  19997     }
  19998 
  19999   public:
  20000     //////////////////////////
  20001     // JSON parser callback //
  20002     //////////////////////////
  20003 
  20004     /// @brief parser event types
  20005     /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
  20006     using parse_event_t = detail::parse_event_t;
  20007 
  20008     /// @brief per-element parser callback type
  20009     /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
  20010     using parser_callback_t = detail::parser_callback_t<basic_json>;
  20011 
  20012     //////////////////
  20013     // constructors //
  20014     //////////////////
  20015 
  20016     /// @name constructors and destructors
  20017     /// Constructors of class @ref basic_json, copy/move constructor, copy
  20018     /// assignment, static functions creating objects, and the destructor.
  20019     /// @{
  20020 
  20021     /// @brief create an empty value with a given type
  20022     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20023     basic_json(const value_t v)
  20024         : m_type(v), m_value(v)
  20025     {
  20026         assert_invariant();
  20027     }
  20028 
  20029     /// @brief create a null object
  20030     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20031     basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
  20032         : basic_json(value_t::null)
  20033     {
  20034         assert_invariant();
  20035     }
  20036 
  20037     /// @brief create a JSON value from compatible types
  20038     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20039     template < typename CompatibleType,
  20040                typename U = detail::uncvref_t<CompatibleType>,
  20041                detail::enable_if_t <
  20042                    !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
  20043     basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
  20044                 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
  20045                                            std::forward<CompatibleType>(val))))
  20046     {
  20047         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
  20048         set_parents();
  20049         assert_invariant();
  20050     }
  20051 
  20052     /// @brief create a JSON value from an existing one
  20053     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20054     template < typename BasicJsonType,
  20055                detail::enable_if_t <
  20056                    detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
  20057     basic_json(const BasicJsonType& val)
  20058     {
  20059         using other_boolean_t = typename BasicJsonType::boolean_t;
  20060         using other_number_float_t = typename BasicJsonType::number_float_t;
  20061         using other_number_integer_t = typename BasicJsonType::number_integer_t;
  20062         using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  20063         using other_string_t = typename BasicJsonType::string_t;
  20064         using other_object_t = typename BasicJsonType::object_t;
  20065         using other_array_t = typename BasicJsonType::array_t;
  20066         using other_binary_t = typename BasicJsonType::binary_t;
  20067 
  20068         switch (val.type())
  20069         {
  20070             case value_t::boolean:
  20071                 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
  20072                 break;
  20073             case value_t::number_float:
  20074                 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
  20075                 break;
  20076             case value_t::number_integer:
  20077                 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
  20078                 break;
  20079             case value_t::number_unsigned:
  20080                 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
  20081                 break;
  20082             case value_t::string:
  20083                 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
  20084                 break;
  20085             case value_t::object:
  20086                 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
  20087                 break;
  20088             case value_t::array:
  20089                 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
  20090                 break;
  20091             case value_t::binary:
  20092                 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
  20093                 break;
  20094             case value_t::null:
  20095                 *this = nullptr;
  20096                 break;
  20097             case value_t::discarded:
  20098                 m_type = value_t::discarded;
  20099                 break;
  20100             default:            // LCOV_EXCL_LINE
  20101                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  20102         }
  20103         JSON_ASSERT(m_type == val.type());
  20104         set_parents();
  20105         assert_invariant();
  20106     }
  20107 
  20108     /// @brief create a container (array or object) from an initializer list
  20109     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20110     basic_json(initializer_list_t init,
  20111                bool type_deduction = true,
  20112                value_t manual_type = value_t::array)
  20113     {
  20114         // check if each element is an array with two elements whose first
  20115         // element is a string
  20116         bool is_an_object = std::all_of(init.begin(), init.end(),
  20117                                         [](const detail::json_ref<basic_json>& element_ref)
  20118         {
  20119             return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
  20120         });
  20121 
  20122         // adjust type if type deduction is not wanted
  20123         if (!type_deduction)
  20124         {
  20125             // if array is wanted, do not create an object though possible
  20126             if (manual_type == value_t::array)
  20127             {
  20128                 is_an_object = false;
  20129             }
  20130 
  20131             // if object is wanted but impossible, throw an exception
  20132             if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
  20133             {
  20134                 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
  20135             }
  20136         }
  20137 
  20138         if (is_an_object)
  20139         {
  20140             // the initializer list is a list of pairs -> create object
  20141             m_type = value_t::object;
  20142             m_value = value_t::object;
  20143 
  20144             for (auto& element_ref : init)
  20145             {
  20146                 auto element = element_ref.moved_or_copied();
  20147                 m_value.object->emplace(
  20148                     std::move(*((*element.m_value.array)[0].m_value.string)),
  20149                     std::move((*element.m_value.array)[1]));
  20150             }
  20151         }
  20152         else
  20153         {
  20154             // the initializer list describes an array -> create array
  20155             m_type = value_t::array;
  20156             m_value.array = create<array_t>(init.begin(), init.end());
  20157         }
  20158 
  20159         set_parents();
  20160         assert_invariant();
  20161     }
  20162 
  20163     /// @brief explicitly create a binary array (without subtype)
  20164     /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20165     JSON_HEDLEY_WARN_UNUSED_RESULT
  20166     static basic_json binary(const typename binary_t::container_type& init)
  20167     {
  20168         auto res = basic_json();
  20169         res.m_type = value_t::binary;
  20170         res.m_value = init;
  20171         return res;
  20172     }
  20173 
  20174     /// @brief explicitly create a binary array (with subtype)
  20175     /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20176     JSON_HEDLEY_WARN_UNUSED_RESULT
  20177     static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
  20178     {
  20179         auto res = basic_json();
  20180         res.m_type = value_t::binary;
  20181         res.m_value = binary_t(init, subtype);
  20182         return res;
  20183     }
  20184 
  20185     /// @brief explicitly create a binary array
  20186     /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20187     JSON_HEDLEY_WARN_UNUSED_RESULT
  20188     static basic_json binary(typename binary_t::container_type&& init)
  20189     {
  20190         auto res = basic_json();
  20191         res.m_type = value_t::binary;
  20192         res.m_value = std::move(init);
  20193         return res;
  20194     }
  20195 
  20196     /// @brief explicitly create a binary array (with subtype)
  20197     /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20198     JSON_HEDLEY_WARN_UNUSED_RESULT
  20199     static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
  20200     {
  20201         auto res = basic_json();
  20202         res.m_type = value_t::binary;
  20203         res.m_value = binary_t(std::move(init), subtype);
  20204         return res;
  20205     }
  20206 
  20207     /// @brief explicitly create an array from an initializer list
  20208     /// @sa https://json.nlohmann.me/api/basic_json/array/
  20209     JSON_HEDLEY_WARN_UNUSED_RESULT
  20210     static basic_json array(initializer_list_t init = {})
  20211     {
  20212         return basic_json(init, false, value_t::array);
  20213     }
  20214 
  20215     /// @brief explicitly create an object from an initializer list
  20216     /// @sa https://json.nlohmann.me/api/basic_json/object/
  20217     JSON_HEDLEY_WARN_UNUSED_RESULT
  20218     static basic_json object(initializer_list_t init = {})
  20219     {
  20220         return basic_json(init, false, value_t::object);
  20221     }
  20222 
  20223     /// @brief construct an array with count copies of given value
  20224     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20225     basic_json(size_type cnt, const basic_json& val)
  20226         : m_type(value_t::array)
  20227     {
  20228         m_value.array = create<array_t>(cnt, val);
  20229         set_parents();
  20230         assert_invariant();
  20231     }
  20232 
  20233     /// @brief construct a JSON container given an iterator range
  20234     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20235     template < class InputIT, typename std::enable_if <
  20236                    std::is_same<InputIT, typename basic_json_t::iterator>::value ||
  20237                    std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
  20238     basic_json(InputIT first, InputIT last)
  20239     {
  20240         JSON_ASSERT(first.m_object != nullptr);
  20241         JSON_ASSERT(last.m_object != nullptr);
  20242 
  20243         // make sure iterator fits the current value
  20244         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  20245         {
  20246             JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
  20247         }
  20248 
  20249         // copy type from first iterator
  20250         m_type = first.m_object->m_type;
  20251 
  20252         // check if iterator range is complete for primitive values
  20253         switch (m_type)
  20254         {
  20255             case value_t::boolean:
  20256             case value_t::number_float:
  20257             case value_t::number_integer:
  20258             case value_t::number_unsigned:
  20259             case value_t::string:
  20260             {
  20261                 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
  20262                                          || !last.m_it.primitive_iterator.is_end()))
  20263                 {
  20264                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
  20265                 }
  20266                 break;
  20267             }
  20268 
  20269             case value_t::null:
  20270             case value_t::object:
  20271             case value_t::array:
  20272             case value_t::binary:
  20273             case value_t::discarded:
  20274             default:
  20275                 break;
  20276         }
  20277 
  20278         switch (m_type)
  20279         {
  20280             case value_t::number_integer:
  20281             {
  20282                 m_value.number_integer = first.m_object->m_value.number_integer;
  20283                 break;
  20284             }
  20285 
  20286             case value_t::number_unsigned:
  20287             {
  20288                 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
  20289                 break;
  20290             }
  20291 
  20292             case value_t::number_float:
  20293             {
  20294                 m_value.number_float = first.m_object->m_value.number_float;
  20295                 break;
  20296             }
  20297 
  20298             case value_t::boolean:
  20299             {
  20300                 m_value.boolean = first.m_object->m_value.boolean;
  20301                 break;
  20302             }
  20303 
  20304             case value_t::string:
  20305             {
  20306                 m_value = *first.m_object->m_value.string;
  20307                 break;
  20308             }
  20309 
  20310             case value_t::object:
  20311             {
  20312                 m_value.object = create<object_t>(first.m_it.object_iterator,
  20313                                                   last.m_it.object_iterator);
  20314                 break;
  20315             }
  20316 
  20317             case value_t::array:
  20318             {
  20319                 m_value.array = create<array_t>(first.m_it.array_iterator,
  20320                                                 last.m_it.array_iterator);
  20321                 break;
  20322             }
  20323 
  20324             case value_t::binary:
  20325             {
  20326                 m_value = *first.m_object->m_value.binary;
  20327                 break;
  20328             }
  20329 
  20330             case value_t::null:
  20331             case value_t::discarded:
  20332             default:
  20333                 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
  20334         }
  20335 
  20336         set_parents();
  20337         assert_invariant();
  20338     }
  20339 
  20340 
  20341     ///////////////////////////////////////
  20342     // other constructors and destructor //
  20343     ///////////////////////////////////////
  20344 
  20345     template<typename JsonRef,
  20346              detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
  20347                                  std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
  20348     basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
  20349 
  20350     /// @brief copy constructor
  20351     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20352     basic_json(const basic_json& other)
  20353         : json_base_class_t(other),
  20354           m_type(other.m_type)
  20355     {
  20356         // check of passed value is valid
  20357         other.assert_invariant();
  20358 
  20359         switch (m_type)
  20360         {
  20361             case value_t::object:
  20362             {
  20363                 m_value = *other.m_value.object;
  20364                 break;
  20365             }
  20366 
  20367             case value_t::array:
  20368             {
  20369                 m_value = *other.m_value.array;
  20370                 break;
  20371             }
  20372 
  20373             case value_t::string:
  20374             {
  20375                 m_value = *other.m_value.string;
  20376                 break;
  20377             }
  20378 
  20379             case value_t::boolean:
  20380             {
  20381                 m_value = other.m_value.boolean;
  20382                 break;
  20383             }
  20384 
  20385             case value_t::number_integer:
  20386             {
  20387                 m_value = other.m_value.number_integer;
  20388                 break;
  20389             }
  20390 
  20391             case value_t::number_unsigned:
  20392             {
  20393                 m_value = other.m_value.number_unsigned;
  20394                 break;
  20395             }
  20396 
  20397             case value_t::number_float:
  20398             {
  20399                 m_value = other.m_value.number_float;
  20400                 break;
  20401             }
  20402 
  20403             case value_t::binary:
  20404             {
  20405                 m_value = *other.m_value.binary;
  20406                 break;
  20407             }
  20408 
  20409             case value_t::null:
  20410             case value_t::discarded:
  20411             default:
  20412                 break;
  20413         }
  20414 
  20415         set_parents();
  20416         assert_invariant();
  20417     }
  20418 
  20419     /// @brief move constructor
  20420     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20421     basic_json(basic_json&& other) noexcept
  20422         : json_base_class_t(std::move(other)),
  20423           m_type(std::move(other.m_type)),
  20424           m_value(std::move(other.m_value))
  20425     {
  20426         // check that passed value is valid
  20427         other.assert_invariant(false); // NOLINT(bugprone-use-after-move,hicpp-invalid-access-moved)
  20428 
  20429         // invalidate payload
  20430         other.m_type = value_t::null;
  20431         other.m_value = {};
  20432 
  20433         set_parents();
  20434         assert_invariant();
  20435     }
  20436 
  20437     /// @brief copy assignment
  20438     /// @sa https://json.nlohmann.me/api/basic_json/operator=/
  20439     basic_json& operator=(basic_json other) noexcept (
  20440         std::is_nothrow_move_constructible<value_t>::value&&
  20441         std::is_nothrow_move_assignable<value_t>::value&&
  20442         std::is_nothrow_move_constructible<json_value>::value&&
  20443         std::is_nothrow_move_assignable<json_value>::value&&
  20444         std::is_nothrow_move_assignable<json_base_class_t>::value
  20445     )
  20446     {
  20447         // check that passed value is valid
  20448         other.assert_invariant();
  20449 
  20450         using std::swap;
  20451         swap(m_type, other.m_type);
  20452         swap(m_value, other.m_value);
  20453         json_base_class_t::operator=(std::move(other));
  20454 
  20455         set_parents();
  20456         assert_invariant();
  20457         return *this;
  20458     }
  20459 
  20460     /// @brief destructor
  20461     /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
  20462     ~basic_json() noexcept
  20463     {
  20464         assert_invariant(false);
  20465         m_value.destroy(m_type);
  20466     }
  20467 
  20468     /// @}
  20469 
  20470   public:
  20471     ///////////////////////
  20472     // object inspection //
  20473     ///////////////////////
  20474 
  20475     /// @name object inspection
  20476     /// Functions to inspect the type of a JSON value.
  20477     /// @{
  20478 
  20479     /// @brief serialization
  20480     /// @sa https://json.nlohmann.me/api/basic_json/dump/
  20481     string_t dump(const int indent = -1,
  20482                   const char indent_char = ' ',
  20483                   const bool ensure_ascii = false,
  20484                   const error_handler_t error_handler = error_handler_t::strict) const
  20485     {
  20486         string_t result;
  20487         serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
  20488 
  20489         if (indent >= 0)
  20490         {
  20491             s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
  20492         }
  20493         else
  20494         {
  20495             s.dump(*this, false, ensure_ascii, 0);
  20496         }
  20497 
  20498         return result;
  20499     }
  20500 
  20501     /// @brief return the type of the JSON value (explicit)
  20502     /// @sa https://json.nlohmann.me/api/basic_json/type/
  20503     constexpr value_t type() const noexcept
  20504     {
  20505         return m_type;
  20506     }
  20507 
  20508     /// @brief return whether type is primitive
  20509     /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
  20510     constexpr bool is_primitive() const noexcept
  20511     {
  20512         return is_null() || is_string() || is_boolean() || is_number() || is_binary();
  20513     }
  20514 
  20515     /// @brief return whether type is structured
  20516     /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
  20517     constexpr bool is_structured() const noexcept
  20518     {
  20519         return is_array() || is_object();
  20520     }
  20521 
  20522     /// @brief return whether value is null
  20523     /// @sa https://json.nlohmann.me/api/basic_json/is_null/
  20524     constexpr bool is_null() const noexcept
  20525     {
  20526         return m_type == value_t::null;
  20527     }
  20528 
  20529     /// @brief return whether value is a boolean
  20530     /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
  20531     constexpr bool is_boolean() const noexcept
  20532     {
  20533         return m_type == value_t::boolean;
  20534     }
  20535 
  20536     /// @brief return whether value is a number
  20537     /// @sa https://json.nlohmann.me/api/basic_json/is_number/
  20538     constexpr bool is_number() const noexcept
  20539     {
  20540         return is_number_integer() || is_number_float();
  20541     }
  20542 
  20543     /// @brief return whether value is an integer number
  20544     /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
  20545     constexpr bool is_number_integer() const noexcept
  20546     {
  20547         return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
  20548     }
  20549 
  20550     /// @brief return whether value is an unsigned integer number
  20551     /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
  20552     constexpr bool is_number_unsigned() const noexcept
  20553     {
  20554         return m_type == value_t::number_unsigned;
  20555     }
  20556 
  20557     /// @brief return whether value is a floating-point number
  20558     /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
  20559     constexpr bool is_number_float() const noexcept
  20560     {
  20561         return m_type == value_t::number_float;
  20562     }
  20563 
  20564     /// @brief return whether value is an object
  20565     /// @sa https://json.nlohmann.me/api/basic_json/is_object/
  20566     constexpr bool is_object() const noexcept
  20567     {
  20568         return m_type == value_t::object;
  20569     }
  20570 
  20571     /// @brief return whether value is an array
  20572     /// @sa https://json.nlohmann.me/api/basic_json/is_array/
  20573     constexpr bool is_array() const noexcept
  20574     {
  20575         return m_type == value_t::array;
  20576     }
  20577 
  20578     /// @brief return whether value is a string
  20579     /// @sa https://json.nlohmann.me/api/basic_json/is_string/
  20580     constexpr bool is_string() const noexcept
  20581     {
  20582         return m_type == value_t::string;
  20583     }
  20584 
  20585     /// @brief return whether value is a binary array
  20586     /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
  20587     constexpr bool is_binary() const noexcept
  20588     {
  20589         return m_type == value_t::binary;
  20590     }
  20591 
  20592     /// @brief return whether value is discarded
  20593     /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
  20594     constexpr bool is_discarded() const noexcept
  20595     {
  20596         return m_type == value_t::discarded;
  20597     }
  20598 
  20599     /// @brief return the type of the JSON value (implicit)
  20600     /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
  20601     constexpr operator value_t() const noexcept
  20602     {
  20603         return m_type;
  20604     }
  20605 
  20606     /// @}
  20607 
  20608   private:
  20609     //////////////////
  20610     // value access //
  20611     //////////////////
  20612 
  20613     /// get a boolean (explicit)
  20614     boolean_t get_impl(boolean_t* /*unused*/) const
  20615     {
  20616         if (JSON_HEDLEY_LIKELY(is_boolean()))
  20617         {
  20618             return m_value.boolean;
  20619         }
  20620 
  20621         JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
  20622     }
  20623 
  20624     /// get a pointer to the value (object)
  20625     object_t* get_impl_ptr(object_t* /*unused*/) noexcept
  20626     {
  20627         return is_object() ? m_value.object : nullptr;
  20628     }
  20629 
  20630     /// get a pointer to the value (object)
  20631     constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
  20632     {
  20633         return is_object() ? m_value.object : nullptr;
  20634     }
  20635 
  20636     /// get a pointer to the value (array)
  20637     array_t* get_impl_ptr(array_t* /*unused*/) noexcept
  20638     {
  20639         return is_array() ? m_value.array : nullptr;
  20640     }
  20641 
  20642     /// get a pointer to the value (array)
  20643     constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
  20644     {
  20645         return is_array() ? m_value.array : nullptr;
  20646     }
  20647 
  20648     /// get a pointer to the value (string)
  20649     string_t* get_impl_ptr(string_t* /*unused*/) noexcept
  20650     {
  20651         return is_string() ? m_value.string : nullptr;
  20652     }
  20653 
  20654     /// get a pointer to the value (string)
  20655     constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
  20656     {
  20657         return is_string() ? m_value.string : nullptr;
  20658     }
  20659 
  20660     /// get a pointer to the value (boolean)
  20661     boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
  20662     {
  20663         return is_boolean() ? &m_value.boolean : nullptr;
  20664     }
  20665 
  20666     /// get a pointer to the value (boolean)
  20667     constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
  20668     {
  20669         return is_boolean() ? &m_value.boolean : nullptr;
  20670     }
  20671 
  20672     /// get a pointer to the value (integer number)
  20673     number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
  20674     {
  20675         return is_number_integer() ? &m_value.number_integer : nullptr;
  20676     }
  20677 
  20678     /// get a pointer to the value (integer number)
  20679     constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
  20680     {
  20681         return is_number_integer() ? &m_value.number_integer : nullptr;
  20682     }
  20683 
  20684     /// get a pointer to the value (unsigned number)
  20685     number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
  20686     {
  20687         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
  20688     }
  20689 
  20690     /// get a pointer to the value (unsigned number)
  20691     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
  20692     {
  20693         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
  20694     }
  20695 
  20696     /// get a pointer to the value (floating-point number)
  20697     number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
  20698     {
  20699         return is_number_float() ? &m_value.number_float : nullptr;
  20700     }
  20701 
  20702     /// get a pointer to the value (floating-point number)
  20703     constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
  20704     {
  20705         return is_number_float() ? &m_value.number_float : nullptr;
  20706     }
  20707 
  20708     /// get a pointer to the value (binary)
  20709     binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
  20710     {
  20711         return is_binary() ? m_value.binary : nullptr;
  20712     }
  20713 
  20714     /// get a pointer to the value (binary)
  20715     constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
  20716     {
  20717         return is_binary() ? m_value.binary : nullptr;
  20718     }
  20719 
  20720     /*!
  20721     @brief helper function to implement get_ref()
  20722 
  20723     This function helps to implement get_ref() without code duplication for
  20724     const and non-const overloads
  20725 
  20726     @tparam ThisType will be deduced as `basic_json` or `const basic_json`
  20727 
  20728     @throw type_error.303 if ReferenceType does not match underlying value
  20729     type of the current JSON
  20730     */
  20731     template<typename ReferenceType, typename ThisType>
  20732     static ReferenceType get_ref_impl(ThisType& obj)
  20733     {
  20734         // delegate the call to get_ptr<>()
  20735         auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
  20736 
  20737         if (JSON_HEDLEY_LIKELY(ptr != nullptr))
  20738         {
  20739             return *ptr;
  20740         }
  20741 
  20742         JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
  20743     }
  20744 
  20745   public:
  20746     /// @name value access
  20747     /// Direct access to the stored value of a JSON value.
  20748     /// @{
  20749 
  20750     /// @brief get a pointer value (implicit)
  20751     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
  20752     template<typename PointerType, typename std::enable_if<
  20753                  std::is_pointer<PointerType>::value, int>::type = 0>
  20754     auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
  20755     {
  20756         // delegate the call to get_impl_ptr<>()
  20757         return get_impl_ptr(static_cast<PointerType>(nullptr));
  20758     }
  20759 
  20760     /// @brief get a pointer value (implicit)
  20761     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
  20762     template < typename PointerType, typename std::enable_if <
  20763                    std::is_pointer<PointerType>::value&&
  20764                    std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
  20765     constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
  20766     {
  20767         // delegate the call to get_impl_ptr<>() const
  20768         return get_impl_ptr(static_cast<PointerType>(nullptr));
  20769     }
  20770 
  20771   private:
  20772     /*!
  20773     @brief get a value (explicit)
  20774 
  20775     Explicit type conversion between the JSON value and a compatible value
  20776     which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
  20777     and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
  20778     The value is converted by calling the @ref json_serializer<ValueType>
  20779     `from_json()` method.
  20780 
  20781     The function is equivalent to executing
  20782     @code {.cpp}
  20783     ValueType ret;
  20784     JSONSerializer<ValueType>::from_json(*this, ret);
  20785     return ret;
  20786     @endcode
  20787 
  20788     This overloads is chosen if:
  20789     - @a ValueType is not @ref basic_json,
  20790     - @ref json_serializer<ValueType> has a `from_json()` method of the form
  20791       `void from_json(const basic_json&, ValueType&)`, and
  20792     - @ref json_serializer<ValueType> does not have a `from_json()` method of
  20793       the form `ValueType from_json(const basic_json&)`
  20794 
  20795     @tparam ValueType the returned value type
  20796 
  20797     @return copy of the JSON value, converted to @a ValueType
  20798 
  20799     @throw what @ref json_serializer<ValueType> `from_json()` method throws
  20800 
  20801     @liveexample{The example below shows several conversions from JSON values
  20802     to other types. There a few things to note: (1) Floating-point numbers can
  20803     be converted to integers\, (2) A JSON array can be converted to a standard
  20804     `std::vector<short>`\, (3) A JSON object can be converted to C++
  20805     associative containers such as `std::unordered_map<std::string\,
  20806     json>`.,get__ValueType_const}
  20807 
  20808     @since version 2.1.0
  20809     */
  20810     template < typename ValueType,
  20811                detail::enable_if_t <
  20812                    detail::is_default_constructible<ValueType>::value&&
  20813                    detail::has_from_json<basic_json_t, ValueType>::value,
  20814                    int > = 0 >
  20815     ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
  20816                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
  20817     {
  20818         auto ret = ValueType();
  20819         JSONSerializer<ValueType>::from_json(*this, ret);
  20820         return ret;
  20821     }
  20822 
  20823     /*!
  20824     @brief get a value (explicit); special case
  20825 
  20826     Explicit type conversion between the JSON value and a compatible value
  20827     which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
  20828     and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
  20829     The value is converted by calling the @ref json_serializer<ValueType>
  20830     `from_json()` method.
  20831 
  20832     The function is equivalent to executing
  20833     @code {.cpp}
  20834     return JSONSerializer<ValueType>::from_json(*this);
  20835     @endcode
  20836 
  20837     This overloads is chosen if:
  20838     - @a ValueType is not @ref basic_json and
  20839     - @ref json_serializer<ValueType> has a `from_json()` method of the form
  20840       `ValueType from_json(const basic_json&)`
  20841 
  20842     @note If @ref json_serializer<ValueType> has both overloads of
  20843     `from_json()`, this one is chosen.
  20844 
  20845     @tparam ValueType the returned value type
  20846 
  20847     @return copy of the JSON value, converted to @a ValueType
  20848 
  20849     @throw what @ref json_serializer<ValueType> `from_json()` method throws
  20850 
  20851     @since version 2.1.0
  20852     */
  20853     template < typename ValueType,
  20854                detail::enable_if_t <
  20855                    detail::has_non_default_from_json<basic_json_t, ValueType>::value,
  20856                    int > = 0 >
  20857     ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
  20858                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
  20859     {
  20860         return JSONSerializer<ValueType>::from_json(*this);
  20861     }
  20862 
  20863     /*!
  20864     @brief get special-case overload
  20865 
  20866     This overloads converts the current @ref basic_json in a different
  20867     @ref basic_json type
  20868 
  20869     @tparam BasicJsonType == @ref basic_json
  20870 
  20871     @return a copy of *this, converted into @a BasicJsonType
  20872 
  20873     @complexity Depending on the implementation of the called `from_json()`
  20874                 method.
  20875 
  20876     @since version 3.2.0
  20877     */
  20878     template < typename BasicJsonType,
  20879                detail::enable_if_t <
  20880                    detail::is_basic_json<BasicJsonType>::value,
  20881                    int > = 0 >
  20882     BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
  20883     {
  20884         return *this;
  20885     }
  20886 
  20887     /*!
  20888     @brief get special-case overload
  20889 
  20890     This overloads avoids a lot of template boilerplate, it can be seen as the
  20891     identity method
  20892 
  20893     @tparam BasicJsonType == @ref basic_json
  20894 
  20895     @return a copy of *this
  20896 
  20897     @complexity Constant.
  20898 
  20899     @since version 2.1.0
  20900     */
  20901     template<typename BasicJsonType,
  20902              detail::enable_if_t<
  20903                  std::is_same<BasicJsonType, basic_json_t>::value,
  20904                  int> = 0>
  20905     basic_json get_impl(detail::priority_tag<3> /*unused*/) const
  20906     {
  20907         return *this;
  20908     }
  20909 
  20910     /*!
  20911     @brief get a pointer value (explicit)
  20912     @copydoc get()
  20913     */
  20914     template<typename PointerType,
  20915              detail::enable_if_t<
  20916                  std::is_pointer<PointerType>::value,
  20917                  int> = 0>
  20918     constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
  20919     -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
  20920     {
  20921         // delegate the call to get_ptr
  20922         return get_ptr<PointerType>();
  20923     }
  20924 
  20925   public:
  20926     /*!
  20927     @brief get a (pointer) value (explicit)
  20928 
  20929     Performs explicit type conversion between the JSON value and a compatible value if required.
  20930 
  20931     - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
  20932     No copies are made.
  20933 
  20934     - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
  20935     from the current @ref basic_json.
  20936 
  20937     - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
  20938     method.
  20939 
  20940     @tparam ValueTypeCV the provided value type
  20941     @tparam ValueType the returned value type
  20942 
  20943     @return copy of the JSON value, converted to @tparam ValueType if necessary
  20944 
  20945     @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
  20946 
  20947     @since version 2.1.0
  20948     */
  20949     template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
  20950 #if defined(JSON_HAS_CPP_14)
  20951     constexpr
  20952 #endif
  20953     auto get() const noexcept(
  20954     noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
  20955     -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
  20956     {
  20957         // we cannot static_assert on ValueTypeCV being non-const, because
  20958         // there is support for get<const basic_json_t>(), which is why we
  20959         // still need the uncvref
  20960         static_assert(!std::is_reference<ValueTypeCV>::value,
  20961                       "get() cannot be used with reference types, you might want to use get_ref()");
  20962         return get_impl<ValueType>(detail::priority_tag<4> {});
  20963     }
  20964 
  20965     /*!
  20966     @brief get a pointer value (explicit)
  20967 
  20968     Explicit pointer access to the internally stored JSON value. No copies are
  20969     made.
  20970 
  20971     @warning The pointer becomes invalid if the underlying JSON object
  20972     changes.
  20973 
  20974     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
  20975     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
  20976     @ref number_unsigned_t, or @ref number_float_t.
  20977 
  20978     @return pointer to the internally stored JSON value if the requested
  20979     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
  20980 
  20981     @complexity Constant.
  20982 
  20983     @liveexample{The example below shows how pointers to internal values of a
  20984     JSON value can be requested. Note that no type conversions are made and a
  20985     `nullptr` is returned if the value and the requested pointer type does not
  20986     match.,get__PointerType}
  20987 
  20988     @sa see @ref get_ptr() for explicit pointer-member access
  20989 
  20990     @since version 1.0.0
  20991     */
  20992     template<typename PointerType, typename std::enable_if<
  20993                  std::is_pointer<PointerType>::value, int>::type = 0>
  20994     auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
  20995     {
  20996         // delegate the call to get_ptr
  20997         return get_ptr<PointerType>();
  20998     }
  20999 
  21000     /// @brief get a value (explicit)
  21001     /// @sa https://json.nlohmann.me/api/basic_json/get_to/
  21002     template < typename ValueType,
  21003                detail::enable_if_t <
  21004                    !detail::is_basic_json<ValueType>::value&&
  21005                    detail::has_from_json<basic_json_t, ValueType>::value,
  21006                    int > = 0 >
  21007     ValueType & get_to(ValueType& v) const noexcept(noexcept(
  21008                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
  21009     {
  21010         JSONSerializer<ValueType>::from_json(*this, v);
  21011         return v;
  21012     }
  21013 
  21014     // specialization to allow calling get_to with a basic_json value
  21015     // see https://github.com/nlohmann/json/issues/2175
  21016     template<typename ValueType,
  21017              detail::enable_if_t <
  21018                  detail::is_basic_json<ValueType>::value,
  21019                  int> = 0>
  21020     ValueType & get_to(ValueType& v) const
  21021     {
  21022         v = *this;
  21023         return v;
  21024     }
  21025 
  21026     template <
  21027         typename T, std::size_t N,
  21028         typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  21029         detail::enable_if_t <
  21030             detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
  21031     Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  21032     noexcept(noexcept(JSONSerializer<Array>::from_json(
  21033                           std::declval<const basic_json_t&>(), v)))
  21034     {
  21035         JSONSerializer<Array>::from_json(*this, v);
  21036         return v;
  21037     }
  21038 
  21039     /// @brief get a reference value (implicit)
  21040     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
  21041     template<typename ReferenceType, typename std::enable_if<
  21042                  std::is_reference<ReferenceType>::value, int>::type = 0>
  21043     ReferenceType get_ref()
  21044     {
  21045         // delegate call to get_ref_impl
  21046         return get_ref_impl<ReferenceType>(*this);
  21047     }
  21048 
  21049     /// @brief get a reference value (implicit)
  21050     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
  21051     template < typename ReferenceType, typename std::enable_if <
  21052                    std::is_reference<ReferenceType>::value&&
  21053                    std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
  21054     ReferenceType get_ref() const
  21055     {
  21056         // delegate call to get_ref_impl
  21057         return get_ref_impl<ReferenceType>(*this);
  21058     }
  21059 
  21060     /*!
  21061     @brief get a value (implicit)
  21062 
  21063     Implicit type conversion between the JSON value and a compatible value.
  21064     The call is realized by calling @ref get() const.
  21065 
  21066     @tparam ValueType non-pointer type compatible to the JSON value, for
  21067     instance `int` for JSON integer numbers, `bool` for JSON booleans, or
  21068     `std::vector` types for JSON arrays. The character type of @ref string_t
  21069     as well as an initializer list of this type is excluded to avoid
  21070     ambiguities as these types implicitly convert to `std::string`.
  21071 
  21072     @return copy of the JSON value, converted to type @a ValueType
  21073 
  21074     @throw type_error.302 in case passed type @a ValueType is incompatible
  21075     to the JSON value type (e.g., the JSON value is of type boolean, but a
  21076     string is requested); see example below
  21077 
  21078     @complexity Linear in the size of the JSON value.
  21079 
  21080     @liveexample{The example below shows several conversions from JSON values
  21081     to other types. There a few things to note: (1) Floating-point numbers can
  21082     be converted to integers\, (2) A JSON array can be converted to a standard
  21083     `std::vector<short>`\, (3) A JSON object can be converted to C++
  21084     associative containers such as `std::unordered_map<std::string\,
  21085     json>`.,operator__ValueType}
  21086 
  21087     @since version 1.0.0
  21088     */
  21089     template < typename ValueType, typename std::enable_if <
  21090                    detail::conjunction <
  21091                        detail::negation<std::is_pointer<ValueType>>,
  21092                        detail::negation<std::is_same<ValueType, std::nullptr_t>>,
  21093                        detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
  21094                                         detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
  21095                                         detail::negation<detail::is_basic_json<ValueType>>,
  21096                                         detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
  21097 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
  21098                                                 detail::negation<std::is_same<ValueType, std::string_view>>,
  21099 #endif
  21100 #if defined(JSON_HAS_CPP_17)
  21101                                                 detail::negation<std::is_same<ValueType, std::any>>,
  21102 #endif
  21103                                                 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
  21104                                                 >::value, int >::type = 0 >
  21105                                         JSON_EXPLICIT operator ValueType() const
  21106     {
  21107         // delegate the call to get<>() const
  21108         return get<ValueType>();
  21109     }
  21110 
  21111     /// @brief get a binary value
  21112     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
  21113     binary_t& get_binary()
  21114     {
  21115         if (!is_binary())
  21116         {
  21117             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
  21118         }
  21119 
  21120         return *get_ptr<binary_t*>();
  21121     }
  21122 
  21123     /// @brief get a binary value
  21124     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
  21125     const binary_t& get_binary() const
  21126     {
  21127         if (!is_binary())
  21128         {
  21129             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
  21130         }
  21131 
  21132         return *get_ptr<const binary_t*>();
  21133     }
  21134 
  21135     /// @}
  21136 
  21137 
  21138     ////////////////////
  21139     // element access //
  21140     ////////////////////
  21141 
  21142     /// @name element access
  21143     /// Access to the JSON value.
  21144     /// @{
  21145 
  21146     /// @brief access specified array element with bounds checking
  21147     /// @sa https://json.nlohmann.me/api/basic_json/at/
  21148     reference at(size_type idx)
  21149     {
  21150         // at only works for arrays
  21151         if (JSON_HEDLEY_LIKELY(is_array()))
  21152         {
  21153             JSON_TRY
  21154             {
  21155                 return set_parent(m_value.array->at(idx));
  21156             }
  21157             JSON_CATCH (std::out_of_range&)
  21158             {
  21159                 // create better exception explanation
  21160                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
  21161             }
  21162         }
  21163         else
  21164         {
  21165             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21166         }
  21167     }
  21168 
  21169     /// @brief access specified array element with bounds checking
  21170     /// @sa https://json.nlohmann.me/api/basic_json/at/
  21171     const_reference at(size_type idx) const
  21172     {
  21173         // at only works for arrays
  21174         if (JSON_HEDLEY_LIKELY(is_array()))
  21175         {
  21176             JSON_TRY
  21177             {
  21178                 return m_value.array->at(idx);
  21179             }
  21180             JSON_CATCH (std::out_of_range&)
  21181             {
  21182                 // create better exception explanation
  21183                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
  21184             }
  21185         }
  21186         else
  21187         {
  21188             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21189         }
  21190     }
  21191 
  21192     /// @brief access specified object element with bounds checking
  21193     /// @sa https://json.nlohmann.me/api/basic_json/at/
  21194     reference at(const typename object_t::key_type& key)
  21195     {
  21196         // at only works for objects
  21197         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21198         {
  21199             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21200         }
  21201 
  21202         auto it = m_value.object->find(key);
  21203         if (it == m_value.object->end())
  21204         {
  21205             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
  21206         }
  21207         return set_parent(it->second);
  21208     }
  21209 
  21210     /// @brief access specified object element with bounds checking
  21211     /// @sa https://json.nlohmann.me/api/basic_json/at/
  21212     template<class KeyType, detail::enable_if_t<
  21213                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21214     reference at(KeyType && key)
  21215     {
  21216         // at only works for objects
  21217         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21218         {
  21219             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21220         }
  21221 
  21222         auto it = m_value.object->find(std::forward<KeyType>(key));
  21223         if (it == m_value.object->end())
  21224         {
  21225             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
  21226         }
  21227         return set_parent(it->second);
  21228     }
  21229 
  21230     /// @brief access specified object element with bounds checking
  21231     /// @sa https://json.nlohmann.me/api/basic_json/at/
  21232     const_reference at(const typename object_t::key_type& key) const
  21233     {
  21234         // at only works for objects
  21235         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21236         {
  21237             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21238         }
  21239 
  21240         auto it = m_value.object->find(key);
  21241         if (it == m_value.object->end())
  21242         {
  21243             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
  21244         }
  21245         return it->second;
  21246     }
  21247 
  21248     /// @brief access specified object element with bounds checking
  21249     /// @sa https://json.nlohmann.me/api/basic_json/at/
  21250     template<class KeyType, detail::enable_if_t<
  21251                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21252     const_reference at(KeyType && key) const
  21253     {
  21254         // at only works for objects
  21255         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21256         {
  21257             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21258         }
  21259 
  21260         auto it = m_value.object->find(std::forward<KeyType>(key));
  21261         if (it == m_value.object->end())
  21262         {
  21263             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
  21264         }
  21265         return it->second;
  21266     }
  21267 
  21268     /// @brief access specified array element
  21269     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21270     reference operator[](size_type idx)
  21271     {
  21272         // implicitly convert null value to an empty array
  21273         if (is_null())
  21274         {
  21275             m_type = value_t::array;
  21276             m_value.array = create<array_t>();
  21277             assert_invariant();
  21278         }
  21279 
  21280         // operator[] only works for arrays
  21281         if (JSON_HEDLEY_LIKELY(is_array()))
  21282         {
  21283             // fill up array with null values if given idx is outside range
  21284             if (idx >= m_value.array->size())
  21285             {
  21286 #if JSON_DIAGNOSTICS
  21287                 // remember array size & capacity before resizing
  21288                 const auto old_size = m_value.array->size();
  21289                 const auto old_capacity = m_value.array->capacity();
  21290 #endif
  21291                 m_value.array->resize(idx + 1);
  21292 
  21293 #if JSON_DIAGNOSTICS
  21294                 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
  21295                 {
  21296                     // capacity has changed: update all parents
  21297                     set_parents();
  21298                 }
  21299                 else
  21300                 {
  21301                     // set parent for values added above
  21302                     set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
  21303                 }
  21304 #endif
  21305                 assert_invariant();
  21306             }
  21307 
  21308             return m_value.array->operator[](idx);
  21309         }
  21310 
  21311         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
  21312     }
  21313 
  21314     /// @brief access specified array element
  21315     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21316     const_reference operator[](size_type idx) const
  21317     {
  21318         // const operator[] only works for arrays
  21319         if (JSON_HEDLEY_LIKELY(is_array()))
  21320         {
  21321             return m_value.array->operator[](idx);
  21322         }
  21323 
  21324         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
  21325     }
  21326 
  21327     /// @brief access specified object element
  21328     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21329     reference operator[](typename object_t::key_type key)
  21330     {
  21331         // implicitly convert null value to an empty object
  21332         if (is_null())
  21333         {
  21334             m_type = value_t::object;
  21335             m_value.object = create<object_t>();
  21336             assert_invariant();
  21337         }
  21338 
  21339         // operator[] only works for objects
  21340         if (JSON_HEDLEY_LIKELY(is_object()))
  21341         {
  21342             auto result = m_value.object->emplace(std::move(key), nullptr);
  21343             return set_parent(result.first->second);
  21344         }
  21345 
  21346         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21347     }
  21348 
  21349     /// @brief access specified object element
  21350     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21351     const_reference operator[](const typename object_t::key_type& key) const
  21352     {
  21353         // const operator[] only works for objects
  21354         if (JSON_HEDLEY_LIKELY(is_object()))
  21355         {
  21356             auto it = m_value.object->find(key);
  21357             JSON_ASSERT(it != m_value.object->end());
  21358             return it->second;
  21359         }
  21360 
  21361         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21362     }
  21363 
  21364     // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
  21365     // (they seemingly cannot be constrained to resolve the ambiguity)
  21366     template<typename T>
  21367     reference operator[](T* key)
  21368     {
  21369         return operator[](typename object_t::key_type(key));
  21370     }
  21371 
  21372     template<typename T>
  21373     const_reference operator[](T* key) const
  21374     {
  21375         return operator[](typename object_t::key_type(key));
  21376     }
  21377 
  21378     /// @brief access specified object element
  21379     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21380     template<class KeyType, detail::enable_if_t<
  21381                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21382     reference operator[](KeyType && key)
  21383     {
  21384         // implicitly convert null value to an empty object
  21385         if (is_null())
  21386         {
  21387             m_type = value_t::object;
  21388             m_value.object = create<object_t>();
  21389             assert_invariant();
  21390         }
  21391 
  21392         // operator[] only works for objects
  21393         if (JSON_HEDLEY_LIKELY(is_object()))
  21394         {
  21395             auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
  21396             return set_parent(result.first->second);
  21397         }
  21398 
  21399         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21400     }
  21401 
  21402     /// @brief access specified object element
  21403     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21404     template<class KeyType, detail::enable_if_t<
  21405                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21406     const_reference operator[](KeyType && key) const
  21407     {
  21408         // const operator[] only works for objects
  21409         if (JSON_HEDLEY_LIKELY(is_object()))
  21410         {
  21411             auto it = m_value.object->find(std::forward<KeyType>(key));
  21412             JSON_ASSERT(it != m_value.object->end());
  21413             return it->second;
  21414         }
  21415 
  21416         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21417     }
  21418 
  21419   private:
  21420     template<typename KeyType>
  21421     using is_comparable_with_object_key = detail::is_comparable <
  21422         object_comparator_t, const typename object_t::key_type&, KeyType >;
  21423 
  21424     template<typename ValueType>
  21425     using value_return_type = std::conditional <
  21426         detail::is_c_string_uncvref<ValueType>::value,
  21427         string_t, typename std::decay<ValueType>::type >;
  21428 
  21429   public:
  21430     /// @brief access specified object element with default value
  21431     /// @sa https://json.nlohmann.me/api/basic_json/value/
  21432     template < class ValueType, detail::enable_if_t <
  21433                    !detail::is_transparent<object_comparator_t>::value
  21434                    && detail::is_getable<basic_json_t, ValueType>::value
  21435                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21436     ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
  21437     {
  21438         // value only works for objects
  21439         if (JSON_HEDLEY_LIKELY(is_object()))
  21440         {
  21441             // if key is found, return value and given default value otherwise
  21442             const auto it = find(key);
  21443             if (it != end())
  21444             {
  21445                 return it->template get<ValueType>();
  21446             }
  21447 
  21448             return default_value;
  21449         }
  21450 
  21451         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21452     }
  21453 
  21454     /// @brief access specified object element with default value
  21455     /// @sa https://json.nlohmann.me/api/basic_json/value/
  21456     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
  21457                detail::enable_if_t <
  21458                    !detail::is_transparent<object_comparator_t>::value
  21459                    && detail::is_getable<basic_json_t, ReturnType>::value
  21460                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21461     ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
  21462     {
  21463         // value only works for objects
  21464         if (JSON_HEDLEY_LIKELY(is_object()))
  21465         {
  21466             // if key is found, return value and given default value otherwise
  21467             const auto it = find(key);
  21468             if (it != end())
  21469             {
  21470                 return it->template get<ReturnType>();
  21471             }
  21472 
  21473             return std::forward<ValueType>(default_value);
  21474         }
  21475 
  21476         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21477     }
  21478 
  21479     /// @brief access specified object element with default value
  21480     /// @sa https://json.nlohmann.me/api/basic_json/value/
  21481     template < class ValueType, class KeyType, detail::enable_if_t <
  21482                    detail::is_transparent<object_comparator_t>::value
  21483                    && !detail::is_json_pointer<KeyType>::value
  21484                    && is_comparable_with_object_key<KeyType>::value
  21485                    && detail::is_getable<basic_json_t, ValueType>::value
  21486                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21487     ValueType value(KeyType && key, const ValueType& default_value) const
  21488     {
  21489         // value only works for objects
  21490         if (JSON_HEDLEY_LIKELY(is_object()))
  21491         {
  21492             // if key is found, return value and given default value otherwise
  21493             const auto it = find(std::forward<KeyType>(key));
  21494             if (it != end())
  21495             {
  21496                 return it->template get<ValueType>();
  21497             }
  21498 
  21499             return default_value;
  21500         }
  21501 
  21502         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21503     }
  21504 
  21505     /// @brief access specified object element via JSON Pointer with default value
  21506     /// @sa https://json.nlohmann.me/api/basic_json/value/
  21507     template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
  21508                detail::enable_if_t <
  21509                    detail::is_transparent<object_comparator_t>::value
  21510                    && !detail::is_json_pointer<KeyType>::value
  21511                    && is_comparable_with_object_key<KeyType>::value
  21512                    && detail::is_getable<basic_json_t, ReturnType>::value
  21513                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21514     ReturnType value(KeyType && key, ValueType && default_value) const
  21515     {
  21516         // value only works for objects
  21517         if (JSON_HEDLEY_LIKELY(is_object()))
  21518         {
  21519             // if key is found, return value and given default value otherwise
  21520             const auto it = find(std::forward<KeyType>(key));
  21521             if (it != end())
  21522             {
  21523                 return it->template get<ReturnType>();
  21524             }
  21525 
  21526             return std::forward<ValueType>(default_value);
  21527         }
  21528 
  21529         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21530     }
  21531 
  21532     /// @brief access specified object element via JSON Pointer with default value
  21533     /// @sa https://json.nlohmann.me/api/basic_json/value/
  21534     template < class ValueType, detail::enable_if_t <
  21535                    detail::is_getable<basic_json_t, ValueType>::value
  21536                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21537     ValueType value(const json_pointer& ptr, const ValueType& default_value) const
  21538     {
  21539         // value only works for objects
  21540         if (JSON_HEDLEY_LIKELY(is_object()))
  21541         {
  21542             // if pointer resolves a value, return it or use default value
  21543             JSON_TRY
  21544             {
  21545                 return ptr.get_checked(this).template get<ValueType>();
  21546             }
  21547             JSON_INTERNAL_CATCH (out_of_range&)
  21548             {
  21549                 return default_value;
  21550             }
  21551         }
  21552 
  21553         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21554     }
  21555 
  21556     /// @brief access specified object element via JSON Pointer with default value
  21557     /// @sa https://json.nlohmann.me/api/basic_json/value/
  21558     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
  21559                detail::enable_if_t <
  21560                    detail::is_getable<basic_json_t, ReturnType>::value
  21561                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21562     ReturnType value(const json_pointer& ptr, ValueType && default_value) const
  21563     {
  21564         // value only works for objects
  21565         if (JSON_HEDLEY_LIKELY(is_object()))
  21566         {
  21567             // if pointer resolves a value, return it or use default value
  21568             JSON_TRY
  21569             {
  21570                 return ptr.get_checked(this).template get<ReturnType>();
  21571             }
  21572             JSON_INTERNAL_CATCH (out_of_range&)
  21573             {
  21574                 return std::forward<ValueType>(default_value);
  21575             }
  21576         }
  21577 
  21578         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21579     }
  21580 
  21581     template < class ValueType, class BasicJsonType, detail::enable_if_t <
  21582                    detail::is_basic_json<BasicJsonType>::value
  21583                    && detail::is_getable<basic_json_t, ValueType>::value
  21584                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21585     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  21586     ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
  21587     {
  21588         return value(ptr.convert(), default_value);
  21589     }
  21590 
  21591     template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
  21592                detail::enable_if_t <
  21593                    detail::is_basic_json<BasicJsonType>::value
  21594                    && detail::is_getable<basic_json_t, ReturnType>::value
  21595                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21596     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  21597     ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
  21598     {
  21599         return value(ptr.convert(), std::forward<ValueType>(default_value));
  21600     }
  21601 
  21602     /// @brief access the first element
  21603     /// @sa https://json.nlohmann.me/api/basic_json/front/
  21604     reference front()
  21605     {
  21606         return *begin();
  21607     }
  21608 
  21609     /// @brief access the first element
  21610     /// @sa https://json.nlohmann.me/api/basic_json/front/
  21611     const_reference front() const
  21612     {
  21613         return *cbegin();
  21614     }
  21615 
  21616     /// @brief access the last element
  21617     /// @sa https://json.nlohmann.me/api/basic_json/back/
  21618     reference back()
  21619     {
  21620         auto tmp = end();
  21621         --tmp;
  21622         return *tmp;
  21623     }
  21624 
  21625     /// @brief access the last element
  21626     /// @sa https://json.nlohmann.me/api/basic_json/back/
  21627     const_reference back() const
  21628     {
  21629         auto tmp = cend();
  21630         --tmp;
  21631         return *tmp;
  21632     }
  21633 
  21634     /// @brief remove element given an iterator
  21635     /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21636     template < class IteratorType, detail::enable_if_t <
  21637                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
  21638                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
  21639     IteratorType erase(IteratorType pos)
  21640     {
  21641         // make sure iterator fits the current value
  21642         if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
  21643         {
  21644             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  21645         }
  21646 
  21647         IteratorType result = end();
  21648 
  21649         switch (m_type)
  21650         {
  21651             case value_t::boolean:
  21652             case value_t::number_float:
  21653             case value_t::number_integer:
  21654             case value_t::number_unsigned:
  21655             case value_t::string:
  21656             case value_t::binary:
  21657             {
  21658                 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
  21659                 {
  21660                     JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
  21661                 }
  21662 
  21663                 if (is_string())
  21664                 {
  21665                     AllocatorType<string_t> alloc;
  21666                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
  21667                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
  21668                     m_value.string = nullptr;
  21669                 }
  21670                 else if (is_binary())
  21671                 {
  21672                     AllocatorType<binary_t> alloc;
  21673                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
  21674                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
  21675                     m_value.binary = nullptr;
  21676                 }
  21677 
  21678                 m_type = value_t::null;
  21679                 assert_invariant();
  21680                 break;
  21681             }
  21682 
  21683             case value_t::object:
  21684             {
  21685                 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
  21686                 break;
  21687             }
  21688 
  21689             case value_t::array:
  21690             {
  21691                 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
  21692                 break;
  21693             }
  21694 
  21695             case value_t::null:
  21696             case value_t::discarded:
  21697             default:
  21698                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21699         }
  21700 
  21701         return result;
  21702     }
  21703 
  21704     /// @brief remove elements given an iterator range
  21705     /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21706     template < class IteratorType, detail::enable_if_t <
  21707                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
  21708                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
  21709     IteratorType erase(IteratorType first, IteratorType last)
  21710     {
  21711         // make sure iterator fits the current value
  21712         if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
  21713         {
  21714             JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
  21715         }
  21716 
  21717         IteratorType result = end();
  21718 
  21719         switch (m_type)
  21720         {
  21721             case value_t::boolean:
  21722             case value_t::number_float:
  21723             case value_t::number_integer:
  21724             case value_t::number_unsigned:
  21725             case value_t::string:
  21726             case value_t::binary:
  21727             {
  21728                 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
  21729                                        || !last.m_it.primitive_iterator.is_end()))
  21730                 {
  21731                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
  21732                 }
  21733 
  21734                 if (is_string())
  21735                 {
  21736                     AllocatorType<string_t> alloc;
  21737                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
  21738                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
  21739                     m_value.string = nullptr;
  21740                 }
  21741                 else if (is_binary())
  21742                 {
  21743                     AllocatorType<binary_t> alloc;
  21744                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
  21745                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
  21746                     m_value.binary = nullptr;
  21747                 }
  21748 
  21749                 m_type = value_t::null;
  21750                 assert_invariant();
  21751                 break;
  21752             }
  21753 
  21754             case value_t::object:
  21755             {
  21756                 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
  21757                                               last.m_it.object_iterator);
  21758                 break;
  21759             }
  21760 
  21761             case value_t::array:
  21762             {
  21763                 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
  21764                                              last.m_it.array_iterator);
  21765                 break;
  21766             }
  21767 
  21768             case value_t::null:
  21769             case value_t::discarded:
  21770             default:
  21771                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21772         }
  21773 
  21774         return result;
  21775     }
  21776 
  21777   private:
  21778     template < typename KeyType, detail::enable_if_t <
  21779                    detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21780     size_type erase_internal(KeyType && key)
  21781     {
  21782         // this erase only works for objects
  21783         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21784         {
  21785             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21786         }
  21787 
  21788         return m_value.object->erase(std::forward<KeyType>(key));
  21789     }
  21790 
  21791     template < typename KeyType, detail::enable_if_t <
  21792                    !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21793     size_type erase_internal(KeyType && key)
  21794     {
  21795         // this erase only works for objects
  21796         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21797         {
  21798             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21799         }
  21800 
  21801         const auto it = m_value.object->find(std::forward<KeyType>(key));
  21802         if (it != m_value.object->end())
  21803         {
  21804             m_value.object->erase(it);
  21805             return 1;
  21806         }
  21807         return 0;
  21808     }
  21809 
  21810   public:
  21811 
  21812     /// @brief remove element from a JSON object given a key
  21813     /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21814     size_type erase(const typename object_t::key_type& key)
  21815     {
  21816         // the indirection via erase_internal() is added to avoid making this
  21817         // function a template and thus de-rank it during overload resolution
  21818         return erase_internal(key);
  21819     }
  21820 
  21821     /// @brief remove element from a JSON object given a key
  21822     /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21823     template<class KeyType, detail::enable_if_t<
  21824                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21825     size_type erase(KeyType && key)
  21826     {
  21827         return erase_internal(std::forward<KeyType>(key));
  21828     }
  21829 
  21830     /// @brief remove element from a JSON array given an index
  21831     /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21832     void erase(const size_type idx)
  21833     {
  21834         // this erase only works for arrays
  21835         if (JSON_HEDLEY_LIKELY(is_array()))
  21836         {
  21837             if (JSON_HEDLEY_UNLIKELY(idx >= size()))
  21838             {
  21839                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
  21840             }
  21841 
  21842             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
  21843         }
  21844         else
  21845         {
  21846             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21847         }
  21848     }
  21849 
  21850     /// @}
  21851 
  21852 
  21853     ////////////
  21854     // lookup //
  21855     ////////////
  21856 
  21857     /// @name lookup
  21858     /// @{
  21859 
  21860     /// @brief find an element in a JSON object
  21861     /// @sa https://json.nlohmann.me/api/basic_json/find/
  21862     iterator find(const typename object_t::key_type& key)
  21863     {
  21864         auto result = end();
  21865 
  21866         if (is_object())
  21867         {
  21868             result.m_it.object_iterator = m_value.object->find(key);
  21869         }
  21870 
  21871         return result;
  21872     }
  21873 
  21874     /// @brief find an element in a JSON object
  21875     /// @sa https://json.nlohmann.me/api/basic_json/find/
  21876     const_iterator find(const typename object_t::key_type& key) const
  21877     {
  21878         auto result = cend();
  21879 
  21880         if (is_object())
  21881         {
  21882             result.m_it.object_iterator = m_value.object->find(key);
  21883         }
  21884 
  21885         return result;
  21886     }
  21887 
  21888     /// @brief find an element in a JSON object
  21889     /// @sa https://json.nlohmann.me/api/basic_json/find/
  21890     template<class KeyType, detail::enable_if_t<
  21891                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21892     iterator find(KeyType && key)
  21893     {
  21894         auto result = end();
  21895 
  21896         if (is_object())
  21897         {
  21898             result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
  21899         }
  21900 
  21901         return result;
  21902     }
  21903 
  21904     /// @brief find an element in a JSON object
  21905     /// @sa https://json.nlohmann.me/api/basic_json/find/
  21906     template<class KeyType, detail::enable_if_t<
  21907                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21908     const_iterator find(KeyType && key) const
  21909     {
  21910         auto result = cend();
  21911 
  21912         if (is_object())
  21913         {
  21914             result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
  21915         }
  21916 
  21917         return result;
  21918     }
  21919 
  21920     /// @brief returns the number of occurrences of a key in a JSON object
  21921     /// @sa https://json.nlohmann.me/api/basic_json/count/
  21922     size_type count(const typename object_t::key_type& key) const
  21923     {
  21924         // return 0 for all nonobject types
  21925         return is_object() ? m_value.object->count(key) : 0;
  21926     }
  21927 
  21928     /// @brief returns the number of occurrences of a key in a JSON object
  21929     /// @sa https://json.nlohmann.me/api/basic_json/count/
  21930     template<class KeyType, detail::enable_if_t<
  21931                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21932     size_type count(KeyType && key) const
  21933     {
  21934         // return 0 for all nonobject types
  21935         return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
  21936     }
  21937 
  21938     /// @brief check the existence of an element in a JSON object
  21939     /// @sa https://json.nlohmann.me/api/basic_json/contains/
  21940     bool contains(const typename object_t::key_type& key) const
  21941     {
  21942         return is_object() && m_value.object->find(key) != m_value.object->end();
  21943     }
  21944 
  21945     /// @brief check the existence of an element in a JSON object
  21946     /// @sa https://json.nlohmann.me/api/basic_json/contains/
  21947     template<class KeyType, detail::enable_if_t<
  21948                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21949     bool contains(KeyType && key) const
  21950     {
  21951         return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
  21952     }
  21953 
  21954     /// @brief check the existence of an element in a JSON object given a JSON pointer
  21955     /// @sa https://json.nlohmann.me/api/basic_json/contains/
  21956     bool contains(const json_pointer& ptr) const
  21957     {
  21958         return ptr.contains(this);
  21959     }
  21960 
  21961     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  21962     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  21963     bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
  21964     {
  21965         return ptr.contains(this);
  21966     }
  21967 
  21968     /// @}
  21969 
  21970 
  21971     ///////////////
  21972     // iterators //
  21973     ///////////////
  21974 
  21975     /// @name iterators
  21976     /// @{
  21977 
  21978     /// @brief returns an iterator to the first element
  21979     /// @sa https://json.nlohmann.me/api/basic_json/begin/
  21980     iterator begin() noexcept
  21981     {
  21982         iterator result(this);
  21983         result.set_begin();
  21984         return result;
  21985     }
  21986 
  21987     /// @brief returns an iterator to the first element
  21988     /// @sa https://json.nlohmann.me/api/basic_json/begin/
  21989     const_iterator begin() const noexcept
  21990     {
  21991         return cbegin();
  21992     }
  21993 
  21994     /// @brief returns a const iterator to the first element
  21995     /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
  21996     const_iterator cbegin() const noexcept
  21997     {
  21998         const_iterator result(this);
  21999         result.set_begin();
  22000         return result;
  22001     }
  22002 
  22003     /// @brief returns an iterator to one past the last element
  22004     /// @sa https://json.nlohmann.me/api/basic_json/end/
  22005     iterator end() noexcept
  22006     {
  22007         iterator result(this);
  22008         result.set_end();
  22009         return result;
  22010     }
  22011 
  22012     /// @brief returns an iterator to one past the last element
  22013     /// @sa https://json.nlohmann.me/api/basic_json/end/
  22014     const_iterator end() const noexcept
  22015     {
  22016         return cend();
  22017     }
  22018 
  22019     /// @brief returns an iterator to one past the last element
  22020     /// @sa https://json.nlohmann.me/api/basic_json/cend/
  22021     const_iterator cend() const noexcept
  22022     {
  22023         const_iterator result(this);
  22024         result.set_end();
  22025         return result;
  22026     }
  22027 
  22028     /// @brief returns an iterator to the reverse-beginning
  22029     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
  22030     reverse_iterator rbegin() noexcept
  22031     {
  22032         return reverse_iterator(end());
  22033     }
  22034 
  22035     /// @brief returns an iterator to the reverse-beginning
  22036     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
  22037     const_reverse_iterator rbegin() const noexcept
  22038     {
  22039         return crbegin();
  22040     }
  22041 
  22042     /// @brief returns an iterator to the reverse-end
  22043     /// @sa https://json.nlohmann.me/api/basic_json/rend/
  22044     reverse_iterator rend() noexcept
  22045     {
  22046         return reverse_iterator(begin());
  22047     }
  22048 
  22049     /// @brief returns an iterator to the reverse-end
  22050     /// @sa https://json.nlohmann.me/api/basic_json/rend/
  22051     const_reverse_iterator rend() const noexcept
  22052     {
  22053         return crend();
  22054     }
  22055 
  22056     /// @brief returns a const reverse iterator to the last element
  22057     /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
  22058     const_reverse_iterator crbegin() const noexcept
  22059     {
  22060         return const_reverse_iterator(cend());
  22061     }
  22062 
  22063     /// @brief returns a const reverse iterator to one before the first
  22064     /// @sa https://json.nlohmann.me/api/basic_json/crend/
  22065     const_reverse_iterator crend() const noexcept
  22066     {
  22067         return const_reverse_iterator(cbegin());
  22068     }
  22069 
  22070   public:
  22071     /// @brief wrapper to access iterator member functions in range-based for
  22072     /// @sa https://json.nlohmann.me/api/basic_json/items/
  22073     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
  22074     ///             version 4.0.0 of the library. Please use @ref items() instead;
  22075     ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
  22076     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
  22077     static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
  22078     {
  22079         return ref.items();
  22080     }
  22081 
  22082     /// @brief wrapper to access iterator member functions in range-based for
  22083     /// @sa https://json.nlohmann.me/api/basic_json/items/
  22084     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
  22085     ///         version 4.0.0 of the library. Please use @ref items() instead;
  22086     ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
  22087     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
  22088     static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
  22089     {
  22090         return ref.items();
  22091     }
  22092 
  22093     /// @brief helper to access iterator member functions in range-based for
  22094     /// @sa https://json.nlohmann.me/api/basic_json/items/
  22095     iteration_proxy<iterator> items() noexcept
  22096     {
  22097         return iteration_proxy<iterator>(*this);
  22098     }
  22099 
  22100     /// @brief helper to access iterator member functions in range-based for
  22101     /// @sa https://json.nlohmann.me/api/basic_json/items/
  22102     iteration_proxy<const_iterator> items() const noexcept
  22103     {
  22104         return iteration_proxy<const_iterator>(*this);
  22105     }
  22106 
  22107     /// @}
  22108 
  22109 
  22110     //////////////
  22111     // capacity //
  22112     //////////////
  22113 
  22114     /// @name capacity
  22115     /// @{
  22116 
  22117     /// @brief checks whether the container is empty.
  22118     /// @sa https://json.nlohmann.me/api/basic_json/empty/
  22119     bool empty() const noexcept
  22120     {
  22121         switch (m_type)
  22122         {
  22123             case value_t::null:
  22124             {
  22125                 // null values are empty
  22126                 return true;
  22127             }
  22128 
  22129             case value_t::array:
  22130             {
  22131                 // delegate call to array_t::empty()
  22132                 return m_value.array->empty();
  22133             }
  22134 
  22135             case value_t::object:
  22136             {
  22137                 // delegate call to object_t::empty()
  22138                 return m_value.object->empty();
  22139             }
  22140 
  22141             case value_t::string:
  22142             case value_t::boolean:
  22143             case value_t::number_integer:
  22144             case value_t::number_unsigned:
  22145             case value_t::number_float:
  22146             case value_t::binary:
  22147             case value_t::discarded:
  22148             default:
  22149             {
  22150                 // all other types are nonempty
  22151                 return false;
  22152             }
  22153         }
  22154     }
  22155 
  22156     /// @brief returns the number of elements
  22157     /// @sa https://json.nlohmann.me/api/basic_json/size/
  22158     size_type size() const noexcept
  22159     {
  22160         switch (m_type)
  22161         {
  22162             case value_t::null:
  22163             {
  22164                 // null values are empty
  22165                 return 0;
  22166             }
  22167 
  22168             case value_t::array:
  22169             {
  22170                 // delegate call to array_t::size()
  22171                 return m_value.array->size();
  22172             }
  22173 
  22174             case value_t::object:
  22175             {
  22176                 // delegate call to object_t::size()
  22177                 return m_value.object->size();
  22178             }
  22179 
  22180             case value_t::string:
  22181             case value_t::boolean:
  22182             case value_t::number_integer:
  22183             case value_t::number_unsigned:
  22184             case value_t::number_float:
  22185             case value_t::binary:
  22186             case value_t::discarded:
  22187             default:
  22188             {
  22189                 // all other types have size 1
  22190                 return 1;
  22191             }
  22192         }
  22193     }
  22194 
  22195     /// @brief returns the maximum possible number of elements
  22196     /// @sa https://json.nlohmann.me/api/basic_json/max_size/
  22197     size_type max_size() const noexcept
  22198     {
  22199         switch (m_type)
  22200         {
  22201             case value_t::array:
  22202             {
  22203                 // delegate call to array_t::max_size()
  22204                 return m_value.array->max_size();
  22205             }
  22206 
  22207             case value_t::object:
  22208             {
  22209                 // delegate call to object_t::max_size()
  22210                 return m_value.object->max_size();
  22211             }
  22212 
  22213             case value_t::null:
  22214             case value_t::string:
  22215             case value_t::boolean:
  22216             case value_t::number_integer:
  22217             case value_t::number_unsigned:
  22218             case value_t::number_float:
  22219             case value_t::binary:
  22220             case value_t::discarded:
  22221             default:
  22222             {
  22223                 // all other types have max_size() == size()
  22224                 return size();
  22225             }
  22226         }
  22227     }
  22228 
  22229     /// @}
  22230 
  22231 
  22232     ///////////////
  22233     // modifiers //
  22234     ///////////////
  22235 
  22236     /// @name modifiers
  22237     /// @{
  22238 
  22239     /// @brief clears the contents
  22240     /// @sa https://json.nlohmann.me/api/basic_json/clear/
  22241     void clear() noexcept
  22242     {
  22243         switch (m_type)
  22244         {
  22245             case value_t::number_integer:
  22246             {
  22247                 m_value.number_integer = 0;
  22248                 break;
  22249             }
  22250 
  22251             case value_t::number_unsigned:
  22252             {
  22253                 m_value.number_unsigned = 0;
  22254                 break;
  22255             }
  22256 
  22257             case value_t::number_float:
  22258             {
  22259                 m_value.number_float = 0.0;
  22260                 break;
  22261             }
  22262 
  22263             case value_t::boolean:
  22264             {
  22265                 m_value.boolean = false;
  22266                 break;
  22267             }
  22268 
  22269             case value_t::string:
  22270             {
  22271                 m_value.string->clear();
  22272                 break;
  22273             }
  22274 
  22275             case value_t::binary:
  22276             {
  22277                 m_value.binary->clear();
  22278                 break;
  22279             }
  22280 
  22281             case value_t::array:
  22282             {
  22283                 m_value.array->clear();
  22284                 break;
  22285             }
  22286 
  22287             case value_t::object:
  22288             {
  22289                 m_value.object->clear();
  22290                 break;
  22291             }
  22292 
  22293             case value_t::null:
  22294             case value_t::discarded:
  22295             default:
  22296                 break;
  22297         }
  22298     }
  22299 
  22300     /// @brief add an object to an array
  22301     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22302     void push_back(basic_json&& val)
  22303     {
  22304         // push_back only works for null objects or arrays
  22305         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
  22306         {
  22307             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
  22308         }
  22309 
  22310         // transform null object into an array
  22311         if (is_null())
  22312         {
  22313             m_type = value_t::array;
  22314             m_value = value_t::array;
  22315             assert_invariant();
  22316         }
  22317 
  22318         // add element to array (move semantics)
  22319         const auto old_capacity = m_value.array->capacity();
  22320         m_value.array->push_back(std::move(val));
  22321         set_parent(m_value.array->back(), old_capacity);
  22322         // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
  22323     }
  22324 
  22325     /// @brief add an object to an array
  22326     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22327     reference operator+=(basic_json&& val)
  22328     {
  22329         push_back(std::move(val));
  22330         return *this;
  22331     }
  22332 
  22333     /// @brief add an object to an array
  22334     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22335     void push_back(const basic_json& val)
  22336     {
  22337         // push_back only works for null objects or arrays
  22338         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
  22339         {
  22340             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
  22341         }
  22342 
  22343         // transform null object into an array
  22344         if (is_null())
  22345         {
  22346             m_type = value_t::array;
  22347             m_value = value_t::array;
  22348             assert_invariant();
  22349         }
  22350 
  22351         // add element to array
  22352         const auto old_capacity = m_value.array->capacity();
  22353         m_value.array->push_back(val);
  22354         set_parent(m_value.array->back(), old_capacity);
  22355     }
  22356 
  22357     /// @brief add an object to an array
  22358     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22359     reference operator+=(const basic_json& val)
  22360     {
  22361         push_back(val);
  22362         return *this;
  22363     }
  22364 
  22365     /// @brief add an object to an object
  22366     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22367     void push_back(const typename object_t::value_type& val)
  22368     {
  22369         // push_back only works for null objects or objects
  22370         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
  22371         {
  22372             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
  22373         }
  22374 
  22375         // transform null object into an object
  22376         if (is_null())
  22377         {
  22378             m_type = value_t::object;
  22379             m_value = value_t::object;
  22380             assert_invariant();
  22381         }
  22382 
  22383         // add element to object
  22384         auto res = m_value.object->insert(val);
  22385         set_parent(res.first->second);
  22386     }
  22387 
  22388     /// @brief add an object to an object
  22389     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22390     reference operator+=(const typename object_t::value_type& val)
  22391     {
  22392         push_back(val);
  22393         return *this;
  22394     }
  22395 
  22396     /// @brief add an object to an object
  22397     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22398     void push_back(initializer_list_t init)
  22399     {
  22400         if (is_object() && init.size() == 2 && (*init.begin())->is_string())
  22401         {
  22402             basic_json&& key = init.begin()->moved_or_copied();
  22403             push_back(typename object_t::value_type(
  22404                           std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
  22405         }
  22406         else
  22407         {
  22408             push_back(basic_json(init));
  22409         }
  22410     }
  22411 
  22412     /// @brief add an object to an object
  22413     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22414     reference operator+=(initializer_list_t init)
  22415     {
  22416         push_back(init);
  22417         return *this;
  22418     }
  22419 
  22420     /// @brief add an object to an array
  22421     /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
  22422     template<class... Args>
  22423     reference emplace_back(Args&& ... args)
  22424     {
  22425         // emplace_back only works for null objects or arrays
  22426         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
  22427         {
  22428             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
  22429         }
  22430 
  22431         // transform null object into an array
  22432         if (is_null())
  22433         {
  22434             m_type = value_t::array;
  22435             m_value = value_t::array;
  22436             assert_invariant();
  22437         }
  22438 
  22439         // add element to array (perfect forwarding)
  22440         const auto old_capacity = m_value.array->capacity();
  22441         m_value.array->emplace_back(std::forward<Args>(args)...);
  22442         return set_parent(m_value.array->back(), old_capacity);
  22443     }
  22444 
  22445     /// @brief add an object to an object if key does not exist
  22446     /// @sa https://json.nlohmann.me/api/basic_json/emplace/
  22447     template<class... Args>
  22448     std::pair<iterator, bool> emplace(Args&& ... args)
  22449     {
  22450         // emplace only works for null objects or arrays
  22451         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
  22452         {
  22453             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
  22454         }
  22455 
  22456         // transform null object into an object
  22457         if (is_null())
  22458         {
  22459             m_type = value_t::object;
  22460             m_value = value_t::object;
  22461             assert_invariant();
  22462         }
  22463 
  22464         // add element to array (perfect forwarding)
  22465         auto res = m_value.object->emplace(std::forward<Args>(args)...);
  22466         set_parent(res.first->second);
  22467 
  22468         // create result iterator and set iterator to the result of emplace
  22469         auto it = begin();
  22470         it.m_it.object_iterator = res.first;
  22471 
  22472         // return pair of iterator and boolean
  22473         return {it, res.second};
  22474     }
  22475 
  22476     /// Helper for insertion of an iterator
  22477     /// @note: This uses std::distance to support GCC 4.8,
  22478     ///        see https://github.com/nlohmann/json/pull/1257
  22479     template<typename... Args>
  22480     iterator insert_iterator(const_iterator pos, Args&& ... args)
  22481     {
  22482         iterator result(this);
  22483         JSON_ASSERT(m_value.array != nullptr);
  22484 
  22485         auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
  22486         m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
  22487         result.m_it.array_iterator = m_value.array->begin() + insert_pos;
  22488 
  22489         // This could have been written as:
  22490         // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
  22491         // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
  22492 
  22493         set_parents();
  22494         return result;
  22495     }
  22496 
  22497     /// @brief inserts element into array
  22498     /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22499     iterator insert(const_iterator pos, const basic_json& val)
  22500     {
  22501         // insert only works for arrays
  22502         if (JSON_HEDLEY_LIKELY(is_array()))
  22503         {
  22504             // check if iterator pos fits to this JSON value
  22505             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22506             {
  22507                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22508             }
  22509 
  22510             // insert to array and return iterator
  22511             return insert_iterator(pos, val);
  22512         }
  22513 
  22514         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22515     }
  22516 
  22517     /// @brief inserts element into array
  22518     /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22519     iterator insert(const_iterator pos, basic_json&& val)
  22520     {
  22521         return insert(pos, val);
  22522     }
  22523 
  22524     /// @brief inserts copies of element into array
  22525     /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22526     iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
  22527     {
  22528         // insert only works for arrays
  22529         if (JSON_HEDLEY_LIKELY(is_array()))
  22530         {
  22531             // check if iterator pos fits to this JSON value
  22532             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22533             {
  22534                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22535             }
  22536 
  22537             // insert to array and return iterator
  22538             return insert_iterator(pos, cnt, val);
  22539         }
  22540 
  22541         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22542     }
  22543 
  22544     /// @brief inserts range of elements into array
  22545     /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22546     iterator insert(const_iterator pos, const_iterator first, const_iterator last)
  22547     {
  22548         // insert only works for arrays
  22549         if (JSON_HEDLEY_UNLIKELY(!is_array()))
  22550         {
  22551             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22552         }
  22553 
  22554         // check if iterator pos fits to this JSON value
  22555         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22556         {
  22557             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22558         }
  22559 
  22560         // check if range iterators belong to the same JSON object
  22561         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  22562         {
  22563             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
  22564         }
  22565 
  22566         if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
  22567         {
  22568             JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
  22569         }
  22570 
  22571         // insert to array and return iterator
  22572         return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
  22573     }
  22574 
  22575     /// @brief inserts elements from initializer list into array
  22576     /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22577     iterator insert(const_iterator pos, initializer_list_t ilist)
  22578     {
  22579         // insert only works for arrays
  22580         if (JSON_HEDLEY_UNLIKELY(!is_array()))
  22581         {
  22582             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22583         }
  22584 
  22585         // check if iterator pos fits to this JSON value
  22586         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22587         {
  22588             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22589         }
  22590 
  22591         // insert to array and return iterator
  22592         return insert_iterator(pos, ilist.begin(), ilist.end());
  22593     }
  22594 
  22595     /// @brief inserts range of elements into object
  22596     /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22597     void insert(const_iterator first, const_iterator last)
  22598     {
  22599         // insert only works for objects
  22600         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  22601         {
  22602             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22603         }
  22604 
  22605         // check if range iterators belong to the same JSON object
  22606         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  22607         {
  22608             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
  22609         }
  22610 
  22611         // passed iterators must belong to objects
  22612         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
  22613         {
  22614             JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
  22615         }
  22616 
  22617         m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
  22618     }
  22619 
  22620     /// @brief updates a JSON object from another object, overwriting existing keys
  22621     /// @sa https://json.nlohmann.me/api/basic_json/update/
  22622     void update(const_reference j, bool merge_objects = false)
  22623     {
  22624         update(j.begin(), j.end(), merge_objects);
  22625     }
  22626 
  22627     /// @brief updates a JSON object from another object, overwriting existing keys
  22628     /// @sa https://json.nlohmann.me/api/basic_json/update/
  22629     void update(const_iterator first, const_iterator last, bool merge_objects = false)
  22630     {
  22631         // implicitly convert null value to an empty object
  22632         if (is_null())
  22633         {
  22634             m_type = value_t::object;
  22635             m_value.object = create<object_t>();
  22636             assert_invariant();
  22637         }
  22638 
  22639         if (JSON_HEDLEY_UNLIKELY(!is_object()))
  22640         {
  22641             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
  22642         }
  22643 
  22644         // check if range iterators belong to the same JSON object
  22645         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  22646         {
  22647             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
  22648         }
  22649 
  22650         // passed iterators must belong to objects
  22651         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
  22652         {
  22653             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
  22654         }
  22655 
  22656         for (auto it = first; it != last; ++it)
  22657         {
  22658             if (merge_objects && it.value().is_object())
  22659             {
  22660                 auto it2 = m_value.object->find(it.key());
  22661                 if (it2 != m_value.object->end())
  22662                 {
  22663                     it2->second.update(it.value(), true);
  22664                     continue;
  22665                 }
  22666             }
  22667             m_value.object->operator[](it.key()) = it.value();
  22668 #if JSON_DIAGNOSTICS
  22669             m_value.object->operator[](it.key()).m_parent = this;
  22670 #endif
  22671         }
  22672     }
  22673 
  22674     /// @brief exchanges the values
  22675     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22676     void swap(reference other) noexcept (
  22677         std::is_nothrow_move_constructible<value_t>::value&&
  22678         std::is_nothrow_move_assignable<value_t>::value&&
  22679         std::is_nothrow_move_constructible<json_value>::value&&
  22680         std::is_nothrow_move_assignable<json_value>::value
  22681     )
  22682     {
  22683         std::swap(m_type, other.m_type);
  22684         std::swap(m_value, other.m_value);
  22685 
  22686         set_parents();
  22687         other.set_parents();
  22688         assert_invariant();
  22689     }
  22690 
  22691     /// @brief exchanges the values
  22692     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22693     friend void swap(reference left, reference right) noexcept (
  22694         std::is_nothrow_move_constructible<value_t>::value&&
  22695         std::is_nothrow_move_assignable<value_t>::value&&
  22696         std::is_nothrow_move_constructible<json_value>::value&&
  22697         std::is_nothrow_move_assignable<json_value>::value
  22698     )
  22699     {
  22700         left.swap(right);
  22701     }
  22702 
  22703     /// @brief exchanges the values
  22704     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22705     void swap(array_t& other) // NOLINT(bugprone-exception-escape)
  22706     {
  22707         // swap only works for arrays
  22708         if (JSON_HEDLEY_LIKELY(is_array()))
  22709         {
  22710             using std::swap;
  22711             swap(*(m_value.array), other);
  22712         }
  22713         else
  22714         {
  22715             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
  22716         }
  22717     }
  22718 
  22719     /// @brief exchanges the values
  22720     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22721     void swap(object_t& other) // NOLINT(bugprone-exception-escape)
  22722     {
  22723         // swap only works for objects
  22724         if (JSON_HEDLEY_LIKELY(is_object()))
  22725         {
  22726             using std::swap;
  22727             swap(*(m_value.object), other);
  22728         }
  22729         else
  22730         {
  22731             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
  22732         }
  22733     }
  22734 
  22735     /// @brief exchanges the values
  22736     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22737     void swap(string_t& other) // NOLINT(bugprone-exception-escape)
  22738     {
  22739         // swap only works for strings
  22740         if (JSON_HEDLEY_LIKELY(is_string()))
  22741         {
  22742             using std::swap;
  22743             swap(*(m_value.string), other);
  22744         }
  22745         else
  22746         {
  22747             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
  22748         }
  22749     }
  22750 
  22751     /// @brief exchanges the values
  22752     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22753     void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
  22754     {
  22755         // swap only works for strings
  22756         if (JSON_HEDLEY_LIKELY(is_binary()))
  22757         {
  22758             using std::swap;
  22759             swap(*(m_value.binary), other);
  22760         }
  22761         else
  22762         {
  22763             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
  22764         }
  22765     }
  22766 
  22767     /// @brief exchanges the values
  22768     /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22769     void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
  22770     {
  22771         // swap only works for strings
  22772         if (JSON_HEDLEY_LIKELY(is_binary()))
  22773         {
  22774             using std::swap;
  22775             swap(*(m_value.binary), other);
  22776         }
  22777         else
  22778         {
  22779             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
  22780         }
  22781     }
  22782 
  22783     /// @}
  22784 
  22785     //////////////////////////////////////////
  22786     // lexicographical comparison operators //
  22787     //////////////////////////////////////////
  22788 
  22789     /// @name lexicographical comparison operators
  22790     /// @{
  22791 
  22792     // note parentheses around operands are necessary; see
  22793     // https://github.com/nlohmann/json/issues/1530
  22794 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
  22795     const auto lhs_type = lhs.type();                                                                    \
  22796     const auto rhs_type = rhs.type();                                                                    \
  22797     \
  22798     if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
  22799     {                                                                                                    \
  22800         switch (lhs_type)                                                                                \
  22801         {                                                                                                \
  22802             case value_t::array:                                                                         \
  22803                 return (*lhs.m_value.array) op (*rhs.m_value.array);                                     \
  22804                 \
  22805             case value_t::object:                                                                        \
  22806                 return (*lhs.m_value.object) op (*rhs.m_value.object);                                   \
  22807                 \
  22808             case value_t::null:                                                                          \
  22809                 return (null_result);                                                                    \
  22810                 \
  22811             case value_t::string:                                                                        \
  22812                 return (*lhs.m_value.string) op (*rhs.m_value.string);                                   \
  22813                 \
  22814             case value_t::boolean:                                                                       \
  22815                 return (lhs.m_value.boolean) op (rhs.m_value.boolean);                                   \
  22816                 \
  22817             case value_t::number_integer:                                                                \
  22818                 return (lhs.m_value.number_integer) op (rhs.m_value.number_integer);                     \
  22819                 \
  22820             case value_t::number_unsigned:                                                               \
  22821                 return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned);                   \
  22822                 \
  22823             case value_t::number_float:                                                                  \
  22824                 return (lhs.m_value.number_float) op (rhs.m_value.number_float);                         \
  22825                 \
  22826             case value_t::binary:                                                                        \
  22827                 return (*lhs.m_value.binary) op (*rhs.m_value.binary);                                   \
  22828                 \
  22829             case value_t::discarded:                                                                     \
  22830             default:                                                                                     \
  22831                 return (unordered_result);                                                               \
  22832         }                                                                                                \
  22833     }                                                                                                    \
  22834     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
  22835     {                                                                                                    \
  22836         return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float;      \
  22837     }                                                                                                    \
  22838     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
  22839     {                                                                                                    \
  22840         return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer);      \
  22841     }                                                                                                    \
  22842     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
  22843     {                                                                                                    \
  22844         return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float;     \
  22845     }                                                                                                    \
  22846     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
  22847     {                                                                                                    \
  22848         return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned);     \
  22849     }                                                                                                    \
  22850     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
  22851     {                                                                                                    \
  22852         return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
  22853     }                                                                                                    \
  22854     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
  22855     {                                                                                                    \
  22856         return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
  22857     }                                                                                                    \
  22858     else if(compares_unordered(lhs, rhs))\
  22859     {\
  22860         return (unordered_result);\
  22861     }\
  22862     \
  22863     return (default_result);
  22864 
  22865   JSON_PRIVATE_UNLESS_TESTED:
  22866     // returns true if:
  22867     // - any operand is NaN and the other operand is of number type
  22868     // - any operand is discarded
  22869     // in legacy mode, discarded values are considered ordered if
  22870     // an operation is computed as an odd number of inverses of others
  22871     static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
  22872     {
  22873         if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
  22874                 || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
  22875         {
  22876             return true;
  22877         }
  22878 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
  22879         return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
  22880 #else
  22881         static_cast<void>(inverse);
  22882         return lhs.is_discarded() || rhs.is_discarded();
  22883 #endif
  22884     }
  22885 
  22886   private:
  22887     bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
  22888     {
  22889         return compares_unordered(*this, rhs, inverse);
  22890     }
  22891 
  22892   public:
  22893 #if JSON_HAS_THREE_WAY_COMPARISON
  22894     /// @brief comparison: equal
  22895     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  22896     bool operator==(const_reference rhs) const noexcept
  22897     {
  22898 #ifdef __GNUC__
  22899 #pragma GCC diagnostic push
  22900 #pragma GCC diagnostic ignored "-Wfloat-equal"
  22901 #endif
  22902         const_reference lhs = *this;
  22903         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
  22904 #ifdef __GNUC__
  22905 #pragma GCC diagnostic pop
  22906 #endif
  22907     }
  22908 
  22909     /// @brief comparison: equal
  22910     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  22911     template<typename ScalarType>
  22912     requires std::is_scalar_v<ScalarType>
  22913     bool operator==(ScalarType rhs) const noexcept
  22914     {
  22915         return *this == basic_json(rhs);
  22916     }
  22917 
  22918     /// @brief comparison: not equal
  22919     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  22920     bool operator!=(const_reference rhs) const noexcept
  22921     {
  22922         if (compares_unordered(rhs, true))
  22923         {
  22924             return false;
  22925         }
  22926         return !operator==(rhs);
  22927     }
  22928 
  22929     /// @brief comparison: 3-way
  22930     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
  22931     std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
  22932     {
  22933         const_reference lhs = *this;
  22934         // default_result is used if we cannot compare values. In that case,
  22935         // we compare types.
  22936         JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
  22937                                 std::partial_ordering::equivalent,
  22938                                 std::partial_ordering::unordered,
  22939                                 lhs_type <=> rhs_type) // *NOPAD*
  22940     }
  22941 
  22942     /// @brief comparison: 3-way
  22943     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
  22944     template<typename ScalarType>
  22945     requires std::is_scalar_v<ScalarType>
  22946     std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
  22947     {
  22948         return *this <=> basic_json(rhs); // *NOPAD*
  22949     }
  22950 
  22951 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
  22952     // all operators that are computed as an odd number of inverses of others
  22953     // need to be overloaded to emulate the legacy comparison behavior
  22954 
  22955     /// @brief comparison: less than or equal
  22956     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  22957     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
  22958     bool operator<=(const_reference rhs) const noexcept
  22959     {
  22960         if (compares_unordered(rhs, true))
  22961         {
  22962             return false;
  22963         }
  22964         return !(rhs < *this);
  22965     }
  22966 
  22967     /// @brief comparison: less than or equal
  22968     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  22969     template<typename ScalarType>
  22970     requires std::is_scalar_v<ScalarType>
  22971     bool operator<=(ScalarType rhs) const noexcept
  22972     {
  22973         return *this <= basic_json(rhs);
  22974     }
  22975 
  22976     /// @brief comparison: greater than or equal
  22977     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  22978     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
  22979     bool operator>=(const_reference rhs) const noexcept
  22980     {
  22981         if (compares_unordered(rhs, true))
  22982         {
  22983             return false;
  22984         }
  22985         return !(*this < rhs);
  22986     }
  22987 
  22988     /// @brief comparison: greater than or equal
  22989     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  22990     template<typename ScalarType>
  22991     requires std::is_scalar_v<ScalarType>
  22992     bool operator>=(ScalarType rhs) const noexcept
  22993     {
  22994         return *this >= basic_json(rhs);
  22995     }
  22996 #endif
  22997 #else
  22998     /// @brief comparison: equal
  22999     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  23000     friend bool operator==(const_reference lhs, const_reference rhs) noexcept
  23001     {
  23002 #ifdef __GNUC__
  23003 #pragma GCC diagnostic push
  23004 #pragma GCC diagnostic ignored "-Wfloat-equal"
  23005 #endif
  23006         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
  23007 #ifdef __GNUC__
  23008 #pragma GCC diagnostic pop
  23009 #endif
  23010     }
  23011 
  23012     /// @brief comparison: equal
  23013     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  23014     template<typename ScalarType, typename std::enable_if<
  23015                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23016     friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
  23017     {
  23018         return lhs == basic_json(rhs);
  23019     }
  23020 
  23021     /// @brief comparison: equal
  23022     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  23023     template<typename ScalarType, typename std::enable_if<
  23024                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23025     friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
  23026     {
  23027         return basic_json(lhs) == rhs;
  23028     }
  23029 
  23030     /// @brief comparison: not equal
  23031     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  23032     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
  23033     {
  23034         if (compares_unordered(lhs, rhs, true))
  23035         {
  23036             return false;
  23037         }
  23038         return !(lhs == rhs);
  23039     }
  23040 
  23041     /// @brief comparison: not equal
  23042     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  23043     template<typename ScalarType, typename std::enable_if<
  23044                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23045     friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
  23046     {
  23047         return lhs != basic_json(rhs);
  23048     }
  23049 
  23050     /// @brief comparison: not equal
  23051     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  23052     template<typename ScalarType, typename std::enable_if<
  23053                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23054     friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
  23055     {
  23056         return basic_json(lhs) != rhs;
  23057     }
  23058 
  23059     /// @brief comparison: less than
  23060     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
  23061     friend bool operator<(const_reference lhs, const_reference rhs) noexcept
  23062     {
  23063         // default_result is used if we cannot compare values. In that case,
  23064         // we compare types. Note we have to call the operator explicitly,
  23065         // because MSVC has problems otherwise.
  23066         JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
  23067     }
  23068 
  23069     /// @brief comparison: less than
  23070     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
  23071     template<typename ScalarType, typename std::enable_if<
  23072                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23073     friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
  23074     {
  23075         return lhs < basic_json(rhs);
  23076     }
  23077 
  23078     /// @brief comparison: less than
  23079     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
  23080     template<typename ScalarType, typename std::enable_if<
  23081                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23082     friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
  23083     {
  23084         return basic_json(lhs) < rhs;
  23085     }
  23086 
  23087     /// @brief comparison: less than or equal
  23088     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23089     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
  23090     {
  23091         if (compares_unordered(lhs, rhs, true))
  23092         {
  23093             return false;
  23094         }
  23095         return !(rhs < lhs);
  23096     }
  23097 
  23098     /// @brief comparison: less than or equal
  23099     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23100     template<typename ScalarType, typename std::enable_if<
  23101                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23102     friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
  23103     {
  23104         return lhs <= basic_json(rhs);
  23105     }
  23106 
  23107     /// @brief comparison: less than or equal
  23108     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23109     template<typename ScalarType, typename std::enable_if<
  23110                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23111     friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
  23112     {
  23113         return basic_json(lhs) <= rhs;
  23114     }
  23115 
  23116     /// @brief comparison: greater than
  23117     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
  23118     friend bool operator>(const_reference lhs, const_reference rhs) noexcept
  23119     {
  23120         // double inverse
  23121         if (compares_unordered(lhs, rhs))
  23122         {
  23123             return false;
  23124         }
  23125         return !(lhs <= rhs);
  23126     }
  23127 
  23128     /// @brief comparison: greater than
  23129     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
  23130     template<typename ScalarType, typename std::enable_if<
  23131                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23132     friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
  23133     {
  23134         return lhs > basic_json(rhs);
  23135     }
  23136 
  23137     /// @brief comparison: greater than
  23138     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
  23139     template<typename ScalarType, typename std::enable_if<
  23140                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23141     friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
  23142     {
  23143         return basic_json(lhs) > rhs;
  23144     }
  23145 
  23146     /// @brief comparison: greater than or equal
  23147     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23148     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
  23149     {
  23150         if (compares_unordered(lhs, rhs, true))
  23151         {
  23152             return false;
  23153         }
  23154         return !(lhs < rhs);
  23155     }
  23156 
  23157     /// @brief comparison: greater than or equal
  23158     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23159     template<typename ScalarType, typename std::enable_if<
  23160                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23161     friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
  23162     {
  23163         return lhs >= basic_json(rhs);
  23164     }
  23165 
  23166     /// @brief comparison: greater than or equal
  23167     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23168     template<typename ScalarType, typename std::enable_if<
  23169                  std::is_scalar<ScalarType>::value, int>::type = 0>
  23170     friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
  23171     {
  23172         return basic_json(lhs) >= rhs;
  23173     }
  23174 #endif
  23175 
  23176 #undef JSON_IMPLEMENT_OPERATOR
  23177 
  23178     /// @}
  23179 
  23180     ///////////////////
  23181     // serialization //
  23182     ///////////////////
  23183 
  23184     /// @name serialization
  23185     /// @{
  23186 #ifndef JSON_NO_IO
  23187     /// @brief serialize to stream
  23188     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
  23189     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
  23190     {
  23191         // read width member and use it as indentation parameter if nonzero
  23192         const bool pretty_print = o.width() > 0;
  23193         const auto indentation = pretty_print ? o.width() : 0;
  23194 
  23195         // reset width to 0 for subsequent calls to this stream
  23196         o.width(0);
  23197 
  23198         // do the actual serialization
  23199         serializer s(detail::output_adapter<char>(o), o.fill());
  23200         s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
  23201         return o;
  23202     }
  23203 
  23204     /// @brief serialize to stream
  23205     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
  23206     /// @deprecated This function is deprecated since 3.0.0 and will be removed in
  23207     ///             version 4.0.0 of the library. Please use
  23208     ///             operator<<(std::ostream&, const basic_json&) instead; that is,
  23209     ///             replace calls like `j >> o;` with `o << j;`.
  23210     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
  23211     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
  23212     {
  23213         return o << j;
  23214     }
  23215 #endif  // JSON_NO_IO
  23216     /// @}
  23217 
  23218 
  23219     /////////////////////
  23220     // deserialization //
  23221     /////////////////////
  23222 
  23223     /// @name deserialization
  23224     /// @{
  23225 
  23226     /// @brief deserialize from a compatible input
  23227     /// @sa https://json.nlohmann.me/api/basic_json/parse/
  23228     template<typename InputType>
  23229     JSON_HEDLEY_WARN_UNUSED_RESULT
  23230     static basic_json parse(InputType&& i,
  23231                             const parser_callback_t cb = nullptr,
  23232                             const bool allow_exceptions = true,
  23233                             const bool ignore_comments = false)
  23234     {
  23235         basic_json result;
  23236         parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
  23237         return result;
  23238     }
  23239 
  23240     /// @brief deserialize from a pair of character iterators
  23241     /// @sa https://json.nlohmann.me/api/basic_json/parse/
  23242     template<typename IteratorType>
  23243     JSON_HEDLEY_WARN_UNUSED_RESULT
  23244     static basic_json parse(IteratorType first,
  23245                             IteratorType last,
  23246                             const parser_callback_t cb = nullptr,
  23247                             const bool allow_exceptions = true,
  23248                             const bool ignore_comments = false)
  23249     {
  23250         basic_json result;
  23251         parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
  23252         return result;
  23253     }
  23254 
  23255     JSON_HEDLEY_WARN_UNUSED_RESULT
  23256     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
  23257     static basic_json parse(detail::span_input_adapter&& i,
  23258                             const parser_callback_t cb = nullptr,
  23259                             const bool allow_exceptions = true,
  23260                             const bool ignore_comments = false)
  23261     {
  23262         basic_json result;
  23263         parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
  23264         return result;
  23265     }
  23266 
  23267     /// @brief check if the input is valid JSON
  23268     /// @sa https://json.nlohmann.me/api/basic_json/accept/
  23269     template<typename InputType>
  23270     static bool accept(InputType&& i,
  23271                        const bool ignore_comments = false)
  23272     {
  23273         return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
  23274     }
  23275 
  23276     /// @brief check if the input is valid JSON
  23277     /// @sa https://json.nlohmann.me/api/basic_json/accept/
  23278     template<typename IteratorType>
  23279     static bool accept(IteratorType first, IteratorType last,
  23280                        const bool ignore_comments = false)
  23281     {
  23282         return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
  23283     }
  23284 
  23285     JSON_HEDLEY_WARN_UNUSED_RESULT
  23286     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
  23287     static bool accept(detail::span_input_adapter&& i,
  23288                        const bool ignore_comments = false)
  23289     {
  23290         return parser(i.get(), nullptr, false, ignore_comments).accept(true);
  23291     }
  23292 
  23293     /// @brief generate SAX events
  23294     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
  23295     template <typename InputType, typename SAX>
  23296     JSON_HEDLEY_NON_NULL(2)
  23297     static bool sax_parse(InputType&& i, SAX* sax,
  23298                           input_format_t format = input_format_t::json,
  23299                           const bool strict = true,
  23300                           const bool ignore_comments = false)
  23301     {
  23302         auto ia = detail::input_adapter(std::forward<InputType>(i));
  23303         return format == input_format_t::json
  23304                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
  23305                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
  23306     }
  23307 
  23308     /// @brief generate SAX events
  23309     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
  23310     template<class IteratorType, class SAX>
  23311     JSON_HEDLEY_NON_NULL(3)
  23312     static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
  23313                           input_format_t format = input_format_t::json,
  23314                           const bool strict = true,
  23315                           const bool ignore_comments = false)
  23316     {
  23317         auto ia = detail::input_adapter(std::move(first), std::move(last));
  23318         return format == input_format_t::json
  23319                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
  23320                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
  23321     }
  23322 
  23323     /// @brief generate SAX events
  23324     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
  23325     /// @deprecated This function is deprecated since 3.8.0 and will be removed in
  23326     ///             version 4.0.0 of the library. Please use
  23327     ///             sax_parse(ptr, ptr + len) instead.
  23328     template <typename SAX>
  23329     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
  23330     JSON_HEDLEY_NON_NULL(2)
  23331     static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
  23332                           input_format_t format = input_format_t::json,
  23333                           const bool strict = true,
  23334                           const bool ignore_comments = false)
  23335     {
  23336         auto ia = i.get();
  23337         return format == input_format_t::json
  23338                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23339                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
  23340                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23341                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
  23342     }
  23343 #ifndef JSON_NO_IO
  23344     /// @brief deserialize from stream
  23345     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
  23346     /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
  23347     ///             version 4.0.0 of the library. Please use
  23348     ///             operator>>(std::istream&, basic_json&) instead; that is,
  23349     ///             replace calls like `j << i;` with `i >> j;`.
  23350     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
  23351     friend std::istream& operator<<(basic_json& j, std::istream& i)
  23352     {
  23353         return operator>>(i, j);
  23354     }
  23355 
  23356     /// @brief deserialize from stream
  23357     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
  23358     friend std::istream& operator>>(std::istream& i, basic_json& j)
  23359     {
  23360         parser(detail::input_adapter(i)).parse(false, j);
  23361         return i;
  23362     }
  23363 #endif  // JSON_NO_IO
  23364     /// @}
  23365 
  23366     ///////////////////////////
  23367     // convenience functions //
  23368     ///////////////////////////
  23369 
  23370     /// @brief return the type as string
  23371     /// @sa https://json.nlohmann.me/api/basic_json/type_name/
  23372     JSON_HEDLEY_RETURNS_NON_NULL
  23373     const char* type_name() const noexcept
  23374     {
  23375         switch (m_type)
  23376         {
  23377             case value_t::null:
  23378                 return "null";
  23379             case value_t::object:
  23380                 return "object";
  23381             case value_t::array:
  23382                 return "array";
  23383             case value_t::string:
  23384                 return "string";
  23385             case value_t::boolean:
  23386                 return "boolean";
  23387             case value_t::binary:
  23388                 return "binary";
  23389             case value_t::discarded:
  23390                 return "discarded";
  23391             case value_t::number_integer:
  23392             case value_t::number_unsigned:
  23393             case value_t::number_float:
  23394             default:
  23395                 return "number";
  23396         }
  23397     }
  23398 
  23399 
  23400   JSON_PRIVATE_UNLESS_TESTED:
  23401     //////////////////////
  23402     // member variables //
  23403     //////////////////////
  23404 
  23405     /// the type of the current element
  23406     value_t m_type = value_t::null;
  23407 
  23408     /// the value of the current element
  23409     json_value m_value = {};
  23410 
  23411 #if JSON_DIAGNOSTICS
  23412     /// a pointer to a parent value (for debugging purposes)
  23413     basic_json* m_parent = nullptr;
  23414 #endif
  23415 
  23416     //////////////////////////////////////////
  23417     // binary serialization/deserialization //
  23418     //////////////////////////////////////////
  23419 
  23420     /// @name binary serialization/deserialization support
  23421     /// @{
  23422 
  23423   public:
  23424     /// @brief create a CBOR serialization of a given JSON value
  23425     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
  23426     static std::vector<std::uint8_t> to_cbor(const basic_json& j)
  23427     {
  23428         std::vector<std::uint8_t> result;
  23429         to_cbor(j, result);
  23430         return result;
  23431     }
  23432 
  23433     /// @brief create a CBOR serialization of a given JSON value
  23434     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
  23435     static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
  23436     {
  23437         binary_writer<std::uint8_t>(o).write_cbor(j);
  23438     }
  23439 
  23440     /// @brief create a CBOR serialization of a given JSON value
  23441     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
  23442     static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
  23443     {
  23444         binary_writer<char>(o).write_cbor(j);
  23445     }
  23446 
  23447     /// @brief create a MessagePack serialization of a given JSON value
  23448     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
  23449     static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
  23450     {
  23451         std::vector<std::uint8_t> result;
  23452         to_msgpack(j, result);
  23453         return result;
  23454     }
  23455 
  23456     /// @brief create a MessagePack serialization of a given JSON value
  23457     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
  23458     static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
  23459     {
  23460         binary_writer<std::uint8_t>(o).write_msgpack(j);
  23461     }
  23462 
  23463     /// @brief create a MessagePack serialization of a given JSON value
  23464     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
  23465     static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
  23466     {
  23467         binary_writer<char>(o).write_msgpack(j);
  23468     }
  23469 
  23470     /// @brief create a UBJSON serialization of a given JSON value
  23471     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
  23472     static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
  23473             const bool use_size = false,
  23474             const bool use_type = false)
  23475     {
  23476         std::vector<std::uint8_t> result;
  23477         to_ubjson(j, result, use_size, use_type);
  23478         return result;
  23479     }
  23480 
  23481     /// @brief create a UBJSON serialization of a given JSON value
  23482     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
  23483     static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
  23484                           const bool use_size = false, const bool use_type = false)
  23485     {
  23486         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
  23487     }
  23488 
  23489     /// @brief create a UBJSON serialization of a given JSON value
  23490     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
  23491     static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
  23492                           const bool use_size = false, const bool use_type = false)
  23493     {
  23494         binary_writer<char>(o).write_ubjson(j, use_size, use_type);
  23495     }
  23496 
  23497     /// @brief create a BJData serialization of a given JSON value
  23498     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
  23499     static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
  23500             const bool use_size = false,
  23501             const bool use_type = false)
  23502     {
  23503         std::vector<std::uint8_t> result;
  23504         to_bjdata(j, result, use_size, use_type);
  23505         return result;
  23506     }
  23507 
  23508     /// @brief create a BJData serialization of a given JSON value
  23509     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
  23510     static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
  23511                           const bool use_size = false, const bool use_type = false)
  23512     {
  23513         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
  23514     }
  23515 
  23516     /// @brief create a BJData serialization of a given JSON value
  23517     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
  23518     static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
  23519                           const bool use_size = false, const bool use_type = false)
  23520     {
  23521         binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
  23522     }
  23523 
  23524     /// @brief create a BSON serialization of a given JSON value
  23525     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
  23526     static std::vector<std::uint8_t> to_bson(const basic_json& j)
  23527     {
  23528         std::vector<std::uint8_t> result;
  23529         to_bson(j, result);
  23530         return result;
  23531     }
  23532 
  23533     /// @brief create a BSON serialization of a given JSON value
  23534     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
  23535     static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
  23536     {
  23537         binary_writer<std::uint8_t>(o).write_bson(j);
  23538     }
  23539 
  23540     /// @brief create a BSON serialization of a given JSON value
  23541     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
  23542     static void to_bson(const basic_json& j, detail::output_adapter<char> o)
  23543     {
  23544         binary_writer<char>(o).write_bson(j);
  23545     }
  23546 
  23547     /// @brief create a JSON value from an input in CBOR format
  23548     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
  23549     template<typename InputType>
  23550     JSON_HEDLEY_WARN_UNUSED_RESULT
  23551     static basic_json from_cbor(InputType&& i,
  23552                                 const bool strict = true,
  23553                                 const bool allow_exceptions = true,
  23554                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23555     {
  23556         basic_json result;
  23557         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23558         auto ia = detail::input_adapter(std::forward<InputType>(i));
  23559         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
  23560         return res ? result : basic_json(value_t::discarded);
  23561     }
  23562 
  23563     /// @brief create a JSON value from an input in CBOR format
  23564     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
  23565     template<typename IteratorType>
  23566     JSON_HEDLEY_WARN_UNUSED_RESULT
  23567     static basic_json from_cbor(IteratorType first, IteratorType last,
  23568                                 const bool strict = true,
  23569                                 const bool allow_exceptions = true,
  23570                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23571     {
  23572         basic_json result;
  23573         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23574         auto ia = detail::input_adapter(std::move(first), std::move(last));
  23575         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
  23576         return res ? result : basic_json(value_t::discarded);
  23577     }
  23578 
  23579     template<typename T>
  23580     JSON_HEDLEY_WARN_UNUSED_RESULT
  23581     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
  23582     static basic_json from_cbor(const T* ptr, std::size_t len,
  23583                                 const bool strict = true,
  23584                                 const bool allow_exceptions = true,
  23585                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23586     {
  23587         return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
  23588     }
  23589 
  23590 
  23591     JSON_HEDLEY_WARN_UNUSED_RESULT
  23592     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
  23593     static basic_json from_cbor(detail::span_input_adapter&& i,
  23594                                 const bool strict = true,
  23595                                 const bool allow_exceptions = true,
  23596                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23597     {
  23598         basic_json result;
  23599         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23600         auto ia = i.get();
  23601         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23602         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
  23603         return res ? result : basic_json(value_t::discarded);
  23604     }
  23605 
  23606     /// @brief create a JSON value from an input in MessagePack format
  23607     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
  23608     template<typename InputType>
  23609     JSON_HEDLEY_WARN_UNUSED_RESULT
  23610     static basic_json from_msgpack(InputType&& i,
  23611                                    const bool strict = true,
  23612                                    const bool allow_exceptions = true)
  23613     {
  23614         basic_json result;
  23615         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23616         auto ia = detail::input_adapter(std::forward<InputType>(i));
  23617         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
  23618         return res ? result : basic_json(value_t::discarded);
  23619     }
  23620 
  23621     /// @brief create a JSON value from an input in MessagePack format
  23622     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
  23623     template<typename IteratorType>
  23624     JSON_HEDLEY_WARN_UNUSED_RESULT
  23625     static basic_json from_msgpack(IteratorType first, IteratorType last,
  23626                                    const bool strict = true,
  23627                                    const bool allow_exceptions = true)
  23628     {
  23629         basic_json result;
  23630         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23631         auto ia = detail::input_adapter(std::move(first), std::move(last));
  23632         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
  23633         return res ? result : basic_json(value_t::discarded);
  23634     }
  23635 
  23636     template<typename T>
  23637     JSON_HEDLEY_WARN_UNUSED_RESULT
  23638     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
  23639     static basic_json from_msgpack(const T* ptr, std::size_t len,
  23640                                    const bool strict = true,
  23641                                    const bool allow_exceptions = true)
  23642     {
  23643         return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
  23644     }
  23645 
  23646     JSON_HEDLEY_WARN_UNUSED_RESULT
  23647     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
  23648     static basic_json from_msgpack(detail::span_input_adapter&& i,
  23649                                    const bool strict = true,
  23650                                    const bool allow_exceptions = true)
  23651     {
  23652         basic_json result;
  23653         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23654         auto ia = i.get();
  23655         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23656         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
  23657         return res ? result : basic_json(value_t::discarded);
  23658     }
  23659 
  23660     /// @brief create a JSON value from an input in UBJSON format
  23661     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
  23662     template<typename InputType>
  23663     JSON_HEDLEY_WARN_UNUSED_RESULT
  23664     static basic_json from_ubjson(InputType&& i,
  23665                                   const bool strict = true,
  23666                                   const bool allow_exceptions = true)
  23667     {
  23668         basic_json result;
  23669         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23670         auto ia = detail::input_adapter(std::forward<InputType>(i));
  23671         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
  23672         return res ? result : basic_json(value_t::discarded);
  23673     }
  23674 
  23675     /// @brief create a JSON value from an input in UBJSON format
  23676     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
  23677     template<typename IteratorType>
  23678     JSON_HEDLEY_WARN_UNUSED_RESULT
  23679     static basic_json from_ubjson(IteratorType first, IteratorType last,
  23680                                   const bool strict = true,
  23681                                   const bool allow_exceptions = true)
  23682     {
  23683         basic_json result;
  23684         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23685         auto ia = detail::input_adapter(std::move(first), std::move(last));
  23686         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
  23687         return res ? result : basic_json(value_t::discarded);
  23688     }
  23689 
  23690     template<typename T>
  23691     JSON_HEDLEY_WARN_UNUSED_RESULT
  23692     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
  23693     static basic_json from_ubjson(const T* ptr, std::size_t len,
  23694                                   const bool strict = true,
  23695                                   const bool allow_exceptions = true)
  23696     {
  23697         return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
  23698     }
  23699 
  23700     JSON_HEDLEY_WARN_UNUSED_RESULT
  23701     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
  23702     static basic_json from_ubjson(detail::span_input_adapter&& i,
  23703                                   const bool strict = true,
  23704                                   const bool allow_exceptions = true)
  23705     {
  23706         basic_json result;
  23707         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23708         auto ia = i.get();
  23709         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23710         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
  23711         return res ? result : basic_json(value_t::discarded);
  23712     }
  23713 
  23714 
  23715     /// @brief create a JSON value from an input in BJData format
  23716     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
  23717     template<typename InputType>
  23718     JSON_HEDLEY_WARN_UNUSED_RESULT
  23719     static basic_json from_bjdata(InputType&& i,
  23720                                   const bool strict = true,
  23721                                   const bool allow_exceptions = true)
  23722     {
  23723         basic_json result;
  23724         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23725         auto ia = detail::input_adapter(std::forward<InputType>(i));
  23726         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
  23727         return res ? result : basic_json(value_t::discarded);
  23728     }
  23729 
  23730     /// @brief create a JSON value from an input in BJData format
  23731     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
  23732     template<typename IteratorType>
  23733     JSON_HEDLEY_WARN_UNUSED_RESULT
  23734     static basic_json from_bjdata(IteratorType first, IteratorType last,
  23735                                   const bool strict = true,
  23736                                   const bool allow_exceptions = true)
  23737     {
  23738         basic_json result;
  23739         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23740         auto ia = detail::input_adapter(std::move(first), std::move(last));
  23741         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
  23742         return res ? result : basic_json(value_t::discarded);
  23743     }
  23744 
  23745     /// @brief create a JSON value from an input in BSON format
  23746     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
  23747     template<typename InputType>
  23748     JSON_HEDLEY_WARN_UNUSED_RESULT
  23749     static basic_json from_bson(InputType&& i,
  23750                                 const bool strict = true,
  23751                                 const bool allow_exceptions = true)
  23752     {
  23753         basic_json result;
  23754         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23755         auto ia = detail::input_adapter(std::forward<InputType>(i));
  23756         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
  23757         return res ? result : basic_json(value_t::discarded);
  23758     }
  23759 
  23760     /// @brief create a JSON value from an input in BSON format
  23761     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
  23762     template<typename IteratorType>
  23763     JSON_HEDLEY_WARN_UNUSED_RESULT
  23764     static basic_json from_bson(IteratorType first, IteratorType last,
  23765                                 const bool strict = true,
  23766                                 const bool allow_exceptions = true)
  23767     {
  23768         basic_json result;
  23769         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23770         auto ia = detail::input_adapter(std::move(first), std::move(last));
  23771         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
  23772         return res ? result : basic_json(value_t::discarded);
  23773     }
  23774 
  23775     template<typename T>
  23776     JSON_HEDLEY_WARN_UNUSED_RESULT
  23777     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
  23778     static basic_json from_bson(const T* ptr, std::size_t len,
  23779                                 const bool strict = true,
  23780                                 const bool allow_exceptions = true)
  23781     {
  23782         return from_bson(ptr, ptr + len, strict, allow_exceptions);
  23783     }
  23784 
  23785     JSON_HEDLEY_WARN_UNUSED_RESULT
  23786     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
  23787     static basic_json from_bson(detail::span_input_adapter&& i,
  23788                                 const bool strict = true,
  23789                                 const bool allow_exceptions = true)
  23790     {
  23791         basic_json result;
  23792         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23793         auto ia = i.get();
  23794         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23795         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
  23796         return res ? result : basic_json(value_t::discarded);
  23797     }
  23798     /// @}
  23799 
  23800     //////////////////////////
  23801     // JSON Pointer support //
  23802     //////////////////////////
  23803 
  23804     /// @name JSON Pointer functions
  23805     /// @{
  23806 
  23807     /// @brief access specified element via JSON Pointer
  23808     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  23809     reference operator[](const json_pointer& ptr)
  23810     {
  23811         return ptr.get_unchecked(this);
  23812     }
  23813 
  23814     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23815     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23816     reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
  23817     {
  23818         return ptr.get_unchecked(this);
  23819     }
  23820 
  23821     /// @brief access specified element via JSON Pointer
  23822     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  23823     const_reference operator[](const json_pointer& ptr) const
  23824     {
  23825         return ptr.get_unchecked(this);
  23826     }
  23827 
  23828     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23829     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23830     const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
  23831     {
  23832         return ptr.get_unchecked(this);
  23833     }
  23834 
  23835     /// @brief access specified element via JSON Pointer
  23836     /// @sa https://json.nlohmann.me/api/basic_json/at/
  23837     reference at(const json_pointer& ptr)
  23838     {
  23839         return ptr.get_checked(this);
  23840     }
  23841 
  23842     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23843     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23844     reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
  23845     {
  23846         return ptr.get_checked(this);
  23847     }
  23848 
  23849     /// @brief access specified element via JSON Pointer
  23850     /// @sa https://json.nlohmann.me/api/basic_json/at/
  23851     const_reference at(const json_pointer& ptr) const
  23852     {
  23853         return ptr.get_checked(this);
  23854     }
  23855 
  23856     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23857     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23858     const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
  23859     {
  23860         return ptr.get_checked(this);
  23861     }
  23862 
  23863     /// @brief return flattened JSON value
  23864     /// @sa https://json.nlohmann.me/api/basic_json/flatten/
  23865     basic_json flatten() const
  23866     {
  23867         basic_json result(value_t::object);
  23868         json_pointer::flatten("", *this, result);
  23869         return result;
  23870     }
  23871 
  23872     /// @brief unflatten a previously flattened JSON value
  23873     /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
  23874     basic_json unflatten() const
  23875     {
  23876         return json_pointer::unflatten(*this);
  23877     }
  23878 
  23879     /// @}
  23880 
  23881     //////////////////////////
  23882     // JSON Patch functions //
  23883     //////////////////////////
  23884 
  23885     /// @name JSON Patch functions
  23886     /// @{
  23887 
  23888     /// @brief applies a JSON patch in-place without copying the object
  23889     /// @sa https://json.nlohmann.me/api/basic_json/patch/
  23890     void patch_inplace(const basic_json& json_patch)
  23891     {
  23892         basic_json& result = *this;
  23893         // the valid JSON Patch operations
  23894         enum class patch_operations {add, remove, replace, move, copy, test, invalid};
  23895 
  23896         const auto get_op = [](const std::string & op)
  23897         {
  23898             if (op == "add")
  23899             {
  23900                 return patch_operations::add;
  23901             }
  23902             if (op == "remove")
  23903             {
  23904                 return patch_operations::remove;
  23905             }
  23906             if (op == "replace")
  23907             {
  23908                 return patch_operations::replace;
  23909             }
  23910             if (op == "move")
  23911             {
  23912                 return patch_operations::move;
  23913             }
  23914             if (op == "copy")
  23915             {
  23916                 return patch_operations::copy;
  23917             }
  23918             if (op == "test")
  23919             {
  23920                 return patch_operations::test;
  23921             }
  23922 
  23923             return patch_operations::invalid;
  23924         };
  23925 
  23926         // wrapper for "add" operation; add value at ptr
  23927         const auto operation_add = [&result](json_pointer & ptr, basic_json val)
  23928         {
  23929             // adding to the root of the target document means replacing it
  23930             if (ptr.empty())
  23931             {
  23932                 result = val;
  23933                 return;
  23934             }
  23935 
  23936             // make sure the top element of the pointer exists
  23937             json_pointer const top_pointer = ptr.top();
  23938             if (top_pointer != ptr)
  23939             {
  23940                 result.at(top_pointer);
  23941             }
  23942 
  23943             // get reference to parent of JSON pointer ptr
  23944             const auto last_path = ptr.back();
  23945             ptr.pop_back();
  23946             // parent must exist when performing patch add per RFC6902 specs
  23947             basic_json& parent = result.at(ptr);
  23948 
  23949             switch (parent.m_type)
  23950             {
  23951                 case value_t::null:
  23952                 case value_t::object:
  23953                 {
  23954                     // use operator[] to add value
  23955                     parent[last_path] = val;
  23956                     break;
  23957                 }
  23958 
  23959                 case value_t::array:
  23960                 {
  23961                     if (last_path == "-")
  23962                     {
  23963                         // special case: append to back
  23964                         parent.push_back(val);
  23965                     }
  23966                     else
  23967                     {
  23968                         const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
  23969                         if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
  23970                         {
  23971                             // avoid undefined behavior
  23972                             JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
  23973                         }
  23974 
  23975                         // default case: insert add offset
  23976                         parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
  23977                     }
  23978                     break;
  23979                 }
  23980 
  23981                 // if there exists a parent it cannot be primitive
  23982                 case value_t::string: // LCOV_EXCL_LINE
  23983                 case value_t::boolean: // LCOV_EXCL_LINE
  23984                 case value_t::number_integer: // LCOV_EXCL_LINE
  23985                 case value_t::number_unsigned: // LCOV_EXCL_LINE
  23986                 case value_t::number_float: // LCOV_EXCL_LINE
  23987                 case value_t::binary: // LCOV_EXCL_LINE
  23988                 case value_t::discarded: // LCOV_EXCL_LINE
  23989                 default:            // LCOV_EXCL_LINE
  23990                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  23991             }
  23992         };
  23993 
  23994         // wrapper for "remove" operation; remove value at ptr
  23995         const auto operation_remove = [this, &result](json_pointer & ptr)
  23996         {
  23997             // get reference to parent of JSON pointer ptr
  23998             const auto last_path = ptr.back();
  23999             ptr.pop_back();
  24000             basic_json& parent = result.at(ptr);
  24001 
  24002             // remove child
  24003             if (parent.is_object())
  24004             {
  24005                 // perform range check
  24006                 auto it = parent.find(last_path);
  24007                 if (JSON_HEDLEY_LIKELY(it != parent.end()))
  24008                 {
  24009                     parent.erase(it);
  24010                 }
  24011                 else
  24012                 {
  24013                     JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
  24014                 }
  24015             }
  24016             else if (parent.is_array())
  24017             {
  24018                 // note erase performs range check
  24019                 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
  24020             }
  24021         };
  24022 
  24023         // type check: top level value must be an array
  24024         if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
  24025         {
  24026             JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
  24027         }
  24028 
  24029         // iterate and apply the operations
  24030         for (const auto& val : json_patch)
  24031         {
  24032             // wrapper to get a value for an operation
  24033             const auto get_value = [&val](const std::string & op,
  24034                                           const std::string & member,
  24035                                           bool string_type) -> basic_json &
  24036             {
  24037                 // find value
  24038                 auto it = val.m_value.object->find(member);
  24039 
  24040                 // context-sensitive error message
  24041                 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
  24042 
  24043                 // check if desired value is present
  24044                 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
  24045                 {
  24046                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
  24047                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
  24048                 }
  24049 
  24050                 // check if result is of type string
  24051                 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
  24052                 {
  24053                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
  24054                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
  24055                 }
  24056 
  24057                 // no error: return value
  24058                 return it->second;
  24059             };
  24060 
  24061             // type check: every element of the array must be an object
  24062             if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
  24063             {
  24064                 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
  24065             }
  24066 
  24067             // collect mandatory members
  24068             const auto op = get_value("op", "op", true).template get<std::string>();
  24069             const auto path = get_value(op, "path", true).template get<std::string>();
  24070             json_pointer ptr(path);
  24071 
  24072             switch (get_op(op))
  24073             {
  24074                 case patch_operations::add:
  24075                 {
  24076                     operation_add(ptr, get_value("add", "value", false));
  24077                     break;
  24078                 }
  24079 
  24080                 case patch_operations::remove:
  24081                 {
  24082                     operation_remove(ptr);
  24083                     break;
  24084                 }
  24085 
  24086                 case patch_operations::replace:
  24087                 {
  24088                     // the "path" location must exist - use at()
  24089                     result.at(ptr) = get_value("replace", "value", false);
  24090                     break;
  24091                 }
  24092 
  24093                 case patch_operations::move:
  24094                 {
  24095                     const auto from_path = get_value("move", "from", true).template get<std::string>();
  24096                     json_pointer from_ptr(from_path);
  24097 
  24098                     // the "from" location must exist - use at()
  24099                     basic_json const v = result.at(from_ptr);
  24100 
  24101                     // The move operation is functionally identical to a
  24102                     // "remove" operation on the "from" location, followed
  24103                     // immediately by an "add" operation at the target
  24104                     // location with the value that was just removed.
  24105                     operation_remove(from_ptr);
  24106                     operation_add(ptr, v);
  24107                     break;
  24108                 }
  24109 
  24110                 case patch_operations::copy:
  24111                 {
  24112                     const auto from_path = get_value("copy", "from", true).template get<std::string>();
  24113                     const json_pointer from_ptr(from_path);
  24114 
  24115                     // the "from" location must exist - use at()
  24116                     basic_json const v = result.at(from_ptr);
  24117 
  24118                     // The copy is functionally identical to an "add"
  24119                     // operation at the target location using the value
  24120                     // specified in the "from" member.
  24121                     operation_add(ptr, v);
  24122                     break;
  24123                 }
  24124 
  24125                 case patch_operations::test:
  24126                 {
  24127                     bool success = false;
  24128                     JSON_TRY
  24129                     {
  24130                         // check if "value" matches the one at "path"
  24131                         // the "path" location must exist - use at()
  24132                         success = (result.at(ptr) == get_value("test", "value", false));
  24133                     }
  24134                     JSON_INTERNAL_CATCH (out_of_range&)
  24135                     {
  24136                         // ignore out of range errors: success remains false
  24137                     }
  24138 
  24139                     // throw an exception if test fails
  24140                     if (JSON_HEDLEY_UNLIKELY(!success))
  24141                     {
  24142                         JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
  24143                     }
  24144 
  24145                     break;
  24146                 }
  24147 
  24148                 case patch_operations::invalid:
  24149                 default:
  24150                 {
  24151                     // op must be "add", "remove", "replace", "move", "copy", or
  24152                     // "test"
  24153                     JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
  24154                 }
  24155             }
  24156         }
  24157     }
  24158 
  24159     /// @brief applies a JSON patch to a copy of the current object
  24160     /// @sa https://json.nlohmann.me/api/basic_json/patch/
  24161     basic_json patch(const basic_json& json_patch) const
  24162     {
  24163         basic_json result = *this;
  24164         result.patch_inplace(json_patch);
  24165         return result;
  24166     }
  24167 
  24168     /// @brief creates a diff as a JSON patch
  24169     /// @sa https://json.nlohmann.me/api/basic_json/diff/
  24170     JSON_HEDLEY_WARN_UNUSED_RESULT
  24171     static basic_json diff(const basic_json& source, const basic_json& target,
  24172                            const std::string& path = "")
  24173     {
  24174         // the patch
  24175         basic_json result(value_t::array);
  24176 
  24177         // if the values are the same, return empty patch
  24178         if (source == target)
  24179         {
  24180             return result;
  24181         }
  24182 
  24183         if (source.type() != target.type())
  24184         {
  24185             // different types: replace value
  24186             result.push_back(
  24187             {
  24188                 {"op", "replace"}, {"path", path}, {"value", target}
  24189             });
  24190             return result;
  24191         }
  24192 
  24193         switch (source.type())
  24194         {
  24195             case value_t::array:
  24196             {
  24197                 // first pass: traverse common elements
  24198                 std::size_t i = 0;
  24199                 while (i < source.size() && i < target.size())
  24200                 {
  24201                     // recursive call to compare array values at index i
  24202                     auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
  24203                     result.insert(result.end(), temp_diff.begin(), temp_diff.end());
  24204                     ++i;
  24205                 }
  24206 
  24207                 // We now reached the end of at least one array
  24208                 // in a second pass, traverse the remaining elements
  24209 
  24210                 // remove my remaining elements
  24211                 const auto end_index = static_cast<difference_type>(result.size());
  24212                 while (i < source.size())
  24213                 {
  24214                     // add operations in reverse order to avoid invalid
  24215                     // indices
  24216                     result.insert(result.begin() + end_index, object(
  24217                     {
  24218                         {"op", "remove"},
  24219                         {"path", detail::concat(path, '/', std::to_string(i))}
  24220                     }));
  24221                     ++i;
  24222                 }
  24223 
  24224                 // add other remaining elements
  24225                 while (i < target.size())
  24226                 {
  24227                     result.push_back(
  24228                     {
  24229                         {"op", "add"},
  24230                         {"path", detail::concat(path, "/-")},
  24231                         {"value", target[i]}
  24232                     });
  24233                     ++i;
  24234                 }
  24235 
  24236                 break;
  24237             }
  24238 
  24239             case value_t::object:
  24240             {
  24241                 // first pass: traverse this object's elements
  24242                 for (auto it = source.cbegin(); it != source.cend(); ++it)
  24243                 {
  24244                     // escape the key name to be used in a JSON patch
  24245                     const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
  24246 
  24247                     if (target.find(it.key()) != target.end())
  24248                     {
  24249                         // recursive call to compare object values at key it
  24250                         auto temp_diff = diff(it.value(), target[it.key()], path_key);
  24251                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());
  24252                     }
  24253                     else
  24254                     {
  24255                         // found a key that is not in o -> remove it
  24256                         result.push_back(object(
  24257                         {
  24258                             {"op", "remove"}, {"path", path_key}
  24259                         }));
  24260                     }
  24261                 }
  24262 
  24263                 // second pass: traverse other object's elements
  24264                 for (auto it = target.cbegin(); it != target.cend(); ++it)
  24265                 {
  24266                     if (source.find(it.key()) == source.end())
  24267                     {
  24268                         // found a key that is not in this -> add it
  24269                         const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
  24270                         result.push_back(
  24271                         {
  24272                             {"op", "add"}, {"path", path_key},
  24273                             {"value", it.value()}
  24274                         });
  24275                     }
  24276                 }
  24277 
  24278                 break;
  24279             }
  24280 
  24281             case value_t::null:
  24282             case value_t::string:
  24283             case value_t::boolean:
  24284             case value_t::number_integer:
  24285             case value_t::number_unsigned:
  24286             case value_t::number_float:
  24287             case value_t::binary:
  24288             case value_t::discarded:
  24289             default:
  24290             {
  24291                 // both primitive type: replace value
  24292                 result.push_back(
  24293                 {
  24294                     {"op", "replace"}, {"path", path}, {"value", target}
  24295                 });
  24296                 break;
  24297             }
  24298         }
  24299 
  24300         return result;
  24301     }
  24302     /// @}
  24303 
  24304     ////////////////////////////////
  24305     // JSON Merge Patch functions //
  24306     ////////////////////////////////
  24307 
  24308     /// @name JSON Merge Patch functions
  24309     /// @{
  24310 
  24311     /// @brief applies a JSON Merge Patch
  24312     /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
  24313     void merge_patch(const basic_json& apply_patch)
  24314     {
  24315         if (apply_patch.is_object())
  24316         {
  24317             if (!is_object())
  24318             {
  24319                 *this = object();
  24320             }
  24321             for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
  24322             {
  24323                 if (it.value().is_null())
  24324                 {
  24325                     erase(it.key());
  24326                 }
  24327                 else
  24328                 {
  24329                     operator[](it.key()).merge_patch(it.value());
  24330                 }
  24331             }
  24332         }
  24333         else
  24334         {
  24335             *this = apply_patch;
  24336         }
  24337     }
  24338 
  24339     /// @}
  24340 };
  24341 
  24342 /// @brief user-defined to_string function for JSON values
  24343 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
  24344 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24345 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
  24346 {
  24347     return j.dump();
  24348 }
  24349 
  24350 inline namespace literals
  24351 {
  24352 inline namespace json_literals
  24353 {
  24354 
  24355 /// @brief user-defined string literal for JSON values
  24356 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
  24357 JSON_HEDLEY_NON_NULL(1)
  24358 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
  24359 {
  24360     return nlohmann::json::parse(s, s + n);
  24361 }
  24362 
  24363 /// @brief user-defined string literal for JSON pointer
  24364 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
  24365 JSON_HEDLEY_NON_NULL(1)
  24366 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
  24367 {
  24368     return nlohmann::json::json_pointer(std::string(s, n));
  24369 }
  24370 
  24371 }  // namespace json_literals
  24372 }  // namespace literals
  24373 NLOHMANN_JSON_NAMESPACE_END
  24374 
  24375 ///////////////////////
  24376 // nonmember support //
  24377 ///////////////////////
  24378 
  24379 namespace std // NOLINT(cert-dcl58-cpp)
  24380 {
  24381 
  24382 /// @brief hash value for JSON objects
  24383 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
  24384 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24385 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
  24386 {
  24387     std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
  24388     {
  24389         return nlohmann::detail::hash(j);
  24390     }
  24391 };
  24392 
  24393 // specialization for std::less<value_t>
  24394 template<>
  24395 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
  24396 {
  24397     /*!
  24398     @brief compare two value_t enum values
  24399     @since version 3.0.0
  24400     */
  24401     bool operator()(::nlohmann::detail::value_t lhs,
  24402                     ::nlohmann::detail::value_t rhs) const noexcept
  24403     {
  24404 #if JSON_HAS_THREE_WAY_COMPARISON
  24405         return std::is_lt(lhs <=> rhs); // *NOPAD*
  24406 #else
  24407         return ::nlohmann::detail::operator<(lhs, rhs);
  24408 #endif
  24409     }
  24410 };
  24411 
  24412 // C++20 prohibit function specialization in the std namespace.
  24413 #ifndef JSON_HAS_CPP_20
  24414 
  24415 /// @brief exchanges the values of two JSON objects
  24416 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
  24417 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24418 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
  24419     is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression)
  24420     is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
  24421 {
  24422     j1.swap(j2);
  24423 }
  24424 
  24425 #endif
  24426 
  24427 }  // namespace std
  24428 
  24429 #if JSON_USE_GLOBAL_UDLS
  24430     using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
  24431     using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
  24432 #endif
  24433 
  24434 // #include <nlohmann/detail/macro_unscope.hpp>
  24435 //     __ _____ _____ _____
  24436 //  __|  |   __|     |   | |  JSON for Modern C++
  24437 // |  |  |__   |  |  | | | |  version 3.11.2
  24438 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  24439 //
  24440 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  24441 // SPDX-License-Identifier: MIT
  24442 
  24443 
  24444 
  24445 // restore clang diagnostic settings
  24446 #if defined(__clang__)
  24447     #pragma clang diagnostic pop
  24448 #endif
  24449 
  24450 // clean up
  24451 #undef JSON_ASSERT
  24452 #undef JSON_INTERNAL_CATCH
  24453 #undef JSON_THROW
  24454 #undef JSON_PRIVATE_UNLESS_TESTED
  24455 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24456 #undef NLOHMANN_BASIC_JSON_TPL
  24457 #undef JSON_EXPLICIT
  24458 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
  24459 #undef JSON_INLINE_VARIABLE
  24460 #undef JSON_NO_UNIQUE_ADDRESS
  24461 #undef JSON_DISABLE_ENUM_SERIALIZATION
  24462 #undef JSON_USE_GLOBAL_UDLS
  24463 
  24464 #ifndef JSON_TEST_KEEP_MACROS
  24465     #undef JSON_CATCH
  24466     #undef JSON_TRY
  24467     #undef JSON_HAS_CPP_11
  24468     #undef JSON_HAS_CPP_14
  24469     #undef JSON_HAS_CPP_17
  24470     #undef JSON_HAS_CPP_20
  24471     #undef JSON_HAS_FILESYSTEM
  24472     #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
  24473     #undef JSON_HAS_THREE_WAY_COMPARISON
  24474     #undef JSON_HAS_RANGES
  24475     #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
  24476 #endif
  24477 
  24478 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
  24479 //     __ _____ _____ _____
  24480 //  __|  |   __|     |   | |  JSON for Modern C++
  24481 // |  |  |__   |  |  | | | |  version 3.11.2
  24482 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  24483 //
  24484 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
  24485 // SPDX-License-Identifier: MIT
  24486 
  24487 
  24488 
  24489 #undef JSON_HEDLEY_ALWAYS_INLINE
  24490 #undef JSON_HEDLEY_ARM_VERSION
  24491 #undef JSON_HEDLEY_ARM_VERSION_CHECK
  24492 #undef JSON_HEDLEY_ARRAY_PARAM
  24493 #undef JSON_HEDLEY_ASSUME
  24494 #undef JSON_HEDLEY_BEGIN_C_DECLS
  24495 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
  24496 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
  24497 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
  24498 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
  24499 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
  24500 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
  24501 #undef JSON_HEDLEY_CLANG_HAS_WARNING
  24502 #undef JSON_HEDLEY_COMPCERT_VERSION
  24503 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
  24504 #undef JSON_HEDLEY_CONCAT
  24505 #undef JSON_HEDLEY_CONCAT3
  24506 #undef JSON_HEDLEY_CONCAT3_EX
  24507 #undef JSON_HEDLEY_CONCAT_EX
  24508 #undef JSON_HEDLEY_CONST
  24509 #undef JSON_HEDLEY_CONSTEXPR
  24510 #undef JSON_HEDLEY_CONST_CAST
  24511 #undef JSON_HEDLEY_CPP_CAST
  24512 #undef JSON_HEDLEY_CRAY_VERSION
  24513 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
  24514 #undef JSON_HEDLEY_C_DECL
  24515 #undef JSON_HEDLEY_DEPRECATED
  24516 #undef JSON_HEDLEY_DEPRECATED_FOR
  24517 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
  24518 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
  24519 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
  24520 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
  24521 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
  24522 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
  24523 #undef JSON_HEDLEY_DIAGNOSTIC_POP
  24524 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
  24525 #undef JSON_HEDLEY_DMC_VERSION
  24526 #undef JSON_HEDLEY_DMC_VERSION_CHECK
  24527 #undef JSON_HEDLEY_EMPTY_BASES
  24528 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
  24529 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
  24530 #undef JSON_HEDLEY_END_C_DECLS
  24531 #undef JSON_HEDLEY_FLAGS
  24532 #undef JSON_HEDLEY_FLAGS_CAST
  24533 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
  24534 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
  24535 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
  24536 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
  24537 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
  24538 #undef JSON_HEDLEY_GCC_HAS_FEATURE
  24539 #undef JSON_HEDLEY_GCC_HAS_WARNING
  24540 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
  24541 #undef JSON_HEDLEY_GCC_VERSION
  24542 #undef JSON_HEDLEY_GCC_VERSION_CHECK
  24543 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
  24544 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
  24545 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
  24546 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
  24547 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
  24548 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
  24549 #undef JSON_HEDLEY_GNUC_HAS_WARNING
  24550 #undef JSON_HEDLEY_GNUC_VERSION
  24551 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
  24552 #undef JSON_HEDLEY_HAS_ATTRIBUTE
  24553 #undef JSON_HEDLEY_HAS_BUILTIN
  24554 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
  24555 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
  24556 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
  24557 #undef JSON_HEDLEY_HAS_EXTENSION
  24558 #undef JSON_HEDLEY_HAS_FEATURE
  24559 #undef JSON_HEDLEY_HAS_WARNING
  24560 #undef JSON_HEDLEY_IAR_VERSION
  24561 #undef JSON_HEDLEY_IAR_VERSION_CHECK
  24562 #undef JSON_HEDLEY_IBM_VERSION
  24563 #undef JSON_HEDLEY_IBM_VERSION_CHECK
  24564 #undef JSON_HEDLEY_IMPORT
  24565 #undef JSON_HEDLEY_INLINE
  24566 #undef JSON_HEDLEY_INTEL_CL_VERSION
  24567 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
  24568 #undef JSON_HEDLEY_INTEL_VERSION
  24569 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
  24570 #undef JSON_HEDLEY_IS_CONSTANT
  24571 #undef JSON_HEDLEY_IS_CONSTEXPR_
  24572 #undef JSON_HEDLEY_LIKELY
  24573 #undef JSON_HEDLEY_MALLOC
  24574 #undef JSON_HEDLEY_MCST_LCC_VERSION
  24575 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
  24576 #undef JSON_HEDLEY_MESSAGE
  24577 #undef JSON_HEDLEY_MSVC_VERSION
  24578 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
  24579 #undef JSON_HEDLEY_NEVER_INLINE
  24580 #undef JSON_HEDLEY_NON_NULL
  24581 #undef JSON_HEDLEY_NO_ESCAPE
  24582 #undef JSON_HEDLEY_NO_RETURN
  24583 #undef JSON_HEDLEY_NO_THROW
  24584 #undef JSON_HEDLEY_NULL
  24585 #undef JSON_HEDLEY_PELLES_VERSION
  24586 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
  24587 #undef JSON_HEDLEY_PGI_VERSION
  24588 #undef JSON_HEDLEY_PGI_VERSION_CHECK
  24589 #undef JSON_HEDLEY_PREDICT
  24590 #undef JSON_HEDLEY_PRINTF_FORMAT
  24591 #undef JSON_HEDLEY_PRIVATE
  24592 #undef JSON_HEDLEY_PUBLIC
  24593 #undef JSON_HEDLEY_PURE
  24594 #undef JSON_HEDLEY_REINTERPRET_CAST
  24595 #undef JSON_HEDLEY_REQUIRE
  24596 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
  24597 #undef JSON_HEDLEY_REQUIRE_MSG
  24598 #undef JSON_HEDLEY_RESTRICT
  24599 #undef JSON_HEDLEY_RETURNS_NON_NULL
  24600 #undef JSON_HEDLEY_SENTINEL
  24601 #undef JSON_HEDLEY_STATIC_ASSERT
  24602 #undef JSON_HEDLEY_STATIC_CAST
  24603 #undef JSON_HEDLEY_STRINGIFY
  24604 #undef JSON_HEDLEY_STRINGIFY_EX
  24605 #undef JSON_HEDLEY_SUNPRO_VERSION
  24606 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
  24607 #undef JSON_HEDLEY_TINYC_VERSION
  24608 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
  24609 #undef JSON_HEDLEY_TI_ARMCL_VERSION
  24610 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
  24611 #undef JSON_HEDLEY_TI_CL2000_VERSION
  24612 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
  24613 #undef JSON_HEDLEY_TI_CL430_VERSION
  24614 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
  24615 #undef JSON_HEDLEY_TI_CL6X_VERSION
  24616 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
  24617 #undef JSON_HEDLEY_TI_CL7X_VERSION
  24618 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
  24619 #undef JSON_HEDLEY_TI_CLPRU_VERSION
  24620 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
  24621 #undef JSON_HEDLEY_TI_VERSION
  24622 #undef JSON_HEDLEY_TI_VERSION_CHECK
  24623 #undef JSON_HEDLEY_UNAVAILABLE
  24624 #undef JSON_HEDLEY_UNLIKELY
  24625 #undef JSON_HEDLEY_UNPREDICTABLE
  24626 #undef JSON_HEDLEY_UNREACHABLE
  24627 #undef JSON_HEDLEY_UNREACHABLE_RETURN
  24628 #undef JSON_HEDLEY_VERSION
  24629 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
  24630 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
  24631 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
  24632 #undef JSON_HEDLEY_VERSION_ENCODE
  24633 #undef JSON_HEDLEY_WARNING
  24634 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
  24635 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
  24636 #undef JSON_HEDLEY_FALL_THROUGH
  24637 
  24638 
  24639 
  24640 #endif  // INCLUDE_NLOHMANN_JSON_HPP_