tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

json-json.hpp (921069B)


      1 // © 2024 and later: Unicode, Inc. and others.
      2 // License & terms of use: http://www.unicode.org/copyright.html
      3 //
      4 // From the nlohmann/json library. Original license:
      5 //
      6 // MIT License
      7 //
      8 // Copyright (c) 2013-2022 Niels Lohmann
      9 //
     10 // Permission is hereby granted, free of charge, to any person obtaining a copy
     11 // of this software and associated documentation files (the "Software"), to deal
     12 // in the Software without restriction, including without limitation the rights
     13 // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
     14 // copies of the Software, and to permit persons to whom the Software is
     15 // furnished to do so, subject to the following conditions:
     16 //
     17 // The above copyright notice and this permission notice shall be included in all
     18 // copies or substantial portions of the Software.
     19 //
     20 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
     21 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
     22 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
     23 // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
     24 // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
     25 // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
     26 // SOFTWARE.
     27 
     28 
     29 //     __ _____ _____ _____
     30 //  __|  |   __|     |   | |  JSON for Modern C++
     31 // |  |  |__   |  |  | | | |  version 3.11.3
     32 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
     33 //
     34 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
     35 // SPDX-License-Identifier: MIT
     36 
     37 /****************************************************************************\
     38 * Note on documentation: The source files contain links to the online      *
     39 * documentation of the public API at https://json.nlohmann.me. This URL    *
     40 * contains the most recent documentation and should also be applicable to  *
     41 * previous versions; documentation for deprecated functions is not         *
     42 * removed, but marked deprecated. See "Generate documentation" section in  *
     43 * file docs/README.md.                                                     *
     44 \****************************************************************************/
     45 
     46 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
     47 #define INCLUDE_NLOHMANN_JSON_HPP_
     48 
     49 #include <algorithm> // all_of, find, for_each
     50 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
     51 #include <functional> // hash, less
     52 #include <initializer_list> // initializer_list
     53 #ifndef JSON_NO_IO
     54    #include <iosfwd> // istream, ostream
     55 #endif  // JSON_NO_IO
     56 #include <iterator> // random_access_iterator_tag
     57 #include <memory> // unique_ptr
     58 #include <string> // string, stoi, to_string
     59 #include <utility> // declval, forward, move, pair, swap
     60 #include <vector> // vector
     61 
     62 // #include <nlohmann/adl_serializer.hpp>
     63 //     __ _____ _____ _____
     64 //  __|  |   __|     |   | |  JSON for Modern C++
     65 // |  |  |__   |  |  | | | |  version 3.11.3
     66 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
     67 //
     68 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
     69 // SPDX-License-Identifier: MIT
     70 
     71 
     72 
     73 #include <utility>
     74 
     75 // #include <nlohmann/detail/abi_macros.hpp>
     76 //     __ _____ _____ _____
     77 //  __|  |   __|     |   | |  JSON for Modern C++
     78 // |  |  |__   |  |  | | | |  version 3.11.3
     79 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
     80 //
     81 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
     82 // SPDX-License-Identifier: MIT
     83 
     84 
     85 
     86 // This file contains all macro definitions affecting or depending on the ABI
     87 
     88 #ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
     89    #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
     90        #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 11 || NLOHMANN_JSON_VERSION_PATCH != 3
     91            #warning "Already included a different version of the library!"
     92        #endif
     93    #endif
     94 #endif
     95 
     96 #define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum)
     97 #define NLOHMANN_JSON_VERSION_MINOR 11  // NOLINT(modernize-macro-to-enum)
     98 #define NLOHMANN_JSON_VERSION_PATCH 3   // NOLINT(modernize-macro-to-enum)
     99 
    100 #ifndef JSON_DIAGNOSTICS
    101    #define JSON_DIAGNOSTICS 0
    102 #endif
    103 
    104 #ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
    105    #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
    106 #endif
    107 
    108 #if JSON_DIAGNOSTICS
    109    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
    110 #else
    111    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
    112 #endif
    113 
    114 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
    115    #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
    116 #else
    117    #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
    118 #endif
    119 
    120 #ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
    121    #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
    122 #endif
    123 
    124 // Construct the namespace ABI tags component
    125 #define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b) json_abi ## a ## b
    126 #define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b) \
    127    NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b)
    128 
    129 #define NLOHMANN_JSON_ABI_TAGS                                       \
    130    NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
    131            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
    132            NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON)
    133 
    134 // Construct the namespace version component
    135 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
    136    _v ## major ## _ ## minor ## _ ## patch
    137 #define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
    138    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
    139 
    140 #if NLOHMANN_JSON_NAMESPACE_NO_VERSION
    141 #define NLOHMANN_JSON_NAMESPACE_VERSION
    142 #else
    143 #define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
    144    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
    145                                           NLOHMANN_JSON_VERSION_MINOR, \
    146                                           NLOHMANN_JSON_VERSION_PATCH)
    147 #endif
    148 
    149 // Combine namespace components
    150 #define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
    151 #define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
    152    NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
    153 
    154 #ifndef NLOHMANN_JSON_NAMESPACE
    155 #define NLOHMANN_JSON_NAMESPACE               \
    156    nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
    157            NLOHMANN_JSON_ABI_TAGS,           \
    158            NLOHMANN_JSON_NAMESPACE_VERSION)
    159 #endif
    160 
    161 #ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
    162 #define NLOHMANN_JSON_NAMESPACE_BEGIN                \
    163    namespace nlohmann                               \
    164    {                                                \
    165    inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
    166                NLOHMANN_JSON_ABI_TAGS,              \
    167                NLOHMANN_JSON_NAMESPACE_VERSION)     \
    168    {
    169 #endif
    170 
    171 #ifndef NLOHMANN_JSON_NAMESPACE_END
    172 #define NLOHMANN_JSON_NAMESPACE_END                                     \
    173    }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
    174    }  // namespace nlohmann
    175 #endif
    176 
    177 // #include <nlohmann/detail/conversions/from_json.hpp>
    178 //     __ _____ _____ _____
    179 //  __|  |   __|     |   | |  JSON for Modern C++
    180 // |  |  |__   |  |  | | | |  version 3.11.3
    181 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    182 //
    183 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    184 // SPDX-License-Identifier: MIT
    185 
    186 
    187 
    188 #include <algorithm> // transform
    189 #include <array> // array
    190 #include <forward_list> // forward_list
    191 #include <iterator> // inserter, front_inserter, end
    192 #include <map> // map
    193 #include <string> // string
    194 #include <tuple> // tuple, make_tuple
    195 #include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
    196 #include <unordered_map> // unordered_map
    197 #include <utility> // pair, declval
    198 #include <valarray> // valarray
    199 
    200 // #include <nlohmann/detail/exceptions.hpp>
    201 //     __ _____ _____ _____
    202 //  __|  |   __|     |   | |  JSON for Modern C++
    203 // |  |  |__   |  |  | | | |  version 3.11.3
    204 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    205 //
    206 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    207 // SPDX-License-Identifier: MIT
    208 
    209 
    210 
    211 #include <cstddef> // nullptr_t
    212 #include <exception> // exception
    213 #if JSON_DIAGNOSTICS
    214    #include <numeric> // accumulate
    215 #endif
    216 #include <stdexcept> // runtime_error
    217 #include <string> // to_string
    218 #include <vector> // vector
    219 
    220 // #include <nlohmann/detail/value_t.hpp>
    221 //     __ _____ _____ _____
    222 //  __|  |   __|     |   | |  JSON for Modern C++
    223 // |  |  |__   |  |  | | | |  version 3.11.3
    224 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    225 //
    226 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    227 // SPDX-License-Identifier: MIT
    228 
    229 
    230 
    231 #include <array> // array
    232 #include <cstddef> // size_t
    233 #include <cstdint> // uint8_t
    234 #include <string> // string
    235 
    236 // #include <nlohmann/detail/macro_scope.hpp>
    237 //     __ _____ _____ _____
    238 //  __|  |   __|     |   | |  JSON for Modern C++
    239 // |  |  |__   |  |  | | | |  version 3.11.3
    240 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    241 //
    242 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    243 // SPDX-License-Identifier: MIT
    244 
    245 
    246 
    247 #include <utility> // declval, pair
    248 // #include <nlohmann/detail/meta/detected.hpp>
    249 //     __ _____ _____ _____
    250 //  __|  |   __|     |   | |  JSON for Modern C++
    251 // |  |  |__   |  |  | | | |  version 3.11.3
    252 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    253 //
    254 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    255 // SPDX-License-Identifier: MIT
    256 
    257 
    258 
    259 #include <type_traits>
    260 
    261 // #include <nlohmann/detail/meta/void_t.hpp>
    262 //     __ _____ _____ _____
    263 //  __|  |   __|     |   | |  JSON for Modern C++
    264 // |  |  |__   |  |  | | | |  version 3.11.3
    265 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    266 //
    267 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    268 // SPDX-License-Identifier: MIT
    269 
    270 
    271 
    272 // #include <nlohmann/detail/abi_macros.hpp>
    273 
    274 
    275 NLOHMANN_JSON_NAMESPACE_BEGIN
    276 namespace detail
    277 {
    278 
    279 template<typename ...Ts> struct make_void
    280 {
    281    using type = void;
    282 };
    283 template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
    284 
    285 }  // namespace detail
    286 NLOHMANN_JSON_NAMESPACE_END
    287 
    288 
    289 NLOHMANN_JSON_NAMESPACE_BEGIN
    290 namespace detail
    291 {
    292 
    293 // https://en.cppreference.com/w/cpp/experimental/is_detected
    294 struct nonesuch
    295 {
    296    nonesuch() = delete;
    297    ~nonesuch() = delete;
    298    nonesuch(nonesuch const&) = delete;
    299    nonesuch(nonesuch const&&) = delete;
    300    void operator=(nonesuch const&) = delete;
    301    void operator=(nonesuch&&) = delete;
    302 };
    303 
    304 template<class Default,
    305         class AlwaysVoid,
    306         template<class...> class Op,
    307         class... Args>
    308 struct detector
    309 {
    310    using value_t = std::false_type;
    311    using type = Default;
    312 };
    313 
    314 template<class Default, template<class...> class Op, class... Args>
    315 struct detector<Default, void_t<Op<Args...>>, Op, Args...>
    316 {
    317    using value_t = std::true_type;
    318    using type = Op<Args...>;
    319 };
    320 
    321 template<template<class...> class Op, class... Args>
    322 using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
    323 
    324 template<template<class...> class Op, class... Args>
    325 struct is_detected_lazy : is_detected<Op, Args...> { };
    326 
    327 template<template<class...> class Op, class... Args>
    328 using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
    329 
    330 template<class Default, template<class...> class Op, class... Args>
    331 using detected_or = detector<Default, void, Op, Args...>;
    332 
    333 template<class Default, template<class...> class Op, class... Args>
    334 using detected_or_t = typename detected_or<Default, Op, Args...>::type;
    335 
    336 template<class Expected, template<class...> class Op, class... Args>
    337 using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
    338 
    339 template<class To, template<class...> class Op, class... Args>
    340 using is_detected_convertible =
    341    std::is_convertible<detected_t<Op, Args...>, To>;
    342 
    343 }  // namespace detail
    344 NLOHMANN_JSON_NAMESPACE_END
    345 
    346 // #include <nlohmann/thirdparty/hedley/hedley.hpp>
    347 
    348 
    349 //     __ _____ _____ _____
    350 //  __|  |   __|     |   | |  JSON for Modern C++
    351 // |  |  |__   |  |  | | | |  version 3.11.3
    352 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    353 //
    354 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
    355 // SPDX-FileCopyrightText: 2016-2021 Evan Nemerson <evan@nemerson.com>
    356 // SPDX-License-Identifier: MIT
    357 
    358 /* Hedley - https://nemequ.github.io/hedley
    359 * Created by Evan Nemerson <evan@nemerson.com>
    360 */
    361 
    362 #if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
    363 #if defined(JSON_HEDLEY_VERSION)
    364    #undef JSON_HEDLEY_VERSION
    365 #endif
    366 #define JSON_HEDLEY_VERSION 15
    367 
    368 #if defined(JSON_HEDLEY_STRINGIFY_EX)
    369    #undef JSON_HEDLEY_STRINGIFY_EX
    370 #endif
    371 #define JSON_HEDLEY_STRINGIFY_EX(x) #x
    372 
    373 #if defined(JSON_HEDLEY_STRINGIFY)
    374    #undef JSON_HEDLEY_STRINGIFY
    375 #endif
    376 #define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
    377 
    378 #if defined(JSON_HEDLEY_CONCAT_EX)
    379    #undef JSON_HEDLEY_CONCAT_EX
    380 #endif
    381 #define JSON_HEDLEY_CONCAT_EX(a,b) a##b
    382 
    383 #if defined(JSON_HEDLEY_CONCAT)
    384    #undef JSON_HEDLEY_CONCAT
    385 #endif
    386 #define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
    387 
    388 #if defined(JSON_HEDLEY_CONCAT3_EX)
    389    #undef JSON_HEDLEY_CONCAT3_EX
    390 #endif
    391 #define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
    392 
    393 #if defined(JSON_HEDLEY_CONCAT3)
    394    #undef JSON_HEDLEY_CONCAT3
    395 #endif
    396 #define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
    397 
    398 #if defined(JSON_HEDLEY_VERSION_ENCODE)
    399    #undef JSON_HEDLEY_VERSION_ENCODE
    400 #endif
    401 #define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
    402 
    403 #if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
    404    #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
    405 #endif
    406 #define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
    407 
    408 #if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
    409    #undef JSON_HEDLEY_VERSION_DECODE_MINOR
    410 #endif
    411 #define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
    412 
    413 #if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
    414    #undef JSON_HEDLEY_VERSION_DECODE_REVISION
    415 #endif
    416 #define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
    417 
    418 #if defined(JSON_HEDLEY_GNUC_VERSION)
    419    #undef JSON_HEDLEY_GNUC_VERSION
    420 #endif
    421 #if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
    422    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
    423 #elif defined(__GNUC__)
    424    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
    425 #endif
    426 
    427 #if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
    428    #undef JSON_HEDLEY_GNUC_VERSION_CHECK
    429 #endif
    430 #if defined(JSON_HEDLEY_GNUC_VERSION)
    431    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    432 #else
    433    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
    434 #endif
    435 
    436 #if defined(JSON_HEDLEY_MSVC_VERSION)
    437    #undef JSON_HEDLEY_MSVC_VERSION
    438 #endif
    439 #if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
    440    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
    441 #elif defined(_MSC_FULL_VER) && !defined(__ICL)
    442    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
    443 #elif defined(_MSC_VER) && !defined(__ICL)
    444    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
    445 #endif
    446 
    447 #if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
    448    #undef JSON_HEDLEY_MSVC_VERSION_CHECK
    449 #endif
    450 #if !defined(JSON_HEDLEY_MSVC_VERSION)
    451    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
    452 #elif defined(_MSC_VER) && (_MSC_VER >= 1400)
    453    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
    454 #elif defined(_MSC_VER) && (_MSC_VER >= 1200)
    455    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
    456 #else
    457    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
    458 #endif
    459 
    460 #if defined(JSON_HEDLEY_INTEL_VERSION)
    461    #undef JSON_HEDLEY_INTEL_VERSION
    462 #endif
    463 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
    464    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
    465 #elif defined(__INTEL_COMPILER) && !defined(__ICL)
    466    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
    467 #endif
    468 
    469 #if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
    470    #undef JSON_HEDLEY_INTEL_VERSION_CHECK
    471 #endif
    472 #if defined(JSON_HEDLEY_INTEL_VERSION)
    473    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    474 #else
    475    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
    476 #endif
    477 
    478 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
    479    #undef JSON_HEDLEY_INTEL_CL_VERSION
    480 #endif
    481 #if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
    482    #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
    483 #endif
    484 
    485 #if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
    486    #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
    487 #endif
    488 #if defined(JSON_HEDLEY_INTEL_CL_VERSION)
    489    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    490 #else
    491    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
    492 #endif
    493 
    494 #if defined(JSON_HEDLEY_PGI_VERSION)
    495    #undef JSON_HEDLEY_PGI_VERSION
    496 #endif
    497 #if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
    498    #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
    499 #endif
    500 
    501 #if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
    502    #undef JSON_HEDLEY_PGI_VERSION_CHECK
    503 #endif
    504 #if defined(JSON_HEDLEY_PGI_VERSION)
    505    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    506 #else
    507    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
    508 #endif
    509 
    510 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
    511    #undef JSON_HEDLEY_SUNPRO_VERSION
    512 #endif
    513 #if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
    514    #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)
    515 #elif defined(__SUNPRO_C)
    516    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
    517 #elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
    518    #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)
    519 #elif defined(__SUNPRO_CC)
    520    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
    521 #endif
    522 
    523 #if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
    524    #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
    525 #endif
    526 #if defined(JSON_HEDLEY_SUNPRO_VERSION)
    527    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    528 #else
    529    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
    530 #endif
    531 
    532 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
    533    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
    534 #endif
    535 #if defined(__EMSCRIPTEN__)
    536    #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
    537 #endif
    538 
    539 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
    540    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
    541 #endif
    542 #if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
    543    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    544 #else
    545    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
    546 #endif
    547 
    548 #if defined(JSON_HEDLEY_ARM_VERSION)
    549    #undef JSON_HEDLEY_ARM_VERSION
    550 #endif
    551 #if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
    552    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
    553 #elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
    554    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
    555 #endif
    556 
    557 #if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
    558    #undef JSON_HEDLEY_ARM_VERSION_CHECK
    559 #endif
    560 #if defined(JSON_HEDLEY_ARM_VERSION)
    561    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    562 #else
    563    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
    564 #endif
    565 
    566 #if defined(JSON_HEDLEY_IBM_VERSION)
    567    #undef JSON_HEDLEY_IBM_VERSION
    568 #endif
    569 #if defined(__ibmxl__)
    570    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
    571 #elif defined(__xlC__) && defined(__xlC_ver__)
    572    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
    573 #elif defined(__xlC__)
    574    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
    575 #endif
    576 
    577 #if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
    578    #undef JSON_HEDLEY_IBM_VERSION_CHECK
    579 #endif
    580 #if defined(JSON_HEDLEY_IBM_VERSION)
    581    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    582 #else
    583    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
    584 #endif
    585 
    586 #if defined(JSON_HEDLEY_TI_VERSION)
    587    #undef JSON_HEDLEY_TI_VERSION
    588 #endif
    589 #if \
    590    defined(__TI_COMPILER_VERSION__) && \
    591    ( \
    592      defined(__TMS470__) || defined(__TI_ARM__) || \
    593      defined(__MSP430__) || \
    594      defined(__TMS320C2000__) \
    595    )
    596 #if (__TI_COMPILER_VERSION__ >= 16000000)
    597    #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    598 #endif
    599 #endif
    600 
    601 #if defined(JSON_HEDLEY_TI_VERSION_CHECK)
    602    #undef JSON_HEDLEY_TI_VERSION_CHECK
    603 #endif
    604 #if defined(JSON_HEDLEY_TI_VERSION)
    605    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    606 #else
    607    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
    608 #endif
    609 
    610 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
    611    #undef JSON_HEDLEY_TI_CL2000_VERSION
    612 #endif
    613 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
    614    #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    615 #endif
    616 
    617 #if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
    618    #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
    619 #endif
    620 #if defined(JSON_HEDLEY_TI_CL2000_VERSION)
    621    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    622 #else
    623    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
    624 #endif
    625 
    626 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
    627    #undef JSON_HEDLEY_TI_CL430_VERSION
    628 #endif
    629 #if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
    630    #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    631 #endif
    632 
    633 #if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
    634    #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
    635 #endif
    636 #if defined(JSON_HEDLEY_TI_CL430_VERSION)
    637    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    638 #else
    639    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
    640 #endif
    641 
    642 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
    643    #undef JSON_HEDLEY_TI_ARMCL_VERSION
    644 #endif
    645 #if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
    646    #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    647 #endif
    648 
    649 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
    650    #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
    651 #endif
    652 #if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
    653    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    654 #else
    655    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
    656 #endif
    657 
    658 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
    659    #undef JSON_HEDLEY_TI_CL6X_VERSION
    660 #endif
    661 #if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
    662    #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    663 #endif
    664 
    665 #if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
    666    #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
    667 #endif
    668 #if defined(JSON_HEDLEY_TI_CL6X_VERSION)
    669    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    670 #else
    671    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
    672 #endif
    673 
    674 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
    675    #undef JSON_HEDLEY_TI_CL7X_VERSION
    676 #endif
    677 #if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
    678    #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    679 #endif
    680 
    681 #if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
    682    #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
    683 #endif
    684 #if defined(JSON_HEDLEY_TI_CL7X_VERSION)
    685    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    686 #else
    687    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
    688 #endif
    689 
    690 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
    691    #undef JSON_HEDLEY_TI_CLPRU_VERSION
    692 #endif
    693 #if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
    694    #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
    695 #endif
    696 
    697 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
    698    #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
    699 #endif
    700 #if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
    701    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    702 #else
    703    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
    704 #endif
    705 
    706 #if defined(JSON_HEDLEY_CRAY_VERSION)
    707    #undef JSON_HEDLEY_CRAY_VERSION
    708 #endif
    709 #if defined(_CRAYC)
    710    #if defined(_RELEASE_PATCHLEVEL)
    711        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
    712    #else
    713        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
    714    #endif
    715 #endif
    716 
    717 #if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
    718    #undef JSON_HEDLEY_CRAY_VERSION_CHECK
    719 #endif
    720 #if defined(JSON_HEDLEY_CRAY_VERSION)
    721    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    722 #else
    723    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
    724 #endif
    725 
    726 #if defined(JSON_HEDLEY_IAR_VERSION)
    727    #undef JSON_HEDLEY_IAR_VERSION
    728 #endif
    729 #if defined(__IAR_SYSTEMS_ICC__)
    730    #if __VER__ > 1000
    731        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
    732    #else
    733        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
    734    #endif
    735 #endif
    736 
    737 #if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
    738    #undef JSON_HEDLEY_IAR_VERSION_CHECK
    739 #endif
    740 #if defined(JSON_HEDLEY_IAR_VERSION)
    741    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    742 #else
    743    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
    744 #endif
    745 
    746 #if defined(JSON_HEDLEY_TINYC_VERSION)
    747    #undef JSON_HEDLEY_TINYC_VERSION
    748 #endif
    749 #if defined(__TINYC__)
    750    #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
    751 #endif
    752 
    753 #if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
    754    #undef JSON_HEDLEY_TINYC_VERSION_CHECK
    755 #endif
    756 #if defined(JSON_HEDLEY_TINYC_VERSION)
    757    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    758 #else
    759    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
    760 #endif
    761 
    762 #if defined(JSON_HEDLEY_DMC_VERSION)
    763    #undef JSON_HEDLEY_DMC_VERSION
    764 #endif
    765 #if defined(__DMC__)
    766    #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
    767 #endif
    768 
    769 #if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
    770    #undef JSON_HEDLEY_DMC_VERSION_CHECK
    771 #endif
    772 #if defined(JSON_HEDLEY_DMC_VERSION)
    773    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    774 #else
    775    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
    776 #endif
    777 
    778 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
    779    #undef JSON_HEDLEY_COMPCERT_VERSION
    780 #endif
    781 #if defined(__COMPCERT_VERSION__)
    782    #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
    783 #endif
    784 
    785 #if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
    786    #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
    787 #endif
    788 #if defined(JSON_HEDLEY_COMPCERT_VERSION)
    789    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    790 #else
    791    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
    792 #endif
    793 
    794 #if defined(JSON_HEDLEY_PELLES_VERSION)
    795    #undef JSON_HEDLEY_PELLES_VERSION
    796 #endif
    797 #if defined(__POCC__)
    798    #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
    799 #endif
    800 
    801 #if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
    802    #undef JSON_HEDLEY_PELLES_VERSION_CHECK
    803 #endif
    804 #if defined(JSON_HEDLEY_PELLES_VERSION)
    805    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    806 #else
    807    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
    808 #endif
    809 
    810 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
    811    #undef JSON_HEDLEY_MCST_LCC_VERSION
    812 #endif
    813 #if defined(__LCC__) && defined(__LCC_MINOR__)
    814    #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
    815 #endif
    816 
    817 #if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
    818    #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
    819 #endif
    820 #if defined(JSON_HEDLEY_MCST_LCC_VERSION)
    821    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    822 #else
    823    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
    824 #endif
    825 
    826 #if defined(JSON_HEDLEY_GCC_VERSION)
    827    #undef JSON_HEDLEY_GCC_VERSION
    828 #endif
    829 #if \
    830    defined(JSON_HEDLEY_GNUC_VERSION) && \
    831    !defined(__clang__) && \
    832    !defined(JSON_HEDLEY_INTEL_VERSION) && \
    833    !defined(JSON_HEDLEY_PGI_VERSION) && \
    834    !defined(JSON_HEDLEY_ARM_VERSION) && \
    835    !defined(JSON_HEDLEY_CRAY_VERSION) && \
    836    !defined(JSON_HEDLEY_TI_VERSION) && \
    837    !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
    838    !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
    839    !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
    840    !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
    841    !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
    842    !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
    843    !defined(__COMPCERT__) && \
    844    !defined(JSON_HEDLEY_MCST_LCC_VERSION)
    845    #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
    846 #endif
    847 
    848 #if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
    849    #undef JSON_HEDLEY_GCC_VERSION_CHECK
    850 #endif
    851 #if defined(JSON_HEDLEY_GCC_VERSION)
    852    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
    853 #else
    854    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
    855 #endif
    856 
    857 #if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
    858    #undef JSON_HEDLEY_HAS_ATTRIBUTE
    859 #endif
    860 #if \
    861  defined(__has_attribute) && \
    862  ( \
    863    (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
    864  )
    865 #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
    866 #else
    867 #  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
    868 #endif
    869 
    870 #if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
    871    #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
    872 #endif
    873 #if defined(__has_attribute)
    874    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
    875 #else
    876    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    877 #endif
    878 
    879 #if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
    880    #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
    881 #endif
    882 #if defined(__has_attribute)
    883    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
    884 #else
    885    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    886 #endif
    887 
    888 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
    889    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
    890 #endif
    891 #if \
    892    defined(__has_cpp_attribute) && \
    893    defined(__cplusplus) && \
    894    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
    895    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
    896 #else
    897    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
    898 #endif
    899 
    900 #if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
    901    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
    902 #endif
    903 #if !defined(__cplusplus) || !defined(__has_cpp_attribute)
    904    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
    905 #elif \
    906    !defined(JSON_HEDLEY_PGI_VERSION) && \
    907    !defined(JSON_HEDLEY_IAR_VERSION) && \
    908    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
    909    (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
    910    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
    911 #else
    912    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
    913 #endif
    914 
    915 #if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
    916    #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
    917 #endif
    918 #if defined(__has_cpp_attribute) && defined(__cplusplus)
    919    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
    920 #else
    921    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    922 #endif
    923 
    924 #if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
    925    #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
    926 #endif
    927 #if defined(__has_cpp_attribute) && defined(__cplusplus)
    928    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
    929 #else
    930    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    931 #endif
    932 
    933 #if defined(JSON_HEDLEY_HAS_BUILTIN)
    934    #undef JSON_HEDLEY_HAS_BUILTIN
    935 #endif
    936 #if defined(__has_builtin)
    937    #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
    938 #else
    939    #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
    940 #endif
    941 
    942 #if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
    943    #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
    944 #endif
    945 #if defined(__has_builtin)
    946    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
    947 #else
    948    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    949 #endif
    950 
    951 #if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
    952    #undef JSON_HEDLEY_GCC_HAS_BUILTIN
    953 #endif
    954 #if defined(__has_builtin)
    955    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
    956 #else
    957    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    958 #endif
    959 
    960 #if defined(JSON_HEDLEY_HAS_FEATURE)
    961    #undef JSON_HEDLEY_HAS_FEATURE
    962 #endif
    963 #if defined(__has_feature)
    964    #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
    965 #else
    966    #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
    967 #endif
    968 
    969 #if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
    970    #undef JSON_HEDLEY_GNUC_HAS_FEATURE
    971 #endif
    972 #if defined(__has_feature)
    973    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
    974 #else
    975    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
    976 #endif
    977 
    978 #if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
    979    #undef JSON_HEDLEY_GCC_HAS_FEATURE
    980 #endif
    981 #if defined(__has_feature)
    982    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
    983 #else
    984    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
    985 #endif
    986 
    987 #if defined(JSON_HEDLEY_HAS_EXTENSION)
    988    #undef JSON_HEDLEY_HAS_EXTENSION
    989 #endif
    990 #if defined(__has_extension)
    991    #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
    992 #else
    993    #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
    994 #endif
    995 
    996 #if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
    997    #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
    998 #endif
    999 #if defined(__has_extension)
   1000    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
   1001 #else
   1002    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
   1003 #endif
   1004 
   1005 #if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
   1006    #undef JSON_HEDLEY_GCC_HAS_EXTENSION
   1007 #endif
   1008 #if defined(__has_extension)
   1009    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
   1010 #else
   1011    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   1012 #endif
   1013 
   1014 #if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
   1015    #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
   1016 #endif
   1017 #if defined(__has_declspec_attribute)
   1018    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
   1019 #else
   1020    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
   1021 #endif
   1022 
   1023 #if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
   1024    #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
   1025 #endif
   1026 #if defined(__has_declspec_attribute)
   1027    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
   1028 #else
   1029    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
   1030 #endif
   1031 
   1032 #if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
   1033    #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
   1034 #endif
   1035 #if defined(__has_declspec_attribute)
   1036    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
   1037 #else
   1038    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   1039 #endif
   1040 
   1041 #if defined(JSON_HEDLEY_HAS_WARNING)
   1042    #undef JSON_HEDLEY_HAS_WARNING
   1043 #endif
   1044 #if defined(__has_warning)
   1045    #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
   1046 #else
   1047    #define JSON_HEDLEY_HAS_WARNING(warning) (0)
   1048 #endif
   1049 
   1050 #if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
   1051    #undef JSON_HEDLEY_GNUC_HAS_WARNING
   1052 #endif
   1053 #if defined(__has_warning)
   1054    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
   1055 #else
   1056    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
   1057 #endif
   1058 
   1059 #if defined(JSON_HEDLEY_GCC_HAS_WARNING)
   1060    #undef JSON_HEDLEY_GCC_HAS_WARNING
   1061 #endif
   1062 #if defined(__has_warning)
   1063    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
   1064 #else
   1065    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   1066 #endif
   1067 
   1068 #if \
   1069    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
   1070    defined(__clang__) || \
   1071    JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
   1072    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1073    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
   1074    JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
   1075    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1076    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1077    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
   1078    JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
   1079    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
   1080    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
   1081    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1082    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1083    JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
   1084    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
   1085    JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
   1086    (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
   1087    #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
   1088 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
   1089    #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
   1090 #else
   1091    #define JSON_HEDLEY_PRAGMA(value)
   1092 #endif
   1093 
   1094 #if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
   1095    #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
   1096 #endif
   1097 #if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
   1098    #undef JSON_HEDLEY_DIAGNOSTIC_POP
   1099 #endif
   1100 #if defined(__clang__)
   1101    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
   1102    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
   1103 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1104    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
   1105    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
   1106 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
   1107    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
   1108    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
   1109 #elif \
   1110    JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
   1111    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1112    #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
   1113    #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
   1114 #elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
   1115    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
   1116    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
   1117 #elif \
   1118    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1119    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1120    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
   1121    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
   1122    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1123    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
   1124    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
   1125    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
   1126 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
   1127    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
   1128    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
   1129 #else
   1130    #define JSON_HEDLEY_DIAGNOSTIC_PUSH
   1131    #define JSON_HEDLEY_DIAGNOSTIC_POP
   1132 #endif
   1133 
   1134 /* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
   1135   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
   1136 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
   1137    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
   1138 #endif
   1139 #if defined(__cplusplus)
   1140 #  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
   1141 #    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
   1142 #      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
   1143 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
   1144    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1145    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
   1146    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
   1147    _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
   1148    xpr \
   1149    JSON_HEDLEY_DIAGNOSTIC_POP
   1150 #      else
   1151 #        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
   1152    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1153    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
   1154    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
   1155    xpr \
   1156    JSON_HEDLEY_DIAGNOSTIC_POP
   1157 #      endif
   1158 #    else
   1159 #      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
   1160    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1161    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
   1162    xpr \
   1163    JSON_HEDLEY_DIAGNOSTIC_POP
   1164 #    endif
   1165 #  endif
   1166 #endif
   1167 #if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
   1168    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
   1169 #endif
   1170 
   1171 #if defined(JSON_HEDLEY_CONST_CAST)
   1172    #undef JSON_HEDLEY_CONST_CAST
   1173 #endif
   1174 #if defined(__cplusplus)
   1175 #  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
   1176 #elif \
   1177  JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
   1178  JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
   1179  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1180 #  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
   1181        JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1182        JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
   1183        ((T) (expr)); \
   1184        JSON_HEDLEY_DIAGNOSTIC_POP \
   1185    }))
   1186 #else
   1187 #  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
   1188 #endif
   1189 
   1190 #if defined(JSON_HEDLEY_REINTERPRET_CAST)
   1191    #undef JSON_HEDLEY_REINTERPRET_CAST
   1192 #endif
   1193 #if defined(__cplusplus)
   1194    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
   1195 #else
   1196    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
   1197 #endif
   1198 
   1199 #if defined(JSON_HEDLEY_STATIC_CAST)
   1200    #undef JSON_HEDLEY_STATIC_CAST
   1201 #endif
   1202 #if defined(__cplusplus)
   1203    #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
   1204 #else
   1205    #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
   1206 #endif
   1207 
   1208 #if defined(JSON_HEDLEY_CPP_CAST)
   1209    #undef JSON_HEDLEY_CPP_CAST
   1210 #endif
   1211 #if defined(__cplusplus)
   1212 #  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
   1213 #    define JSON_HEDLEY_CPP_CAST(T, expr) \
   1214    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1215    _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
   1216    ((T) (expr)) \
   1217    JSON_HEDLEY_DIAGNOSTIC_POP
   1218 #  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
   1219 #    define JSON_HEDLEY_CPP_CAST(T, expr) \
   1220    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   1221    _Pragma("diag_suppress=Pe137") \
   1222    JSON_HEDLEY_DIAGNOSTIC_POP
   1223 #  else
   1224 #    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
   1225 #  endif
   1226 #else
   1227 #  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
   1228 #endif
   1229 
   1230 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
   1231    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
   1232 #endif
   1233 #if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
   1234    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
   1235 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1236    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
   1237 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1238    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
   1239 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
   1240    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
   1241 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
   1242    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
   1243 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
   1244    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
   1245 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
   1246    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
   1247 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1248    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
   1249 #elif \
   1250    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1251    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1252    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1253    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1254    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1255    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1256    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1257    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1258    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1259    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1260    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
   1261    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
   1262 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
   1263    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
   1264 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
   1265    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
   1266 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1267    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
   1268 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
   1269    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
   1270 #else
   1271    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
   1272 #endif
   1273 
   1274 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
   1275    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
   1276 #endif
   1277 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
   1278    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
   1279 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1280    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
   1281 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1282    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
   1283 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
   1284    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
   1285 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
   1286    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
   1287 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
   1288    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
   1289 #elif \
   1290    JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
   1291    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
   1292    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1293    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
   1294    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
   1295 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
   1296    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
   1297 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1298    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
   1299 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1300    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
   1301 #else
   1302    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
   1303 #endif
   1304 
   1305 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
   1306    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
   1307 #endif
   1308 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
   1309    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
   1310 #elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
   1311    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
   1312 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
   1313    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
   1314 #elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1315    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
   1316 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
   1317    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
   1318 #elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
   1319    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
   1320 #elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
   1321    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
   1322 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
   1323    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
   1324 #elif \
   1325    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
   1326    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
   1327    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
   1328    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
   1329 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1330    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
   1331 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1332    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
   1333 #else
   1334    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
   1335 #endif
   1336 
   1337 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
   1338    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
   1339 #endif
   1340 #if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
   1341    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
   1342 #elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   1343    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
   1344 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
   1345    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
   1346 #else
   1347    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
   1348 #endif
   1349 
   1350 #if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
   1351    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
   1352 #endif
   1353 #if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
   1354    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
   1355 #elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
   1356    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
   1357 #elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
   1358    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
   1359 #elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1360    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
   1361 #else
   1362    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
   1363 #endif
   1364 
   1365 #if defined(JSON_HEDLEY_DEPRECATED)
   1366    #undef JSON_HEDLEY_DEPRECATED
   1367 #endif
   1368 #if defined(JSON_HEDLEY_DEPRECATED_FOR)
   1369    #undef JSON_HEDLEY_DEPRECATED_FOR
   1370 #endif
   1371 #if \
   1372    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
   1373    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1374    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
   1375    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
   1376 #elif \
   1377    (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
   1378    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
   1379    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1380    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
   1381    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
   1382    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1383    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
   1384    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
   1385    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
   1386    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1387    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
   1388    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1389    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
   1390    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
   1391 #elif defined(__cplusplus) && (__cplusplus >= 201402L)
   1392    #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
   1393    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
   1394 #elif \
   1395    JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
   1396    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1397    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1398    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1399    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1400    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1401    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1402    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1403    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1404    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1405    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1406    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1407    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1408    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1409    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
   1410    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1411    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
   1412    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
   1413 #elif \
   1414    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1415    JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
   1416    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1417    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
   1418    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
   1419 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1420    #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
   1421    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
   1422 #else
   1423    #define JSON_HEDLEY_DEPRECATED(since)
   1424    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
   1425 #endif
   1426 
   1427 #if defined(JSON_HEDLEY_UNAVAILABLE)
   1428    #undef JSON_HEDLEY_UNAVAILABLE
   1429 #endif
   1430 #if \
   1431    JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
   1432    JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
   1433    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1434    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1435    #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
   1436 #else
   1437    #define JSON_HEDLEY_UNAVAILABLE(available_since)
   1438 #endif
   1439 
   1440 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
   1441    #undef JSON_HEDLEY_WARN_UNUSED_RESULT
   1442 #endif
   1443 #if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
   1444    #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
   1445 #endif
   1446 #if \
   1447    JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
   1448    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
   1449    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1450    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1451    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1452    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1453    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1454    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1455    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1456    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1457    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1458    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1459    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1460    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1461    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
   1462    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1463    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1464    #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
   1465    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
   1466 #elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
   1467    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
   1468    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
   1469 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
   1470    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
   1471    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
   1472 #elif defined(_Check_return_) /* SAL */
   1473    #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
   1474    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
   1475 #else
   1476    #define JSON_HEDLEY_WARN_UNUSED_RESULT
   1477    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
   1478 #endif
   1479 
   1480 #if defined(JSON_HEDLEY_SENTINEL)
   1481    #undef JSON_HEDLEY_SENTINEL
   1482 #endif
   1483 #if \
   1484    JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
   1485    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
   1486    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1487    JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
   1488    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1489    #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
   1490 #else
   1491    #define JSON_HEDLEY_SENTINEL(position)
   1492 #endif
   1493 
   1494 #if defined(JSON_HEDLEY_NO_RETURN)
   1495    #undef JSON_HEDLEY_NO_RETURN
   1496 #endif
   1497 #if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1498    #define JSON_HEDLEY_NO_RETURN __noreturn
   1499 #elif \
   1500    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1501    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1502    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
   1503 #elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
   1504    #define JSON_HEDLEY_NO_RETURN _Noreturn
   1505 #elif defined(__cplusplus) && (__cplusplus >= 201103L)
   1506    #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
   1507 #elif \
   1508    JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
   1509    JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
   1510    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1511    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1512    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1513    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1514    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1515    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1516    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1517    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1518    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1519    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1520    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1521    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1522    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1523    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1524    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1525    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
   1526 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1527    #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
   1528 #elif \
   1529    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1530    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1531    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
   1532 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
   1533    #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
   1534 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
   1535    #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
   1536 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
   1537    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
   1538 #else
   1539    #define JSON_HEDLEY_NO_RETURN
   1540 #endif
   1541 
   1542 #if defined(JSON_HEDLEY_NO_ESCAPE)
   1543    #undef JSON_HEDLEY_NO_ESCAPE
   1544 #endif
   1545 #if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
   1546    #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
   1547 #else
   1548    #define JSON_HEDLEY_NO_ESCAPE
   1549 #endif
   1550 
   1551 #if defined(JSON_HEDLEY_UNREACHABLE)
   1552    #undef JSON_HEDLEY_UNREACHABLE
   1553 #endif
   1554 #if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
   1555    #undef JSON_HEDLEY_UNREACHABLE_RETURN
   1556 #endif
   1557 #if defined(JSON_HEDLEY_ASSUME)
   1558    #undef JSON_HEDLEY_ASSUME
   1559 #endif
   1560 #if \
   1561    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1562    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1563    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1564    #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
   1565 #elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
   1566    #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
   1567 #elif \
   1568    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
   1569    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
   1570    #if defined(__cplusplus)
   1571        #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
   1572    #else
   1573        #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
   1574    #endif
   1575 #endif
   1576 #if \
   1577    (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
   1578    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
   1579    JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
   1580    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1581    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
   1582    JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
   1583    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1584    #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
   1585 #elif defined(JSON_HEDLEY_ASSUME)
   1586    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
   1587 #endif
   1588 #if !defined(JSON_HEDLEY_ASSUME)
   1589    #if defined(JSON_HEDLEY_UNREACHABLE)
   1590        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
   1591    #else
   1592        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
   1593    #endif
   1594 #endif
   1595 #if defined(JSON_HEDLEY_UNREACHABLE)
   1596    #if  \
   1597        JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
   1598        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
   1599        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
   1600    #else
   1601        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
   1602    #endif
   1603 #else
   1604    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
   1605 #endif
   1606 #if !defined(JSON_HEDLEY_UNREACHABLE)
   1607    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
   1608 #endif
   1609 
   1610 JSON_HEDLEY_DIAGNOSTIC_PUSH
   1611 #if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
   1612    #pragma clang diagnostic ignored "-Wpedantic"
   1613 #endif
   1614 #if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
   1615    #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
   1616 #endif
   1617 #if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
   1618    #if defined(__clang__)
   1619        #pragma clang diagnostic ignored "-Wvariadic-macros"
   1620    #elif defined(JSON_HEDLEY_GCC_VERSION)
   1621        #pragma GCC diagnostic ignored "-Wvariadic-macros"
   1622    #endif
   1623 #endif
   1624 #if defined(JSON_HEDLEY_NON_NULL)
   1625    #undef JSON_HEDLEY_NON_NULL
   1626 #endif
   1627 #if \
   1628    JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
   1629    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
   1630    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1631    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
   1632    #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
   1633 #else
   1634    #define JSON_HEDLEY_NON_NULL(...)
   1635 #endif
   1636 JSON_HEDLEY_DIAGNOSTIC_POP
   1637 
   1638 #if defined(JSON_HEDLEY_PRINTF_FORMAT)
   1639    #undef JSON_HEDLEY_PRINTF_FORMAT
   1640 #endif
   1641 #if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
   1642    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
   1643 #elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
   1644    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
   1645 #elif \
   1646    JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
   1647    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1648    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1649    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
   1650    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1651    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1652    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1653    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1654    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1655    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1656    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1657    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1658    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1659    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1660    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1661    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1662    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1663    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
   1664 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
   1665    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
   1666 #else
   1667    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
   1668 #endif
   1669 
   1670 #if defined(JSON_HEDLEY_CONSTEXPR)
   1671    #undef JSON_HEDLEY_CONSTEXPR
   1672 #endif
   1673 #if defined(__cplusplus)
   1674    #if __cplusplus >= 201103L
   1675        #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
   1676    #endif
   1677 #endif
   1678 #if !defined(JSON_HEDLEY_CONSTEXPR)
   1679    #define JSON_HEDLEY_CONSTEXPR
   1680 #endif
   1681 
   1682 #if defined(JSON_HEDLEY_PREDICT)
   1683    #undef JSON_HEDLEY_PREDICT
   1684 #endif
   1685 #if defined(JSON_HEDLEY_LIKELY)
   1686    #undef JSON_HEDLEY_LIKELY
   1687 #endif
   1688 #if defined(JSON_HEDLEY_UNLIKELY)
   1689    #undef JSON_HEDLEY_UNLIKELY
   1690 #endif
   1691 #if defined(JSON_HEDLEY_UNPREDICTABLE)
   1692    #undef JSON_HEDLEY_UNPREDICTABLE
   1693 #endif
   1694 #if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
   1695    #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
   1696 #endif
   1697 #if \
   1698  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
   1699  JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
   1700  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1701 #  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
   1702 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
   1703 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
   1704 #  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
   1705 #  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
   1706 #elif \
   1707  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
   1708  JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
   1709  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1710  (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
   1711  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1712  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1713  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1714  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
   1715  JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
   1716  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
   1717  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
   1718  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1719  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1720  JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
   1721  JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
   1722  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1723 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
   1724    (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
   1725 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
   1726    (__extension__ ({ \
   1727        double hedley_probability_ = (probability); \
   1728        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
   1729    }))
   1730 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
   1731    (__extension__ ({ \
   1732        double hedley_probability_ = (probability); \
   1733        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
   1734    }))
   1735 #  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
   1736 #  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
   1737 #else
   1738 #  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
   1739 #  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
   1740 #  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
   1741 #  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
   1742 #  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
   1743 #endif
   1744 #if !defined(JSON_HEDLEY_UNPREDICTABLE)
   1745    #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
   1746 #endif
   1747 
   1748 #if defined(JSON_HEDLEY_MALLOC)
   1749    #undef JSON_HEDLEY_MALLOC
   1750 #endif
   1751 #if \
   1752    JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
   1753    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1754    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1755    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1756    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1757    JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
   1758    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1759    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1760    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1761    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1762    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1763    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1764    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1765    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1766    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1767    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1768    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1769    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1770    #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
   1771 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1772    #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
   1773 #elif \
   1774    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
   1775    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1776    #define JSON_HEDLEY_MALLOC __declspec(restrict)
   1777 #else
   1778    #define JSON_HEDLEY_MALLOC
   1779 #endif
   1780 
   1781 #if defined(JSON_HEDLEY_PURE)
   1782    #undef JSON_HEDLEY_PURE
   1783 #endif
   1784 #if \
   1785  JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
   1786  JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
   1787  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1788  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1789  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1790  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1791  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1792  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1793  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1794  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1795  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1796  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1797  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1798  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1799  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1800  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1801  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1802  JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1803  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1804 #  define JSON_HEDLEY_PURE __attribute__((__pure__))
   1805 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1806 #  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
   1807 #elif defined(__cplusplus) && \
   1808    ( \
   1809      JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
   1810      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
   1811      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
   1812    )
   1813 #  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
   1814 #else
   1815 #  define JSON_HEDLEY_PURE
   1816 #endif
   1817 
   1818 #if defined(JSON_HEDLEY_CONST)
   1819    #undef JSON_HEDLEY_CONST
   1820 #endif
   1821 #if \
   1822    JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
   1823    JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
   1824    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1825    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1826    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1827    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1828    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1829    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1830    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1831    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1832    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1833    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1834    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1835    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1836    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1837    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1838    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1839    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1840    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1841    #define JSON_HEDLEY_CONST __attribute__((__const__))
   1842 #elif \
   1843    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
   1844    #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
   1845 #else
   1846    #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
   1847 #endif
   1848 
   1849 #if defined(JSON_HEDLEY_RESTRICT)
   1850    #undef JSON_HEDLEY_RESTRICT
   1851 #endif
   1852 #if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
   1853    #define JSON_HEDLEY_RESTRICT restrict
   1854 #elif \
   1855    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
   1856    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
   1857    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1858    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
   1859    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1860    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1861    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
   1862    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1863    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
   1864    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
   1865    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1866    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
   1867    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
   1868    defined(__clang__) || \
   1869    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1870    #define JSON_HEDLEY_RESTRICT __restrict
   1871 #elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
   1872    #define JSON_HEDLEY_RESTRICT _Restrict
   1873 #else
   1874    #define JSON_HEDLEY_RESTRICT
   1875 #endif
   1876 
   1877 #if defined(JSON_HEDLEY_INLINE)
   1878    #undef JSON_HEDLEY_INLINE
   1879 #endif
   1880 #if \
   1881    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
   1882    (defined(__cplusplus) && (__cplusplus >= 199711L))
   1883    #define JSON_HEDLEY_INLINE inline
   1884 #elif \
   1885    defined(JSON_HEDLEY_GCC_VERSION) || \
   1886    JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
   1887    #define JSON_HEDLEY_INLINE __inline__
   1888 #elif \
   1889    JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
   1890    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
   1891    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1892    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
   1893    JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
   1894    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
   1895    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
   1896    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1897    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1898    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   1899    #define JSON_HEDLEY_INLINE __inline
   1900 #else
   1901    #define JSON_HEDLEY_INLINE
   1902 #endif
   1903 
   1904 #if defined(JSON_HEDLEY_ALWAYS_INLINE)
   1905    #undef JSON_HEDLEY_ALWAYS_INLINE
   1906 #endif
   1907 #if \
   1908  JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
   1909  JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
   1910  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1911  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1912  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1913  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1914  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1915  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1916  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1917  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1918  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1919  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1920  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1921  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1922  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1923  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1924  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1925  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
   1926  JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1927 #  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
   1928 #elif \
   1929  JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
   1930  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1931 #  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
   1932 #elif defined(__cplusplus) && \
   1933    ( \
   1934      JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1935      JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1936      JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1937      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
   1938      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1939      JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
   1940    )
   1941 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
   1942 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1943 #  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
   1944 #else
   1945 #  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
   1946 #endif
   1947 
   1948 #if defined(JSON_HEDLEY_NEVER_INLINE)
   1949    #undef JSON_HEDLEY_NEVER_INLINE
   1950 #endif
   1951 #if \
   1952    JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
   1953    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
   1954    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   1955    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   1956    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   1957    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
   1958    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
   1959    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1960    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
   1961    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1962    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
   1963    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1964    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
   1965    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   1966    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
   1967    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
   1968    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
   1969    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
   1970    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
   1971    #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
   1972 #elif \
   1973    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
   1974    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   1975    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
   1976 #elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
   1977    #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
   1978 #elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
   1979    #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
   1980 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   1981    #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
   1982 #elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
   1983    #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
   1984 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
   1985    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
   1986 #else
   1987    #define JSON_HEDLEY_NEVER_INLINE
   1988 #endif
   1989 
   1990 #if defined(JSON_HEDLEY_PRIVATE)
   1991    #undef JSON_HEDLEY_PRIVATE
   1992 #endif
   1993 #if defined(JSON_HEDLEY_PUBLIC)
   1994    #undef JSON_HEDLEY_PUBLIC
   1995 #endif
   1996 #if defined(JSON_HEDLEY_IMPORT)
   1997    #undef JSON_HEDLEY_IMPORT
   1998 #endif
   1999 #if defined(_WIN32) || defined(__CYGWIN__)
   2000 #  define JSON_HEDLEY_PRIVATE
   2001 #  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
   2002 #  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
   2003 #else
   2004 #  if \
   2005    JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
   2006    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
   2007    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
   2008    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2009    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   2010    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
   2011    ( \
   2012      defined(__TI_EABI__) && \
   2013      ( \
   2014        (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
   2015        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
   2016      ) \
   2017    ) || \
   2018    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2019 #    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
   2020 #    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
   2021 #  else
   2022 #    define JSON_HEDLEY_PRIVATE
   2023 #    define JSON_HEDLEY_PUBLIC
   2024 #  endif
   2025 #  define JSON_HEDLEY_IMPORT    extern
   2026 #endif
   2027 
   2028 #if defined(JSON_HEDLEY_NO_THROW)
   2029    #undef JSON_HEDLEY_NO_THROW
   2030 #endif
   2031 #if \
   2032    JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
   2033    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
   2034    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2035    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2036    #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
   2037 #elif \
   2038    JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
   2039    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
   2040    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
   2041    #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
   2042 #else
   2043    #define JSON_HEDLEY_NO_THROW
   2044 #endif
   2045 
   2046 #if defined(JSON_HEDLEY_FALL_THROUGH)
   2047    #undef JSON_HEDLEY_FALL_THROUGH
   2048 #endif
   2049 #if \
   2050    JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
   2051    JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
   2052    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2053    #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
   2054 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
   2055    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
   2056 #elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
   2057    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
   2058 #elif defined(__fallthrough) /* SAL */
   2059    #define JSON_HEDLEY_FALL_THROUGH __fallthrough
   2060 #else
   2061    #define JSON_HEDLEY_FALL_THROUGH
   2062 #endif
   2063 
   2064 #if defined(JSON_HEDLEY_RETURNS_NON_NULL)
   2065    #undef JSON_HEDLEY_RETURNS_NON_NULL
   2066 #endif
   2067 #if \
   2068    JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
   2069    JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
   2070    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2071    #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
   2072 #elif defined(_Ret_notnull_) /* SAL */
   2073    #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
   2074 #else
   2075    #define JSON_HEDLEY_RETURNS_NON_NULL
   2076 #endif
   2077 
   2078 #if defined(JSON_HEDLEY_ARRAY_PARAM)
   2079    #undef JSON_HEDLEY_ARRAY_PARAM
   2080 #endif
   2081 #if \
   2082    defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
   2083    !defined(__STDC_NO_VLA__) && \
   2084    !defined(__cplusplus) && \
   2085    !defined(JSON_HEDLEY_PGI_VERSION) && \
   2086    !defined(JSON_HEDLEY_TINYC_VERSION)
   2087    #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
   2088 #else
   2089    #define JSON_HEDLEY_ARRAY_PARAM(name)
   2090 #endif
   2091 
   2092 #if defined(JSON_HEDLEY_IS_CONSTANT)
   2093    #undef JSON_HEDLEY_IS_CONSTANT
   2094 #endif
   2095 #if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
   2096    #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
   2097 #endif
   2098 /* JSON_HEDLEY_IS_CONSTEXPR_ is for
   2099   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
   2100 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
   2101    #undef JSON_HEDLEY_IS_CONSTEXPR_
   2102 #endif
   2103 #if \
   2104    JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
   2105    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
   2106    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2107    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
   2108    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
   2109    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
   2110    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
   2111    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
   2112    JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
   2113    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
   2114    #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
   2115 #endif
   2116 #if !defined(__cplusplus)
   2117 #  if \
   2118       JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
   2119       JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
   2120       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2121       JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
   2122       JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
   2123       JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
   2124       JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
   2125 #if defined(__INTPTR_TYPE__)
   2126    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
   2127 #else
   2128    #include <stdint.h>
   2129    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
   2130 #endif
   2131 #  elif \
   2132       ( \
   2133          defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
   2134          !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
   2135          !defined(JSON_HEDLEY_PGI_VERSION) && \
   2136          !defined(JSON_HEDLEY_IAR_VERSION)) || \
   2137       (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
   2138       JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
   2139       JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
   2140       JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
   2141       JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
   2142 #if defined(__INTPTR_TYPE__)
   2143    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
   2144 #else
   2145    #include <stdint.h>
   2146    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
   2147 #endif
   2148 #  elif \
   2149       defined(JSON_HEDLEY_GCC_VERSION) || \
   2150       defined(JSON_HEDLEY_INTEL_VERSION) || \
   2151       defined(JSON_HEDLEY_TINYC_VERSION) || \
   2152       defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
   2153       JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
   2154       defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
   2155       defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
   2156       defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
   2157       defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
   2158       defined(__clang__)
   2159 #    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
   2160        sizeof(void) != \
   2161        sizeof(*( \
   2162                  1 ? \
   2163                  ((void*) ((expr) * 0L) ) : \
   2164 ((struct { char v[sizeof(void) * 2]; } *) 1) \
   2165                ) \
   2166              ) \
   2167                                            )
   2168 #  endif
   2169 #endif
   2170 #if defined(JSON_HEDLEY_IS_CONSTEXPR_)
   2171    #if !defined(JSON_HEDLEY_IS_CONSTANT)
   2172        #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
   2173    #endif
   2174    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
   2175 #else
   2176    #if !defined(JSON_HEDLEY_IS_CONSTANT)
   2177        #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
   2178    #endif
   2179    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
   2180 #endif
   2181 
   2182 #if defined(JSON_HEDLEY_BEGIN_C_DECLS)
   2183    #undef JSON_HEDLEY_BEGIN_C_DECLS
   2184 #endif
   2185 #if defined(JSON_HEDLEY_END_C_DECLS)
   2186    #undef JSON_HEDLEY_END_C_DECLS
   2187 #endif
   2188 #if defined(JSON_HEDLEY_C_DECL)
   2189    #undef JSON_HEDLEY_C_DECL
   2190 #endif
   2191 #if defined(__cplusplus)
   2192    #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
   2193    #define JSON_HEDLEY_END_C_DECLS }
   2194    #define JSON_HEDLEY_C_DECL extern "C"
   2195 #else
   2196    #define JSON_HEDLEY_BEGIN_C_DECLS
   2197    #define JSON_HEDLEY_END_C_DECLS
   2198    #define JSON_HEDLEY_C_DECL
   2199 #endif
   2200 
   2201 #if defined(JSON_HEDLEY_STATIC_ASSERT)
   2202    #undef JSON_HEDLEY_STATIC_ASSERT
   2203 #endif
   2204 #if \
   2205  !defined(__cplusplus) && ( \
   2206      (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
   2207      (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
   2208      JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
   2209      JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
   2210      defined(_Static_assert) \
   2211    )
   2212 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
   2213 #elif \
   2214  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
   2215  JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
   2216  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   2217 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
   2218 #else
   2219 #  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
   2220 #endif
   2221 
   2222 #if defined(JSON_HEDLEY_NULL)
   2223    #undef JSON_HEDLEY_NULL
   2224 #endif
   2225 #if defined(__cplusplus)
   2226    #if __cplusplus >= 201103L
   2227        #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
   2228    #elif defined(NULL)
   2229        #define JSON_HEDLEY_NULL NULL
   2230    #else
   2231        #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
   2232    #endif
   2233 #elif defined(NULL)
   2234    #define JSON_HEDLEY_NULL NULL
   2235 #else
   2236    #define JSON_HEDLEY_NULL ((void*) 0)
   2237 #endif
   2238 
   2239 #if defined(JSON_HEDLEY_MESSAGE)
   2240    #undef JSON_HEDLEY_MESSAGE
   2241 #endif
   2242 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
   2243 #  define JSON_HEDLEY_MESSAGE(msg) \
   2244    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2245    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
   2246    JSON_HEDLEY_PRAGMA(message msg) \
   2247    JSON_HEDLEY_DIAGNOSTIC_POP
   2248 #elif \
   2249  JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
   2250  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   2251 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
   2252 #elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
   2253 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
   2254 #elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
   2255 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
   2256 #elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
   2257 #  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
   2258 #else
   2259 #  define JSON_HEDLEY_MESSAGE(msg)
   2260 #endif
   2261 
   2262 #if defined(JSON_HEDLEY_WARNING)
   2263    #undef JSON_HEDLEY_WARNING
   2264 #endif
   2265 #if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
   2266 #  define JSON_HEDLEY_WARNING(msg) \
   2267    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2268    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
   2269    JSON_HEDLEY_PRAGMA(clang warning msg) \
   2270    JSON_HEDLEY_DIAGNOSTIC_POP
   2271 #elif \
   2272  JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
   2273  JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
   2274  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
   2275 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
   2276 #elif \
   2277  JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
   2278  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   2279 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
   2280 #else
   2281 #  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
   2282 #endif
   2283 
   2284 #if defined(JSON_HEDLEY_REQUIRE)
   2285    #undef JSON_HEDLEY_REQUIRE
   2286 #endif
   2287 #if defined(JSON_HEDLEY_REQUIRE_MSG)
   2288    #undef JSON_HEDLEY_REQUIRE_MSG
   2289 #endif
   2290 #if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
   2291 #  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
   2292 #    define JSON_HEDLEY_REQUIRE(expr) \
   2293    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2294    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
   2295    __attribute__((diagnose_if(!(expr), #expr, "error"))) \
   2296    JSON_HEDLEY_DIAGNOSTIC_POP
   2297 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
   2298    JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2299    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
   2300    __attribute__((diagnose_if(!(expr), msg, "error"))) \
   2301    JSON_HEDLEY_DIAGNOSTIC_POP
   2302 #  else
   2303 #    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
   2304 #    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
   2305 #  endif
   2306 #else
   2307 #  define JSON_HEDLEY_REQUIRE(expr)
   2308 #  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
   2309 #endif
   2310 
   2311 #if defined(JSON_HEDLEY_FLAGS)
   2312    #undef JSON_HEDLEY_FLAGS
   2313 #endif
   2314 #if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
   2315    #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
   2316 #else
   2317    #define JSON_HEDLEY_FLAGS
   2318 #endif
   2319 
   2320 #if defined(JSON_HEDLEY_FLAGS_CAST)
   2321    #undef JSON_HEDLEY_FLAGS_CAST
   2322 #endif
   2323 #if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
   2324 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
   2325        JSON_HEDLEY_DIAGNOSTIC_PUSH \
   2326        _Pragma("warning(disable:188)") \
   2327        ((T) (expr)); \
   2328        JSON_HEDLEY_DIAGNOSTIC_POP \
   2329    }))
   2330 #else
   2331 #  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
   2332 #endif
   2333 
   2334 #if defined(JSON_HEDLEY_EMPTY_BASES)
   2335    #undef JSON_HEDLEY_EMPTY_BASES
   2336 #endif
   2337 #if \
   2338    (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
   2339    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
   2340    #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
   2341 #else
   2342    #define JSON_HEDLEY_EMPTY_BASES
   2343 #endif
   2344 
   2345 /* Remaining macros are deprecated. */
   2346 
   2347 #if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
   2348    #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
   2349 #endif
   2350 #if defined(__clang__)
   2351    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
   2352 #else
   2353    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
   2354 #endif
   2355 
   2356 #if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
   2357    #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
   2358 #endif
   2359 #define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
   2360 
   2361 #if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
   2362    #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
   2363 #endif
   2364 #define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
   2365 
   2366 #if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
   2367    #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
   2368 #endif
   2369 #define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
   2370 
   2371 #if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
   2372    #undef JSON_HEDLEY_CLANG_HAS_FEATURE
   2373 #endif
   2374 #define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
   2375 
   2376 #if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
   2377    #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
   2378 #endif
   2379 #define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
   2380 
   2381 #if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
   2382    #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
   2383 #endif
   2384 #define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
   2385 
   2386 #if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
   2387    #undef JSON_HEDLEY_CLANG_HAS_WARNING
   2388 #endif
   2389 #define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
   2390 
   2391 #endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
   2392 
   2393 
   2394 // This file contains all internal macro definitions (except those affecting ABI)
   2395 // You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
   2396 
   2397 // #include <nlohmann/detail/abi_macros.hpp>
   2398 
   2399 
   2400 // exclude unsupported compilers
   2401 #if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
   2402    #if defined(__clang__)
   2403        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
   2404            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
   2405        #endif
   2406    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
   2407        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
   2408            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
   2409        #endif
   2410    #endif
   2411 #endif
   2412 
   2413 // C++ language standard detection
   2414 // if the user manually specified the used c++ version this is skipped
   2415 #if !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
   2416    #if (defined(__cplusplus) && __cplusplus >= 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG >= 202002L)
   2417        #define JSON_HAS_CPP_20
   2418        #define JSON_HAS_CPP_17
   2419        #define JSON_HAS_CPP_14
   2420    #elif (defined(__cplusplus) && __cplusplus >= 201703L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
   2421        #define JSON_HAS_CPP_17
   2422        #define JSON_HAS_CPP_14
   2423    #elif (defined(__cplusplus) && __cplusplus >= 201402L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
   2424        #define JSON_HAS_CPP_14
   2425    #endif
   2426    // the cpp 11 flag is always specified because it is the minimal required version
   2427    #define JSON_HAS_CPP_11
   2428 #endif
   2429 
   2430 #ifdef __has_include
   2431    #if __has_include(<version>)
   2432        #include <version>
   2433    #endif
   2434 #endif
   2435 
   2436 #if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
   2437    #ifdef JSON_HAS_CPP_17
   2438        #if defined(__cpp_lib_filesystem)
   2439            #define JSON_HAS_FILESYSTEM 1
   2440        #elif defined(__cpp_lib_experimental_filesystem)
   2441            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
   2442        #elif !defined(__has_include)
   2443            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
   2444        #elif __has_include(<filesystem>)
   2445            #define JSON_HAS_FILESYSTEM 1
   2446        #elif __has_include(<experimental/filesystem>)
   2447            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
   2448        #endif
   2449 
   2450        // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
   2451        #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
   2452            #undef JSON_HAS_FILESYSTEM
   2453            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2454        #endif
   2455 
   2456        // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
   2457        #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
   2458            #undef JSON_HAS_FILESYSTEM
   2459            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2460        #endif
   2461 
   2462        // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
   2463        #if defined(__clang_major__) && __clang_major__ < 7
   2464            #undef JSON_HAS_FILESYSTEM
   2465            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2466        #endif
   2467 
   2468        // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
   2469        #if defined(_MSC_VER) && _MSC_VER < 1914
   2470            #undef JSON_HAS_FILESYSTEM
   2471            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2472        #endif
   2473 
   2474        // no filesystem support before iOS 13
   2475        #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
   2476            #undef JSON_HAS_FILESYSTEM
   2477            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2478        #endif
   2479 
   2480        // no filesystem support before macOS Catalina
   2481        #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
   2482            #undef JSON_HAS_FILESYSTEM
   2483            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2484        #endif
   2485    #endif
   2486 #endif
   2487 
   2488 #ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
   2489    #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
   2490 #endif
   2491 
   2492 #ifndef JSON_HAS_FILESYSTEM
   2493    #define JSON_HAS_FILESYSTEM 0
   2494 #endif
   2495 
   2496 #ifndef JSON_HAS_THREE_WAY_COMPARISON
   2497    #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
   2498        && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
   2499        #define JSON_HAS_THREE_WAY_COMPARISON 1
   2500    #else
   2501        #define JSON_HAS_THREE_WAY_COMPARISON 0
   2502    #endif
   2503 #endif
   2504 
   2505 #ifndef JSON_HAS_RANGES
   2506    // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
   2507    #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
   2508        #define JSON_HAS_RANGES 0
   2509    #elif defined(__cpp_lib_ranges)
   2510        #define JSON_HAS_RANGES 1
   2511    #else
   2512        #define JSON_HAS_RANGES 0
   2513    #endif
   2514 #endif
   2515 
   2516 #ifndef JSON_HAS_STATIC_RTTI
   2517    #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
   2518        #define JSON_HAS_STATIC_RTTI 1
   2519    #else
   2520        #define JSON_HAS_STATIC_RTTI 0
   2521    #endif
   2522 #endif
   2523 
   2524 #ifdef JSON_HAS_CPP_17
   2525    #define JSON_INLINE_VARIABLE inline
   2526 #else
   2527    #define JSON_INLINE_VARIABLE
   2528 #endif
   2529 
   2530 #if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
   2531    #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
   2532 #else
   2533    #define JSON_NO_UNIQUE_ADDRESS
   2534 #endif
   2535 
   2536 // disable documentation warnings on clang
   2537 #if defined(__clang__)
   2538    #pragma clang diagnostic push
   2539    #pragma clang diagnostic ignored "-Wdocumentation"
   2540    #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
   2541 #endif
   2542 
   2543 // allow disabling exceptions
   2544 #if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
   2545    #define JSON_THROW(exception) throw exception
   2546    #define JSON_TRY try
   2547    #define JSON_CATCH(exception) catch(exception)
   2548    #define JSON_INTERNAL_CATCH(exception) catch(exception)
   2549 #else
   2550    #include <cstdlib>
   2551    #define JSON_THROW(exception) std::abort()
   2552    #define JSON_TRY if(true)
   2553    #define JSON_CATCH(exception) if(false)
   2554    #define JSON_INTERNAL_CATCH(exception) if(false)
   2555 #endif
   2556 
   2557 // override exception macros
   2558 #if defined(JSON_THROW_USER)
   2559    #undef JSON_THROW
   2560    #define JSON_THROW JSON_THROW_USER
   2561 #endif
   2562 #if defined(JSON_TRY_USER)
   2563    #undef JSON_TRY
   2564    #define JSON_TRY JSON_TRY_USER
   2565 #endif
   2566 #if defined(JSON_CATCH_USER)
   2567    #undef JSON_CATCH
   2568    #define JSON_CATCH JSON_CATCH_USER
   2569    #undef JSON_INTERNAL_CATCH
   2570    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
   2571 #endif
   2572 #if defined(JSON_INTERNAL_CATCH_USER)
   2573    #undef JSON_INTERNAL_CATCH
   2574    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
   2575 #endif
   2576 
   2577 // allow overriding assert
   2578 #if !defined(JSON_ASSERT)
   2579    #include <cassert> // assert
   2580    #define JSON_ASSERT(x) assert(x)
   2581 #endif
   2582 
   2583 // allow to access some private functions (needed by the test suite)
   2584 #if defined(JSON_TESTS_PRIVATE)
   2585    #define JSON_PRIVATE_UNLESS_TESTED public
   2586 #else
   2587    #define JSON_PRIVATE_UNLESS_TESTED private
   2588 #endif
   2589 
   2590 /*!
   2591 @brief macro to briefly define a mapping between an enum and JSON
   2592 @def NLOHMANN_JSON_SERIALIZE_ENUM
   2593 @since version 3.4.0
   2594 */
   2595 #define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
   2596    template<typename BasicJsonType>                                                            \
   2597    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
   2598    {                                                                                           \
   2599        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
   2600        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
   2601        auto it = std::find_if(std::begin(m), std::end(m),                                      \
   2602                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
   2603        {                                                                                       \
   2604            return ej_pair.first == e;                                                          \
   2605        });                                                                                     \
   2606        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
   2607    }                                                                                           \
   2608    template<typename BasicJsonType>                                                            \
   2609    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
   2610    {                                                                                           \
   2611        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
   2612        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
   2613        auto it = std::find_if(std::begin(m), std::end(m),                                      \
   2614                               [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
   2615        {                                                                                       \
   2616            return ej_pair.second == j;                                                         \
   2617        });                                                                                     \
   2618        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
   2619    }
   2620 
   2621 // Ugly macros to avoid uglier copy-paste when specializing basic_json. They
   2622 // may be removed in the future once the class is split.
   2623 
   2624 #define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
   2625    template<template<typename, typename, typename...> class ObjectType,   \
   2626             template<typename, typename...> class ArrayType,              \
   2627             class StringType, class BooleanType, class NumberIntegerType, \
   2628             class NumberUnsignedType, class NumberFloatType,              \
   2629             template<typename> class AllocatorType,                       \
   2630             template<typename, typename = void> class JSONSerializer,     \
   2631             class BinaryType,                                             \
   2632             class CustomBaseClass>
   2633 
   2634 #define NLOHMANN_BASIC_JSON_TPL                                            \
   2635    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
   2636    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
   2637    AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
   2638 
   2639 // Macros to simplify conversion from/to types
   2640 
   2641 #define NLOHMANN_JSON_EXPAND( x ) x
   2642 #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
   2643 #define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
   2644        NLOHMANN_JSON_PASTE64, \
   2645        NLOHMANN_JSON_PASTE63, \
   2646        NLOHMANN_JSON_PASTE62, \
   2647        NLOHMANN_JSON_PASTE61, \
   2648        NLOHMANN_JSON_PASTE60, \
   2649        NLOHMANN_JSON_PASTE59, \
   2650        NLOHMANN_JSON_PASTE58, \
   2651        NLOHMANN_JSON_PASTE57, \
   2652        NLOHMANN_JSON_PASTE56, \
   2653        NLOHMANN_JSON_PASTE55, \
   2654        NLOHMANN_JSON_PASTE54, \
   2655        NLOHMANN_JSON_PASTE53, \
   2656        NLOHMANN_JSON_PASTE52, \
   2657        NLOHMANN_JSON_PASTE51, \
   2658        NLOHMANN_JSON_PASTE50, \
   2659        NLOHMANN_JSON_PASTE49, \
   2660        NLOHMANN_JSON_PASTE48, \
   2661        NLOHMANN_JSON_PASTE47, \
   2662        NLOHMANN_JSON_PASTE46, \
   2663        NLOHMANN_JSON_PASTE45, \
   2664        NLOHMANN_JSON_PASTE44, \
   2665        NLOHMANN_JSON_PASTE43, \
   2666        NLOHMANN_JSON_PASTE42, \
   2667        NLOHMANN_JSON_PASTE41, \
   2668        NLOHMANN_JSON_PASTE40, \
   2669        NLOHMANN_JSON_PASTE39, \
   2670        NLOHMANN_JSON_PASTE38, \
   2671        NLOHMANN_JSON_PASTE37, \
   2672        NLOHMANN_JSON_PASTE36, \
   2673        NLOHMANN_JSON_PASTE35, \
   2674        NLOHMANN_JSON_PASTE34, \
   2675        NLOHMANN_JSON_PASTE33, \
   2676        NLOHMANN_JSON_PASTE32, \
   2677        NLOHMANN_JSON_PASTE31, \
   2678        NLOHMANN_JSON_PASTE30, \
   2679        NLOHMANN_JSON_PASTE29, \
   2680        NLOHMANN_JSON_PASTE28, \
   2681        NLOHMANN_JSON_PASTE27, \
   2682        NLOHMANN_JSON_PASTE26, \
   2683        NLOHMANN_JSON_PASTE25, \
   2684        NLOHMANN_JSON_PASTE24, \
   2685        NLOHMANN_JSON_PASTE23, \
   2686        NLOHMANN_JSON_PASTE22, \
   2687        NLOHMANN_JSON_PASTE21, \
   2688        NLOHMANN_JSON_PASTE20, \
   2689        NLOHMANN_JSON_PASTE19, \
   2690        NLOHMANN_JSON_PASTE18, \
   2691        NLOHMANN_JSON_PASTE17, \
   2692        NLOHMANN_JSON_PASTE16, \
   2693        NLOHMANN_JSON_PASTE15, \
   2694        NLOHMANN_JSON_PASTE14, \
   2695        NLOHMANN_JSON_PASTE13, \
   2696        NLOHMANN_JSON_PASTE12, \
   2697        NLOHMANN_JSON_PASTE11, \
   2698        NLOHMANN_JSON_PASTE10, \
   2699        NLOHMANN_JSON_PASTE9, \
   2700        NLOHMANN_JSON_PASTE8, \
   2701        NLOHMANN_JSON_PASTE7, \
   2702        NLOHMANN_JSON_PASTE6, \
   2703        NLOHMANN_JSON_PASTE5, \
   2704        NLOHMANN_JSON_PASTE4, \
   2705        NLOHMANN_JSON_PASTE3, \
   2706        NLOHMANN_JSON_PASTE2, \
   2707        NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
   2708 #define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
   2709 #define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
   2710 #define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
   2711 #define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
   2712 #define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
   2713 #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)
   2714 #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)
   2715 #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)
   2716 #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)
   2717 #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)
   2718 #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)
   2719 #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)
   2720 #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)
   2721 #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)
   2722 #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)
   2723 #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)
   2724 #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)
   2725 #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)
   2726 #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)
   2727 #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)
   2728 #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)
   2729 #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)
   2730 #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)
   2731 #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)
   2732 #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)
   2733 #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)
   2734 #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)
   2735 #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)
   2736 #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)
   2737 #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)
   2738 #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)
   2739 #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)
   2740 #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)
   2741 #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)
   2742 #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)
   2743 #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)
   2744 #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)
   2745 #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)
   2746 #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)
   2747 #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)
   2748 #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)
   2749 #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)
   2750 #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)
   2751 #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)
   2752 #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)
   2753 #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)
   2754 #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)
   2755 #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)
   2756 #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)
   2757 #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)
   2758 #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)
   2759 #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)
   2760 #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)
   2761 #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)
   2762 #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)
   2763 #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)
   2764 #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)
   2765 #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)
   2766 #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)
   2767 #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)
   2768 #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)
   2769 #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)
   2770 #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)
   2771 
   2772 #define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
   2773 #define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
   2774 #define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1);
   2775 
   2776 /*!
   2777 @brief macro
   2778 @def NLOHMANN_DEFINE_TYPE_INTRUSIVE
   2779 @since version 3.9.0
   2780 */
   2781 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
   2782    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__)) } \
   2783    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__)) }
   2784 
   2785 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
   2786    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__)) } \
   2787    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__)) }
   2788 
   2789 #define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \
   2790    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__)) }
   2791 
   2792 /*!
   2793 @brief macro
   2794 @def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
   2795 @since version 3.9.0
   2796 */
   2797 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
   2798    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__)) } \
   2799    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__)) }
   2800 
   2801 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \
   2802    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__)) }
   2803 
   2804 #define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
   2805    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__)) } \
   2806    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__)) }
   2807 
   2808 // inspired from https://stackoverflow.com/a/26745591
   2809 // allows to call any std function as if (e.g. with begin):
   2810 // using std::begin; begin(x);
   2811 //
   2812 // it allows using the detected idiom to retrieve the return type
   2813 // of such an expression
   2814 #define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \
   2815    namespace detail {                                                            \
   2816    using std::std_name;                                                          \
   2817    \
   2818    template<typename... T>                                                       \
   2819    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
   2820    }                                                                             \
   2821    \
   2822    namespace detail2 {                                                           \
   2823    struct std_name##_tag                                                         \
   2824    {                                                                             \
   2825    };                                                                            \
   2826    \
   2827    template<typename... T>                                                       \
   2828    std_name##_tag std_name(T&&...);                                              \
   2829    \
   2830    template<typename... T>                                                       \
   2831    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
   2832    \
   2833    template<typename... T>                                                       \
   2834    struct would_call_std_##std_name                                              \
   2835    {                                                                             \
   2836        static constexpr auto const value = ::nlohmann::detail::                  \
   2837                                            is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
   2838    };                                                                            \
   2839    } /* namespace detail2 */ \
   2840    \
   2841    template<typename... T>                                                       \
   2842    struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \
   2843    {                                                                             \
   2844    }
   2845 
   2846 #ifndef JSON_USE_IMPLICIT_CONVERSIONS
   2847    #define JSON_USE_IMPLICIT_CONVERSIONS 1
   2848 #endif
   2849 
   2850 #if JSON_USE_IMPLICIT_CONVERSIONS
   2851    #define JSON_EXPLICIT
   2852 #else
   2853    #define JSON_EXPLICIT explicit
   2854 #endif
   2855 
   2856 #ifndef JSON_DISABLE_ENUM_SERIALIZATION
   2857    #define JSON_DISABLE_ENUM_SERIALIZATION 0
   2858 #endif
   2859 
   2860 #ifndef JSON_USE_GLOBAL_UDLS
   2861    #define JSON_USE_GLOBAL_UDLS 1
   2862 #endif
   2863 
   2864 #if JSON_HAS_THREE_WAY_COMPARISON
   2865    #include <compare> // partial_ordering
   2866 #endif
   2867 
   2868 NLOHMANN_JSON_NAMESPACE_BEGIN
   2869 namespace detail
   2870 {
   2871 
   2872 ///////////////////////////
   2873 // JSON type enumeration //
   2874 ///////////////////////////
   2875 
   2876 /*!
   2877 @brief the JSON type enumeration
   2878 
   2879 This enumeration collects the different JSON types. It is internally used to
   2880 distinguish the stored values, and the functions @ref basic_json::is_null(),
   2881 @ref basic_json::is_object(), @ref basic_json::is_array(),
   2882 @ref basic_json::is_string(), @ref basic_json::is_boolean(),
   2883 @ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
   2884 @ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
   2885 @ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
   2886 @ref basic_json::is_structured() rely on it.
   2887 
   2888 @note There are three enumeration entries (number_integer, number_unsigned, and
   2889 number_float), because the library distinguishes these three types for numbers:
   2890 @ref basic_json::number_unsigned_t is used for unsigned integers,
   2891 @ref basic_json::number_integer_t is used for signed integers, and
   2892 @ref basic_json::number_float_t is used for floating-point numbers or to
   2893 approximate integers which do not fit in the limits of their respective type.
   2894 
   2895 @sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
   2896 value with the default value for a given type
   2897 
   2898 @since version 1.0.0
   2899 */
   2900 enum class value_t : std::uint8_t
   2901 {
   2902    null,             ///< null value
   2903    object,           ///< object (unordered set of name/value pairs)
   2904    array,            ///< array (ordered collection of values)
   2905    string,           ///< string value
   2906    boolean,          ///< boolean value
   2907    number_integer,   ///< number value (signed integer)
   2908    number_unsigned,  ///< number value (unsigned integer)
   2909    number_float,     ///< number value (floating-point)
   2910    binary,           ///< binary array (ordered collection of bytes)
   2911    discarded         ///< discarded by the parser callback function
   2912 };
   2913 
   2914 /*!
   2915 @brief comparison operator for JSON types
   2916 
   2917 Returns an ordering that is similar to Python:
   2918 - order: null < boolean < number < object < array < string < binary
   2919 - furthermore, each type is not smaller than itself
   2920 - discarded values are not comparable
   2921 - binary is represented as a b"" string in python and directly comparable to a
   2922  string; however, making a binary array directly comparable with a string would
   2923  be surprising behavior in a JSON file.
   2924 
   2925 @since version 1.0.0
   2926 */
   2927 #if JSON_HAS_THREE_WAY_COMPARISON
   2928    inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
   2929 #else
   2930    inline bool operator<(const value_t lhs, const value_t rhs) noexcept
   2931 #endif
   2932 {
   2933    static constexpr std::array<std::uint8_t, 9> order = {{
   2934            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
   2935            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
   2936            6 /* binary */
   2937        }
   2938    };
   2939 
   2940    const auto l_index = static_cast<std::size_t>(lhs);
   2941    const auto r_index = static_cast<std::size_t>(rhs);
   2942 #if JSON_HAS_THREE_WAY_COMPARISON
   2943    if (l_index < order.size() && r_index < order.size())
   2944    {
   2945        return order[l_index] <=> order[r_index]; // *NOPAD*
   2946    }
   2947    return std::partial_ordering::unordered;
   2948 #else
   2949    return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
   2950 #endif
   2951 }
   2952 
   2953 // GCC selects the built-in operator< over an operator rewritten from
   2954 // a user-defined spaceship operator
   2955 // Clang, MSVC, and ICC select the rewritten candidate
   2956 // (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
   2957 #if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
   2958 inline bool operator<(const value_t lhs, const value_t rhs) noexcept
   2959 {
   2960    return std::is_lt(lhs <=> rhs); // *NOPAD*
   2961 }
   2962 #endif
   2963 
   2964 }  // namespace detail
   2965 NLOHMANN_JSON_NAMESPACE_END
   2966 
   2967 // #include <nlohmann/detail/string_escape.hpp>
   2968 //     __ _____ _____ _____
   2969 //  __|  |   __|     |   | |  JSON for Modern C++
   2970 // |  |  |__   |  |  | | | |  version 3.11.3
   2971 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   2972 //
   2973 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   2974 // SPDX-License-Identifier: MIT
   2975 
   2976 
   2977 
   2978 // #include <nlohmann/detail/abi_macros.hpp>
   2979 
   2980 
   2981 NLOHMANN_JSON_NAMESPACE_BEGIN
   2982 namespace detail
   2983 {
   2984 
   2985 /*!
   2986 @brief replace all occurrences of a substring by another string
   2987 
   2988 @param[in,out] s  the string to manipulate; changed so that all
   2989               occurrences of @a f are replaced with @a t
   2990 @param[in]     f  the substring to replace with @a t
   2991 @param[in]     t  the string to replace @a f
   2992 
   2993 @pre The search string @a f must not be empty. **This precondition is
   2994 enforced with an assertion.**
   2995 
   2996 @since version 2.0.0
   2997 */
   2998 template<typename StringType>
   2999 inline void replace_substring(StringType& s, const StringType& f,
   3000                              const StringType& t)
   3001 {
   3002    JSON_ASSERT(!f.empty());
   3003    for (auto pos = s.find(f);                // find first occurrence of f
   3004            pos != StringType::npos;          // make sure f was found
   3005            s.replace(pos, f.size(), t),      // replace with t, and
   3006            pos = s.find(f, pos + t.size()))  // find next occurrence of f
   3007    {}
   3008 }
   3009 
   3010 /*!
   3011 * @brief string escaping as described in RFC 6901 (Sect. 4)
   3012 * @param[in] s string to escape
   3013 * @return    escaped string
   3014 *
   3015 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
   3016 */
   3017 template<typename StringType>
   3018 inline StringType escape(StringType s)
   3019 {
   3020    replace_substring(s, StringType{"~"}, StringType{"~0"});
   3021    replace_substring(s, StringType{"/"}, StringType{"~1"});
   3022    return s;
   3023 }
   3024 
   3025 /*!
   3026 * @brief string unescaping as described in RFC 6901 (Sect. 4)
   3027 * @param[in] s string to unescape
   3028 * @return    unescaped string
   3029 *
   3030 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
   3031 */
   3032 template<typename StringType>
   3033 static void unescape(StringType& s)
   3034 {
   3035    replace_substring(s, StringType{"~1"}, StringType{"/"});
   3036    replace_substring(s, StringType{"~0"}, StringType{"~"});
   3037 }
   3038 
   3039 }  // namespace detail
   3040 NLOHMANN_JSON_NAMESPACE_END
   3041 
   3042 // #include <nlohmann/detail/input/position_t.hpp>
   3043 //     __ _____ _____ _____
   3044 //  __|  |   __|     |   | |  JSON for Modern C++
   3045 // |  |  |__   |  |  | | | |  version 3.11.3
   3046 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3047 //
   3048 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3049 // SPDX-License-Identifier: MIT
   3050 
   3051 
   3052 
   3053 #include <cstddef> // size_t
   3054 
   3055 // #include <nlohmann/detail/abi_macros.hpp>
   3056 
   3057 
   3058 NLOHMANN_JSON_NAMESPACE_BEGIN
   3059 namespace detail
   3060 {
   3061 
   3062 /// struct to capture the start position of the current token
   3063 struct position_t
   3064 {
   3065    /// the total number of characters read
   3066    std::size_t chars_read_total = 0;
   3067    /// the number of characters read in the current line
   3068    std::size_t chars_read_current_line = 0;
   3069    /// the number of lines read
   3070    std::size_t lines_read = 0;
   3071 
   3072    /// conversion to size_t to preserve SAX interface
   3073    constexpr operator size_t() const
   3074    {
   3075        return chars_read_total;
   3076    }
   3077 };
   3078 
   3079 }  // namespace detail
   3080 NLOHMANN_JSON_NAMESPACE_END
   3081 
   3082 // #include <nlohmann/detail/macro_scope.hpp>
   3083 
   3084 // #include <nlohmann/detail/meta/cpp_future.hpp>
   3085 //     __ _____ _____ _____
   3086 //  __|  |   __|     |   | |  JSON for Modern C++
   3087 // |  |  |__   |  |  | | | |  version 3.11.3
   3088 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3089 //
   3090 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3091 // SPDX-FileCopyrightText: 2018 The Abseil Authors
   3092 // SPDX-License-Identifier: MIT
   3093 
   3094 
   3095 
   3096 #include <array> // array
   3097 #include <cstddef> // size_t
   3098 #include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
   3099 #include <utility> // index_sequence, make_index_sequence, index_sequence_for
   3100 
   3101 // #include <nlohmann/detail/macro_scope.hpp>
   3102 
   3103 
   3104 NLOHMANN_JSON_NAMESPACE_BEGIN
   3105 namespace detail
   3106 {
   3107 
   3108 template<typename T>
   3109 using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
   3110 
   3111 #ifdef JSON_HAS_CPP_14
   3112 
   3113 // the following utilities are natively available in C++14
   3114 using std::enable_if_t;
   3115 using std::index_sequence;
   3116 using std::make_index_sequence;
   3117 using std::index_sequence_for;
   3118 
   3119 #else
   3120 
   3121 // alias templates to reduce boilerplate
   3122 template<bool B, typename T = void>
   3123 using enable_if_t = typename std::enable_if<B, T>::type;
   3124 
   3125 // The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
   3126 // which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
   3127 
   3128 //// START OF CODE FROM GOOGLE ABSEIL
   3129 
   3130 // integer_sequence
   3131 //
   3132 // Class template representing a compile-time integer sequence. An instantiation
   3133 // of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
   3134 // type through its template arguments (which is a common need when
   3135 // working with C++11 variadic templates). `absl::integer_sequence` is designed
   3136 // to be a drop-in replacement for C++14's `std::integer_sequence`.
   3137 //
   3138 // Example:
   3139 //
   3140 //   template< class T, T... Ints >
   3141 //   void user_function(integer_sequence<T, Ints...>);
   3142 //
   3143 //   int main()
   3144 //   {
   3145 //     // user_function's `T` will be deduced to `int` and `Ints...`
   3146 //     // will be deduced to `0, 1, 2, 3, 4`.
   3147 //     user_function(make_integer_sequence<int, 5>());
   3148 //   }
   3149 template <typename T, T... Ints>
   3150 struct integer_sequence
   3151 {
   3152    using value_type = T;
   3153    static constexpr std::size_t size() noexcept
   3154    {
   3155        return sizeof...(Ints);
   3156    }
   3157 };
   3158 
   3159 // index_sequence
   3160 //
   3161 // A helper template for an `integer_sequence` of `size_t`,
   3162 // `absl::index_sequence` is designed to be a drop-in replacement for C++14's
   3163 // `std::index_sequence`.
   3164 template <size_t... Ints>
   3165 using index_sequence = integer_sequence<size_t, Ints...>;
   3166 
   3167 namespace utility_internal
   3168 {
   3169 
   3170 template <typename Seq, size_t SeqSize, size_t Rem>
   3171 struct Extend;
   3172 
   3173 // Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
   3174 template <typename T, T... Ints, size_t SeqSize>
   3175 struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
   3176 {
   3177    using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
   3178 };
   3179 
   3180 template <typename T, T... Ints, size_t SeqSize>
   3181 struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
   3182 {
   3183    using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
   3184 };
   3185 
   3186 // Recursion helper for 'make_integer_sequence<T, N>'.
   3187 // 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
   3188 template <typename T, size_t N>
   3189 struct Gen
   3190 {
   3191    using type =
   3192        typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
   3193 };
   3194 
   3195 template <typename T>
   3196 struct Gen<T, 0>
   3197 {
   3198    using type = integer_sequence<T>;
   3199 };
   3200 
   3201 }  // namespace utility_internal
   3202 
   3203 // Compile-time sequences of integers
   3204 
   3205 // make_integer_sequence
   3206 //
   3207 // This template alias is equivalent to
   3208 // `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
   3209 // replacement for C++14's `std::make_integer_sequence`.
   3210 template <typename T, T N>
   3211 using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
   3212 
   3213 // make_index_sequence
   3214 //
   3215 // This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
   3216 // and is designed to be a drop-in replacement for C++14's
   3217 // `std::make_index_sequence`.
   3218 template <size_t N>
   3219 using make_index_sequence = make_integer_sequence<size_t, N>;
   3220 
   3221 // index_sequence_for
   3222 //
   3223 // Converts a typename pack into an index sequence of the same length, and
   3224 // is designed to be a drop-in replacement for C++14's
   3225 // `std::index_sequence_for()`
   3226 template <typename... Ts>
   3227 using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
   3228 
   3229 //// END OF CODE FROM GOOGLE ABSEIL
   3230 
   3231 #endif
   3232 
   3233 // dispatch utility (taken from ranges-v3)
   3234 template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
   3235 template<> struct priority_tag<0> {};
   3236 
   3237 // taken from ranges-v3
   3238 template<typename T>
   3239 struct static_const
   3240 {
   3241    static JSON_INLINE_VARIABLE constexpr T value{};
   3242 };
   3243 
   3244 #ifndef JSON_HAS_CPP_17
   3245    template<typename T>
   3246    constexpr T static_const<T>::value;
   3247 #endif
   3248 
   3249 template<typename T, typename... Args>
   3250 inline constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
   3251 {
   3252    return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
   3253 }
   3254 
   3255 }  // namespace detail
   3256 NLOHMANN_JSON_NAMESPACE_END
   3257 
   3258 // #include <nlohmann/detail/meta/type_traits.hpp>
   3259 //     __ _____ _____ _____
   3260 //  __|  |   __|     |   | |  JSON for Modern C++
   3261 // |  |  |__   |  |  | | | |  version 3.11.3
   3262 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3263 //
   3264 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3265 // SPDX-License-Identifier: MIT
   3266 
   3267 
   3268 
   3269 #include <limits> // numeric_limits
   3270 #include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
   3271 #include <utility> // declval
   3272 #include <tuple> // tuple
   3273 #include <string> // char_traits
   3274 
   3275 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
   3276 //     __ _____ _____ _____
   3277 //  __|  |   __|     |   | |  JSON for Modern C++
   3278 // |  |  |__   |  |  | | | |  version 3.11.3
   3279 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3280 //
   3281 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3282 // SPDX-License-Identifier: MIT
   3283 
   3284 
   3285 
   3286 #include <iterator> // random_access_iterator_tag
   3287 
   3288 // #include <nlohmann/detail/abi_macros.hpp>
   3289 
   3290 // #include <nlohmann/detail/meta/void_t.hpp>
   3291 
   3292 // #include <nlohmann/detail/meta/cpp_future.hpp>
   3293 
   3294 
   3295 NLOHMANN_JSON_NAMESPACE_BEGIN
   3296 namespace detail
   3297 {
   3298 
   3299 template<typename It, typename = void>
   3300 struct iterator_types {};
   3301 
   3302 template<typename It>
   3303 struct iterator_types <
   3304    It,
   3305    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
   3306    typename It::reference, typename It::iterator_category >>
   3307 {
   3308    using difference_type = typename It::difference_type;
   3309    using value_type = typename It::value_type;
   3310    using pointer = typename It::pointer;
   3311    using reference = typename It::reference;
   3312    using iterator_category = typename It::iterator_category;
   3313 };
   3314 
   3315 // This is required as some compilers implement std::iterator_traits in a way that
   3316 // doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
   3317 template<typename T, typename = void>
   3318 struct iterator_traits
   3319 {
   3320 };
   3321 
   3322 template<typename T>
   3323 struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
   3324            : iterator_types<T>
   3325 {
   3326 };
   3327 
   3328 template<typename T>
   3329 struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
   3330 {
   3331    using iterator_category = std::random_access_iterator_tag;
   3332    using value_type = T;
   3333    using difference_type = ptrdiff_t;
   3334    using pointer = T*;
   3335    using reference = T&;
   3336 };
   3337 
   3338 }  // namespace detail
   3339 NLOHMANN_JSON_NAMESPACE_END
   3340 
   3341 // #include <nlohmann/detail/macro_scope.hpp>
   3342 
   3343 // #include <nlohmann/detail/meta/call_std/begin.hpp>
   3344 //     __ _____ _____ _____
   3345 //  __|  |   __|     |   | |  JSON for Modern C++
   3346 // |  |  |__   |  |  | | | |  version 3.11.3
   3347 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3348 //
   3349 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3350 // SPDX-License-Identifier: MIT
   3351 
   3352 
   3353 
   3354 // #include <nlohmann/detail/macro_scope.hpp>
   3355 
   3356 
   3357 NLOHMANN_JSON_NAMESPACE_BEGIN
   3358 
   3359 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
   3360 
   3361 NLOHMANN_JSON_NAMESPACE_END
   3362 
   3363 // #include <nlohmann/detail/meta/call_std/end.hpp>
   3364 //     __ _____ _____ _____
   3365 //  __|  |   __|     |   | |  JSON for Modern C++
   3366 // |  |  |__   |  |  | | | |  version 3.11.3
   3367 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3368 //
   3369 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3370 // SPDX-License-Identifier: MIT
   3371 
   3372 
   3373 
   3374 // #include <nlohmann/detail/macro_scope.hpp>
   3375 
   3376 
   3377 NLOHMANN_JSON_NAMESPACE_BEGIN
   3378 
   3379 NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
   3380 
   3381 NLOHMANN_JSON_NAMESPACE_END
   3382 
   3383 // #include <nlohmann/detail/meta/cpp_future.hpp>
   3384 
   3385 // #include <nlohmann/detail/meta/detected.hpp>
   3386 
   3387 // #include <nlohmann/json_fwd.hpp>
   3388 //     __ _____ _____ _____
   3389 //  __|  |   __|     |   | |  JSON for Modern C++
   3390 // |  |  |__   |  |  | | | |  version 3.11.3
   3391 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   3392 //
   3393 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   3394 // SPDX-License-Identifier: MIT
   3395 
   3396 #ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
   3397    #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
   3398 
   3399    #include <cstdint> // int64_t, uint64_t
   3400    #include <map> // map
   3401    #include <memory> // allocator
   3402    #include <string> // string
   3403    #include <vector> // vector
   3404 
   3405    // #include <nlohmann/detail/abi_macros.hpp>
   3406 
   3407 
   3408    /*!
   3409    @brief namespace for Niels Lohmann
   3410    @see https://github.com/nlohmann
   3411    @since version 1.0.0
   3412    */
   3413    NLOHMANN_JSON_NAMESPACE_BEGIN
   3414 
   3415    /*!
   3416    @brief default JSONSerializer template argument
   3417 
   3418    This serializer ignores the template arguments and uses ADL
   3419    ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
   3420    for serialization.
   3421    */
   3422    template<typename T = void, typename SFINAE = void>
   3423    struct adl_serializer;
   3424 
   3425    /// a class to store JSON values
   3426    /// @sa https://json.nlohmann.me/api/basic_json/
   3427    template<template<typename U, typename V, typename... Args> class ObjectType =
   3428    std::map,
   3429    template<typename U, typename... Args> class ArrayType = std::vector,
   3430    class StringType = std::string, class BooleanType = bool,
   3431    class NumberIntegerType = std::int64_t,
   3432    class NumberUnsignedType = std::uint64_t,
   3433    class NumberFloatType = double,
   3434    template<typename U> class AllocatorType = std::allocator,
   3435    template<typename T, typename SFINAE = void> class JSONSerializer =
   3436    adl_serializer,
   3437    class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
   3438    class CustomBaseClass = void>
   3439    class basic_json;
   3440 
   3441    /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
   3442    /// @sa https://json.nlohmann.me/api/json_pointer/
   3443    template<typename RefStringType>
   3444    class json_pointer;
   3445 
   3446    /*!
   3447    @brief default specialization
   3448    @sa https://json.nlohmann.me/api/json/
   3449    */
   3450    using json = basic_json<>;
   3451 
   3452    /// @brief a minimal map-like container that preserves insertion order
   3453    /// @sa https://json.nlohmann.me/api/ordered_map/
   3454    template<class Key, class T, class IgnoredLess, class Allocator>
   3455    struct ordered_map;
   3456 
   3457    /// @brief specialization that maintains the insertion order of object keys
   3458    /// @sa https://json.nlohmann.me/api/ordered_json/
   3459    using ordered_json = basic_json<nlohmann::ordered_map>;
   3460 
   3461    NLOHMANN_JSON_NAMESPACE_END
   3462 
   3463 #endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
   3464 
   3465 
   3466 NLOHMANN_JSON_NAMESPACE_BEGIN
   3467 /*!
   3468 @brief detail namespace with internal helper functions
   3469 
   3470 This namespace collects functions that should not be exposed,
   3471 implementations of some @ref basic_json methods, and meta-programming helpers.
   3472 
   3473 @since version 2.1.0
   3474 */
   3475 namespace detail
   3476 {
   3477 
   3478 /////////////
   3479 // helpers //
   3480 /////////////
   3481 
   3482 // Note to maintainers:
   3483 //
   3484 // Every trait in this file expects a non CV-qualified type.
   3485 // The only exceptions are in the 'aliases for detected' section
   3486 // (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
   3487 //
   3488 // In this case, T has to be properly CV-qualified to constraint the function arguments
   3489 // (e.g. to_json(BasicJsonType&, const T&))
   3490 
   3491 template<typename> struct is_basic_json : std::false_type {};
   3492 
   3493 NLOHMANN_BASIC_JSON_TPL_DECLARATION
   3494 struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
   3495 
   3496 // used by exceptions create() member functions
   3497 // true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
   3498 // false_type otherwise
   3499 template<typename BasicJsonContext>
   3500 struct is_basic_json_context :
   3501    std::integral_constant < bool,
   3502    is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
   3503    || std::is_same<BasicJsonContext, std::nullptr_t>::value >
   3504 {};
   3505 
   3506 //////////////////////
   3507 // json_ref helpers //
   3508 //////////////////////
   3509 
   3510 template<typename>
   3511 class json_ref;
   3512 
   3513 template<typename>
   3514 struct is_json_ref : std::false_type {};
   3515 
   3516 template<typename T>
   3517 struct is_json_ref<json_ref<T>> : std::true_type {};
   3518 
   3519 //////////////////////////
   3520 // aliases for detected //
   3521 //////////////////////////
   3522 
   3523 template<typename T>
   3524 using mapped_type_t = typename T::mapped_type;
   3525 
   3526 template<typename T>
   3527 using key_type_t = typename T::key_type;
   3528 
   3529 template<typename T>
   3530 using value_type_t = typename T::value_type;
   3531 
   3532 template<typename T>
   3533 using difference_type_t = typename T::difference_type;
   3534 
   3535 template<typename T>
   3536 using pointer_t = typename T::pointer;
   3537 
   3538 template<typename T>
   3539 using reference_t = typename T::reference;
   3540 
   3541 template<typename T>
   3542 using iterator_category_t = typename T::iterator_category;
   3543 
   3544 template<typename T, typename... Args>
   3545 using to_json_function = decltype(T::to_json(std::declval<Args>()...));
   3546 
   3547 template<typename T, typename... Args>
   3548 using from_json_function = decltype(T::from_json(std::declval<Args>()...));
   3549 
   3550 template<typename T, typename U>
   3551 using get_template_function = decltype(std::declval<T>().template get<U>());
   3552 
   3553 // trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
   3554 template<typename BasicJsonType, typename T, typename = void>
   3555 struct has_from_json : std::false_type {};
   3556 
   3557 // trait checking if j.get<T> is valid
   3558 // use this trait instead of std::is_constructible or std::is_convertible,
   3559 // both rely on, or make use of implicit conversions, and thus fail when T
   3560 // has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
   3561 template <typename BasicJsonType, typename T>
   3562 struct is_getable
   3563 {
   3564    static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
   3565 };
   3566 
   3567 template<typename BasicJsonType, typename T>
   3568 struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
   3569 {
   3570    using serializer = typename BasicJsonType::template json_serializer<T, void>;
   3571 
   3572    static constexpr bool value =
   3573        is_detected_exact<void, from_json_function, serializer,
   3574        const BasicJsonType&, T&>::value;
   3575 };
   3576 
   3577 // This trait checks if JSONSerializer<T>::from_json(json const&) exists
   3578 // this overload is used for non-default-constructible user-defined-types
   3579 template<typename BasicJsonType, typename T, typename = void>
   3580 struct has_non_default_from_json : std::false_type {};
   3581 
   3582 template<typename BasicJsonType, typename T>
   3583 struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
   3584 {
   3585    using serializer = typename BasicJsonType::template json_serializer<T, void>;
   3586 
   3587    static constexpr bool value =
   3588        is_detected_exact<T, from_json_function, serializer,
   3589        const BasicJsonType&>::value;
   3590 };
   3591 
   3592 // This trait checks if BasicJsonType::json_serializer<T>::to_json exists
   3593 // Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
   3594 template<typename BasicJsonType, typename T, typename = void>
   3595 struct has_to_json : std::false_type {};
   3596 
   3597 template<typename BasicJsonType, typename T>
   3598 struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
   3599 {
   3600    using serializer = typename BasicJsonType::template json_serializer<T, void>;
   3601 
   3602    static constexpr bool value =
   3603        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
   3604        T>::value;
   3605 };
   3606 
   3607 template<typename T>
   3608 using detect_key_compare = typename T::key_compare;
   3609 
   3610 template<typename T>
   3611 struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
   3612 
   3613 // obtains the actual object key comparator
   3614 template<typename BasicJsonType>
   3615 struct actual_object_comparator
   3616 {
   3617    using object_t = typename BasicJsonType::object_t;
   3618    using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
   3619    using type = typename std::conditional < has_key_compare<object_t>::value,
   3620          typename object_t::key_compare, object_comparator_t>::type;
   3621 };
   3622 
   3623 template<typename BasicJsonType>
   3624 using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
   3625 
   3626 /////////////////
   3627 // char_traits //
   3628 /////////////////
   3629 
   3630 // Primary template of char_traits calls std char_traits
   3631 template<typename T>
   3632 struct char_traits : std::char_traits<T>
   3633 {};
   3634 
   3635 // Explicitly define char traits for unsigned char since it is not standard
   3636 template<>
   3637 struct char_traits<unsigned char> : std::char_traits<char>
   3638 {
   3639    using char_type = unsigned char;
   3640    using int_type = uint64_t;
   3641 
   3642    // Redefine to_int_type function
   3643    static int_type to_int_type(char_type c) noexcept
   3644    {
   3645        return static_cast<int_type>(c);
   3646    }
   3647 
   3648    static char_type to_char_type(int_type i) noexcept
   3649    {
   3650        return static_cast<char_type>(i);
   3651    }
   3652 
   3653    static constexpr int_type eof() noexcept
   3654    {
   3655        return static_cast<int_type>(EOF);
   3656    }
   3657 };
   3658 
   3659 // Explicitly define char traits for signed char since it is not standard
   3660 template<>
   3661 struct char_traits<signed char> : std::char_traits<char>
   3662 {
   3663    using char_type = signed char;
   3664    using int_type = uint64_t;
   3665 
   3666    // Redefine to_int_type function
   3667    static int_type to_int_type(char_type c) noexcept
   3668    {
   3669        return static_cast<int_type>(c);
   3670    }
   3671 
   3672    static char_type to_char_type(int_type i) noexcept
   3673    {
   3674        return static_cast<char_type>(i);
   3675    }
   3676 
   3677    static constexpr int_type eof() noexcept
   3678    {
   3679        return static_cast<int_type>(EOF);
   3680    }
   3681 };
   3682 
   3683 ///////////////////
   3684 // is_ functions //
   3685 ///////////////////
   3686 
   3687 // https://en.cppreference.com/w/cpp/types/conjunction
   3688 template<class...> struct conjunction : std::true_type { };
   3689 template<class B> struct conjunction<B> : B { };
   3690 template<class B, class... Bn>
   3691 struct conjunction<B, Bn...>
   3692 : std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
   3693 
   3694 // https://en.cppreference.com/w/cpp/types/negation
   3695 template<class B> struct negation : std::integral_constant < bool, !B::value > { };
   3696 
   3697 // Reimplementation of is_constructible and is_default_constructible, due to them being broken for
   3698 // std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
   3699 // This causes compile errors in e.g. clang 3.5 or gcc 4.9.
   3700 template <typename T>
   3701 struct is_default_constructible : std::is_default_constructible<T> {};
   3702 
   3703 template <typename T1, typename T2>
   3704 struct is_default_constructible<std::pair<T1, T2>>
   3705            : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
   3706 
   3707 template <typename T1, typename T2>
   3708 struct is_default_constructible<const std::pair<T1, T2>>
   3709            : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
   3710 
   3711 template <typename... Ts>
   3712 struct is_default_constructible<std::tuple<Ts...>>
   3713            : conjunction<is_default_constructible<Ts>...> {};
   3714 
   3715 template <typename... Ts>
   3716 struct is_default_constructible<const std::tuple<Ts...>>
   3717            : conjunction<is_default_constructible<Ts>...> {};
   3718 
   3719 template <typename T, typename... Args>
   3720 struct is_constructible : std::is_constructible<T, Args...> {};
   3721 
   3722 template <typename T1, typename T2>
   3723 struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
   3724 
   3725 template <typename T1, typename T2>
   3726 struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
   3727 
   3728 template <typename... Ts>
   3729 struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
   3730 
   3731 template <typename... Ts>
   3732 struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
   3733 
   3734 template<typename T, typename = void>
   3735 struct is_iterator_traits : std::false_type {};
   3736 
   3737 template<typename T>
   3738 struct is_iterator_traits<iterator_traits<T>>
   3739 {
   3740  private:
   3741    using traits = iterator_traits<T>;
   3742 
   3743  public:
   3744    static constexpr auto value =
   3745        is_detected<value_type_t, traits>::value &&
   3746        is_detected<difference_type_t, traits>::value &&
   3747        is_detected<pointer_t, traits>::value &&
   3748        is_detected<iterator_category_t, traits>::value &&
   3749        is_detected<reference_t, traits>::value;
   3750 };
   3751 
   3752 template<typename T>
   3753 struct is_range
   3754 {
   3755  private:
   3756    using t_ref = typename std::add_lvalue_reference<T>::type;
   3757 
   3758    using iterator = detected_t<result_of_begin, t_ref>;
   3759    using sentinel = detected_t<result_of_end, t_ref>;
   3760 
   3761    // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
   3762    // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
   3763    // but reimplementing these would be too much work, as a lot of other concepts are used underneath
   3764    static constexpr auto is_iterator_begin =
   3765        is_iterator_traits<iterator_traits<iterator>>::value;
   3766 
   3767  public:
   3768    static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
   3769 };
   3770 
   3771 template<typename R>
   3772 using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
   3773 
   3774 template<typename T>
   3775 using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
   3776 
   3777 // The following implementation of is_complete_type is taken from
   3778 // https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
   3779 // and is written by Xiang Fan who agreed to using it in this library.
   3780 
   3781 template<typename T, typename = void>
   3782 struct is_complete_type : std::false_type {};
   3783 
   3784 template<typename T>
   3785 struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
   3786 
   3787 template<typename BasicJsonType, typename CompatibleObjectType,
   3788         typename = void>
   3789 struct is_compatible_object_type_impl : std::false_type {};
   3790 
   3791 template<typename BasicJsonType, typename CompatibleObjectType>
   3792 struct is_compatible_object_type_impl <
   3793    BasicJsonType, CompatibleObjectType,
   3794    enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
   3795    is_detected<key_type_t, CompatibleObjectType>::value >>
   3796 {
   3797    using object_t = typename BasicJsonType::object_t;
   3798 
   3799    // macOS's is_constructible does not play well with nonesuch...
   3800    static constexpr bool value =
   3801        is_constructible<typename object_t::key_type,
   3802        typename CompatibleObjectType::key_type>::value &&
   3803        is_constructible<typename object_t::mapped_type,
   3804        typename CompatibleObjectType::mapped_type>::value;
   3805 };
   3806 
   3807 template<typename BasicJsonType, typename CompatibleObjectType>
   3808 struct is_compatible_object_type
   3809    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
   3810 
   3811 template<typename BasicJsonType, typename ConstructibleObjectType,
   3812         typename = void>
   3813 struct is_constructible_object_type_impl : std::false_type {};
   3814 
   3815 template<typename BasicJsonType, typename ConstructibleObjectType>
   3816 struct is_constructible_object_type_impl <
   3817    BasicJsonType, ConstructibleObjectType,
   3818    enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
   3819    is_detected<key_type_t, ConstructibleObjectType>::value >>
   3820 {
   3821    using object_t = typename BasicJsonType::object_t;
   3822 
   3823    static constexpr bool value =
   3824        (is_default_constructible<ConstructibleObjectType>::value &&
   3825         (std::is_move_assignable<ConstructibleObjectType>::value ||
   3826          std::is_copy_assignable<ConstructibleObjectType>::value) &&
   3827         (is_constructible<typename ConstructibleObjectType::key_type,
   3828          typename object_t::key_type>::value &&
   3829          std::is_same <
   3830          typename object_t::mapped_type,
   3831          typename ConstructibleObjectType::mapped_type >::value)) ||
   3832        (has_from_json<BasicJsonType,
   3833         typename ConstructibleObjectType::mapped_type>::value ||
   3834         has_non_default_from_json <
   3835         BasicJsonType,
   3836         typename ConstructibleObjectType::mapped_type >::value);
   3837 };
   3838 
   3839 template<typename BasicJsonType, typename ConstructibleObjectType>
   3840 struct is_constructible_object_type
   3841    : is_constructible_object_type_impl<BasicJsonType,
   3842      ConstructibleObjectType> {};
   3843 
   3844 template<typename BasicJsonType, typename CompatibleStringType>
   3845 struct is_compatible_string_type
   3846 {
   3847    static constexpr auto value =
   3848        is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
   3849 };
   3850 
   3851 template<typename BasicJsonType, typename ConstructibleStringType>
   3852 struct is_constructible_string_type
   3853 {
   3854    // launder type through decltype() to fix compilation failure on ICPC
   3855 #ifdef __INTEL_COMPILER
   3856    using laundered_type = decltype(std::declval<ConstructibleStringType>());
   3857 #else
   3858    using laundered_type = ConstructibleStringType;
   3859 #endif
   3860 
   3861    static constexpr auto value =
   3862        conjunction <
   3863        is_constructible<laundered_type, typename BasicJsonType::string_t>,
   3864        is_detected_exact<typename BasicJsonType::string_t::value_type,
   3865        value_type_t, laundered_type >>::value;
   3866 };
   3867 
   3868 template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
   3869 struct is_compatible_array_type_impl : std::false_type {};
   3870 
   3871 template<typename BasicJsonType, typename CompatibleArrayType>
   3872 struct is_compatible_array_type_impl <
   3873    BasicJsonType, CompatibleArrayType,
   3874    enable_if_t <
   3875    is_detected<iterator_t, CompatibleArrayType>::value&&
   3876    is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
   3877 // special case for types like std::filesystem::path whose iterator's value_type are themselves
   3878 // c.f. https://github.com/nlohmann/json/pull/3073
   3879    !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
   3880 {
   3881    static constexpr bool value =
   3882        is_constructible<BasicJsonType,
   3883        range_value_t<CompatibleArrayType>>::value;
   3884 };
   3885 
   3886 template<typename BasicJsonType, typename CompatibleArrayType>
   3887 struct is_compatible_array_type
   3888    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
   3889 
   3890 template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
   3891 struct is_constructible_array_type_impl : std::false_type {};
   3892 
   3893 template<typename BasicJsonType, typename ConstructibleArrayType>
   3894 struct is_constructible_array_type_impl <
   3895    BasicJsonType, ConstructibleArrayType,
   3896    enable_if_t<std::is_same<ConstructibleArrayType,
   3897    typename BasicJsonType::value_type>::value >>
   3898            : std::true_type {};
   3899 
   3900 template<typename BasicJsonType, typename ConstructibleArrayType>
   3901 struct is_constructible_array_type_impl <
   3902    BasicJsonType, ConstructibleArrayType,
   3903    enable_if_t < !std::is_same<ConstructibleArrayType,
   3904    typename BasicJsonType::value_type>::value&&
   3905    !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
   3906    is_default_constructible<ConstructibleArrayType>::value&&
   3907 (std::is_move_assignable<ConstructibleArrayType>::value ||
   3908 std::is_copy_assignable<ConstructibleArrayType>::value)&&
   3909 is_detected<iterator_t, ConstructibleArrayType>::value&&
   3910 is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
   3911 is_detected<range_value_t, ConstructibleArrayType>::value&&
   3912 // special case for types like std::filesystem::path whose iterator's value_type are themselves
   3913 // c.f. https://github.com/nlohmann/json/pull/3073
   3914 !std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
   3915        is_complete_type <
   3916        detected_t<range_value_t, ConstructibleArrayType >>::value >>
   3917 {
   3918    using value_type = range_value_t<ConstructibleArrayType>;
   3919 
   3920    static constexpr bool value =
   3921        std::is_same<value_type,
   3922        typename BasicJsonType::array_t::value_type>::value ||
   3923        has_from_json<BasicJsonType,
   3924        value_type>::value ||
   3925        has_non_default_from_json <
   3926        BasicJsonType,
   3927        value_type >::value;
   3928 };
   3929 
   3930 template<typename BasicJsonType, typename ConstructibleArrayType>
   3931 struct is_constructible_array_type
   3932    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
   3933 
   3934 template<typename RealIntegerType, typename CompatibleNumberIntegerType,
   3935         typename = void>
   3936 struct is_compatible_integer_type_impl : std::false_type {};
   3937 
   3938 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
   3939 struct is_compatible_integer_type_impl <
   3940    RealIntegerType, CompatibleNumberIntegerType,
   3941    enable_if_t < std::is_integral<RealIntegerType>::value&&
   3942    std::is_integral<CompatibleNumberIntegerType>::value&&
   3943    !std::is_same<bool, CompatibleNumberIntegerType>::value >>
   3944 {
   3945    // is there an assert somewhere on overflows?
   3946    using RealLimits = std::numeric_limits<RealIntegerType>;
   3947    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
   3948 
   3949    static constexpr auto value =
   3950        is_constructible<RealIntegerType,
   3951        CompatibleNumberIntegerType>::value &&
   3952        CompatibleLimits::is_integer &&
   3953        RealLimits::is_signed == CompatibleLimits::is_signed;
   3954 };
   3955 
   3956 template<typename RealIntegerType, typename CompatibleNumberIntegerType>
   3957 struct is_compatible_integer_type
   3958    : is_compatible_integer_type_impl<RealIntegerType,
   3959      CompatibleNumberIntegerType> {};
   3960 
   3961 template<typename BasicJsonType, typename CompatibleType, typename = void>
   3962 struct is_compatible_type_impl: std::false_type {};
   3963 
   3964 template<typename BasicJsonType, typename CompatibleType>
   3965 struct is_compatible_type_impl <
   3966    BasicJsonType, CompatibleType,
   3967    enable_if_t<is_complete_type<CompatibleType>::value >>
   3968 {
   3969    static constexpr bool value =
   3970        has_to_json<BasicJsonType, CompatibleType>::value;
   3971 };
   3972 
   3973 template<typename BasicJsonType, typename CompatibleType>
   3974 struct is_compatible_type
   3975    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
   3976 
   3977 template<typename T1, typename T2>
   3978 struct is_constructible_tuple : std::false_type {};
   3979 
   3980 template<typename T1, typename... Args>
   3981 struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
   3982 
   3983 template<typename BasicJsonType, typename T>
   3984 struct is_json_iterator_of : std::false_type {};
   3985 
   3986 template<typename BasicJsonType>
   3987 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
   3988 
   3989 template<typename BasicJsonType>
   3990 struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
   3991 {};
   3992 
   3993 // checks if a given type T is a template specialization of Primary
   3994 template<template <typename...> class Primary, typename T>
   3995 struct is_specialization_of : std::false_type {};
   3996 
   3997 template<template <typename...> class Primary, typename... Args>
   3998 struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
   3999 
   4000 template<typename T>
   4001 using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
   4002 
   4003 // checks if A and B are comparable using Compare functor
   4004 template<typename Compare, typename A, typename B, typename = void>
   4005 struct is_comparable : std::false_type {};
   4006 
   4007 template<typename Compare, typename A, typename B>
   4008 struct is_comparable<Compare, A, B, void_t<
   4009 decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
   4010 decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
   4011 >> : std::true_type {};
   4012 
   4013 template<typename T>
   4014 using detect_is_transparent = typename T::is_transparent;
   4015 
   4016 // type trait to check if KeyType can be used as object key (without a BasicJsonType)
   4017 // see is_usable_as_basic_json_key_type below
   4018 template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
   4019         bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
   4020 using is_usable_as_key_type = typename std::conditional <
   4021                              is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
   4022                              && !(ExcludeObjectKeyType && std::is_same<KeyType,
   4023                                   ObjectKeyType>::value)
   4024                              && (!RequireTransparentComparator
   4025                                  || is_detected <detect_is_transparent, Comparator>::value)
   4026                              && !is_json_pointer<KeyType>::value,
   4027                              std::true_type,
   4028                              std::false_type >::type;
   4029 
   4030 // type trait to check if KeyType can be used as object key
   4031 // true if:
   4032 //   - KeyType is comparable with BasicJsonType::object_t::key_type
   4033 //   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
   4034 //   - the comparator is transparent or RequireTransparentComparator is false
   4035 //   - KeyType is not a JSON iterator or json_pointer
   4036 template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
   4037         bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
   4038 using is_usable_as_basic_json_key_type = typename std::conditional <
   4039        is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
   4040        typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
   4041        RequireTransparentComparator, ExcludeObjectKeyType>::value
   4042        && !is_json_iterator_of<BasicJsonType, KeyType>::value,
   4043        std::true_type,
   4044        std::false_type >::type;
   4045 
   4046 template<typename ObjectType, typename KeyType>
   4047 using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
   4048 
   4049 // type trait to check if object_t has an erase() member functions accepting KeyType
   4050 template<typename BasicJsonType, typename KeyType>
   4051 using has_erase_with_key_type = typename std::conditional <
   4052                                is_detected <
   4053                                detect_erase_with_key_type,
   4054                                typename BasicJsonType::object_t, KeyType >::value,
   4055                                std::true_type,
   4056                                std::false_type >::type;
   4057 
   4058 // a naive helper to check if a type is an ordered_map (exploits the fact that
   4059 // ordered_map inherits capacity() from std::vector)
   4060 template <typename T>
   4061 struct is_ordered_map
   4062 {
   4063    using one = char;
   4064 
   4065    struct two
   4066    {
   4067        char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   4068    };
   4069 
   4070    template <typename C> static one test( decltype(&C::capacity) ) ;
   4071    template <typename C> static two test(...);
   4072 
   4073    enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   4074 };
   4075 
   4076 // to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
   4077 template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
   4078 T conditional_static_cast(U value)
   4079 {
   4080    return static_cast<T>(value);
   4081 }
   4082 
   4083 template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
   4084 T conditional_static_cast(U value)
   4085 {
   4086    return value;
   4087 }
   4088 
   4089 template<typename... Types>
   4090 using all_integral = conjunction<std::is_integral<Types>...>;
   4091 
   4092 template<typename... Types>
   4093 using all_signed = conjunction<std::is_signed<Types>...>;
   4094 
   4095 template<typename... Types>
   4096 using all_unsigned = conjunction<std::is_unsigned<Types>...>;
   4097 
   4098 // there's a disjunction trait in another PR; replace when merged
   4099 template<typename... Types>
   4100 using same_sign = std::integral_constant < bool,
   4101      all_signed<Types...>::value || all_unsigned<Types...>::value >;
   4102 
   4103 template<typename OfType, typename T>
   4104 using never_out_of_range = std::integral_constant < bool,
   4105      (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
   4106      || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
   4107 
   4108 template<typename OfType, typename T,
   4109         bool OfTypeSigned = std::is_signed<OfType>::value,
   4110         bool TSigned = std::is_signed<T>::value>
   4111 struct value_in_range_of_impl2;
   4112 
   4113 template<typename OfType, typename T>
   4114 struct value_in_range_of_impl2<OfType, T, false, false>
   4115 {
   4116    static constexpr bool test(T val)
   4117    {
   4118        using CommonType = typename std::common_type<OfType, T>::type;
   4119        return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4120    }
   4121 };
   4122 
   4123 template<typename OfType, typename T>
   4124 struct value_in_range_of_impl2<OfType, T, true, false>
   4125 {
   4126    static constexpr bool test(T val)
   4127    {
   4128        using CommonType = typename std::common_type<OfType, T>::type;
   4129        return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4130    }
   4131 };
   4132 
   4133 template<typename OfType, typename T>
   4134 struct value_in_range_of_impl2<OfType, T, false, true>
   4135 {
   4136    static constexpr bool test(T val)
   4137    {
   4138        using CommonType = typename std::common_type<OfType, T>::type;
   4139        return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4140    }
   4141 };
   4142 
   4143 template<typename OfType, typename T>
   4144 struct value_in_range_of_impl2<OfType, T, true, true>
   4145 {
   4146    static constexpr bool test(T val)
   4147    {
   4148        using CommonType = typename std::common_type<OfType, T>::type;
   4149        return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
   4150               && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
   4151    }
   4152 };
   4153 
   4154 template<typename OfType, typename T,
   4155         bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
   4156         typename = detail::enable_if_t<all_integral<OfType, T>::value>>
   4157 struct value_in_range_of_impl1;
   4158 
   4159 template<typename OfType, typename T>
   4160 struct value_in_range_of_impl1<OfType, T, false>
   4161 {
   4162    static constexpr bool test(T val)
   4163    {
   4164        return value_in_range_of_impl2<OfType, T>::test(val);
   4165    }
   4166 };
   4167 
   4168 template<typename OfType, typename T>
   4169 struct value_in_range_of_impl1<OfType, T, true>
   4170 {
   4171    static constexpr bool test(T /*val*/)
   4172    {
   4173        return true;
   4174    }
   4175 };
   4176 
   4177 template<typename OfType, typename T>
   4178 inline constexpr bool value_in_range_of(T val)
   4179 {
   4180    return value_in_range_of_impl1<OfType, T>::test(val);
   4181 }
   4182 
   4183 template<bool Value>
   4184 using bool_constant = std::integral_constant<bool, Value>;
   4185 
   4186 ///////////////////////////////////////////////////////////////////////////////
   4187 // is_c_string
   4188 ///////////////////////////////////////////////////////////////////////////////
   4189 
   4190 namespace impl
   4191 {
   4192 
   4193 template<typename T>
   4194 inline constexpr bool is_c_string()
   4195 {
   4196    using TUnExt = typename std::remove_extent<T>::type;
   4197    using TUnCVExt = typename std::remove_cv<TUnExt>::type;
   4198    using TUnPtr = typename std::remove_pointer<T>::type;
   4199    using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
   4200    return
   4201        (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
   4202        || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
   4203 }
   4204 
   4205 }  // namespace impl
   4206 
   4207 // checks whether T is a [cv] char */[cv] char[] C string
   4208 template<typename T>
   4209 struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
   4210 
   4211 template<typename T>
   4212 using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
   4213 
   4214 ///////////////////////////////////////////////////////////////////////////////
   4215 // is_transparent
   4216 ///////////////////////////////////////////////////////////////////////////////
   4217 
   4218 namespace impl
   4219 {
   4220 
   4221 template<typename T>
   4222 inline constexpr bool is_transparent()
   4223 {
   4224    return is_detected<detect_is_transparent, T>::value;
   4225 }
   4226 
   4227 }  // namespace impl
   4228 
   4229 // checks whether T has a member named is_transparent
   4230 template<typename T>
   4231 struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
   4232 
   4233 ///////////////////////////////////////////////////////////////////////////////
   4234 
   4235 }  // namespace detail
   4236 NLOHMANN_JSON_NAMESPACE_END
   4237 
   4238 // #include <nlohmann/detail/string_concat.hpp>
   4239 //     __ _____ _____ _____
   4240 //  __|  |   __|     |   | |  JSON for Modern C++
   4241 // |  |  |__   |  |  | | | |  version 3.11.3
   4242 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   4243 //
   4244 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   4245 // SPDX-License-Identifier: MIT
   4246 
   4247 
   4248 
   4249 #include <cstring> // strlen
   4250 #include <string> // string
   4251 #include <utility> // forward
   4252 
   4253 // #include <nlohmann/detail/meta/cpp_future.hpp>
   4254 
   4255 // #include <nlohmann/detail/meta/detected.hpp>
   4256 
   4257 
   4258 NLOHMANN_JSON_NAMESPACE_BEGIN
   4259 namespace detail
   4260 {
   4261 
   4262 inline std::size_t concat_length()
   4263 {
   4264    return 0;
   4265 }
   4266 
   4267 template<typename... Args>
   4268 inline std::size_t concat_length(const char* cstr, const Args& ... rest);
   4269 
   4270 template<typename StringType, typename... Args>
   4271 inline std::size_t concat_length(const StringType& str, const Args& ... rest);
   4272 
   4273 template<typename... Args>
   4274 inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
   4275 {
   4276    return 1 + concat_length(rest...);
   4277 }
   4278 
   4279 template<typename... Args>
   4280 inline std::size_t concat_length(const char* cstr, const Args& ... rest)
   4281 {
   4282    // cppcheck-suppress ignoredReturnValue
   4283    return ::strlen(cstr) + concat_length(rest...);
   4284 }
   4285 
   4286 template<typename StringType, typename... Args>
   4287 inline std::size_t concat_length(const StringType& str, const Args& ... rest)
   4288 {
   4289    return str.size() + concat_length(rest...);
   4290 }
   4291 
   4292 template<typename OutStringType>
   4293 inline void concat_into(OutStringType& /*out*/)
   4294 {}
   4295 
   4296 template<typename StringType, typename Arg>
   4297 using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
   4298 
   4299 template<typename StringType, typename Arg>
   4300 using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
   4301 
   4302 template<typename StringType, typename Arg>
   4303 using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
   4304 
   4305 template<typename StringType, typename Arg>
   4306 using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
   4307 
   4308 template<typename StringType, typename Arg>
   4309 using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
   4310 
   4311 template<typename StringType, typename Arg>
   4312 using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
   4313 
   4314 template<typename StringType, typename Arg>
   4315 using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
   4316 
   4317 template<typename StringType, typename Arg>
   4318 using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
   4319 
   4320 template < typename OutStringType, typename Arg, typename... Args,
   4321           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4322                         && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
   4323 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
   4324 
   4325 template < typename OutStringType, typename Arg, typename... Args,
   4326           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4327                         && !detect_string_can_append_op<OutStringType, Arg>::value
   4328                         && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
   4329 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
   4330 
   4331 template < typename OutStringType, typename Arg, typename... Args,
   4332           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4333                         && !detect_string_can_append_op<OutStringType, Arg>::value
   4334                         && !detect_string_can_append_iter<OutStringType, Arg>::value
   4335                         && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
   4336 inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
   4337 
   4338 template<typename OutStringType, typename Arg, typename... Args,
   4339         enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
   4340 inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
   4341 {
   4342    out.append(std::forward<Arg>(arg));
   4343    concat_into(out, std::forward<Args>(rest)...);
   4344 }
   4345 
   4346 template < typename OutStringType, typename Arg, typename... Args,
   4347           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4348                         && detect_string_can_append_op<OutStringType, Arg>::value, int > >
   4349 inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
   4350 {
   4351    out += std::forward<Arg>(arg);
   4352    concat_into(out, std::forward<Args>(rest)...);
   4353 }
   4354 
   4355 template < typename OutStringType, typename Arg, typename... Args,
   4356           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4357                         && !detect_string_can_append_op<OutStringType, Arg>::value
   4358                         && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
   4359 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
   4360 {
   4361    out.append(arg.begin(), arg.end());
   4362    concat_into(out, std::forward<Args>(rest)...);
   4363 }
   4364 
   4365 template < typename OutStringType, typename Arg, typename... Args,
   4366           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
   4367                         && !detect_string_can_append_op<OutStringType, Arg>::value
   4368                         && !detect_string_can_append_iter<OutStringType, Arg>::value
   4369                         && detect_string_can_append_data<OutStringType, Arg>::value, int > >
   4370 inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
   4371 {
   4372    out.append(arg.data(), arg.size());
   4373    concat_into(out, std::forward<Args>(rest)...);
   4374 }
   4375 
   4376 template<typename OutStringType = std::string, typename... Args>
   4377 inline OutStringType concat(Args && ... args)
   4378 {
   4379    OutStringType str;
   4380    str.reserve(concat_length(args...));
   4381    concat_into(str, std::forward<Args>(args)...);
   4382    return str;
   4383 }
   4384 
   4385 }  // namespace detail
   4386 NLOHMANN_JSON_NAMESPACE_END
   4387 
   4388 
   4389 NLOHMANN_JSON_NAMESPACE_BEGIN
   4390 namespace detail
   4391 {
   4392 
   4393 ////////////////
   4394 // exceptions //
   4395 ////////////////
   4396 
   4397 /// @brief general exception of the @ref basic_json class
   4398 /// @sa https://json.nlohmann.me/api/basic_json/exception/
   4399 class exception : public std::exception
   4400 {
   4401  public:
   4402    /// returns the explanatory string
   4403    const char* what() const noexcept override
   4404    {
   4405        return m.what();
   4406    }
   4407 
   4408    /// the id of the exception
   4409    const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
   4410 
   4411  protected:
   4412    JSON_HEDLEY_NON_NULL(3)
   4413    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
   4414 
   4415    static std::string name(const std::string& ename, int id_)
   4416    {
   4417        return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
   4418    }
   4419 
   4420    static std::string diagnostics(std::nullptr_t /*leaf_element*/)
   4421    {
   4422        return "";
   4423    }
   4424 
   4425    template<typename BasicJsonType>
   4426    static std::string diagnostics(const BasicJsonType* leaf_element)
   4427    {
   4428 #if JSON_DIAGNOSTICS
   4429        std::vector<std::string> tokens;
   4430        for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
   4431        {
   4432            switch (current->m_parent->type())
   4433            {
   4434                case value_t::array:
   4435                {
   4436                    for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
   4437                    {
   4438                        if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
   4439                        {
   4440                            tokens.emplace_back(std::to_string(i));
   4441                            break;
   4442                        }
   4443                    }
   4444                    break;
   4445                }
   4446 
   4447                case value_t::object:
   4448                {
   4449                    for (const auto& element : *current->m_parent->m_data.m_value.object)
   4450                    {
   4451                        if (&element.second == current)
   4452                        {
   4453                            tokens.emplace_back(element.first.c_str());
   4454                            break;
   4455                        }
   4456                    }
   4457                    break;
   4458                }
   4459 
   4460                case value_t::null: // LCOV_EXCL_LINE
   4461                case value_t::string: // LCOV_EXCL_LINE
   4462                case value_t::boolean: // LCOV_EXCL_LINE
   4463                case value_t::number_integer: // LCOV_EXCL_LINE
   4464                case value_t::number_unsigned: // LCOV_EXCL_LINE
   4465                case value_t::number_float: // LCOV_EXCL_LINE
   4466                case value_t::binary: // LCOV_EXCL_LINE
   4467                case value_t::discarded: // LCOV_EXCL_LINE
   4468                default:   // LCOV_EXCL_LINE
   4469                    break; // LCOV_EXCL_LINE
   4470            }
   4471        }
   4472 
   4473        if (tokens.empty())
   4474        {
   4475            return "";
   4476        }
   4477 
   4478        auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
   4479                                   [](const std::string & a, const std::string & b)
   4480        {
   4481            return concat(a, '/', detail::escape(b));
   4482        });
   4483        return concat('(', str, ") ");
   4484 #else
   4485        static_cast<void>(leaf_element);
   4486        return "";
   4487 #endif
   4488    }
   4489 
   4490  private:
   4491    /// an exception object as storage for error messages
   4492    std::runtime_error m;
   4493 };
   4494 
   4495 /// @brief exception indicating a parse error
   4496 /// @sa https://json.nlohmann.me/api/basic_json/parse_error/
   4497 class parse_error : public exception
   4498 {
   4499  public:
   4500    /*!
   4501    @brief create a parse error exception
   4502    @param[in] id_       the id of the exception
   4503    @param[in] pos       the position where the error occurred (or with
   4504                         chars_read_total=0 if the position cannot be
   4505                         determined)
   4506    @param[in] what_arg  the explanatory string
   4507    @return parse_error object
   4508    */
   4509    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4510    static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
   4511    {
   4512        const std::string w = concat(exception::name("parse_error", id_), "parse error",
   4513                                     position_string(pos), ": ", exception::diagnostics(context), what_arg);
   4514        return {id_, pos.chars_read_total, w.c_str()};
   4515    }
   4516 
   4517    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4518    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
   4519    {
   4520        const std::string w = concat(exception::name("parse_error", id_), "parse error",
   4521                                     (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
   4522                                     ": ", exception::diagnostics(context), what_arg);
   4523        return {id_, byte_, w.c_str()};
   4524    }
   4525 
   4526    /*!
   4527    @brief byte index of the parse error
   4528 
   4529    The byte index of the last read character in the input file.
   4530 
   4531    @note For an input with n bytes, 1 is the index of the first character and
   4532          n+1 is the index of the terminating null byte or the end of file.
   4533          This also holds true when reading a byte vector (CBOR or MessagePack).
   4534    */
   4535    const std::size_t byte;
   4536 
   4537  private:
   4538    parse_error(int id_, std::size_t byte_, const char* what_arg)
   4539        : exception(id_, what_arg), byte(byte_) {}
   4540 
   4541    static std::string position_string(const position_t& pos)
   4542    {
   4543        return concat(" at line ", std::to_string(pos.lines_read + 1),
   4544                      ", column ", std::to_string(pos.chars_read_current_line));
   4545    }
   4546 };
   4547 
   4548 /// @brief exception indicating errors with iterators
   4549 /// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
   4550 class invalid_iterator : public exception
   4551 {
   4552  public:
   4553    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4554    static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
   4555    {
   4556        const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
   4557        return {id_, w.c_str()};
   4558    }
   4559 
   4560  private:
   4561    JSON_HEDLEY_NON_NULL(3)
   4562    invalid_iterator(int id_, const char* what_arg)
   4563        : exception(id_, what_arg) {}
   4564 };
   4565 
   4566 /// @brief exception indicating executing a member function with a wrong type
   4567 /// @sa https://json.nlohmann.me/api/basic_json/type_error/
   4568 class type_error : public exception
   4569 {
   4570  public:
   4571    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4572    static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
   4573    {
   4574        const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
   4575        return {id_, w.c_str()};
   4576    }
   4577 
   4578  private:
   4579    JSON_HEDLEY_NON_NULL(3)
   4580    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
   4581 };
   4582 
   4583 /// @brief exception indicating access out of the defined range
   4584 /// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
   4585 class out_of_range : public exception
   4586 {
   4587  public:
   4588    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4589    static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
   4590    {
   4591        const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
   4592        return {id_, w.c_str()};
   4593    }
   4594 
   4595  private:
   4596    JSON_HEDLEY_NON_NULL(3)
   4597    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
   4598 };
   4599 
   4600 /// @brief exception indicating other library errors
   4601 /// @sa https://json.nlohmann.me/api/basic_json/other_error/
   4602 class other_error : public exception
   4603 {
   4604  public:
   4605    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
   4606    static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
   4607    {
   4608        const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
   4609        return {id_, w.c_str()};
   4610    }
   4611 
   4612  private:
   4613    JSON_HEDLEY_NON_NULL(3)
   4614    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
   4615 };
   4616 
   4617 }  // namespace detail
   4618 NLOHMANN_JSON_NAMESPACE_END
   4619 
   4620 // #include <nlohmann/detail/macro_scope.hpp>
   4621 
   4622 // #include <nlohmann/detail/meta/cpp_future.hpp>
   4623 
   4624 // #include <nlohmann/detail/meta/identity_tag.hpp>
   4625 //     __ _____ _____ _____
   4626 //  __|  |   __|     |   | |  JSON for Modern C++
   4627 // |  |  |__   |  |  | | | |  version 3.11.3
   4628 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   4629 //
   4630 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   4631 // SPDX-License-Identifier: MIT
   4632 
   4633 
   4634 
   4635 // #include <nlohmann/detail/abi_macros.hpp>
   4636 
   4637 
   4638 NLOHMANN_JSON_NAMESPACE_BEGIN
   4639 namespace detail
   4640 {
   4641 
   4642 // dispatching helper struct
   4643 template <class T> struct identity_tag {};
   4644 
   4645 }  // namespace detail
   4646 NLOHMANN_JSON_NAMESPACE_END
   4647 
   4648 // #include <nlohmann/detail/meta/std_fs.hpp>
   4649 //     __ _____ _____ _____
   4650 //  __|  |   __|     |   | |  JSON for Modern C++
   4651 // |  |  |__   |  |  | | | |  version 3.11.3
   4652 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   4653 //
   4654 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   4655 // SPDX-License-Identifier: MIT
   4656 
   4657 
   4658 
   4659 // #include <nlohmann/detail/macro_scope.hpp>
   4660 
   4661 
   4662 #if JSON_HAS_EXPERIMENTAL_FILESYSTEM
   4663 #include <experimental/filesystem>
   4664 NLOHMANN_JSON_NAMESPACE_BEGIN
   4665 namespace detail
   4666 {
   4667 namespace std_fs = std::experimental::filesystem;
   4668 }  // namespace detail
   4669 NLOHMANN_JSON_NAMESPACE_END
   4670 #elif JSON_HAS_FILESYSTEM
   4671 #include <filesystem>
   4672 NLOHMANN_JSON_NAMESPACE_BEGIN
   4673 namespace detail
   4674 {
   4675 namespace std_fs = std::filesystem;
   4676 }  // namespace detail
   4677 NLOHMANN_JSON_NAMESPACE_END
   4678 #endif
   4679 
   4680 // #include <nlohmann/detail/meta/type_traits.hpp>
   4681 
   4682 // #include <nlohmann/detail/string_concat.hpp>
   4683 
   4684 // #include <nlohmann/detail/value_t.hpp>
   4685 
   4686 
   4687 NLOHMANN_JSON_NAMESPACE_BEGIN
   4688 namespace detail
   4689 {
   4690 
   4691 template<typename BasicJsonType>
   4692 inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
   4693 {
   4694    if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
   4695    {
   4696        JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
   4697    }
   4698    n = nullptr;
   4699 }
   4700 
   4701 // overloads for basic_json template parameters
   4702 template < typename BasicJsonType, typename ArithmeticType,
   4703           enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
   4704                         !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
   4705                         int > = 0 >
   4706 void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
   4707 {
   4708    switch (static_cast<value_t>(j))
   4709    {
   4710        case value_t::number_unsigned:
   4711        {
   4712            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
   4713            break;
   4714        }
   4715        case value_t::number_integer:
   4716        {
   4717            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
   4718            break;
   4719        }
   4720        case value_t::number_float:
   4721        {
   4722            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
   4723            break;
   4724        }
   4725 
   4726        case value_t::null:
   4727        case value_t::object:
   4728        case value_t::array:
   4729        case value_t::string:
   4730        case value_t::boolean:
   4731        case value_t::binary:
   4732        case value_t::discarded:
   4733        default:
   4734            JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
   4735    }
   4736 }
   4737 
   4738 template<typename BasicJsonType>
   4739 inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
   4740 {
   4741    if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
   4742    {
   4743        JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
   4744    }
   4745    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
   4746 }
   4747 
   4748 template<typename BasicJsonType>
   4749 inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
   4750 {
   4751    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
   4752    {
   4753        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
   4754    }
   4755    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
   4756 }
   4757 
   4758 template <
   4759    typename BasicJsonType, typename StringType,
   4760    enable_if_t <
   4761        std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
   4762        && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
   4763        && !std::is_same<typename BasicJsonType::string_t, StringType>::value
   4764        && !is_json_ref<StringType>::value, int > = 0 >
   4765 inline void from_json(const BasicJsonType& j, StringType& s)
   4766 {
   4767    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
   4768    {
   4769        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
   4770    }
   4771 
   4772    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
   4773 }
   4774 
   4775 template<typename BasicJsonType>
   4776 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
   4777 {
   4778    get_arithmetic_value(j, val);
   4779 }
   4780 
   4781 template<typename BasicJsonType>
   4782 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
   4783 {
   4784    get_arithmetic_value(j, val);
   4785 }
   4786 
   4787 template<typename BasicJsonType>
   4788 inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
   4789 {
   4790    get_arithmetic_value(j, val);
   4791 }
   4792 
   4793 #if !JSON_DISABLE_ENUM_SERIALIZATION
   4794 template<typename BasicJsonType, typename EnumType,
   4795         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
   4796 inline void from_json(const BasicJsonType& j, EnumType& e)
   4797 {
   4798    typename std::underlying_type<EnumType>::type val;
   4799    get_arithmetic_value(j, val);
   4800    e = static_cast<EnumType>(val);
   4801 }
   4802 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
   4803 
   4804 // forward_list doesn't have an insert method
   4805 template<typename BasicJsonType, typename T, typename Allocator,
   4806         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
   4807 inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
   4808 {
   4809    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4810    {
   4811        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4812    }
   4813    l.clear();
   4814    std::transform(j.rbegin(), j.rend(),
   4815                   std::front_inserter(l), [](const BasicJsonType & i)
   4816    {
   4817        return i.template get<T>();
   4818    });
   4819 }
   4820 
   4821 // valarray doesn't have an insert method
   4822 template<typename BasicJsonType, typename T,
   4823         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
   4824 inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
   4825 {
   4826    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4827    {
   4828        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4829    }
   4830    l.resize(j.size());
   4831    std::transform(j.begin(), j.end(), std::begin(l),
   4832                   [](const BasicJsonType & elem)
   4833    {
   4834        return elem.template get<T>();
   4835    });
   4836 }
   4837 
   4838 template<typename BasicJsonType, typename T, std::size_t N>
   4839 auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   4840 -> decltype(j.template get<T>(), void())
   4841 {
   4842    for (std::size_t i = 0; i < N; ++i)
   4843    {
   4844        arr[i] = j.at(i).template get<T>();
   4845    }
   4846 }
   4847 
   4848 template<typename BasicJsonType>
   4849 inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
   4850 {
   4851    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
   4852 }
   4853 
   4854 template<typename BasicJsonType, typename T, std::size_t N>
   4855 auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
   4856                          priority_tag<2> /*unused*/)
   4857 -> decltype(j.template get<T>(), void())
   4858 {
   4859    for (std::size_t i = 0; i < N; ++i)
   4860    {
   4861        arr[i] = j.at(i).template get<T>();
   4862    }
   4863 }
   4864 
   4865 template<typename BasicJsonType, typename ConstructibleArrayType,
   4866         enable_if_t<
   4867             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
   4868             int> = 0>
   4869 auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
   4870 -> decltype(
   4871    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
   4872    j.template get<typename ConstructibleArrayType::value_type>(),
   4873    void())
   4874 {
   4875    using std::end;
   4876 
   4877    ConstructibleArrayType ret;
   4878    ret.reserve(j.size());
   4879    std::transform(j.begin(), j.end(),
   4880                   std::inserter(ret, end(ret)), [](const BasicJsonType & i)
   4881    {
   4882        // get<BasicJsonType>() returns *this, this won't call a from_json
   4883        // method when value_type is BasicJsonType
   4884        return i.template get<typename ConstructibleArrayType::value_type>();
   4885    });
   4886    arr = std::move(ret);
   4887 }
   4888 
   4889 template<typename BasicJsonType, typename ConstructibleArrayType,
   4890         enable_if_t<
   4891             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
   4892             int> = 0>
   4893 inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
   4894                                 priority_tag<0> /*unused*/)
   4895 {
   4896    using std::end;
   4897 
   4898    ConstructibleArrayType ret;
   4899    std::transform(
   4900        j.begin(), j.end(), std::inserter(ret, end(ret)),
   4901        [](const BasicJsonType & i)
   4902    {
   4903        // get<BasicJsonType>() returns *this, this won't call a from_json
   4904        // method when value_type is BasicJsonType
   4905        return i.template get<typename ConstructibleArrayType::value_type>();
   4906    });
   4907    arr = std::move(ret);
   4908 }
   4909 
   4910 template < typename BasicJsonType, typename ConstructibleArrayType,
   4911           enable_if_t <
   4912               is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
   4913               !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
   4914               !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
   4915               !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
   4916               !is_basic_json<ConstructibleArrayType>::value,
   4917               int > = 0 >
   4918 auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
   4919 -> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
   4920 j.template get<typename ConstructibleArrayType::value_type>(),
   4921 void())
   4922 {
   4923    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4924    {
   4925        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4926    }
   4927 
   4928    from_json_array_impl(j, arr, priority_tag<3> {});
   4929 }
   4930 
   4931 template < typename BasicJsonType, typename T, std::size_t... Idx >
   4932 std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
   4933        identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
   4934 {
   4935    return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
   4936 }
   4937 
   4938 template < typename BasicJsonType, typename T, std::size_t N >
   4939 auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
   4940 -> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
   4941 {
   4942    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   4943    {
   4944        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   4945    }
   4946 
   4947    return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
   4948 }
   4949 
   4950 template<typename BasicJsonType>
   4951 inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
   4952 {
   4953    if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
   4954    {
   4955        JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
   4956    }
   4957 
   4958    bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
   4959 }
   4960 
   4961 template<typename BasicJsonType, typename ConstructibleObjectType,
   4962         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
   4963 inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
   4964 {
   4965    if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
   4966    {
   4967        JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
   4968    }
   4969 
   4970    ConstructibleObjectType ret;
   4971    const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
   4972    using value_type = typename ConstructibleObjectType::value_type;
   4973    std::transform(
   4974        inner_object->begin(), inner_object->end(),
   4975        std::inserter(ret, ret.begin()),
   4976        [](typename BasicJsonType::object_t::value_type const & p)
   4977    {
   4978        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
   4979    });
   4980    obj = std::move(ret);
   4981 }
   4982 
   4983 // overload for arithmetic types, not chosen for basic_json template arguments
   4984 // (BooleanType, etc..); note: Is it really necessary to provide explicit
   4985 // overloads for boolean_t etc. in case of a custom BooleanType which is not
   4986 // an arithmetic type?
   4987 template < typename BasicJsonType, typename ArithmeticType,
   4988           enable_if_t <
   4989               std::is_arithmetic<ArithmeticType>::value&&
   4990               !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
   4991               !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
   4992               !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
   4993               !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
   4994               int > = 0 >
   4995 inline void from_json(const BasicJsonType& j, ArithmeticType& val)
   4996 {
   4997    switch (static_cast<value_t>(j))
   4998    {
   4999        case value_t::number_unsigned:
   5000        {
   5001            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
   5002            break;
   5003        }
   5004        case value_t::number_integer:
   5005        {
   5006            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
   5007            break;
   5008        }
   5009        case value_t::number_float:
   5010        {
   5011            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
   5012            break;
   5013        }
   5014        case value_t::boolean:
   5015        {
   5016            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
   5017            break;
   5018        }
   5019 
   5020        case value_t::null:
   5021        case value_t::object:
   5022        case value_t::array:
   5023        case value_t::string:
   5024        case value_t::binary:
   5025        case value_t::discarded:
   5026        default:
   5027            JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
   5028    }
   5029 }
   5030 
   5031 template<typename BasicJsonType, typename... Args, std::size_t... Idx>
   5032 std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
   5033 {
   5034    return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
   5035 }
   5036 
   5037 template < typename BasicJsonType, class A1, class A2 >
   5038 std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
   5039 {
   5040    return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
   5041            std::forward<BasicJsonType>(j).at(1).template get<A2>()};
   5042 }
   5043 
   5044 template<typename BasicJsonType, typename A1, typename A2>
   5045 inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
   5046 {
   5047    p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
   5048 }
   5049 
   5050 template<typename BasicJsonType, typename... Args>
   5051 std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
   5052 {
   5053    return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
   5054 }
   5055 
   5056 template<typename BasicJsonType, typename... Args>
   5057 inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
   5058 {
   5059    t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
   5060 }
   5061 
   5062 template<typename BasicJsonType, typename TupleRelated>
   5063 auto from_json(BasicJsonType&& j, TupleRelated&& t)
   5064 -> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
   5065 {
   5066    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   5067    {
   5068        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   5069    }
   5070 
   5071    return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
   5072 }
   5073 
   5074 template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
   5075           typename = enable_if_t < !std::is_constructible <
   5076                                        typename BasicJsonType::string_t, Key >::value >>
   5077 inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
   5078 {
   5079    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   5080    {
   5081        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   5082    }
   5083    m.clear();
   5084    for (const auto& p : j)
   5085    {
   5086        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
   5087        {
   5088            JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
   5089        }
   5090        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
   5091    }
   5092 }
   5093 
   5094 template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
   5095           typename = enable_if_t < !std::is_constructible <
   5096                                        typename BasicJsonType::string_t, Key >::value >>
   5097 inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
   5098 {
   5099    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
   5100    {
   5101        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
   5102    }
   5103    m.clear();
   5104    for (const auto& p : j)
   5105    {
   5106        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
   5107        {
   5108            JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
   5109        }
   5110        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
   5111    }
   5112 }
   5113 
   5114 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
   5115 template<typename BasicJsonType>
   5116 inline void from_json(const BasicJsonType& j, std_fs::path& p)
   5117 {
   5118    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
   5119    {
   5120        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
   5121    }
   5122    p = *j.template get_ptr<const typename BasicJsonType::string_t*>();
   5123 }
   5124 #endif
   5125 
   5126 struct from_json_fn
   5127 {
   5128    template<typename BasicJsonType, typename T>
   5129    auto operator()(const BasicJsonType& j, T&& val) const
   5130    noexcept(noexcept(from_json(j, std::forward<T>(val))))
   5131    -> decltype(from_json(j, std::forward<T>(val)))
   5132    {
   5133        return from_json(j, std::forward<T>(val));
   5134    }
   5135 };
   5136 
   5137 }  // namespace detail
   5138 
   5139 #ifndef JSON_HAS_CPP_17
   5140 /// namespace to hold default `from_json` function
   5141 /// to see why this is required:
   5142 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
   5143 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
   5144 {
   5145 #endif
   5146 JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
   5147    detail::static_const<detail::from_json_fn>::value;
   5148 #ifndef JSON_HAS_CPP_17
   5149 }  // namespace
   5150 #endif
   5151 
   5152 NLOHMANN_JSON_NAMESPACE_END
   5153 
   5154 // #include <nlohmann/detail/conversions/to_json.hpp>
   5155 //     __ _____ _____ _____
   5156 //  __|  |   __|     |   | |  JSON for Modern C++
   5157 // |  |  |__   |  |  | | | |  version 3.11.3
   5158 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5159 //
   5160 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   5161 // SPDX-License-Identifier: MIT
   5162 
   5163 
   5164 
   5165 #include <algorithm> // copy
   5166 #include <iterator> // begin, end
   5167 #include <string> // string
   5168 #include <tuple> // tuple, get
   5169 #include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
   5170 #include <utility> // move, forward, declval, pair
   5171 #include <valarray> // valarray
   5172 #include <vector> // vector
   5173 
   5174 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
   5175 //     __ _____ _____ _____
   5176 //  __|  |   __|     |   | |  JSON for Modern C++
   5177 // |  |  |__   |  |  | | | |  version 3.11.3
   5178 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5179 //
   5180 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   5181 // SPDX-License-Identifier: MIT
   5182 
   5183 
   5184 
   5185 #include <cstddef> // size_t
   5186 #include <iterator> // input_iterator_tag
   5187 #include <string> // string, to_string
   5188 #include <tuple> // tuple_size, get, tuple_element
   5189 #include <utility> // move
   5190 
   5191 #if JSON_HAS_RANGES
   5192    #include <ranges> // enable_borrowed_range
   5193 #endif
   5194 
   5195 // #include <nlohmann/detail/abi_macros.hpp>
   5196 
   5197 // #include <nlohmann/detail/meta/type_traits.hpp>
   5198 
   5199 // #include <nlohmann/detail/value_t.hpp>
   5200 
   5201 
   5202 NLOHMANN_JSON_NAMESPACE_BEGIN
   5203 namespace detail
   5204 {
   5205 
   5206 template<typename string_type>
   5207 void int_to_string( string_type& target, std::size_t value )
   5208 {
   5209    // For ADL
   5210    using std::to_string;
   5211    target = to_string(value);
   5212 }
   5213 template<typename IteratorType> class iteration_proxy_value
   5214 {
   5215  public:
   5216    using difference_type = std::ptrdiff_t;
   5217    using value_type = iteration_proxy_value;
   5218    using pointer = value_type *;
   5219    using reference = value_type &;
   5220    using iterator_category = std::input_iterator_tag;
   5221    using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
   5222 
   5223  private:
   5224    /// the iterator
   5225    IteratorType anchor{};
   5226    /// an index for arrays (used to create key names)
   5227    std::size_t array_index = 0;
   5228    /// last stringified array index
   5229    mutable std::size_t array_index_last = 0;
   5230    /// a string representation of the array index
   5231    mutable string_type array_index_str = "0";
   5232    /// an empty string (to return a reference for primitive values)
   5233    string_type empty_str{};
   5234 
   5235  public:
   5236    explicit iteration_proxy_value() = default;
   5237    explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
   5238    noexcept(std::is_nothrow_move_constructible<IteratorType>::value
   5239             && std::is_nothrow_default_constructible<string_type>::value)
   5240        : anchor(std::move(it))
   5241        , array_index(array_index_)
   5242    {}
   5243 
   5244    iteration_proxy_value(iteration_proxy_value const&) = default;
   5245    iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
   5246    // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
   5247    iteration_proxy_value(iteration_proxy_value&&)
   5248    noexcept(std::is_nothrow_move_constructible<IteratorType>::value
   5249             && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
   5250    iteration_proxy_value& operator=(iteration_proxy_value&&)
   5251    noexcept(std::is_nothrow_move_assignable<IteratorType>::value
   5252             && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
   5253    ~iteration_proxy_value() = default;
   5254 
   5255    /// dereference operator (needed for range-based for)
   5256    const iteration_proxy_value& operator*() const
   5257    {
   5258        return *this;
   5259    }
   5260 
   5261    /// increment operator (needed for range-based for)
   5262    iteration_proxy_value& operator++()
   5263    {
   5264        ++anchor;
   5265        ++array_index;
   5266 
   5267        return *this;
   5268    }
   5269 
   5270    iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
   5271    {
   5272        auto tmp = iteration_proxy_value(anchor, array_index);
   5273        ++anchor;
   5274        ++array_index;
   5275        return tmp;
   5276    }
   5277 
   5278    /// equality operator (needed for InputIterator)
   5279    bool operator==(const iteration_proxy_value& o) const
   5280    {
   5281        return anchor == o.anchor;
   5282    }
   5283 
   5284    /// inequality operator (needed for range-based for)
   5285    bool operator!=(const iteration_proxy_value& o) const
   5286    {
   5287        return anchor != o.anchor;
   5288    }
   5289 
   5290    /// return key of the iterator
   5291    const string_type& key() const
   5292    {
   5293        JSON_ASSERT(anchor.m_object != nullptr);
   5294 
   5295        switch (anchor.m_object->type())
   5296        {
   5297            // use integer array index as key
   5298            case value_t::array:
   5299            {
   5300                if (array_index != array_index_last)
   5301                {
   5302                    int_to_string( array_index_str, array_index );
   5303                    array_index_last = array_index;
   5304                }
   5305                return array_index_str;
   5306            }
   5307 
   5308            // use key from the object
   5309            case value_t::object:
   5310                return anchor.key();
   5311 
   5312            // use an empty key for all primitive types
   5313            case value_t::null:
   5314            case value_t::string:
   5315            case value_t::boolean:
   5316            case value_t::number_integer:
   5317            case value_t::number_unsigned:
   5318            case value_t::number_float:
   5319            case value_t::binary:
   5320            case value_t::discarded:
   5321            default:
   5322                return empty_str;
   5323        }
   5324    }
   5325 
   5326    /// return value of the iterator
   5327    typename IteratorType::reference value() const
   5328    {
   5329        return anchor.value();
   5330    }
   5331 };
   5332 
   5333 /// proxy class for the items() function
   5334 template<typename IteratorType> class iteration_proxy
   5335 {
   5336  private:
   5337    /// the container to iterate
   5338    typename IteratorType::pointer container = nullptr;
   5339 
   5340  public:
   5341    explicit iteration_proxy() = default;
   5342 
   5343    /// construct iteration proxy from a container
   5344    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
   5345        : container(&cont) {}
   5346 
   5347    iteration_proxy(iteration_proxy const&) = default;
   5348    iteration_proxy& operator=(iteration_proxy const&) = default;
   5349    iteration_proxy(iteration_proxy&&) noexcept = default;
   5350    iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
   5351    ~iteration_proxy() = default;
   5352 
   5353    /// return iterator begin (needed for range-based for)
   5354    iteration_proxy_value<IteratorType> begin() const noexcept
   5355    {
   5356        return iteration_proxy_value<IteratorType>(container->begin());
   5357    }
   5358 
   5359    /// return iterator end (needed for range-based for)
   5360    iteration_proxy_value<IteratorType> end() const noexcept
   5361    {
   5362        return iteration_proxy_value<IteratorType>(container->end());
   5363    }
   5364 };
   5365 
   5366 // Structured Bindings Support
   5367 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
   5368 // And see https://github.com/nlohmann/json/pull/1391
   5369 template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
   5370 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
   5371 {
   5372    return i.key();
   5373 }
   5374 // Structured Bindings Support
   5375 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
   5376 // And see https://github.com/nlohmann/json/pull/1391
   5377 template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
   5378 auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
   5379 {
   5380    return i.value();
   5381 }
   5382 
   5383 }  // namespace detail
   5384 NLOHMANN_JSON_NAMESPACE_END
   5385 
   5386 // The Addition to the STD Namespace is required to add
   5387 // Structured Bindings Support to the iteration_proxy_value class
   5388 // For further reference see https://blog.tartanllama.xyz/structured-bindings/
   5389 // And see https://github.com/nlohmann/json/pull/1391
   5390 namespace std
   5391 {
   5392 
   5393 #if defined(__clang__)
   5394    // Fix: https://github.com/nlohmann/json/issues/1401
   5395    #pragma clang diagnostic push
   5396    #pragma clang diagnostic ignored "-Wmismatched-tags"
   5397 #endif
   5398 template<typename IteratorType>
   5399 class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
   5400            : public std::integral_constant<std::size_t, 2> {};
   5401 
   5402 template<std::size_t N, typename IteratorType>
   5403 class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
   5404 {
   5405  public:
   5406    using type = decltype(
   5407                     get<N>(std::declval <
   5408                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
   5409 };
   5410 #if defined(__clang__)
   5411    #pragma clang diagnostic pop
   5412 #endif
   5413 
   5414 }  // namespace std
   5415 
   5416 #if JSON_HAS_RANGES
   5417    template <typename IteratorType>
   5418    inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
   5419 #endif
   5420 
   5421 // #include <nlohmann/detail/macro_scope.hpp>
   5422 
   5423 // #include <nlohmann/detail/meta/cpp_future.hpp>
   5424 
   5425 // #include <nlohmann/detail/meta/std_fs.hpp>
   5426 
   5427 // #include <nlohmann/detail/meta/type_traits.hpp>
   5428 
   5429 // #include <nlohmann/detail/value_t.hpp>
   5430 
   5431 
   5432 NLOHMANN_JSON_NAMESPACE_BEGIN
   5433 namespace detail
   5434 {
   5435 
   5436 //////////////////
   5437 // constructors //
   5438 //////////////////
   5439 
   5440 /*
   5441 * Note all external_constructor<>::construct functions need to call
   5442 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
   5443 * allocated value (e.g., a string). See bug issue
   5444 * https://github.com/nlohmann/json/issues/2865 for more information.
   5445 */
   5446 
   5447 template<value_t> struct external_constructor;
   5448 
   5449 template<>
   5450 struct external_constructor<value_t::boolean>
   5451 {
   5452    template<typename BasicJsonType>
   5453    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
   5454    {
   5455        j.m_data.m_value.destroy(j.m_data.m_type);
   5456        j.m_data.m_type = value_t::boolean;
   5457        j.m_data.m_value = b;
   5458        j.assert_invariant();
   5459    }
   5460 };
   5461 
   5462 template<>
   5463 struct external_constructor<value_t::string>
   5464 {
   5465    template<typename BasicJsonType>
   5466    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
   5467    {
   5468        j.m_data.m_value.destroy(j.m_data.m_type);
   5469        j.m_data.m_type = value_t::string;
   5470        j.m_data.m_value = s;
   5471        j.assert_invariant();
   5472    }
   5473 
   5474    template<typename BasicJsonType>
   5475    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
   5476    {
   5477        j.m_data.m_value.destroy(j.m_data.m_type);
   5478        j.m_data.m_type = value_t::string;
   5479        j.m_data.m_value = std::move(s);
   5480        j.assert_invariant();
   5481    }
   5482 
   5483    template < typename BasicJsonType, typename CompatibleStringType,
   5484               enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
   5485                             int > = 0 >
   5486    static void construct(BasicJsonType& j, const CompatibleStringType& str)
   5487    {
   5488        j.m_data.m_value.destroy(j.m_data.m_type);
   5489        j.m_data.m_type = value_t::string;
   5490        j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
   5491        j.assert_invariant();
   5492    }
   5493 };
   5494 
   5495 template<>
   5496 struct external_constructor<value_t::binary>
   5497 {
   5498    template<typename BasicJsonType>
   5499    static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
   5500    {
   5501        j.m_data.m_value.destroy(j.m_data.m_type);
   5502        j.m_data.m_type = value_t::binary;
   5503        j.m_data.m_value = typename BasicJsonType::binary_t(b);
   5504        j.assert_invariant();
   5505    }
   5506 
   5507    template<typename BasicJsonType>
   5508    static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
   5509    {
   5510        j.m_data.m_value.destroy(j.m_data.m_type);
   5511        j.m_data.m_type = value_t::binary;
   5512        j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
   5513        j.assert_invariant();
   5514    }
   5515 };
   5516 
   5517 template<>
   5518 struct external_constructor<value_t::number_float>
   5519 {
   5520    template<typename BasicJsonType>
   5521    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
   5522    {
   5523        j.m_data.m_value.destroy(j.m_data.m_type);
   5524        j.m_data.m_type = value_t::number_float;
   5525        j.m_data.m_value = val;
   5526        j.assert_invariant();
   5527    }
   5528 };
   5529 
   5530 template<>
   5531 struct external_constructor<value_t::number_unsigned>
   5532 {
   5533    template<typename BasicJsonType>
   5534    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
   5535    {
   5536        j.m_data.m_value.destroy(j.m_data.m_type);
   5537        j.m_data.m_type = value_t::number_unsigned;
   5538        j.m_data.m_value = val;
   5539        j.assert_invariant();
   5540    }
   5541 };
   5542 
   5543 template<>
   5544 struct external_constructor<value_t::number_integer>
   5545 {
   5546    template<typename BasicJsonType>
   5547    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
   5548    {
   5549        j.m_data.m_value.destroy(j.m_data.m_type);
   5550        j.m_data.m_type = value_t::number_integer;
   5551        j.m_data.m_value = val;
   5552        j.assert_invariant();
   5553    }
   5554 };
   5555 
   5556 template<>
   5557 struct external_constructor<value_t::array>
   5558 {
   5559    template<typename BasicJsonType>
   5560    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
   5561    {
   5562        j.m_data.m_value.destroy(j.m_data.m_type);
   5563        j.m_data.m_type = value_t::array;
   5564        j.m_data.m_value = arr;
   5565        j.set_parents();
   5566        j.assert_invariant();
   5567    }
   5568 
   5569    template<typename BasicJsonType>
   5570    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
   5571    {
   5572        j.m_data.m_value.destroy(j.m_data.m_type);
   5573        j.m_data.m_type = value_t::array;
   5574        j.m_data.m_value = std::move(arr);
   5575        j.set_parents();
   5576        j.assert_invariant();
   5577    }
   5578 
   5579    template < typename BasicJsonType, typename CompatibleArrayType,
   5580               enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
   5581                             int > = 0 >
   5582    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
   5583    {
   5584        using std::begin;
   5585        using std::end;
   5586 
   5587        j.m_data.m_value.destroy(j.m_data.m_type);
   5588        j.m_data.m_type = value_t::array;
   5589        j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
   5590        j.set_parents();
   5591        j.assert_invariant();
   5592    }
   5593 
   5594    template<typename BasicJsonType>
   5595    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
   5596    {
   5597        j.m_data.m_value.destroy(j.m_data.m_type);
   5598        j.m_data.m_type = value_t::array;
   5599        j.m_data.m_value = value_t::array;
   5600        j.m_data.m_value.array->reserve(arr.size());
   5601        for (const bool x : arr)
   5602        {
   5603            j.m_data.m_value.array->push_back(x);
   5604            j.set_parent(j.m_data.m_value.array->back());
   5605        }
   5606        j.assert_invariant();
   5607    }
   5608 
   5609    template<typename BasicJsonType, typename T,
   5610             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
   5611    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
   5612    {
   5613        j.m_data.m_value.destroy(j.m_data.m_type);
   5614        j.m_data.m_type = value_t::array;
   5615        j.m_data.m_value = value_t::array;
   5616        j.m_data.m_value.array->resize(arr.size());
   5617        if (arr.size() > 0)
   5618        {
   5619            std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
   5620        }
   5621        j.set_parents();
   5622        j.assert_invariant();
   5623    }
   5624 };
   5625 
   5626 template<>
   5627 struct external_constructor<value_t::object>
   5628 {
   5629    template<typename BasicJsonType>
   5630    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
   5631    {
   5632        j.m_data.m_value.destroy(j.m_data.m_type);
   5633        j.m_data.m_type = value_t::object;
   5634        j.m_data.m_value = obj;
   5635        j.set_parents();
   5636        j.assert_invariant();
   5637    }
   5638 
   5639    template<typename BasicJsonType>
   5640    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
   5641    {
   5642        j.m_data.m_value.destroy(j.m_data.m_type);
   5643        j.m_data.m_type = value_t::object;
   5644        j.m_data.m_value = std::move(obj);
   5645        j.set_parents();
   5646        j.assert_invariant();
   5647    }
   5648 
   5649    template < typename BasicJsonType, typename CompatibleObjectType,
   5650               enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
   5651    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
   5652    {
   5653        using std::begin;
   5654        using std::end;
   5655 
   5656        j.m_data.m_value.destroy(j.m_data.m_type);
   5657        j.m_data.m_type = value_t::object;
   5658        j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
   5659        j.set_parents();
   5660        j.assert_invariant();
   5661    }
   5662 };
   5663 
   5664 /////////////
   5665 // to_json //
   5666 /////////////
   5667 
   5668 template<typename BasicJsonType, typename T,
   5669         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
   5670 inline void to_json(BasicJsonType& j, T b) noexcept
   5671 {
   5672    external_constructor<value_t::boolean>::construct(j, b);
   5673 }
   5674 
   5675 template < typename BasicJsonType, typename BoolRef,
   5676           enable_if_t <
   5677               ((std::is_same<std::vector<bool>::reference, BoolRef>::value
   5678                 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
   5679                || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
   5680                    && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
   5681                                      typename BasicJsonType::boolean_t >::value))
   5682               && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
   5683 inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
   5684 {
   5685    external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
   5686 }
   5687 
   5688 template<typename BasicJsonType, typename CompatibleString,
   5689         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
   5690 inline void to_json(BasicJsonType& j, const CompatibleString& s)
   5691 {
   5692    external_constructor<value_t::string>::construct(j, s);
   5693 }
   5694 
   5695 template<typename BasicJsonType>
   5696 inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
   5697 {
   5698    external_constructor<value_t::string>::construct(j, std::move(s));
   5699 }
   5700 
   5701 template<typename BasicJsonType, typename FloatType,
   5702         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
   5703 inline void to_json(BasicJsonType& j, FloatType val) noexcept
   5704 {
   5705    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
   5706 }
   5707 
   5708 template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
   5709         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
   5710 inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
   5711 {
   5712    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
   5713 }
   5714 
   5715 template<typename BasicJsonType, typename CompatibleNumberIntegerType,
   5716         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
   5717 inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
   5718 {
   5719    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
   5720 }
   5721 
   5722 #if !JSON_DISABLE_ENUM_SERIALIZATION
   5723 template<typename BasicJsonType, typename EnumType,
   5724         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
   5725 inline void to_json(BasicJsonType& j, EnumType e) noexcept
   5726 {
   5727    using underlying_type = typename std::underlying_type<EnumType>::type;
   5728    external_constructor<value_t::number_integer>::construct(j, static_cast<underlying_type>(e));
   5729 }
   5730 #endif  // JSON_DISABLE_ENUM_SERIALIZATION
   5731 
   5732 template<typename BasicJsonType>
   5733 inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
   5734 {
   5735    external_constructor<value_t::array>::construct(j, e);
   5736 }
   5737 
   5738 template < typename BasicJsonType, typename CompatibleArrayType,
   5739           enable_if_t < is_compatible_array_type<BasicJsonType,
   5740                         CompatibleArrayType>::value&&
   5741                         !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
   5742                         !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
   5743                         !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
   5744                         !is_basic_json<CompatibleArrayType>::value,
   5745                         int > = 0 >
   5746 inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
   5747 {
   5748    external_constructor<value_t::array>::construct(j, arr);
   5749 }
   5750 
   5751 template<typename BasicJsonType>
   5752 inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
   5753 {
   5754    external_constructor<value_t::binary>::construct(j, bin);
   5755 }
   5756 
   5757 template<typename BasicJsonType, typename T,
   5758         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
   5759 inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
   5760 {
   5761    external_constructor<value_t::array>::construct(j, std::move(arr));
   5762 }
   5763 
   5764 template<typename BasicJsonType>
   5765 inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
   5766 {
   5767    external_constructor<value_t::array>::construct(j, std::move(arr));
   5768 }
   5769 
   5770 template < typename BasicJsonType, typename CompatibleObjectType,
   5771           enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
   5772 inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
   5773 {
   5774    external_constructor<value_t::object>::construct(j, obj);
   5775 }
   5776 
   5777 template<typename BasicJsonType>
   5778 inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
   5779 {
   5780    external_constructor<value_t::object>::construct(j, std::move(obj));
   5781 }
   5782 
   5783 template <
   5784    typename BasicJsonType, typename T, std::size_t N,
   5785    enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
   5786                  const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   5787                  int > = 0 >
   5788 inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
   5789 {
   5790    external_constructor<value_t::array>::construct(j, arr);
   5791 }
   5792 
   5793 template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
   5794 inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
   5795 {
   5796    j = { p.first, p.second };
   5797 }
   5798 
   5799 // for https://github.com/nlohmann/json/pull/1134
   5800 template<typename BasicJsonType, typename T,
   5801         enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
   5802 inline void to_json(BasicJsonType& j, const T& b)
   5803 {
   5804    j = { {b.key(), b.value()} };
   5805 }
   5806 
   5807 template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
   5808 inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
   5809 {
   5810    j = { std::get<Idx>(t)... };
   5811 }
   5812 
   5813 template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
   5814 inline void to_json(BasicJsonType& j, const T& t)
   5815 {
   5816    to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
   5817 }
   5818 
   5819 #if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
   5820 template<typename BasicJsonType>
   5821 inline void to_json(BasicJsonType& j, const std_fs::path& p)
   5822 {
   5823    j = p.string();
   5824 }
   5825 #endif
   5826 
   5827 struct to_json_fn
   5828 {
   5829    template<typename BasicJsonType, typename T>
   5830    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
   5831    -> decltype(to_json(j, std::forward<T>(val)), void())
   5832    {
   5833        return to_json(j, std::forward<T>(val));
   5834    }
   5835 };
   5836 }  // namespace detail
   5837 
   5838 #ifndef JSON_HAS_CPP_17
   5839 /// namespace to hold default `to_json` function
   5840 /// to see why this is required:
   5841 /// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
   5842 namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
   5843 {
   5844 #endif
   5845 JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
   5846    detail::static_const<detail::to_json_fn>::value;
   5847 #ifndef JSON_HAS_CPP_17
   5848 }  // namespace
   5849 #endif
   5850 
   5851 NLOHMANN_JSON_NAMESPACE_END
   5852 
   5853 // #include <nlohmann/detail/meta/identity_tag.hpp>
   5854 
   5855 
   5856 NLOHMANN_JSON_NAMESPACE_BEGIN
   5857 
   5858 /// @sa https://json.nlohmann.me/api/adl_serializer/
   5859 template<typename ValueType, typename>
   5860 struct adl_serializer
   5861 {
   5862    /// @brief convert a JSON value to any value type
   5863    /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
   5864    template<typename BasicJsonType, typename TargetType = ValueType>
   5865    static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
   5866        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
   5867    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
   5868    {
   5869        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
   5870    }
   5871 
   5872    /// @brief convert a JSON value to any value type
   5873    /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
   5874    template<typename BasicJsonType, typename TargetType = ValueType>
   5875    static auto from_json(BasicJsonType && j) noexcept(
   5876    noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
   5877    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
   5878    {
   5879        return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
   5880    }
   5881 
   5882    /// @brief convert any value type to a JSON value
   5883    /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
   5884    template<typename BasicJsonType, typename TargetType = ValueType>
   5885    static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
   5886        noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
   5887    -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
   5888    {
   5889        ::nlohmann::to_json(j, std::forward<TargetType>(val));
   5890    }
   5891 };
   5892 
   5893 NLOHMANN_JSON_NAMESPACE_END
   5894 
   5895 // #include <nlohmann/byte_container_with_subtype.hpp>
   5896 //     __ _____ _____ _____
   5897 //  __|  |   __|     |   | |  JSON for Modern C++
   5898 // |  |  |__   |  |  | | | |  version 3.11.3
   5899 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5900 //
   5901 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   5902 // SPDX-License-Identifier: MIT
   5903 
   5904 
   5905 
   5906 #include <cstdint> // uint8_t, uint64_t
   5907 #include <tuple> // tie
   5908 #include <utility> // move
   5909 
   5910 // #include <nlohmann/detail/abi_macros.hpp>
   5911 
   5912 
   5913 NLOHMANN_JSON_NAMESPACE_BEGIN
   5914 
   5915 /// @brief an internal type for a backed binary type
   5916 /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
   5917 template<typename BinaryType>
   5918 class byte_container_with_subtype : public BinaryType
   5919 {
   5920  public:
   5921    using container_type = BinaryType;
   5922    using subtype_type = std::uint64_t;
   5923 
   5924    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5925    byte_container_with_subtype() noexcept(noexcept(container_type()))
   5926        : container_type()
   5927    {}
   5928 
   5929    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5930    byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
   5931        : container_type(b)
   5932    {}
   5933 
   5934    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5935    byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
   5936        : container_type(std::move(b))
   5937    {}
   5938 
   5939    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5940    byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
   5941        : container_type(b)
   5942        , m_subtype(subtype_)
   5943        , m_has_subtype(true)
   5944    {}
   5945 
   5946    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
   5947    byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
   5948        : container_type(std::move(b))
   5949        , m_subtype(subtype_)
   5950        , m_has_subtype(true)
   5951    {}
   5952 
   5953    bool operator==(const byte_container_with_subtype& rhs) const
   5954    {
   5955        return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
   5956               std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
   5957    }
   5958 
   5959    bool operator!=(const byte_container_with_subtype& rhs) const
   5960    {
   5961        return !(rhs == *this);
   5962    }
   5963 
   5964    /// @brief sets the binary subtype
   5965    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
   5966    void set_subtype(subtype_type subtype_) noexcept
   5967    {
   5968        m_subtype = subtype_;
   5969        m_has_subtype = true;
   5970    }
   5971 
   5972    /// @brief return the binary subtype
   5973    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
   5974    constexpr subtype_type subtype() const noexcept
   5975    {
   5976        return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
   5977    }
   5978 
   5979    /// @brief return whether the value has a subtype
   5980    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
   5981    constexpr bool has_subtype() const noexcept
   5982    {
   5983        return m_has_subtype;
   5984    }
   5985 
   5986    /// @brief clears the binary subtype
   5987    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
   5988    void clear_subtype() noexcept
   5989    {
   5990        m_subtype = 0;
   5991        m_has_subtype = false;
   5992    }
   5993 
   5994  private:
   5995    subtype_type m_subtype = 0;
   5996    bool m_has_subtype = false;
   5997 };
   5998 
   5999 NLOHMANN_JSON_NAMESPACE_END
   6000 
   6001 // #include <nlohmann/detail/conversions/from_json.hpp>
   6002 
   6003 // #include <nlohmann/detail/conversions/to_json.hpp>
   6004 
   6005 // #include <nlohmann/detail/exceptions.hpp>
   6006 
   6007 // #include <nlohmann/detail/hash.hpp>
   6008 //     __ _____ _____ _____
   6009 //  __|  |   __|     |   | |  JSON for Modern C++
   6010 // |  |  |__   |  |  | | | |  version 3.11.3
   6011 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6012 //
   6013 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   6014 // SPDX-License-Identifier: MIT
   6015 
   6016 
   6017 
   6018 #include <cstdint> // uint8_t
   6019 #include <cstddef> // size_t
   6020 #include <functional> // hash
   6021 
   6022 // #include <nlohmann/detail/abi_macros.hpp>
   6023 
   6024 // #include <nlohmann/detail/value_t.hpp>
   6025 
   6026 
   6027 NLOHMANN_JSON_NAMESPACE_BEGIN
   6028 namespace detail
   6029 {
   6030 
   6031 // boost::hash_combine
   6032 inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
   6033 {
   6034    seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
   6035    return seed;
   6036 }
   6037 
   6038 /*!
   6039 @brief hash a JSON value
   6040 
   6041 The hash function tries to rely on std::hash where possible. Furthermore, the
   6042 type of the JSON value is taken into account to have different hash values for
   6043 null, 0, 0U, and false, etc.
   6044 
   6045 @tparam BasicJsonType basic_json specialization
   6046 @param j JSON value to hash
   6047 @return hash value of j
   6048 */
   6049 template<typename BasicJsonType>
   6050 std::size_t hash(const BasicJsonType& j)
   6051 {
   6052    using string_t = typename BasicJsonType::string_t;
   6053    using number_integer_t = typename BasicJsonType::number_integer_t;
   6054    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   6055    using number_float_t = typename BasicJsonType::number_float_t;
   6056 
   6057    const auto type = static_cast<std::size_t>(j.type());
   6058    switch (j.type())
   6059    {
   6060        case BasicJsonType::value_t::null:
   6061        case BasicJsonType::value_t::discarded:
   6062        {
   6063            return combine(type, 0);
   6064        }
   6065 
   6066        case BasicJsonType::value_t::object:
   6067        {
   6068            auto seed = combine(type, j.size());
   6069            for (const auto& element : j.items())
   6070            {
   6071                const auto h = std::hash<string_t> {}(element.key());
   6072                seed = combine(seed, h);
   6073                seed = combine(seed, hash(element.value()));
   6074            }
   6075            return seed;
   6076        }
   6077 
   6078        case BasicJsonType::value_t::array:
   6079        {
   6080            auto seed = combine(type, j.size());
   6081            for (const auto& element : j)
   6082            {
   6083                seed = combine(seed, hash(element));
   6084            }
   6085            return seed;
   6086        }
   6087 
   6088        case BasicJsonType::value_t::string:
   6089        {
   6090            const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
   6091            return combine(type, h);
   6092        }
   6093 
   6094        case BasicJsonType::value_t::boolean:
   6095        {
   6096            const auto h = std::hash<bool> {}(j.template get<bool>());
   6097            return combine(type, h);
   6098        }
   6099 
   6100        case BasicJsonType::value_t::number_integer:
   6101        {
   6102            const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
   6103            return combine(type, h);
   6104        }
   6105 
   6106        case BasicJsonType::value_t::number_unsigned:
   6107        {
   6108            const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
   6109            return combine(type, h);
   6110        }
   6111 
   6112        case BasicJsonType::value_t::number_float:
   6113        {
   6114            const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
   6115            return combine(type, h);
   6116        }
   6117 
   6118        case BasicJsonType::value_t::binary:
   6119        {
   6120            auto seed = combine(type, j.get_binary().size());
   6121            const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
   6122            seed = combine(seed, h);
   6123            seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
   6124            for (const auto byte : j.get_binary())
   6125            {
   6126                seed = combine(seed, std::hash<std::uint8_t> {}(byte));
   6127            }
   6128            return seed;
   6129        }
   6130 
   6131        default:                   // LCOV_EXCL_LINE
   6132            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   6133            return 0;              // LCOV_EXCL_LINE
   6134    }
   6135 }
   6136 
   6137 }  // namespace detail
   6138 NLOHMANN_JSON_NAMESPACE_END
   6139 
   6140 // #include <nlohmann/detail/input/binary_reader.hpp>
   6141 //     __ _____ _____ _____
   6142 //  __|  |   __|     |   | |  JSON for Modern C++
   6143 // |  |  |__   |  |  | | | |  version 3.11.3
   6144 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6145 //
   6146 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   6147 // SPDX-License-Identifier: MIT
   6148 
   6149 
   6150 
   6151 #include <algorithm> // generate_n
   6152 #include <array> // array
   6153 #include <cmath> // ldexp
   6154 #include <cstddef> // size_t
   6155 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
   6156 #include <cstdio> // snprintf
   6157 #include <cstring> // memcpy
   6158 #include <iterator> // back_inserter
   6159 #include <limits> // numeric_limits
   6160 #include <string> // char_traits, string
   6161 #include <utility> // make_pair, move
   6162 #include <vector> // vector
   6163 
   6164 // #include <nlohmann/detail/exceptions.hpp>
   6165 
   6166 // #include <nlohmann/detail/input/input_adapters.hpp>
   6167 //     __ _____ _____ _____
   6168 //  __|  |   __|     |   | |  JSON for Modern C++
   6169 // |  |  |__   |  |  | | | |  version 3.11.3
   6170 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6171 //
   6172 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   6173 // SPDX-License-Identifier: MIT
   6174 
   6175 
   6176 
   6177 #include <array> // array
   6178 #include <cstddef> // size_t
   6179 #include <cstring> // strlen
   6180 #include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
   6181 #include <memory> // shared_ptr, make_shared, addressof
   6182 #include <numeric> // accumulate
   6183 #include <string> // string, char_traits
   6184 #include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
   6185 #include <utility> // pair, declval
   6186 
   6187 #ifndef JSON_NO_IO
   6188    #include <cstdio>   // FILE *
   6189    #include <istream>  // istream
   6190 #endif                  // JSON_NO_IO
   6191 
   6192 // #include <nlohmann/detail/iterators/iterator_traits.hpp>
   6193 
   6194 // #include <nlohmann/detail/macro_scope.hpp>
   6195 
   6196 // #include <nlohmann/detail/meta/type_traits.hpp>
   6197 
   6198 
   6199 NLOHMANN_JSON_NAMESPACE_BEGIN
   6200 namespace detail
   6201 {
   6202 
   6203 /// the supported input formats
   6204 enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
   6205 
   6206 ////////////////////
   6207 // input adapters //
   6208 ////////////////////
   6209 
   6210 #ifndef JSON_NO_IO
   6211 /*!
   6212 Input adapter for stdio file access. This adapter read only 1 byte and do not use any
   6213 buffer. This adapter is a very low level adapter.
   6214 */
   6215 class file_input_adapter
   6216 {
   6217  public:
   6218    using char_type = char;
   6219 
   6220    JSON_HEDLEY_NON_NULL(2)
   6221    explicit file_input_adapter(std::FILE* f) noexcept
   6222        : m_file(f)
   6223    {
   6224        JSON_ASSERT(m_file != nullptr);
   6225    }
   6226 
   6227    // make class move-only
   6228    file_input_adapter(const file_input_adapter&) = delete;
   6229    file_input_adapter(file_input_adapter&&) noexcept = default;
   6230    file_input_adapter& operator=(const file_input_adapter&) = delete;
   6231    file_input_adapter& operator=(file_input_adapter&&) = delete;
   6232    ~file_input_adapter() = default;
   6233 
   6234    std::char_traits<char>::int_type get_character() noexcept
   6235    {
   6236        return std::fgetc(m_file);
   6237    }
   6238 
   6239  private:
   6240    /// the file pointer to read from
   6241    std::FILE* m_file;
   6242 };
   6243 
   6244 /*!
   6245 Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
   6246 beginning of input. Does not support changing the underlying std::streambuf
   6247 in mid-input. Maintains underlying std::istream and std::streambuf to support
   6248 subsequent use of standard std::istream operations to process any input
   6249 characters following those used in parsing the JSON input.  Clears the
   6250 std::istream flags; any input errors (e.g., EOF) will be detected by the first
   6251 subsequent call for input from the std::istream.
   6252 */
   6253 class input_stream_adapter
   6254 {
   6255  public:
   6256    using char_type = char;
   6257 
   6258    ~input_stream_adapter()
   6259    {
   6260        // clear stream flags; we use underlying streambuf I/O, do not
   6261        // maintain ifstream flags, except eof
   6262        if (is != nullptr)
   6263        {
   6264            is->clear(is->rdstate() & std::ios::eofbit);
   6265        }
   6266    }
   6267 
   6268    explicit input_stream_adapter(std::istream& i)
   6269        : is(&i), sb(i.rdbuf())
   6270    {}
   6271 
   6272    // delete because of pointer members
   6273    input_stream_adapter(const input_stream_adapter&) = delete;
   6274    input_stream_adapter& operator=(input_stream_adapter&) = delete;
   6275    input_stream_adapter& operator=(input_stream_adapter&&) = delete;
   6276 
   6277    input_stream_adapter(input_stream_adapter&& rhs) noexcept
   6278        : is(rhs.is), sb(rhs.sb)
   6279    {
   6280        rhs.is = nullptr;
   6281        rhs.sb = nullptr;
   6282    }
   6283 
   6284    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
   6285    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
   6286    // end up as the same value, e.g. 0xFFFFFFFF.
   6287    std::char_traits<char>::int_type get_character()
   6288    {
   6289        auto res = sb->sbumpc();
   6290        // set eof manually, as we don't use the istream interface.
   6291        if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
   6292        {
   6293            is->clear(is->rdstate() | std::ios::eofbit);
   6294        }
   6295        return res;
   6296    }
   6297 
   6298  private:
   6299    /// the associated input stream
   6300    std::istream* is = nullptr;
   6301    std::streambuf* sb = nullptr;
   6302 };
   6303 #endif  // JSON_NO_IO
   6304 
   6305 // General-purpose iterator-based adapter. It might not be as fast as
   6306 // theoretically possible for some containers, but it is extremely versatile.
   6307 template<typename IteratorType>
   6308 class iterator_input_adapter
   6309 {
   6310  public:
   6311    using char_type = typename std::iterator_traits<IteratorType>::value_type;
   6312 
   6313    iterator_input_adapter(IteratorType first, IteratorType last)
   6314        : current(std::move(first)), end(std::move(last))
   6315    {}
   6316 
   6317    typename char_traits<char_type>::int_type get_character()
   6318    {
   6319        if (JSON_HEDLEY_LIKELY(current != end))
   6320        {
   6321            auto result = char_traits<char_type>::to_int_type(*current);
   6322            std::advance(current, 1);
   6323            return result;
   6324        }
   6325 
   6326        return char_traits<char_type>::eof();
   6327    }
   6328 
   6329  private:
   6330    IteratorType current;
   6331    IteratorType end;
   6332 
   6333    template<typename BaseInputAdapter, size_t T>
   6334    friend struct wide_string_input_helper;
   6335 
   6336    bool empty() const
   6337    {
   6338        return current == end;
   6339    }
   6340 };
   6341 
   6342 template<typename BaseInputAdapter, size_t T>
   6343 struct wide_string_input_helper;
   6344 
   6345 template<typename BaseInputAdapter>
   6346 struct wide_string_input_helper<BaseInputAdapter, 4>
   6347 {
   6348    // UTF-32
   6349    static void fill_buffer(BaseInputAdapter& input,
   6350                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
   6351                            size_t& utf8_bytes_index,
   6352                            size_t& utf8_bytes_filled)
   6353    {
   6354        utf8_bytes_index = 0;
   6355 
   6356        if (JSON_HEDLEY_UNLIKELY(input.empty()))
   6357        {
   6358            utf8_bytes[0] = std::char_traits<char>::eof();
   6359            utf8_bytes_filled = 1;
   6360        }
   6361        else
   6362        {
   6363            // get the current character
   6364            const auto wc = input.get_character();
   6365 
   6366            // UTF-32 to UTF-8 encoding
   6367            if (wc < 0x80)
   6368            {
   6369                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6370                utf8_bytes_filled = 1;
   6371            }
   6372            else if (wc <= 0x7FF)
   6373            {
   6374                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
   6375                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6376                utf8_bytes_filled = 2;
   6377            }
   6378            else if (wc <= 0xFFFF)
   6379            {
   6380                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
   6381                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
   6382                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6383                utf8_bytes_filled = 3;
   6384            }
   6385            else if (wc <= 0x10FFFF)
   6386            {
   6387                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
   6388                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
   6389                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
   6390                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6391                utf8_bytes_filled = 4;
   6392            }
   6393            else
   6394            {
   6395                // unknown character
   6396                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6397                utf8_bytes_filled = 1;
   6398            }
   6399        }
   6400    }
   6401 };
   6402 
   6403 template<typename BaseInputAdapter>
   6404 struct wide_string_input_helper<BaseInputAdapter, 2>
   6405 {
   6406    // UTF-16
   6407    static void fill_buffer(BaseInputAdapter& input,
   6408                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
   6409                            size_t& utf8_bytes_index,
   6410                            size_t& utf8_bytes_filled)
   6411    {
   6412        utf8_bytes_index = 0;
   6413 
   6414        if (JSON_HEDLEY_UNLIKELY(input.empty()))
   6415        {
   6416            utf8_bytes[0] = std::char_traits<char>::eof();
   6417            utf8_bytes_filled = 1;
   6418        }
   6419        else
   6420        {
   6421            // get the current character
   6422            const auto wc = input.get_character();
   6423 
   6424            // UTF-16 to UTF-8 encoding
   6425            if (wc < 0x80)
   6426            {
   6427                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6428                utf8_bytes_filled = 1;
   6429            }
   6430            else if (wc <= 0x7FF)
   6431            {
   6432                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
   6433                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6434                utf8_bytes_filled = 2;
   6435            }
   6436            else if (0xD800 > wc || wc >= 0xE000)
   6437            {
   6438                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
   6439                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
   6440                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
   6441                utf8_bytes_filled = 3;
   6442            }
   6443            else
   6444            {
   6445                if (JSON_HEDLEY_UNLIKELY(!input.empty()))
   6446                {
   6447                    const auto wc2 = static_cast<unsigned int>(input.get_character());
   6448                    const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
   6449                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
   6450                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
   6451                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
   6452                    utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
   6453                    utf8_bytes_filled = 4;
   6454                }
   6455                else
   6456                {
   6457                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
   6458                    utf8_bytes_filled = 1;
   6459                }
   6460            }
   6461        }
   6462    }
   6463 };
   6464 
   6465 // Wraps another input adapter to convert wide character types into individual bytes.
   6466 template<typename BaseInputAdapter, typename WideCharType>
   6467 class wide_string_input_adapter
   6468 {
   6469  public:
   6470    using char_type = char;
   6471 
   6472    wide_string_input_adapter(BaseInputAdapter base)
   6473        : base_adapter(base) {}
   6474 
   6475    typename std::char_traits<char>::int_type get_character() noexcept
   6476    {
   6477        // check if buffer needs to be filled
   6478        if (utf8_bytes_index == utf8_bytes_filled)
   6479        {
   6480            fill_buffer<sizeof(WideCharType)>();
   6481 
   6482            JSON_ASSERT(utf8_bytes_filled > 0);
   6483            JSON_ASSERT(utf8_bytes_index == 0);
   6484        }
   6485 
   6486        // use buffer
   6487        JSON_ASSERT(utf8_bytes_filled > 0);
   6488        JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
   6489        return utf8_bytes[utf8_bytes_index++];
   6490    }
   6491 
   6492  private:
   6493    BaseInputAdapter base_adapter;
   6494 
   6495    template<size_t T>
   6496    void fill_buffer()
   6497    {
   6498        wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
   6499    }
   6500 
   6501    /// a buffer for UTF-8 bytes
   6502    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
   6503 
   6504    /// index to the utf8_codes array for the next valid byte
   6505    std::size_t utf8_bytes_index = 0;
   6506    /// number of valid bytes in the utf8_codes array
   6507    std::size_t utf8_bytes_filled = 0;
   6508 };
   6509 
   6510 template<typename IteratorType, typename Enable = void>
   6511 struct iterator_input_adapter_factory
   6512 {
   6513    using iterator_type = IteratorType;
   6514    using char_type = typename std::iterator_traits<iterator_type>::value_type;
   6515    using adapter_type = iterator_input_adapter<iterator_type>;
   6516 
   6517    static adapter_type create(IteratorType first, IteratorType last)
   6518    {
   6519        return adapter_type(std::move(first), std::move(last));
   6520    }
   6521 };
   6522 
   6523 template<typename T>
   6524 struct is_iterator_of_multibyte
   6525 {
   6526    using value_type = typename std::iterator_traits<T>::value_type;
   6527    enum
   6528    {
   6529        value = sizeof(value_type) > 1
   6530    };
   6531 };
   6532 
   6533 template<typename IteratorType>
   6534 struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
   6535 {
   6536    using iterator_type = IteratorType;
   6537    using char_type = typename std::iterator_traits<iterator_type>::value_type;
   6538    using base_adapter_type = iterator_input_adapter<iterator_type>;
   6539    using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
   6540 
   6541    static adapter_type create(IteratorType first, IteratorType last)
   6542    {
   6543        return adapter_type(base_adapter_type(std::move(first), std::move(last)));
   6544    }
   6545 };
   6546 
   6547 // General purpose iterator-based input
   6548 template<typename IteratorType>
   6549 typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
   6550 {
   6551    using factory_type = iterator_input_adapter_factory<IteratorType>;
   6552    return factory_type::create(first, last);
   6553 }
   6554 
   6555 // Convenience shorthand from container to iterator
   6556 // Enables ADL on begin(container) and end(container)
   6557 // Encloses the using declarations in namespace for not to leak them to outside scope
   6558 
   6559 namespace container_input_adapter_factory_impl
   6560 {
   6561 
   6562 using std::begin;
   6563 using std::end;
   6564 
   6565 template<typename ContainerType, typename Enable = void>
   6566 struct container_input_adapter_factory {};
   6567 
   6568 template<typename ContainerType>
   6569 struct container_input_adapter_factory< ContainerType,
   6570       void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
   6571       {
   6572           using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
   6573 
   6574           static adapter_type create(const ContainerType& container)
   6575 {
   6576    return input_adapter(begin(container), end(container));
   6577 }
   6578       };
   6579 
   6580 }  // namespace container_input_adapter_factory_impl
   6581 
   6582 template<typename ContainerType>
   6583 typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
   6584 {
   6585    return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
   6586 }
   6587 
   6588 #ifndef JSON_NO_IO
   6589 // Special cases with fast paths
   6590 inline file_input_adapter input_adapter(std::FILE* file)
   6591 {
   6592    return file_input_adapter(file);
   6593 }
   6594 
   6595 inline input_stream_adapter input_adapter(std::istream& stream)
   6596 {
   6597    return input_stream_adapter(stream);
   6598 }
   6599 
   6600 inline input_stream_adapter input_adapter(std::istream&& stream)
   6601 {
   6602    return input_stream_adapter(stream);
   6603 }
   6604 #endif  // JSON_NO_IO
   6605 
   6606 using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
   6607 
   6608 // Null-delimited strings, and the like.
   6609 template < typename CharT,
   6610           typename std::enable_if <
   6611               std::is_pointer<CharT>::value&&
   6612               !std::is_array<CharT>::value&&
   6613               std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
   6614               sizeof(typename std::remove_pointer<CharT>::type) == 1,
   6615               int >::type = 0 >
   6616 contiguous_bytes_input_adapter input_adapter(CharT b)
   6617 {
   6618    auto length = std::strlen(reinterpret_cast<const char*>(b));
   6619    const auto* ptr = reinterpret_cast<const char*>(b);
   6620    return input_adapter(ptr, ptr + length);
   6621 }
   6622 
   6623 template<typename T, std::size_t N>
   6624 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)
   6625 {
   6626    return input_adapter(array, array + N);
   6627 }
   6628 
   6629 // This class only handles inputs of input_buffer_adapter type.
   6630 // It's required so that expressions like {ptr, len} can be implicitly cast
   6631 // to the correct adapter.
   6632 class span_input_adapter
   6633 {
   6634  public:
   6635    template < typename CharT,
   6636               typename std::enable_if <
   6637                   std::is_pointer<CharT>::value&&
   6638                   std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
   6639                   sizeof(typename std::remove_pointer<CharT>::type) == 1,
   6640                   int >::type = 0 >
   6641    span_input_adapter(CharT b, std::size_t l)
   6642        : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
   6643 
   6644    template<class IteratorType,
   6645             typename std::enable_if<
   6646                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
   6647                 int>::type = 0>
   6648    span_input_adapter(IteratorType first, IteratorType last)
   6649        : ia(input_adapter(first, last)) {}
   6650 
   6651    contiguous_bytes_input_adapter&& get()
   6652    {
   6653        return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
   6654    }
   6655 
   6656  private:
   6657    contiguous_bytes_input_adapter ia;
   6658 };
   6659 
   6660 }  // namespace detail
   6661 NLOHMANN_JSON_NAMESPACE_END
   6662 
   6663 // #include <nlohmann/detail/input/json_sax.hpp>
   6664 //     __ _____ _____ _____
   6665 //  __|  |   __|     |   | |  JSON for Modern C++
   6666 // |  |  |__   |  |  | | | |  version 3.11.3
   6667 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   6668 //
   6669 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   6670 // SPDX-License-Identifier: MIT
   6671 
   6672 
   6673 
   6674 #include <cstddef>
   6675 #include <string> // string
   6676 #include <utility> // move
   6677 #include <vector> // vector
   6678 
   6679 // #include <nlohmann/detail/exceptions.hpp>
   6680 
   6681 // #include <nlohmann/detail/macro_scope.hpp>
   6682 
   6683 // #include <nlohmann/detail/string_concat.hpp>
   6684 
   6685 
   6686 NLOHMANN_JSON_NAMESPACE_BEGIN
   6687 
   6688 /*!
   6689 @brief SAX interface
   6690 
   6691 This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
   6692 Each function is called in different situations while the input is parsed. The
   6693 boolean return value informs the parser whether to continue processing the
   6694 input.
   6695 */
   6696 template<typename BasicJsonType>
   6697 struct json_sax
   6698 {
   6699    using number_integer_t = typename BasicJsonType::number_integer_t;
   6700    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   6701    using number_float_t = typename BasicJsonType::number_float_t;
   6702    using string_t = typename BasicJsonType::string_t;
   6703    using binary_t = typename BasicJsonType::binary_t;
   6704 
   6705    /*!
   6706    @brief a null value was read
   6707    @return whether parsing should proceed
   6708    */
   6709    virtual bool null() = 0;
   6710 
   6711    /*!
   6712    @brief a boolean value was read
   6713    @param[in] val  boolean value
   6714    @return whether parsing should proceed
   6715    */
   6716    virtual bool boolean(bool val) = 0;
   6717 
   6718    /*!
   6719    @brief an integer number was read
   6720    @param[in] val  integer value
   6721    @return whether parsing should proceed
   6722    */
   6723    virtual bool number_integer(number_integer_t val) = 0;
   6724 
   6725    /*!
   6726    @brief an unsigned integer number was read
   6727    @param[in] val  unsigned integer value
   6728    @return whether parsing should proceed
   6729    */
   6730    virtual bool number_unsigned(number_unsigned_t val) = 0;
   6731 
   6732    /*!
   6733    @brief a floating-point number was read
   6734    @param[in] val  floating-point value
   6735    @param[in] s    raw token value
   6736    @return whether parsing should proceed
   6737    */
   6738    virtual bool number_float(number_float_t val, const string_t& s) = 0;
   6739 
   6740    /*!
   6741    @brief a string value was read
   6742    @param[in] val  string value
   6743    @return whether parsing should proceed
   6744    @note It is safe to move the passed string value.
   6745    */
   6746    virtual bool string(string_t& val) = 0;
   6747 
   6748    /*!
   6749    @brief a binary value was read
   6750    @param[in] val  binary value
   6751    @return whether parsing should proceed
   6752    @note It is safe to move the passed binary value.
   6753    */
   6754    virtual bool binary(binary_t& val) = 0;
   6755 
   6756    /*!
   6757    @brief the beginning of an object was read
   6758    @param[in] elements  number of object elements or -1 if unknown
   6759    @return whether parsing should proceed
   6760    @note binary formats may report the number of elements
   6761    */
   6762    virtual bool start_object(std::size_t elements) = 0;
   6763 
   6764    /*!
   6765    @brief an object key was read
   6766    @param[in] val  object key
   6767    @return whether parsing should proceed
   6768    @note It is safe to move the passed string.
   6769    */
   6770    virtual bool key(string_t& val) = 0;
   6771 
   6772    /*!
   6773    @brief the end of an object was read
   6774    @return whether parsing should proceed
   6775    */
   6776    virtual bool end_object() = 0;
   6777 
   6778    /*!
   6779    @brief the beginning of an array was read
   6780    @param[in] elements  number of array elements or -1 if unknown
   6781    @return whether parsing should proceed
   6782    @note binary formats may report the number of elements
   6783    */
   6784    virtual bool start_array(std::size_t elements) = 0;
   6785 
   6786    /*!
   6787    @brief the end of an array was read
   6788    @return whether parsing should proceed
   6789    */
   6790    virtual bool end_array() = 0;
   6791 
   6792    /*!
   6793    @brief a parse error occurred
   6794    @param[in] position    the position in the input where the error occurs
   6795    @param[in] last_token  the last read token
   6796    @param[in] ex          an exception object describing the error
   6797    @return whether parsing should proceed (must return false)
   6798    */
   6799    virtual bool parse_error(std::size_t position,
   6800                             const std::string& last_token,
   6801                             const detail::exception& ex) = 0;
   6802 
   6803    json_sax() = default;
   6804    json_sax(const json_sax&) = default;
   6805    json_sax(json_sax&&) noexcept = default;
   6806    json_sax& operator=(const json_sax&) = default;
   6807    json_sax& operator=(json_sax&&) noexcept = default;
   6808    virtual ~json_sax() = default;
   6809 };
   6810 
   6811 namespace detail
   6812 {
   6813 /*!
   6814 @brief SAX implementation to create a JSON value from SAX events
   6815 
   6816 This class implements the @ref json_sax interface and processes the SAX events
   6817 to create a JSON value which makes it basically a DOM parser. The structure or
   6818 hierarchy of the JSON value is managed by the stack `ref_stack` which contains
   6819 a pointer to the respective array or object for each recursion depth.
   6820 
   6821 After successful parsing, the value that is passed by reference to the
   6822 constructor contains the parsed value.
   6823 
   6824 @tparam BasicJsonType  the JSON type
   6825 */
   6826 template<typename BasicJsonType>
   6827 class json_sax_dom_parser
   6828 {
   6829  public:
   6830    using number_integer_t = typename BasicJsonType::number_integer_t;
   6831    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   6832    using number_float_t = typename BasicJsonType::number_float_t;
   6833    using string_t = typename BasicJsonType::string_t;
   6834    using binary_t = typename BasicJsonType::binary_t;
   6835 
   6836    /*!
   6837    @param[in,out] r  reference to a JSON value that is manipulated while
   6838                       parsing
   6839    @param[in] allow_exceptions_  whether parse errors yield exceptions
   6840    */
   6841    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true)
   6842        : root(r), allow_exceptions(allow_exceptions_)
   6843    {}
   6844 
   6845    // make class move-only
   6846    json_sax_dom_parser(const json_sax_dom_parser&) = delete;
   6847    json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   6848    json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
   6849    json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   6850    ~json_sax_dom_parser() = default;
   6851 
   6852    bool null()
   6853    {
   6854        handle_value(nullptr);
   6855        return true;
   6856    }
   6857 
   6858    bool boolean(bool val)
   6859    {
   6860        handle_value(val);
   6861        return true;
   6862    }
   6863 
   6864    bool number_integer(number_integer_t val)
   6865    {
   6866        handle_value(val);
   6867        return true;
   6868    }
   6869 
   6870    bool number_unsigned(number_unsigned_t val)
   6871    {
   6872        handle_value(val);
   6873        return true;
   6874    }
   6875 
   6876    bool number_float(number_float_t val, const string_t& /*unused*/)
   6877    {
   6878        handle_value(val);
   6879        return true;
   6880    }
   6881 
   6882    bool string(string_t& val)
   6883    {
   6884        handle_value(val);
   6885        return true;
   6886    }
   6887 
   6888    bool binary(binary_t& val)
   6889    {
   6890        handle_value(std::move(val));
   6891        return true;
   6892    }
   6893 
   6894    bool start_object(std::size_t len)
   6895    {
   6896        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
   6897 
   6898        if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   6899        {
   6900            JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
   6901        }
   6902 
   6903        return true;
   6904    }
   6905 
   6906    bool key(string_t& val)
   6907    {
   6908        JSON_ASSERT(!ref_stack.empty());
   6909        JSON_ASSERT(ref_stack.back()->is_object());
   6910 
   6911        // add null at given key and store the reference for later
   6912        object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
   6913        return true;
   6914    }
   6915 
   6916    bool end_object()
   6917    {
   6918        JSON_ASSERT(!ref_stack.empty());
   6919        JSON_ASSERT(ref_stack.back()->is_object());
   6920 
   6921        ref_stack.back()->set_parents();
   6922        ref_stack.pop_back();
   6923        return true;
   6924    }
   6925 
   6926    bool start_array(std::size_t len)
   6927    {
   6928        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
   6929 
   6930        if (JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   6931        {
   6932            JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
   6933        }
   6934 
   6935        return true;
   6936    }
   6937 
   6938    bool end_array()
   6939    {
   6940        JSON_ASSERT(!ref_stack.empty());
   6941        JSON_ASSERT(ref_stack.back()->is_array());
   6942 
   6943        ref_stack.back()->set_parents();
   6944        ref_stack.pop_back();
   6945        return true;
   6946    }
   6947 
   6948    template<class Exception>
   6949    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
   6950                     const Exception& ex)
   6951    {
   6952        errored = true;
   6953        static_cast<void>(ex);
   6954        if (allow_exceptions)
   6955        {
   6956            JSON_THROW(ex);
   6957        }
   6958        return false;
   6959    }
   6960 
   6961    constexpr bool is_errored() const
   6962    {
   6963        return errored;
   6964    }
   6965 
   6966  private:
   6967    /*!
   6968    @invariant If the ref stack is empty, then the passed value will be the new
   6969               root.
   6970    @invariant If the ref stack contains a value, then it is an array or an
   6971               object to which we can add elements
   6972    */
   6973    template<typename Value>
   6974    JSON_HEDLEY_RETURNS_NON_NULL
   6975    BasicJsonType* handle_value(Value&& v)
   6976    {
   6977        if (ref_stack.empty())
   6978        {
   6979            root = BasicJsonType(std::forward<Value>(v));
   6980            return &root;
   6981        }
   6982 
   6983        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
   6984 
   6985        if (ref_stack.back()->is_array())
   6986        {
   6987            ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
   6988            return &(ref_stack.back()->m_data.m_value.array->back());
   6989        }
   6990 
   6991        JSON_ASSERT(ref_stack.back()->is_object());
   6992        JSON_ASSERT(object_element);
   6993        *object_element = BasicJsonType(std::forward<Value>(v));
   6994        return object_element;
   6995    }
   6996 
   6997    /// the parsed JSON value
   6998    BasicJsonType& root;
   6999    /// stack to model hierarchy of values
   7000    std::vector<BasicJsonType*> ref_stack {};
   7001    /// helper to hold the reference for the next object element
   7002    BasicJsonType* object_element = nullptr;
   7003    /// whether a syntax error occurred
   7004    bool errored = false;
   7005    /// whether to throw exceptions in case of errors
   7006    const bool allow_exceptions = true;
   7007 };
   7008 
   7009 template<typename BasicJsonType>
   7010 class json_sax_dom_callback_parser
   7011 {
   7012  public:
   7013    using number_integer_t = typename BasicJsonType::number_integer_t;
   7014    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   7015    using number_float_t = typename BasicJsonType::number_float_t;
   7016    using string_t = typename BasicJsonType::string_t;
   7017    using binary_t = typename BasicJsonType::binary_t;
   7018    using parser_callback_t = typename BasicJsonType::parser_callback_t;
   7019    using parse_event_t = typename BasicJsonType::parse_event_t;
   7020 
   7021    json_sax_dom_callback_parser(BasicJsonType& r,
   7022                                 const parser_callback_t cb,
   7023                                 const bool allow_exceptions_ = true)
   7024        : root(r), callback(cb), allow_exceptions(allow_exceptions_)
   7025    {
   7026        keep_stack.push_back(true);
   7027    }
   7028 
   7029    // make class move-only
   7030    json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
   7031    json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   7032    json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
   7033    json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   7034    ~json_sax_dom_callback_parser() = default;
   7035 
   7036    bool null()
   7037    {
   7038        handle_value(nullptr);
   7039        return true;
   7040    }
   7041 
   7042    bool boolean(bool val)
   7043    {
   7044        handle_value(val);
   7045        return true;
   7046    }
   7047 
   7048    bool number_integer(number_integer_t val)
   7049    {
   7050        handle_value(val);
   7051        return true;
   7052    }
   7053 
   7054    bool number_unsigned(number_unsigned_t val)
   7055    {
   7056        handle_value(val);
   7057        return true;
   7058    }
   7059 
   7060    bool number_float(number_float_t val, const string_t& /*unused*/)
   7061    {
   7062        handle_value(val);
   7063        return true;
   7064    }
   7065 
   7066    bool string(string_t& val)
   7067    {
   7068        handle_value(val);
   7069        return true;
   7070    }
   7071 
   7072    bool binary(binary_t& val)
   7073    {
   7074        handle_value(std::move(val));
   7075        return true;
   7076    }
   7077 
   7078    bool start_object(std::size_t len)
   7079    {
   7080        // check callback for object start
   7081        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
   7082        keep_stack.push_back(keep);
   7083 
   7084        auto val = handle_value(BasicJsonType::value_t::object, true);
   7085        ref_stack.push_back(val.second);
   7086 
   7087        // check object limit
   7088        if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   7089        {
   7090            JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
   7091        }
   7092 
   7093        return true;
   7094    }
   7095 
   7096    bool key(string_t& val)
   7097    {
   7098        BasicJsonType k = BasicJsonType(val);
   7099 
   7100        // check callback for key
   7101        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
   7102        key_keep_stack.push_back(keep);
   7103 
   7104        // add discarded value at given key and store the reference for later
   7105        if (keep && ref_stack.back())
   7106        {
   7107            object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
   7108        }
   7109 
   7110        return true;
   7111    }
   7112 
   7113    bool end_object()
   7114    {
   7115        if (ref_stack.back())
   7116        {
   7117            if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
   7118            {
   7119                // discard object
   7120                *ref_stack.back() = discarded;
   7121            }
   7122            else
   7123            {
   7124                ref_stack.back()->set_parents();
   7125            }
   7126        }
   7127 
   7128        JSON_ASSERT(!ref_stack.empty());
   7129        JSON_ASSERT(!keep_stack.empty());
   7130        ref_stack.pop_back();
   7131        keep_stack.pop_back();
   7132 
   7133        if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
   7134        {
   7135            // remove discarded value
   7136            for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
   7137            {
   7138                if (it->is_discarded())
   7139                {
   7140                    ref_stack.back()->erase(it);
   7141                    break;
   7142                }
   7143            }
   7144        }
   7145 
   7146        return true;
   7147    }
   7148 
   7149    bool start_array(std::size_t len)
   7150    {
   7151        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
   7152        keep_stack.push_back(keep);
   7153 
   7154        auto val = handle_value(BasicJsonType::value_t::array, true);
   7155        ref_stack.push_back(val.second);
   7156 
   7157        // check array limit
   7158        if (ref_stack.back() && JSON_HEDLEY_UNLIKELY(len != static_cast<std::size_t>(-1) && len > ref_stack.back()->max_size()))
   7159        {
   7160            JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
   7161        }
   7162 
   7163        return true;
   7164    }
   7165 
   7166    bool end_array()
   7167    {
   7168        bool keep = true;
   7169 
   7170        if (ref_stack.back())
   7171        {
   7172            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
   7173            if (keep)
   7174            {
   7175                ref_stack.back()->set_parents();
   7176            }
   7177            else
   7178            {
   7179                // discard array
   7180                *ref_stack.back() = discarded;
   7181            }
   7182        }
   7183 
   7184        JSON_ASSERT(!ref_stack.empty());
   7185        JSON_ASSERT(!keep_stack.empty());
   7186        ref_stack.pop_back();
   7187        keep_stack.pop_back();
   7188 
   7189        // remove discarded value
   7190        if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
   7191        {
   7192            ref_stack.back()->m_data.m_value.array->pop_back();
   7193        }
   7194 
   7195        return true;
   7196    }
   7197 
   7198    template<class Exception>
   7199    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
   7200                     const Exception& ex)
   7201    {
   7202        errored = true;
   7203        static_cast<void>(ex);
   7204        if (allow_exceptions)
   7205        {
   7206            JSON_THROW(ex);
   7207        }
   7208        return false;
   7209    }
   7210 
   7211    constexpr bool is_errored() const
   7212    {
   7213        return errored;
   7214    }
   7215 
   7216  private:
   7217    /*!
   7218    @param[in] v  value to add to the JSON value we build during parsing
   7219    @param[in] skip_callback  whether we should skip calling the callback
   7220               function; this is required after start_array() and
   7221               start_object() SAX events, because otherwise we would call the
   7222               callback function with an empty array or object, respectively.
   7223 
   7224    @invariant If the ref stack is empty, then the passed value will be the new
   7225               root.
   7226    @invariant If the ref stack contains a value, then it is an array or an
   7227               object to which we can add elements
   7228 
   7229    @return pair of boolean (whether value should be kept) and pointer (to the
   7230            passed value in the ref_stack hierarchy; nullptr if not kept)
   7231    */
   7232    template<typename Value>
   7233    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
   7234    {
   7235        JSON_ASSERT(!keep_stack.empty());
   7236 
   7237        // do not handle this value if we know it would be added to a discarded
   7238        // container
   7239        if (!keep_stack.back())
   7240        {
   7241            return {false, nullptr};
   7242        }
   7243 
   7244        // create value
   7245        auto value = BasicJsonType(std::forward<Value>(v));
   7246 
   7247        // check callback
   7248        const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
   7249 
   7250        // do not handle this value if we just learnt it shall be discarded
   7251        if (!keep)
   7252        {
   7253            return {false, nullptr};
   7254        }
   7255 
   7256        if (ref_stack.empty())
   7257        {
   7258            root = std::move(value);
   7259            return {true, & root};
   7260        }
   7261 
   7262        // skip this value if we already decided to skip the parent
   7263        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
   7264        if (!ref_stack.back())
   7265        {
   7266            return {false, nullptr};
   7267        }
   7268 
   7269        // we now only expect arrays and objects
   7270        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
   7271 
   7272        // array
   7273        if (ref_stack.back()->is_array())
   7274        {
   7275            ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
   7276            return {true, & (ref_stack.back()->m_data.m_value.array->back())};
   7277        }
   7278 
   7279        // object
   7280        JSON_ASSERT(ref_stack.back()->is_object());
   7281        // check if we should store an element for the current key
   7282        JSON_ASSERT(!key_keep_stack.empty());
   7283        const bool store_element = key_keep_stack.back();
   7284        key_keep_stack.pop_back();
   7285 
   7286        if (!store_element)
   7287        {
   7288            return {false, nullptr};
   7289        }
   7290 
   7291        JSON_ASSERT(object_element);
   7292        *object_element = std::move(value);
   7293        return {true, object_element};
   7294    }
   7295 
   7296    /// the parsed JSON value
   7297    BasicJsonType& root;
   7298    /// stack to model hierarchy of values
   7299    std::vector<BasicJsonType*> ref_stack {};
   7300    /// stack to manage which values to keep
   7301    std::vector<bool> keep_stack {};
   7302    /// stack to manage which object keys to keep
   7303    std::vector<bool> key_keep_stack {};
   7304    /// helper to hold the reference for the next object element
   7305    BasicJsonType* object_element = nullptr;
   7306    /// whether a syntax error occurred
   7307    bool errored = false;
   7308    /// callback function
   7309    const parser_callback_t callback = nullptr;
   7310    /// whether to throw exceptions in case of errors
   7311    const bool allow_exceptions = true;
   7312    /// a discarded value for the callback
   7313    BasicJsonType discarded = BasicJsonType::value_t::discarded;
   7314 };
   7315 
   7316 template<typename BasicJsonType>
   7317 class json_sax_acceptor
   7318 {
   7319  public:
   7320    using number_integer_t = typename BasicJsonType::number_integer_t;
   7321    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   7322    using number_float_t = typename BasicJsonType::number_float_t;
   7323    using string_t = typename BasicJsonType::string_t;
   7324    using binary_t = typename BasicJsonType::binary_t;
   7325 
   7326    bool null()
   7327    {
   7328        return true;
   7329    }
   7330 
   7331    bool boolean(bool /*unused*/)
   7332    {
   7333        return true;
   7334    }
   7335 
   7336    bool number_integer(number_integer_t /*unused*/)
   7337    {
   7338        return true;
   7339    }
   7340 
   7341    bool number_unsigned(number_unsigned_t /*unused*/)
   7342    {
   7343        return true;
   7344    }
   7345 
   7346    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
   7347    {
   7348        return true;
   7349    }
   7350 
   7351    bool string(string_t& /*unused*/)
   7352    {
   7353        return true;
   7354    }
   7355 
   7356    bool binary(binary_t& /*unused*/)
   7357    {
   7358        return true;
   7359    }
   7360 
   7361    bool start_object(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
   7362    {
   7363        return true;
   7364    }
   7365 
   7366    bool key(string_t& /*unused*/)
   7367    {
   7368        return true;
   7369    }
   7370 
   7371    bool end_object()
   7372    {
   7373        return true;
   7374    }
   7375 
   7376    bool start_array(std::size_t /*unused*/ = static_cast<std::size_t>(-1))
   7377    {
   7378        return true;
   7379    }
   7380 
   7381    bool end_array()
   7382    {
   7383        return true;
   7384    }
   7385 
   7386    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
   7387    {
   7388        return false;
   7389    }
   7390 };
   7391 
   7392 }  // namespace detail
   7393 NLOHMANN_JSON_NAMESPACE_END
   7394 
   7395 // #include <nlohmann/detail/input/lexer.hpp>
   7396 //     __ _____ _____ _____
   7397 //  __|  |   __|     |   | |  JSON for Modern C++
   7398 // |  |  |__   |  |  | | | |  version 3.11.3
   7399 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   7400 //
   7401 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   7402 // SPDX-License-Identifier: MIT
   7403 
   7404 
   7405 
   7406 #include <array> // array
   7407 #include <clocale> // localeconv
   7408 #include <cstddef> // size_t
   7409 #include <cstdio> // snprintf
   7410 #include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
   7411 #include <initializer_list> // initializer_list
   7412 #include <string> // char_traits, string
   7413 #include <utility> // move
   7414 #include <vector> // vector
   7415 
   7416 // #include <nlohmann/detail/input/input_adapters.hpp>
   7417 
   7418 // #include <nlohmann/detail/input/position_t.hpp>
   7419 
   7420 // #include <nlohmann/detail/macro_scope.hpp>
   7421 
   7422 // #include <nlohmann/detail/meta/type_traits.hpp>
   7423 
   7424 
   7425 NLOHMANN_JSON_NAMESPACE_BEGIN
   7426 namespace detail
   7427 {
   7428 
   7429 ///////////
   7430 // lexer //
   7431 ///////////
   7432 
   7433 template<typename BasicJsonType>
   7434 class lexer_base
   7435 {
   7436  public:
   7437    /// token types for the parser
   7438    enum class token_type
   7439    {
   7440        uninitialized,    ///< indicating the scanner is uninitialized
   7441        literal_true,     ///< the `true` literal
   7442        literal_false,    ///< the `false` literal
   7443        literal_null,     ///< the `null` literal
   7444        value_string,     ///< a string -- use get_string() for actual value
   7445        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
   7446        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
   7447        value_float,      ///< an floating point number -- use get_number_float() for actual value
   7448        begin_array,      ///< the character for array begin `[`
   7449        begin_object,     ///< the character for object begin `{`
   7450        end_array,        ///< the character for array end `]`
   7451        end_object,       ///< the character for object end `}`
   7452        name_separator,   ///< the name separator `:`
   7453        value_separator,  ///< the value separator `,`
   7454        parse_error,      ///< indicating a parse error
   7455        end_of_input,     ///< indicating the end of the input buffer
   7456        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
   7457    };
   7458 
   7459    /// return name of values of type token_type (only used for errors)
   7460    JSON_HEDLEY_RETURNS_NON_NULL
   7461    JSON_HEDLEY_CONST
   7462    static const char* token_type_name(const token_type t) noexcept
   7463    {
   7464        switch (t)
   7465        {
   7466            case token_type::uninitialized:
   7467                return "<uninitialized>";
   7468            case token_type::literal_true:
   7469                return "true literal";
   7470            case token_type::literal_false:
   7471                return "false literal";
   7472            case token_type::literal_null:
   7473                return "null literal";
   7474            case token_type::value_string:
   7475                return "string literal";
   7476            case token_type::value_unsigned:
   7477            case token_type::value_integer:
   7478            case token_type::value_float:
   7479                return "number literal";
   7480            case token_type::begin_array:
   7481                return "'['";
   7482            case token_type::begin_object:
   7483                return "'{'";
   7484            case token_type::end_array:
   7485                return "']'";
   7486            case token_type::end_object:
   7487                return "'}'";
   7488            case token_type::name_separator:
   7489                return "':'";
   7490            case token_type::value_separator:
   7491                return "','";
   7492            case token_type::parse_error:
   7493                return "<parse error>";
   7494            case token_type::end_of_input:
   7495                return "end of input";
   7496            case token_type::literal_or_value:
   7497                return "'[', '{', or a literal";
   7498            // LCOV_EXCL_START
   7499            default: // catch non-enum values
   7500                return "unknown token";
   7501                // LCOV_EXCL_STOP
   7502        }
   7503    }
   7504 };
   7505 /*!
   7506 @brief lexical analysis
   7507 
   7508 This class organizes the lexical analysis during JSON deserialization.
   7509 */
   7510 template<typename BasicJsonType, typename InputAdapterType>
   7511 class lexer : public lexer_base<BasicJsonType>
   7512 {
   7513    using number_integer_t = typename BasicJsonType::number_integer_t;
   7514    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   7515    using number_float_t = typename BasicJsonType::number_float_t;
   7516    using string_t = typename BasicJsonType::string_t;
   7517    using char_type = typename InputAdapterType::char_type;
   7518    using char_int_type = typename char_traits<char_type>::int_type;
   7519 
   7520  public:
   7521    using token_type = typename lexer_base<BasicJsonType>::token_type;
   7522 
   7523    explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
   7524        : ia(std::move(adapter))
   7525        , ignore_comments(ignore_comments_)
   7526        , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
   7527    {}
   7528 
   7529    // delete because of pointer members
   7530    lexer(const lexer&) = delete;
   7531    lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   7532    lexer& operator=(lexer&) = delete;
   7533    lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   7534    ~lexer() = default;
   7535 
   7536  private:
   7537    /////////////////////
   7538    // locales
   7539    /////////////////////
   7540 
   7541    /// return the locale-dependent decimal point
   7542    JSON_HEDLEY_PURE
   7543    static char get_decimal_point() noexcept
   7544    {
   7545        const auto* loc = localeconv();
   7546        JSON_ASSERT(loc != nullptr);
   7547        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
   7548    }
   7549 
   7550    /////////////////////
   7551    // scan functions
   7552    /////////////////////
   7553 
   7554    /*!
   7555    @brief get codepoint from 4 hex characters following `\u`
   7556 
   7557    For input "\u c1 c2 c3 c4" the codepoint is:
   7558      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
   7559    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
   7560 
   7561    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
   7562    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
   7563    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
   7564    between the ASCII value of the character and the desired integer value.
   7565 
   7566    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
   7567            non-hex character)
   7568    */
   7569    int get_codepoint()
   7570    {
   7571        // this function only makes sense after reading `\u`
   7572        JSON_ASSERT(current == 'u');
   7573        int codepoint = 0;
   7574 
   7575        const auto factors = { 12u, 8u, 4u, 0u };
   7576        for (const auto factor : factors)
   7577        {
   7578            get();
   7579 
   7580            if (current >= '0' && current <= '9')
   7581            {
   7582                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
   7583            }
   7584            else if (current >= 'A' && current <= 'F')
   7585            {
   7586                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
   7587            }
   7588            else if (current >= 'a' && current <= 'f')
   7589            {
   7590                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
   7591            }
   7592            else
   7593            {
   7594                return -1;
   7595            }
   7596        }
   7597 
   7598        JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
   7599        return codepoint;
   7600    }
   7601 
   7602    /*!
   7603    @brief check if the next byte(s) are inside a given range
   7604 
   7605    Adds the current byte and, for each passed range, reads a new byte and
   7606    checks if it is inside the range. If a violation was detected, set up an
   7607    error message and return false. Otherwise, return true.
   7608 
   7609    @param[in] ranges  list of integers; interpreted as list of pairs of
   7610                       inclusive lower and upper bound, respectively
   7611 
   7612    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
   7613         1, 2, or 3 pairs. This precondition is enforced by an assertion.
   7614 
   7615    @return true if and only if no range violation was detected
   7616    */
   7617    bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
   7618    {
   7619        JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
   7620        add(current);
   7621 
   7622        for (auto range = ranges.begin(); range != ranges.end(); ++range)
   7623        {
   7624            get();
   7625            if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
   7626            {
   7627                add(current);
   7628            }
   7629            else
   7630            {
   7631                error_message = "invalid string: ill-formed UTF-8 byte";
   7632                return false;
   7633            }
   7634        }
   7635 
   7636        return true;
   7637    }
   7638 
   7639    /*!
   7640    @brief scan a string literal
   7641 
   7642    This function scans a string according to Sect. 7 of RFC 8259. While
   7643    scanning, bytes are escaped and copied into buffer token_buffer. Then the
   7644    function returns successfully, token_buffer is *not* null-terminated (as it
   7645    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
   7646    string.
   7647 
   7648    @return token_type::value_string if string could be successfully scanned,
   7649            token_type::parse_error otherwise
   7650 
   7651    @note In case of errors, variable error_message contains a textual
   7652          description.
   7653    */
   7654    token_type scan_string()
   7655    {
   7656        // reset token_buffer (ignore opening quote)
   7657        reset();
   7658 
   7659        // we entered the function by reading an open quote
   7660        JSON_ASSERT(current == '\"');
   7661 
   7662        while (true)
   7663        {
   7664            // get next character
   7665            switch (get())
   7666            {
   7667                // end of file while parsing string
   7668                case char_traits<char_type>::eof():
   7669                {
   7670                    error_message = "invalid string: missing closing quote";
   7671                    return token_type::parse_error;
   7672                }
   7673 
   7674                // closing quote
   7675                case '\"':
   7676                {
   7677                    return token_type::value_string;
   7678                }
   7679 
   7680                // escapes
   7681                case '\\':
   7682                {
   7683                    switch (get())
   7684                    {
   7685                        // quotation mark
   7686                        case '\"':
   7687                            add('\"');
   7688                            break;
   7689                        // reverse solidus
   7690                        case '\\':
   7691                            add('\\');
   7692                            break;
   7693                        // solidus
   7694                        case '/':
   7695                            add('/');
   7696                            break;
   7697                        // backspace
   7698                        case 'b':
   7699                            add('\b');
   7700                            break;
   7701                        // form feed
   7702                        case 'f':
   7703                            add('\f');
   7704                            break;
   7705                        // line feed
   7706                        case 'n':
   7707                            add('\n');
   7708                            break;
   7709                        // carriage return
   7710                        case 'r':
   7711                            add('\r');
   7712                            break;
   7713                        // tab
   7714                        case 't':
   7715                            add('\t');
   7716                            break;
   7717 
   7718                        // unicode escapes
   7719                        case 'u':
   7720                        {
   7721                            const int codepoint1 = get_codepoint();
   7722                            int codepoint = codepoint1; // start with codepoint1
   7723 
   7724                            if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
   7725                            {
   7726                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
   7727                                return token_type::parse_error;
   7728                            }
   7729 
   7730                            // check if code point is a high surrogate
   7731                            if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
   7732                            {
   7733                                // expect next \uxxxx entry
   7734                                if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
   7735                                {
   7736                                    const int codepoint2 = get_codepoint();
   7737 
   7738                                    if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
   7739                                    {
   7740                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
   7741                                        return token_type::parse_error;
   7742                                    }
   7743 
   7744                                    // check if codepoint2 is a low surrogate
   7745                                    if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
   7746                                    {
   7747                                        // overwrite codepoint
   7748                                        codepoint = static_cast<int>(
   7749                                                        // high surrogate occupies the most significant 22 bits
   7750                                                        (static_cast<unsigned int>(codepoint1) << 10u)
   7751                                                        // low surrogate occupies the least significant 15 bits
   7752                                                        + static_cast<unsigned int>(codepoint2)
   7753                                                        // there is still the 0xD800, 0xDC00 and 0x10000 noise
   7754                                                        // in the result, so we have to subtract with:
   7755                                                        // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
   7756                                                        - 0x35FDC00u);
   7757                                    }
   7758                                    else
   7759                                    {
   7760                                        // ICU PATCH - See ICU-23090
   7761                                        codepoint = codepoint1;
   7762                                    }
   7763                                }
   7764                                else
   7765                                {
   7766                                    // ICU PATCH - See ICU-23090
   7767                                    codepoint = codepoint1;
   7768                                }
   7769                            }
   7770                            else
   7771                            {
   7772                                if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
   7773                                {
   7774                                    // ICU PATCH - See ICU-23090
   7775                                    codepoint = codepoint1;
   7776                                }
   7777                            }
   7778 
   7779                            // result of the above calculation yields a proper codepoint
   7780                            JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
   7781 
   7782                            // translate codepoint into bytes
   7783                            if (codepoint < 0x80)
   7784                            {
   7785                                // 1-byte characters: 0xxxxxxx (ASCII)
   7786                                add(static_cast<char_int_type>(codepoint));
   7787                            }
   7788                            else if (codepoint <= 0x7FF)
   7789                            {
   7790                                // 2-byte characters: 110xxxxx 10xxxxxx
   7791                                add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
   7792                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
   7793                            }
   7794                            else if (codepoint <= 0xFFFF)
   7795                            {
   7796                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
   7797                                add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
   7798                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
   7799                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
   7800                            }
   7801                            else
   7802                            {
   7803                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
   7804                                add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
   7805                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
   7806                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
   7807                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
   7808                            }
   7809 
   7810                            break;
   7811                        }
   7812 
   7813                        // other characters after escape
   7814                        default:
   7815                            error_message = "invalid string: forbidden character after backslash";
   7816                            return token_type::parse_error;
   7817                    }
   7818 
   7819                    break;
   7820                }
   7821 
   7822                // invalid control characters
   7823                case 0x00:
   7824                {
   7825                    error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
   7826                    return token_type::parse_error;
   7827                }
   7828 
   7829                case 0x01:
   7830                {
   7831                    error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
   7832                    return token_type::parse_error;
   7833                }
   7834 
   7835                case 0x02:
   7836                {
   7837                    error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
   7838                    return token_type::parse_error;
   7839                }
   7840 
   7841                case 0x03:
   7842                {
   7843                    error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
   7844                    return token_type::parse_error;
   7845                }
   7846 
   7847                case 0x04:
   7848                {
   7849                    error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
   7850                    return token_type::parse_error;
   7851                }
   7852 
   7853                case 0x05:
   7854                {
   7855                    error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
   7856                    return token_type::parse_error;
   7857                }
   7858 
   7859                case 0x06:
   7860                {
   7861                    error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
   7862                    return token_type::parse_error;
   7863                }
   7864 
   7865                case 0x07:
   7866                {
   7867                    error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
   7868                    return token_type::parse_error;
   7869                }
   7870 
   7871                case 0x08:
   7872                {
   7873                    error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
   7874                    return token_type::parse_error;
   7875                }
   7876 
   7877                case 0x09:
   7878                {
   7879                    error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
   7880                    return token_type::parse_error;
   7881                }
   7882 
   7883                case 0x0A:
   7884                {
   7885                    error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
   7886                    return token_type::parse_error;
   7887                }
   7888 
   7889                case 0x0B:
   7890                {
   7891                    error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
   7892                    return token_type::parse_error;
   7893                }
   7894 
   7895                case 0x0C:
   7896                {
   7897                    error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
   7898                    return token_type::parse_error;
   7899                }
   7900 
   7901                case 0x0D:
   7902                {
   7903                    error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
   7904                    return token_type::parse_error;
   7905                }
   7906 
   7907                case 0x0E:
   7908                {
   7909                    error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
   7910                    return token_type::parse_error;
   7911                }
   7912 
   7913                case 0x0F:
   7914                {
   7915                    error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
   7916                    return token_type::parse_error;
   7917                }
   7918 
   7919                case 0x10:
   7920                {
   7921                    error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
   7922                    return token_type::parse_error;
   7923                }
   7924 
   7925                case 0x11:
   7926                {
   7927                    error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
   7928                    return token_type::parse_error;
   7929                }
   7930 
   7931                case 0x12:
   7932                {
   7933                    error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
   7934                    return token_type::parse_error;
   7935                }
   7936 
   7937                case 0x13:
   7938                {
   7939                    error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
   7940                    return token_type::parse_error;
   7941                }
   7942 
   7943                case 0x14:
   7944                {
   7945                    error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
   7946                    return token_type::parse_error;
   7947                }
   7948 
   7949                case 0x15:
   7950                {
   7951                    error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
   7952                    return token_type::parse_error;
   7953                }
   7954 
   7955                case 0x16:
   7956                {
   7957                    error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
   7958                    return token_type::parse_error;
   7959                }
   7960 
   7961                case 0x17:
   7962                {
   7963                    error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
   7964                    return token_type::parse_error;
   7965                }
   7966 
   7967                case 0x18:
   7968                {
   7969                    error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
   7970                    return token_type::parse_error;
   7971                }
   7972 
   7973                case 0x19:
   7974                {
   7975                    error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
   7976                    return token_type::parse_error;
   7977                }
   7978 
   7979                case 0x1A:
   7980                {
   7981                    error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
   7982                    return token_type::parse_error;
   7983                }
   7984 
   7985                case 0x1B:
   7986                {
   7987                    error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
   7988                    return token_type::parse_error;
   7989                }
   7990 
   7991                case 0x1C:
   7992                {
   7993                    error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
   7994                    return token_type::parse_error;
   7995                }
   7996 
   7997                case 0x1D:
   7998                {
   7999                    error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
   8000                    return token_type::parse_error;
   8001                }
   8002 
   8003                case 0x1E:
   8004                {
   8005                    error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
   8006                    return token_type::parse_error;
   8007                }
   8008 
   8009                case 0x1F:
   8010                {
   8011                    error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
   8012                    return token_type::parse_error;
   8013                }
   8014 
   8015                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
   8016                case 0x20:
   8017                case 0x21:
   8018                case 0x23:
   8019                case 0x24:
   8020                case 0x25:
   8021                case 0x26:
   8022                case 0x27:
   8023                case 0x28:
   8024                case 0x29:
   8025                case 0x2A:
   8026                case 0x2B:
   8027                case 0x2C:
   8028                case 0x2D:
   8029                case 0x2E:
   8030                case 0x2F:
   8031                case 0x30:
   8032                case 0x31:
   8033                case 0x32:
   8034                case 0x33:
   8035                case 0x34:
   8036                case 0x35:
   8037                case 0x36:
   8038                case 0x37:
   8039                case 0x38:
   8040                case 0x39:
   8041                case 0x3A:
   8042                case 0x3B:
   8043                case 0x3C:
   8044                case 0x3D:
   8045                case 0x3E:
   8046                case 0x3F:
   8047                case 0x40:
   8048                case 0x41:
   8049                case 0x42:
   8050                case 0x43:
   8051                case 0x44:
   8052                case 0x45:
   8053                case 0x46:
   8054                case 0x47:
   8055                case 0x48:
   8056                case 0x49:
   8057                case 0x4A:
   8058                case 0x4B:
   8059                case 0x4C:
   8060                case 0x4D:
   8061                case 0x4E:
   8062                case 0x4F:
   8063                case 0x50:
   8064                case 0x51:
   8065                case 0x52:
   8066                case 0x53:
   8067                case 0x54:
   8068                case 0x55:
   8069                case 0x56:
   8070                case 0x57:
   8071                case 0x58:
   8072                case 0x59:
   8073                case 0x5A:
   8074                case 0x5B:
   8075                case 0x5D:
   8076                case 0x5E:
   8077                case 0x5F:
   8078                case 0x60:
   8079                case 0x61:
   8080                case 0x62:
   8081                case 0x63:
   8082                case 0x64:
   8083                case 0x65:
   8084                case 0x66:
   8085                case 0x67:
   8086                case 0x68:
   8087                case 0x69:
   8088                case 0x6A:
   8089                case 0x6B:
   8090                case 0x6C:
   8091                case 0x6D:
   8092                case 0x6E:
   8093                case 0x6F:
   8094                case 0x70:
   8095                case 0x71:
   8096                case 0x72:
   8097                case 0x73:
   8098                case 0x74:
   8099                case 0x75:
   8100                case 0x76:
   8101                case 0x77:
   8102                case 0x78:
   8103                case 0x79:
   8104                case 0x7A:
   8105                case 0x7B:
   8106                case 0x7C:
   8107                case 0x7D:
   8108                case 0x7E:
   8109                case 0x7F:
   8110                {
   8111                    add(current);
   8112                    break;
   8113                }
   8114 
   8115                // U+0080..U+07FF: bytes C2..DF 80..BF
   8116                case 0xC2:
   8117                case 0xC3:
   8118                case 0xC4:
   8119                case 0xC5:
   8120                case 0xC6:
   8121                case 0xC7:
   8122                case 0xC8:
   8123                case 0xC9:
   8124                case 0xCA:
   8125                case 0xCB:
   8126                case 0xCC:
   8127                case 0xCD:
   8128                case 0xCE:
   8129                case 0xCF:
   8130                case 0xD0:
   8131                case 0xD1:
   8132                case 0xD2:
   8133                case 0xD3:
   8134                case 0xD4:
   8135                case 0xD5:
   8136                case 0xD6:
   8137                case 0xD7:
   8138                case 0xD8:
   8139                case 0xD9:
   8140                case 0xDA:
   8141                case 0xDB:
   8142                case 0xDC:
   8143                case 0xDD:
   8144                case 0xDE:
   8145                case 0xDF:
   8146                {
   8147                    if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
   8148                    {
   8149                        return token_type::parse_error;
   8150                    }
   8151                    break;
   8152                }
   8153 
   8154                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
   8155                case 0xE0:
   8156                {
   8157                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
   8158                    {
   8159                        return token_type::parse_error;
   8160                    }
   8161                    break;
   8162                }
   8163 
   8164                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
   8165                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
   8166                case 0xE1:
   8167                case 0xE2:
   8168                case 0xE3:
   8169                case 0xE4:
   8170                case 0xE5:
   8171                case 0xE6:
   8172                case 0xE7:
   8173                case 0xE8:
   8174                case 0xE9:
   8175                case 0xEA:
   8176                case 0xEB:
   8177                case 0xEC:
   8178                case 0xEE:
   8179                case 0xEF:
   8180                {
   8181                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
   8182                    {
   8183                        return token_type::parse_error;
   8184                    }
   8185                    break;
   8186                }
   8187 
   8188                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
   8189                case 0xED:
   8190                {
   8191                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
   8192                    {
   8193                        return token_type::parse_error;
   8194                    }
   8195                    break;
   8196                }
   8197 
   8198                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
   8199                case 0xF0:
   8200                {
   8201                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
   8202                    {
   8203                        return token_type::parse_error;
   8204                    }
   8205                    break;
   8206                }
   8207 
   8208                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
   8209                case 0xF1:
   8210                case 0xF2:
   8211                case 0xF3:
   8212                {
   8213                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
   8214                    {
   8215                        return token_type::parse_error;
   8216                    }
   8217                    break;
   8218                }
   8219 
   8220                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
   8221                case 0xF4:
   8222                {
   8223                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
   8224                    {
   8225                        return token_type::parse_error;
   8226                    }
   8227                    break;
   8228                }
   8229 
   8230                // remaining bytes (80..C1 and F5..FF) are ill-formed
   8231                default:
   8232                {
   8233                    error_message = "invalid string: ill-formed UTF-8 byte";
   8234                    return token_type::parse_error;
   8235                }
   8236            }
   8237        }
   8238    }
   8239 
   8240    /*!
   8241     * @brief scan a comment
   8242     * @return whether comment could be scanned successfully
   8243     */
   8244    bool scan_comment()
   8245    {
   8246        switch (get())
   8247        {
   8248            // single-line comments skip input until a newline or EOF is read
   8249            case '/':
   8250            {
   8251                while (true)
   8252                {
   8253                    switch (get())
   8254                    {
   8255                        case '\n':
   8256                        case '\r':
   8257                        case char_traits<char_type>::eof():
   8258                        case '\0':
   8259                            return true;
   8260 
   8261                        default:
   8262                            break;
   8263                    }
   8264                }
   8265            }
   8266 
   8267            // multi-line comments skip input until */ is read
   8268            case '*':
   8269            {
   8270                while (true)
   8271                {
   8272                    switch (get())
   8273                    {
   8274                        case char_traits<char_type>::eof():
   8275                        case '\0':
   8276                        {
   8277                            error_message = "invalid comment; missing closing '*/'";
   8278                            return false;
   8279                        }
   8280 
   8281                        case '*':
   8282                        {
   8283                            switch (get())
   8284                            {
   8285                                case '/':
   8286                                    return true;
   8287 
   8288                                default:
   8289                                {
   8290                                    unget();
   8291                                    continue;
   8292                                }
   8293                            }
   8294                        }
   8295 
   8296                        default:
   8297                            continue;
   8298                    }
   8299                }
   8300            }
   8301 
   8302            // unexpected character after reading '/'
   8303            default:
   8304            {
   8305                error_message = "invalid comment; expecting '/' or '*' after '/'";
   8306                return false;
   8307            }
   8308        }
   8309    }
   8310 
   8311    JSON_HEDLEY_NON_NULL(2)
   8312    static void strtof(float& f, const char* str, char** endptr) noexcept
   8313    {
   8314        f = std::strtof(str, endptr);
   8315    }
   8316 
   8317    JSON_HEDLEY_NON_NULL(2)
   8318    static void strtof(double& f, const char* str, char** endptr) noexcept
   8319    {
   8320        f = std::strtod(str, endptr);
   8321    }
   8322 
   8323    JSON_HEDLEY_NON_NULL(2)
   8324    static void strtof(long double& f, const char* str, char** endptr) noexcept
   8325    {
   8326        f = std::strtold(str, endptr);
   8327    }
   8328 
   8329    /*!
   8330    @brief scan a number literal
   8331 
   8332    This function scans a string according to Sect. 6 of RFC 8259.
   8333 
   8334    The function is realized with a deterministic finite state machine derived
   8335    from the grammar described in RFC 8259. Starting in state "init", the
   8336    input is read and used to determined the next state. Only state "done"
   8337    accepts the number. State "error" is a trap state to model errors. In the
   8338    table below, "anything" means any character but the ones listed before.
   8339 
   8340    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
   8341    ---------|----------|----------|----------|---------|---------|----------|-----------
   8342    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
   8343    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
   8344    zero     | done     | done     | exponent | done    | done    | decimal1 | done
   8345    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
   8346    decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error]
   8347    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
   8348    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
   8349    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
   8350    any2     | any2     | any2     | done     | done    | done    | done     | done
   8351 
   8352    The state machine is realized with one label per state (prefixed with
   8353    "scan_number_") and `goto` statements between them. The state machine
   8354    contains cycles, but any cycle can be left when EOF is read. Therefore,
   8355    the function is guaranteed to terminate.
   8356 
   8357    During scanning, the read bytes are stored in token_buffer. This string is
   8358    then converted to a signed integer, an unsigned integer, or a
   8359    floating-point number.
   8360 
   8361    @return token_type::value_unsigned, token_type::value_integer, or
   8362            token_type::value_float if number could be successfully scanned,
   8363            token_type::parse_error otherwise
   8364 
   8365    @note The scanner is independent of the current locale. Internally, the
   8366          locale's decimal point is used instead of `.` to work with the
   8367          locale-dependent converters.
   8368    */
   8369    token_type scan_number()  // lgtm [cpp/use-of-goto]
   8370    {
   8371        // reset token_buffer to store the number's bytes
   8372        reset();
   8373 
   8374        // the type of the parsed number; initially set to unsigned; will be
   8375        // changed if minus sign, decimal point or exponent is read
   8376        token_type number_type = token_type::value_unsigned;
   8377 
   8378        // state (init): we just found out we need to scan a number
   8379        switch (current)
   8380        {
   8381            case '-':
   8382            {
   8383                add(current);
   8384                goto scan_number_minus;
   8385            }
   8386 
   8387            case '0':
   8388            {
   8389                add(current);
   8390                goto scan_number_zero;
   8391            }
   8392 
   8393            case '1':
   8394            case '2':
   8395            case '3':
   8396            case '4':
   8397            case '5':
   8398            case '6':
   8399            case '7':
   8400            case '8':
   8401            case '9':
   8402            {
   8403                add(current);
   8404                goto scan_number_any1;
   8405            }
   8406 
   8407            // all other characters are rejected outside scan_number()
   8408            default:            // LCOV_EXCL_LINE
   8409                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   8410        }
   8411 
   8412 scan_number_minus:
   8413        // state: we just parsed a leading minus sign
   8414        number_type = token_type::value_integer;
   8415        switch (get())
   8416        {
   8417            case '0':
   8418            {
   8419                add(current);
   8420                goto scan_number_zero;
   8421            }
   8422 
   8423            case '1':
   8424            case '2':
   8425            case '3':
   8426            case '4':
   8427            case '5':
   8428            case '6':
   8429            case '7':
   8430            case '8':
   8431            case '9':
   8432            {
   8433                add(current);
   8434                goto scan_number_any1;
   8435            }
   8436 
   8437            default:
   8438            {
   8439                error_message = "invalid number; expected digit after '-'";
   8440                return token_type::parse_error;
   8441            }
   8442        }
   8443 
   8444 scan_number_zero:
   8445        // state: we just parse a zero (maybe with a leading minus sign)
   8446        switch (get())
   8447        {
   8448            case '.':
   8449            {
   8450                add(decimal_point_char);
   8451                goto scan_number_decimal1;
   8452            }
   8453 
   8454            case 'e':
   8455            case 'E':
   8456            {
   8457                add(current);
   8458                goto scan_number_exponent;
   8459            }
   8460 
   8461            default:
   8462                goto scan_number_done;
   8463        }
   8464 
   8465 scan_number_any1:
   8466        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
   8467        switch (get())
   8468        {
   8469            case '0':
   8470            case '1':
   8471            case '2':
   8472            case '3':
   8473            case '4':
   8474            case '5':
   8475            case '6':
   8476            case '7':
   8477            case '8':
   8478            case '9':
   8479            {
   8480                add(current);
   8481                goto scan_number_any1;
   8482            }
   8483 
   8484            case '.':
   8485            {
   8486                add(decimal_point_char);
   8487                goto scan_number_decimal1;
   8488            }
   8489 
   8490            case 'e':
   8491            case 'E':
   8492            {
   8493                add(current);
   8494                goto scan_number_exponent;
   8495            }
   8496 
   8497            default:
   8498                goto scan_number_done;
   8499        }
   8500 
   8501 scan_number_decimal1:
   8502        // state: we just parsed a decimal point
   8503        number_type = token_type::value_float;
   8504        switch (get())
   8505        {
   8506            case '0':
   8507            case '1':
   8508            case '2':
   8509            case '3':
   8510            case '4':
   8511            case '5':
   8512            case '6':
   8513            case '7':
   8514            case '8':
   8515            case '9':
   8516            {
   8517                add(current);
   8518                goto scan_number_decimal2;
   8519            }
   8520 
   8521            default:
   8522            {
   8523                error_message = "invalid number; expected digit after '.'";
   8524                return token_type::parse_error;
   8525            }
   8526        }
   8527 
   8528 scan_number_decimal2:
   8529        // we just parsed at least one number after a decimal point
   8530        switch (get())
   8531        {
   8532            case '0':
   8533            case '1':
   8534            case '2':
   8535            case '3':
   8536            case '4':
   8537            case '5':
   8538            case '6':
   8539            case '7':
   8540            case '8':
   8541            case '9':
   8542            {
   8543                add(current);
   8544                goto scan_number_decimal2;
   8545            }
   8546 
   8547            case 'e':
   8548            case 'E':
   8549            {
   8550                add(current);
   8551                goto scan_number_exponent;
   8552            }
   8553 
   8554            default:
   8555                goto scan_number_done;
   8556        }
   8557 
   8558 scan_number_exponent:
   8559        // we just parsed an exponent
   8560        number_type = token_type::value_float;
   8561        switch (get())
   8562        {
   8563            case '+':
   8564            case '-':
   8565            {
   8566                add(current);
   8567                goto scan_number_sign;
   8568            }
   8569 
   8570            case '0':
   8571            case '1':
   8572            case '2':
   8573            case '3':
   8574            case '4':
   8575            case '5':
   8576            case '6':
   8577            case '7':
   8578            case '8':
   8579            case '9':
   8580            {
   8581                add(current);
   8582                goto scan_number_any2;
   8583            }
   8584 
   8585            default:
   8586            {
   8587                error_message =
   8588                    "invalid number; expected '+', '-', or digit after exponent";
   8589                return token_type::parse_error;
   8590            }
   8591        }
   8592 
   8593 scan_number_sign:
   8594        // we just parsed an exponent sign
   8595        switch (get())
   8596        {
   8597            case '0':
   8598            case '1':
   8599            case '2':
   8600            case '3':
   8601            case '4':
   8602            case '5':
   8603            case '6':
   8604            case '7':
   8605            case '8':
   8606            case '9':
   8607            {
   8608                add(current);
   8609                goto scan_number_any2;
   8610            }
   8611 
   8612            default:
   8613            {
   8614                error_message = "invalid number; expected digit after exponent sign";
   8615                return token_type::parse_error;
   8616            }
   8617        }
   8618 
   8619 scan_number_any2:
   8620        // we just parsed a number after the exponent or exponent sign
   8621        switch (get())
   8622        {
   8623            case '0':
   8624            case '1':
   8625            case '2':
   8626            case '3':
   8627            case '4':
   8628            case '5':
   8629            case '6':
   8630            case '7':
   8631            case '8':
   8632            case '9':
   8633            {
   8634                add(current);
   8635                goto scan_number_any2;
   8636            }
   8637 
   8638            default:
   8639                goto scan_number_done;
   8640        }
   8641 
   8642 scan_number_done:
   8643        // unget the character after the number (we only read it to know that
   8644        // we are done scanning a number)
   8645        unget();
   8646 
   8647        char* endptr = nullptr; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   8648        errno = 0;
   8649 
   8650        // try to parse integers first and fall back to floats
   8651        if (number_type == token_type::value_unsigned)
   8652        {
   8653            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
   8654 
   8655            // we checked the number format before
   8656            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
   8657 
   8658            if (errno == 0)
   8659            {
   8660                value_unsigned = static_cast<number_unsigned_t>(x);
   8661                if (value_unsigned == x)
   8662                {
   8663                    return token_type::value_unsigned;
   8664                }
   8665            }
   8666        }
   8667        else if (number_type == token_type::value_integer)
   8668        {
   8669            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
   8670 
   8671            // we checked the number format before
   8672            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
   8673 
   8674            if (errno == 0)
   8675            {
   8676                value_integer = static_cast<number_integer_t>(x);
   8677                if (value_integer == x)
   8678                {
   8679                    return token_type::value_integer;
   8680                }
   8681            }
   8682        }
   8683 
   8684        // this code is reached if we parse a floating-point number or if an
   8685        // integer conversion above failed
   8686        strtof(value_float, token_buffer.data(), &endptr);
   8687 
   8688        // we checked the number format before
   8689        JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
   8690 
   8691        return token_type::value_float;
   8692    }
   8693 
   8694    /*!
   8695    @param[in] literal_text  the literal text to expect
   8696    @param[in] length        the length of the passed literal text
   8697    @param[in] return_type   the token type to return on success
   8698    */
   8699    JSON_HEDLEY_NON_NULL(2)
   8700    token_type scan_literal(const char_type* literal_text, const std::size_t length,
   8701                            token_type return_type)
   8702    {
   8703        JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
   8704        for (std::size_t i = 1; i < length; ++i)
   8705        {
   8706            if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
   8707            {
   8708                error_message = "invalid literal";
   8709                return token_type::parse_error;
   8710            }
   8711        }
   8712        return return_type;
   8713    }
   8714 
   8715    /////////////////////
   8716    // input management
   8717    /////////////////////
   8718 
   8719    /// reset token_buffer; current character is beginning of token
   8720    void reset() noexcept
   8721    {
   8722        token_buffer.clear();
   8723        token_string.clear();
   8724        token_string.push_back(char_traits<char_type>::to_char_type(current));
   8725    }
   8726 
   8727    /*
   8728    @brief get next character from the input
   8729 
   8730    This function provides the interface to the used input adapter. It does
   8731    not throw in case the input reached EOF, but returns a
   8732    `char_traits<char>::eof()` in that case.  Stores the scanned characters
   8733    for use in error messages.
   8734 
   8735    @return character read from the input
   8736    */
   8737    char_int_type get()
   8738    {
   8739        ++position.chars_read_total;
   8740        ++position.chars_read_current_line;
   8741 
   8742        if (next_unget)
   8743        {
   8744            // just reset the next_unget variable and work with current
   8745            next_unget = false;
   8746        }
   8747        else
   8748        {
   8749            current = ia.get_character();
   8750        }
   8751 
   8752        if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
   8753        {
   8754            token_string.push_back(char_traits<char_type>::to_char_type(current));
   8755        }
   8756 
   8757        if (current == '\n')
   8758        {
   8759            ++position.lines_read;
   8760            position.chars_read_current_line = 0;
   8761        }
   8762 
   8763        return current;
   8764    }
   8765 
   8766    /*!
   8767    @brief unget current character (read it again on next get)
   8768 
   8769    We implement unget by setting variable next_unget to true. The input is not
   8770    changed - we just simulate ungetting by modifying chars_read_total,
   8771    chars_read_current_line, and token_string. The next call to get() will
   8772    behave as if the unget character is read again.
   8773    */
   8774    void unget()
   8775    {
   8776        next_unget = true;
   8777 
   8778        --position.chars_read_total;
   8779 
   8780        // in case we "unget" a newline, we have to also decrement the lines_read
   8781        if (position.chars_read_current_line == 0)
   8782        {
   8783            if (position.lines_read > 0)
   8784            {
   8785                --position.lines_read;
   8786            }
   8787        }
   8788        else
   8789        {
   8790            --position.chars_read_current_line;
   8791        }
   8792 
   8793        if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
   8794        {
   8795            JSON_ASSERT(!token_string.empty());
   8796            token_string.pop_back();
   8797        }
   8798    }
   8799 
   8800    /// add a character to token_buffer
   8801    void add(char_int_type c)
   8802    {
   8803        token_buffer.push_back(static_cast<typename string_t::value_type>(c));
   8804    }
   8805 
   8806  public:
   8807    /////////////////////
   8808    // value getters
   8809    /////////////////////
   8810 
   8811    /// return integer value
   8812    constexpr number_integer_t get_number_integer() const noexcept
   8813    {
   8814        return value_integer;
   8815    }
   8816 
   8817    /// return unsigned integer value
   8818    constexpr number_unsigned_t get_number_unsigned() const noexcept
   8819    {
   8820        return value_unsigned;
   8821    }
   8822 
   8823    /// return floating-point value
   8824    constexpr number_float_t get_number_float() const noexcept
   8825    {
   8826        return value_float;
   8827    }
   8828 
   8829    /// return current string value (implicitly resets the token; useful only once)
   8830    string_t& get_string()
   8831    {
   8832        return token_buffer;
   8833    }
   8834 
   8835    /////////////////////
   8836    // diagnostics
   8837    /////////////////////
   8838 
   8839    /// return position of last read token
   8840    constexpr position_t get_position() const noexcept
   8841    {
   8842        return position;
   8843    }
   8844 
   8845    /// return the last read token (for errors only).  Will never contain EOF
   8846    /// (an arbitrary value that is not a valid char value, often -1), because
   8847    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
   8848    std::string get_token_string() const
   8849    {
   8850        // escape control characters
   8851        std::string result;
   8852        for (const auto c : token_string)
   8853        {
   8854            if (static_cast<unsigned char>(c) <= '\x1F')
   8855            {
   8856                // escape control characters
   8857                std::array<char, 9> cs{{}};
   8858                static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   8859                result += cs.data();
   8860            }
   8861            else
   8862            {
   8863                // add character as is
   8864                result.push_back(static_cast<std::string::value_type>(c));
   8865            }
   8866        }
   8867 
   8868        return result;
   8869    }
   8870 
   8871    /// return syntax error message
   8872    JSON_HEDLEY_RETURNS_NON_NULL
   8873    constexpr const char* get_error_message() const noexcept
   8874    {
   8875        return error_message;
   8876    }
   8877 
   8878    /////////////////////
   8879    // actual scanner
   8880    /////////////////////
   8881 
   8882    /*!
   8883    @brief skip the UTF-8 byte order mark
   8884    @return true iff there is no BOM or the correct BOM has been skipped
   8885    */
   8886    bool skip_bom()
   8887    {
   8888        if (get() == 0xEF)
   8889        {
   8890            // check if we completely parse the BOM
   8891            return get() == 0xBB && get() == 0xBF;
   8892        }
   8893 
   8894        // the first character is not the beginning of the BOM; unget it to
   8895        // process is later
   8896        unget();
   8897        return true;
   8898    }
   8899 
   8900    void skip_whitespace()
   8901    {
   8902        do
   8903        {
   8904            get();
   8905        }
   8906        while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
   8907    }
   8908 
   8909    token_type scan()
   8910    {
   8911        // initially, skip the BOM
   8912        if (position.chars_read_total == 0 && !skip_bom())
   8913        {
   8914            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
   8915            return token_type::parse_error;
   8916        }
   8917 
   8918        // read next character and ignore whitespace
   8919        skip_whitespace();
   8920 
   8921        // ignore comments
   8922        while (ignore_comments && current == '/')
   8923        {
   8924            if (!scan_comment())
   8925            {
   8926                return token_type::parse_error;
   8927            }
   8928 
   8929            // skip following whitespace
   8930            skip_whitespace();
   8931        }
   8932 
   8933        switch (current)
   8934        {
   8935            // structural characters
   8936            case '[':
   8937                return token_type::begin_array;
   8938            case ']':
   8939                return token_type::end_array;
   8940            case '{':
   8941                return token_type::begin_object;
   8942            case '}':
   8943                return token_type::end_object;
   8944            case ':':
   8945                return token_type::name_separator;
   8946            case ',':
   8947                return token_type::value_separator;
   8948 
   8949            // literals
   8950            case 't':
   8951            {
   8952                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')}};
   8953                return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
   8954            }
   8955            case 'f':
   8956            {
   8957                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')}};
   8958                return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
   8959            }
   8960            case 'n':
   8961            {
   8962                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')}};
   8963                return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
   8964            }
   8965 
   8966            // string
   8967            case '\"':
   8968                return scan_string();
   8969 
   8970            // number
   8971            case '-':
   8972            case '0':
   8973            case '1':
   8974            case '2':
   8975            case '3':
   8976            case '4':
   8977            case '5':
   8978            case '6':
   8979            case '7':
   8980            case '8':
   8981            case '9':
   8982                return scan_number();
   8983 
   8984            // end of input (the null byte is needed when parsing from
   8985            // string literals)
   8986            case '\0':
   8987            case char_traits<char_type>::eof():
   8988                return token_type::end_of_input;
   8989 
   8990            // error
   8991            default:
   8992                error_message = "invalid literal";
   8993                return token_type::parse_error;
   8994        }
   8995    }
   8996 
   8997  private:
   8998    /// input adapter
   8999    InputAdapterType ia;
   9000 
   9001    /// whether comments should be ignored (true) or signaled as errors (false)
   9002    const bool ignore_comments = false;
   9003 
   9004    /// the current character
   9005    char_int_type current = char_traits<char_type>::eof();
   9006 
   9007    /// whether the next get() call should just return current
   9008    bool next_unget = false;
   9009 
   9010    /// the start position of the current token
   9011    position_t position {};
   9012 
   9013    /// raw input token string (for error messages)
   9014    std::vector<char_type> token_string {};
   9015 
   9016    /// buffer for variable-length tokens (numbers, strings)
   9017    string_t token_buffer {};
   9018 
   9019    /// a description of occurred lexer errors
   9020    const char* error_message = "";
   9021 
   9022    // number values
   9023    number_integer_t value_integer = 0;
   9024    number_unsigned_t value_unsigned = 0;
   9025    number_float_t value_float = 0;
   9026 
   9027    /// the decimal point
   9028    const char_int_type decimal_point_char = '.';
   9029 };
   9030 
   9031 }  // namespace detail
   9032 NLOHMANN_JSON_NAMESPACE_END
   9033 
   9034 // #include <nlohmann/detail/macro_scope.hpp>
   9035 
   9036 // #include <nlohmann/detail/meta/is_sax.hpp>
   9037 //     __ _____ _____ _____
   9038 //  __|  |   __|     |   | |  JSON for Modern C++
   9039 // |  |  |__   |  |  | | | |  version 3.11.3
   9040 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   9041 //
   9042 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   9043 // SPDX-License-Identifier: MIT
   9044 
   9045 
   9046 
   9047 #include <cstdint> // size_t
   9048 #include <utility> // declval
   9049 #include <string> // string
   9050 
   9051 // #include <nlohmann/detail/abi_macros.hpp>
   9052 
   9053 // #include <nlohmann/detail/meta/detected.hpp>
   9054 
   9055 // #include <nlohmann/detail/meta/type_traits.hpp>
   9056 
   9057 
   9058 NLOHMANN_JSON_NAMESPACE_BEGIN
   9059 namespace detail
   9060 {
   9061 
   9062 template<typename T>
   9063 using null_function_t = decltype(std::declval<T&>().null());
   9064 
   9065 template<typename T>
   9066 using boolean_function_t =
   9067    decltype(std::declval<T&>().boolean(std::declval<bool>()));
   9068 
   9069 template<typename T, typename Integer>
   9070 using number_integer_function_t =
   9071    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
   9072 
   9073 template<typename T, typename Unsigned>
   9074 using number_unsigned_function_t =
   9075    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
   9076 
   9077 template<typename T, typename Float, typename String>
   9078 using number_float_function_t = decltype(std::declval<T&>().number_float(
   9079                                    std::declval<Float>(), std::declval<const String&>()));
   9080 
   9081 template<typename T, typename String>
   9082 using string_function_t =
   9083    decltype(std::declval<T&>().string(std::declval<String&>()));
   9084 
   9085 template<typename T, typename Binary>
   9086 using binary_function_t =
   9087    decltype(std::declval<T&>().binary(std::declval<Binary&>()));
   9088 
   9089 template<typename T>
   9090 using start_object_function_t =
   9091    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
   9092 
   9093 template<typename T, typename String>
   9094 using key_function_t =
   9095    decltype(std::declval<T&>().key(std::declval<String&>()));
   9096 
   9097 template<typename T>
   9098 using end_object_function_t = decltype(std::declval<T&>().end_object());
   9099 
   9100 template<typename T>
   9101 using start_array_function_t =
   9102    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
   9103 
   9104 template<typename T>
   9105 using end_array_function_t = decltype(std::declval<T&>().end_array());
   9106 
   9107 template<typename T, typename Exception>
   9108 using parse_error_function_t = decltype(std::declval<T&>().parse_error(
   9109        std::declval<std::size_t>(), std::declval<const std::string&>(),
   9110        std::declval<const Exception&>()));
   9111 
   9112 template<typename SAX, typename BasicJsonType>
   9113 struct is_sax
   9114 {
   9115  private:
   9116    static_assert(is_basic_json<BasicJsonType>::value,
   9117                  "BasicJsonType must be of type basic_json<...>");
   9118 
   9119    using number_integer_t = typename BasicJsonType::number_integer_t;
   9120    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   9121    using number_float_t = typename BasicJsonType::number_float_t;
   9122    using string_t = typename BasicJsonType::string_t;
   9123    using binary_t = typename BasicJsonType::binary_t;
   9124    using exception_t = typename BasicJsonType::exception;
   9125 
   9126  public:
   9127    static constexpr bool value =
   9128        is_detected_exact<bool, null_function_t, SAX>::value &&
   9129        is_detected_exact<bool, boolean_function_t, SAX>::value &&
   9130        is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
   9131        is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
   9132        is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
   9133        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
   9134        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
   9135        is_detected_exact<bool, start_object_function_t, SAX>::value &&
   9136        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
   9137        is_detected_exact<bool, end_object_function_t, SAX>::value &&
   9138        is_detected_exact<bool, start_array_function_t, SAX>::value &&
   9139        is_detected_exact<bool, end_array_function_t, SAX>::value &&
   9140        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
   9141 };
   9142 
   9143 template<typename SAX, typename BasicJsonType>
   9144 struct is_sax_static_asserts
   9145 {
   9146  private:
   9147    static_assert(is_basic_json<BasicJsonType>::value,
   9148                  "BasicJsonType must be of type basic_json<...>");
   9149 
   9150    using number_integer_t = typename BasicJsonType::number_integer_t;
   9151    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   9152    using number_float_t = typename BasicJsonType::number_float_t;
   9153    using string_t = typename BasicJsonType::string_t;
   9154    using binary_t = typename BasicJsonType::binary_t;
   9155    using exception_t = typename BasicJsonType::exception;
   9156 
   9157  public:
   9158    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
   9159                  "Missing/invalid function: bool null()");
   9160    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
   9161                  "Missing/invalid function: bool boolean(bool)");
   9162    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
   9163                  "Missing/invalid function: bool boolean(bool)");
   9164    static_assert(
   9165        is_detected_exact<bool, number_integer_function_t, SAX,
   9166        number_integer_t>::value,
   9167        "Missing/invalid function: bool number_integer(number_integer_t)");
   9168    static_assert(
   9169        is_detected_exact<bool, number_unsigned_function_t, SAX,
   9170        number_unsigned_t>::value,
   9171        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
   9172    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
   9173                  number_float_t, string_t>::value,
   9174                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
   9175    static_assert(
   9176        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
   9177        "Missing/invalid function: bool string(string_t&)");
   9178    static_assert(
   9179        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
   9180        "Missing/invalid function: bool binary(binary_t&)");
   9181    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
   9182                  "Missing/invalid function: bool start_object(std::size_t)");
   9183    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
   9184                  "Missing/invalid function: bool key(string_t&)");
   9185    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
   9186                  "Missing/invalid function: bool end_object()");
   9187    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
   9188                  "Missing/invalid function: bool start_array(std::size_t)");
   9189    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
   9190                  "Missing/invalid function: bool end_array()");
   9191    static_assert(
   9192        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
   9193        "Missing/invalid function: bool parse_error(std::size_t, const "
   9194        "std::string&, const exception&)");
   9195 };
   9196 
   9197 }  // namespace detail
   9198 NLOHMANN_JSON_NAMESPACE_END
   9199 
   9200 // #include <nlohmann/detail/meta/type_traits.hpp>
   9201 
   9202 // #include <nlohmann/detail/string_concat.hpp>
   9203 
   9204 // #include <nlohmann/detail/value_t.hpp>
   9205 
   9206 
   9207 NLOHMANN_JSON_NAMESPACE_BEGIN
   9208 namespace detail
   9209 {
   9210 
   9211 /// how to treat CBOR tags
   9212 enum class cbor_tag_handler_t
   9213 {
   9214    error,   ///< throw a parse_error exception in case of a tag
   9215    ignore,  ///< ignore tags
   9216    store    ///< store tags as binary type
   9217 };
   9218 
   9219 /*!
   9220 @brief determine system byte order
   9221 
   9222 @return true if and only if system's byte order is little endian
   9223 
   9224 @note from https://stackoverflow.com/a/1001328/266378
   9225 */
   9226 static inline bool little_endianness(int num = 1) noexcept
   9227 {
   9228    return *reinterpret_cast<char*>(&num) == 1;
   9229 }
   9230 
   9231 ///////////////////
   9232 // binary reader //
   9233 ///////////////////
   9234 
   9235 /*!
   9236 @brief deserialization of CBOR, MessagePack, and UBJSON values
   9237 */
   9238 template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType>>
   9239 class binary_reader
   9240 {
   9241    using number_integer_t = typename BasicJsonType::number_integer_t;
   9242    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
   9243    using number_float_t = typename BasicJsonType::number_float_t;
   9244    using string_t = typename BasicJsonType::string_t;
   9245    using binary_t = typename BasicJsonType::binary_t;
   9246    using json_sax_t = SAX;
   9247    using char_type = typename InputAdapterType::char_type;
   9248    using char_int_type = typename char_traits<char_type>::int_type;
   9249 
   9250  public:
   9251    /*!
   9252    @brief create a binary reader
   9253 
   9254    @param[in] adapter  input adapter to read from
   9255    */
   9256    explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
   9257    {
   9258        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
   9259    }
   9260 
   9261    // make class move-only
   9262    binary_reader(const binary_reader&) = delete;
   9263    binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   9264    binary_reader& operator=(const binary_reader&) = delete;
   9265    binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
   9266    ~binary_reader() = default;
   9267 
   9268    /*!
   9269    @param[in] format  the binary format to parse
   9270    @param[in] sax_    a SAX event processor
   9271    @param[in] strict  whether to expect the input to be consumed completed
   9272    @param[in] tag_handler  how to treat CBOR tags
   9273 
   9274    @return whether parsing was successful
   9275    */
   9276    JSON_HEDLEY_NON_NULL(3)
   9277    bool sax_parse(const input_format_t format,
   9278                   json_sax_t* sax_,
   9279                   const bool strict = true,
   9280                   const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
   9281    {
   9282        sax = sax_;
   9283        bool result = false;
   9284 
   9285        switch (format)
   9286        {
   9287            case input_format_t::bson:
   9288                result = parse_bson_internal();
   9289                break;
   9290 
   9291            case input_format_t::cbor:
   9292                result = parse_cbor_internal(true, tag_handler);
   9293                break;
   9294 
   9295            case input_format_t::msgpack:
   9296                result = parse_msgpack_internal();
   9297                break;
   9298 
   9299            case input_format_t::ubjson:
   9300            case input_format_t::bjdata:
   9301                result = parse_ubjson_internal();
   9302                break;
   9303 
   9304            case input_format_t::json: // LCOV_EXCL_LINE
   9305            default:            // LCOV_EXCL_LINE
   9306                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   9307        }
   9308 
   9309        // strict mode: next byte must be EOF
   9310        if (result && strict)
   9311        {
   9312            if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
   9313            {
   9314                get_ignore_noop();
   9315            }
   9316            else
   9317            {
   9318                get();
   9319            }
   9320 
   9321            if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
   9322            {
   9323                return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
   9324                                        exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
   9325            }
   9326        }
   9327 
   9328        return result;
   9329    }
   9330 
   9331  private:
   9332    //////////
   9333    // BSON //
   9334    //////////
   9335 
   9336    /*!
   9337    @brief Reads in a BSON-object and passes it to the SAX-parser.
   9338    @return whether a valid BSON-value was passed to the SAX parser
   9339    */
   9340    bool parse_bson_internal()
   9341    {
   9342        std::int32_t document_size{};
   9343        get_number<std::int32_t, true>(input_format_t::bson, document_size);
   9344 
   9345        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
   9346        {
   9347            return false;
   9348        }
   9349 
   9350        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
   9351        {
   9352            return false;
   9353        }
   9354 
   9355        return sax->end_object();
   9356    }
   9357 
   9358    /*!
   9359    @brief Parses a C-style string from the BSON input.
   9360    @param[in,out] result  A reference to the string variable where the read
   9361                            string is to be stored.
   9362    @return `true` if the \x00-byte indicating the end of the string was
   9363             encountered before the EOF; false` indicates an unexpected EOF.
   9364    */
   9365    bool get_bson_cstr(string_t& result)
   9366    {
   9367        auto out = std::back_inserter(result);
   9368        while (true)
   9369        {
   9370            get();
   9371            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
   9372            {
   9373                return false;
   9374            }
   9375            if (current == 0x00)
   9376            {
   9377                return true;
   9378            }
   9379            *out++ = static_cast<typename string_t::value_type>(current);
   9380        }
   9381    }
   9382 
   9383    /*!
   9384    @brief Parses a zero-terminated string of length @a len from the BSON
   9385           input.
   9386    @param[in] len  The length (including the zero-byte at the end) of the
   9387                    string to be read.
   9388    @param[in,out] result  A reference to the string variable where the read
   9389                            string is to be stored.
   9390    @tparam NumberType The type of the length @a len
   9391    @pre len >= 1
   9392    @return `true` if the string was successfully parsed
   9393    */
   9394    template<typename NumberType>
   9395    bool get_bson_string(const NumberType len, string_t& result)
   9396    {
   9397        if (JSON_HEDLEY_UNLIKELY(len < 1))
   9398        {
   9399            auto last_token = get_token_string();
   9400            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9401                                    exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
   9402        }
   9403 
   9404        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
   9405    }
   9406 
   9407    /*!
   9408    @brief Parses a byte array input of length @a len from the BSON input.
   9409    @param[in] len  The length of the byte array to be read.
   9410    @param[in,out] result  A reference to the binary variable where the read
   9411                            array is to be stored.
   9412    @tparam NumberType The type of the length @a len
   9413    @pre len >= 0
   9414    @return `true` if the byte array was successfully parsed
   9415    */
   9416    template<typename NumberType>
   9417    bool get_bson_binary(const NumberType len, binary_t& result)
   9418    {
   9419        if (JSON_HEDLEY_UNLIKELY(len < 0))
   9420        {
   9421            auto last_token = get_token_string();
   9422            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9423                                    exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
   9424        }
   9425 
   9426        // All BSON binary values have a subtype
   9427        std::uint8_t subtype{};
   9428        get_number<std::uint8_t>(input_format_t::bson, subtype);
   9429        result.set_subtype(subtype);
   9430 
   9431        return get_binary(input_format_t::bson, len, result);
   9432    }
   9433 
   9434    /*!
   9435    @brief Read a BSON document element of the given @a element_type.
   9436    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
   9437    @param[in] element_type_parse_position The position in the input stream,
   9438               where the `element_type` was read.
   9439    @warning Not all BSON element types are supported yet. An unsupported
   9440             @a element_type will give rise to a parse_error.114:
   9441             Unsupported BSON record type 0x...
   9442    @return whether a valid BSON-object/array was passed to the SAX parser
   9443    */
   9444    bool parse_bson_element_internal(const char_int_type element_type,
   9445                                     const std::size_t element_type_parse_position)
   9446    {
   9447        switch (element_type)
   9448        {
   9449            case 0x01: // double
   9450            {
   9451                double number{};
   9452                return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
   9453            }
   9454 
   9455            case 0x02: // string
   9456            {
   9457                std::int32_t len{};
   9458                string_t value;
   9459                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
   9460            }
   9461 
   9462            case 0x03: // object
   9463            {
   9464                return parse_bson_internal();
   9465            }
   9466 
   9467            case 0x04: // array
   9468            {
   9469                return parse_bson_array();
   9470            }
   9471 
   9472            case 0x05: // binary
   9473            {
   9474                std::int32_t len{};
   9475                binary_t value;
   9476                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
   9477            }
   9478 
   9479            case 0x08: // boolean
   9480            {
   9481                return sax->boolean(get() != 0);
   9482            }
   9483 
   9484            case 0x0A: // null
   9485            {
   9486                return sax->null();
   9487            }
   9488 
   9489            case 0x10: // int32
   9490            {
   9491                std::int32_t value{};
   9492                return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
   9493            }
   9494 
   9495            case 0x12: // int64
   9496            {
   9497                std::int64_t value{};
   9498                return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
   9499            }
   9500 
   9501            default: // anything else not supported (yet)
   9502            {
   9503                std::array<char, 3> cr{{}};
   9504                static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
   9505                const std::string cr_str{cr.data()};
   9506                return sax->parse_error(element_type_parse_position, cr_str,
   9507                                        parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
   9508            }
   9509        }
   9510    }
   9511 
   9512    /*!
   9513    @brief Read a BSON element list (as specified in the BSON-spec)
   9514 
   9515    The same binary layout is used for objects and arrays, hence it must be
   9516    indicated with the argument @a is_array which one is expected
   9517    (true --> array, false --> object).
   9518 
   9519    @param[in] is_array Determines if the element list being read is to be
   9520                        treated as an object (@a is_array == false), or as an
   9521                        array (@a is_array == true).
   9522    @return whether a valid BSON-object/array was passed to the SAX parser
   9523    */
   9524    bool parse_bson_element_list(const bool is_array)
   9525    {
   9526        string_t key;
   9527 
   9528        while (auto element_type = get())
   9529        {
   9530            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
   9531            {
   9532                return false;
   9533            }
   9534 
   9535            const std::size_t element_type_parse_position = chars_read;
   9536            if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
   9537            {
   9538                return false;
   9539            }
   9540 
   9541            if (!is_array && !sax->key(key))
   9542            {
   9543                return false;
   9544            }
   9545 
   9546            if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
   9547            {
   9548                return false;
   9549            }
   9550 
   9551            // get_bson_cstr only appends
   9552            key.clear();
   9553        }
   9554 
   9555        return true;
   9556    }
   9557 
   9558    /*!
   9559    @brief Reads an array from the BSON input and passes it to the SAX-parser.
   9560    @return whether a valid BSON-array was passed to the SAX parser
   9561    */
   9562    bool parse_bson_array()
   9563    {
   9564        std::int32_t document_size{};
   9565        get_number<std::int32_t, true>(input_format_t::bson, document_size);
   9566 
   9567        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
   9568        {
   9569            return false;
   9570        }
   9571 
   9572        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
   9573        {
   9574            return false;
   9575        }
   9576 
   9577        return sax->end_array();
   9578    }
   9579 
   9580    //////////
   9581    // CBOR //
   9582    //////////
   9583 
   9584    /*!
   9585    @param[in] get_char  whether a new character should be retrieved from the
   9586                         input (true) or whether the last read character should
   9587                         be considered instead (false)
   9588    @param[in] tag_handler how CBOR tags should be treated
   9589 
   9590    @return whether a valid CBOR value was passed to the SAX parser
   9591    */
   9592    bool parse_cbor_internal(const bool get_char,
   9593                             const cbor_tag_handler_t tag_handler)
   9594    {
   9595        switch (get_char ? get() : current)
   9596        {
   9597            // EOF
   9598            case char_traits<char_type>::eof():
   9599                return unexpect_eof(input_format_t::cbor, "value");
   9600 
   9601            // Integer 0x00..0x17 (0..23)
   9602            case 0x00:
   9603            case 0x01:
   9604            case 0x02:
   9605            case 0x03:
   9606            case 0x04:
   9607            case 0x05:
   9608            case 0x06:
   9609            case 0x07:
   9610            case 0x08:
   9611            case 0x09:
   9612            case 0x0A:
   9613            case 0x0B:
   9614            case 0x0C:
   9615            case 0x0D:
   9616            case 0x0E:
   9617            case 0x0F:
   9618            case 0x10:
   9619            case 0x11:
   9620            case 0x12:
   9621            case 0x13:
   9622            case 0x14:
   9623            case 0x15:
   9624            case 0x16:
   9625            case 0x17:
   9626                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
   9627 
   9628            case 0x18: // Unsigned integer (one-byte uint8_t follows)
   9629            {
   9630                std::uint8_t number{};
   9631                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9632            }
   9633 
   9634            case 0x19: // Unsigned integer (two-byte uint16_t follows)
   9635            {
   9636                std::uint16_t number{};
   9637                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9638            }
   9639 
   9640            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
   9641            {
   9642                std::uint32_t number{};
   9643                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9644            }
   9645 
   9646            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
   9647            {
   9648                std::uint64_t number{};
   9649                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
   9650            }
   9651 
   9652            // Negative integer -1-0x00..-1-0x17 (-1..-24)
   9653            case 0x20:
   9654            case 0x21:
   9655            case 0x22:
   9656            case 0x23:
   9657            case 0x24:
   9658            case 0x25:
   9659            case 0x26:
   9660            case 0x27:
   9661            case 0x28:
   9662            case 0x29:
   9663            case 0x2A:
   9664            case 0x2B:
   9665            case 0x2C:
   9666            case 0x2D:
   9667            case 0x2E:
   9668            case 0x2F:
   9669            case 0x30:
   9670            case 0x31:
   9671            case 0x32:
   9672            case 0x33:
   9673            case 0x34:
   9674            case 0x35:
   9675            case 0x36:
   9676            case 0x37:
   9677                return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
   9678 
   9679            case 0x38: // Negative integer (one-byte uint8_t follows)
   9680            {
   9681                std::uint8_t number{};
   9682                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
   9683            }
   9684 
   9685            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
   9686            {
   9687                std::uint16_t number{};
   9688                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
   9689            }
   9690 
   9691            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
   9692            {
   9693                std::uint32_t number{};
   9694                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
   9695            }
   9696 
   9697            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
   9698            {
   9699                std::uint64_t number{};
   9700                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
   9701                        - static_cast<number_integer_t>(number));
   9702            }
   9703 
   9704            // Binary data (0x00..0x17 bytes follow)
   9705            case 0x40:
   9706            case 0x41:
   9707            case 0x42:
   9708            case 0x43:
   9709            case 0x44:
   9710            case 0x45:
   9711            case 0x46:
   9712            case 0x47:
   9713            case 0x48:
   9714            case 0x49:
   9715            case 0x4A:
   9716            case 0x4B:
   9717            case 0x4C:
   9718            case 0x4D:
   9719            case 0x4E:
   9720            case 0x4F:
   9721            case 0x50:
   9722            case 0x51:
   9723            case 0x52:
   9724            case 0x53:
   9725            case 0x54:
   9726            case 0x55:
   9727            case 0x56:
   9728            case 0x57:
   9729            case 0x58: // Binary data (one-byte uint8_t for n follows)
   9730            case 0x59: // Binary data (two-byte uint16_t for n follow)
   9731            case 0x5A: // Binary data (four-byte uint32_t for n follow)
   9732            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
   9733            case 0x5F: // Binary data (indefinite length)
   9734            {
   9735                binary_t b;
   9736                return get_cbor_binary(b) && sax->binary(b);
   9737            }
   9738 
   9739            // UTF-8 string (0x00..0x17 bytes follow)
   9740            case 0x60:
   9741            case 0x61:
   9742            case 0x62:
   9743            case 0x63:
   9744            case 0x64:
   9745            case 0x65:
   9746            case 0x66:
   9747            case 0x67:
   9748            case 0x68:
   9749            case 0x69:
   9750            case 0x6A:
   9751            case 0x6B:
   9752            case 0x6C:
   9753            case 0x6D:
   9754            case 0x6E:
   9755            case 0x6F:
   9756            case 0x70:
   9757            case 0x71:
   9758            case 0x72:
   9759            case 0x73:
   9760            case 0x74:
   9761            case 0x75:
   9762            case 0x76:
   9763            case 0x77:
   9764            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
   9765            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
   9766            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
   9767            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
   9768            case 0x7F: // UTF-8 string (indefinite length)
   9769            {
   9770                string_t s;
   9771                return get_cbor_string(s) && sax->string(s);
   9772            }
   9773 
   9774            // array (0x00..0x17 data items follow)
   9775            case 0x80:
   9776            case 0x81:
   9777            case 0x82:
   9778            case 0x83:
   9779            case 0x84:
   9780            case 0x85:
   9781            case 0x86:
   9782            case 0x87:
   9783            case 0x88:
   9784            case 0x89:
   9785            case 0x8A:
   9786            case 0x8B:
   9787            case 0x8C:
   9788            case 0x8D:
   9789            case 0x8E:
   9790            case 0x8F:
   9791            case 0x90:
   9792            case 0x91:
   9793            case 0x92:
   9794            case 0x93:
   9795            case 0x94:
   9796            case 0x95:
   9797            case 0x96:
   9798            case 0x97:
   9799                return get_cbor_array(
   9800                           conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
   9801 
   9802            case 0x98: // array (one-byte uint8_t for n follows)
   9803            {
   9804                std::uint8_t len{};
   9805                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
   9806            }
   9807 
   9808            case 0x99: // array (two-byte uint16_t for n follow)
   9809            {
   9810                std::uint16_t len{};
   9811                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
   9812            }
   9813 
   9814            case 0x9A: // array (four-byte uint32_t for n follow)
   9815            {
   9816                std::uint32_t len{};
   9817                return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
   9818            }
   9819 
   9820            case 0x9B: // array (eight-byte uint64_t for n follow)
   9821            {
   9822                std::uint64_t len{};
   9823                return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
   9824            }
   9825 
   9826            case 0x9F: // array (indefinite length)
   9827                return get_cbor_array(static_cast<std::size_t>(-1), tag_handler);
   9828 
   9829            // map (0x00..0x17 pairs of data items follow)
   9830            case 0xA0:
   9831            case 0xA1:
   9832            case 0xA2:
   9833            case 0xA3:
   9834            case 0xA4:
   9835            case 0xA5:
   9836            case 0xA6:
   9837            case 0xA7:
   9838            case 0xA8:
   9839            case 0xA9:
   9840            case 0xAA:
   9841            case 0xAB:
   9842            case 0xAC:
   9843            case 0xAD:
   9844            case 0xAE:
   9845            case 0xAF:
   9846            case 0xB0:
   9847            case 0xB1:
   9848            case 0xB2:
   9849            case 0xB3:
   9850            case 0xB4:
   9851            case 0xB5:
   9852            case 0xB6:
   9853            case 0xB7:
   9854                return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
   9855 
   9856            case 0xB8: // map (one-byte uint8_t for n follows)
   9857            {
   9858                std::uint8_t len{};
   9859                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
   9860            }
   9861 
   9862            case 0xB9: // map (two-byte uint16_t for n follow)
   9863            {
   9864                std::uint16_t len{};
   9865                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
   9866            }
   9867 
   9868            case 0xBA: // map (four-byte uint32_t for n follow)
   9869            {
   9870                std::uint32_t len{};
   9871                return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
   9872            }
   9873 
   9874            case 0xBB: // map (eight-byte uint64_t for n follow)
   9875            {
   9876                std::uint64_t len{};
   9877                return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
   9878            }
   9879 
   9880            case 0xBF: // map (indefinite length)
   9881                return get_cbor_object(static_cast<std::size_t>(-1), tag_handler);
   9882 
   9883            case 0xC6: // tagged item
   9884            case 0xC7:
   9885            case 0xC8:
   9886            case 0xC9:
   9887            case 0xCA:
   9888            case 0xCB:
   9889            case 0xCC:
   9890            case 0xCD:
   9891            case 0xCE:
   9892            case 0xCF:
   9893            case 0xD0:
   9894            case 0xD1:
   9895            case 0xD2:
   9896            case 0xD3:
   9897            case 0xD4:
   9898            case 0xD8: // tagged item (1 bytes follow)
   9899            case 0xD9: // tagged item (2 bytes follow)
   9900            case 0xDA: // tagged item (4 bytes follow)
   9901            case 0xDB: // tagged item (8 bytes follow)
   9902            {
   9903                switch (tag_handler)
   9904                {
   9905                    case cbor_tag_handler_t::error:
   9906                    {
   9907                        auto last_token = get_token_string();
   9908                        return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
   9909                                                exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
   9910                    }
   9911 
   9912                    case cbor_tag_handler_t::ignore:
   9913                    {
   9914                        // ignore binary subtype
   9915                        switch (current)
   9916                        {
   9917                            case 0xD8:
   9918                            {
   9919                                std::uint8_t subtype_to_ignore{};
   9920                                get_number(input_format_t::cbor, subtype_to_ignore);
   9921                                break;
   9922                            }
   9923                            case 0xD9:
   9924                            {
   9925                                std::uint16_t subtype_to_ignore{};
   9926                                get_number(input_format_t::cbor, subtype_to_ignore);
   9927                                break;
   9928                            }
   9929                            case 0xDA:
   9930                            {
   9931                                std::uint32_t subtype_to_ignore{};
   9932                                get_number(input_format_t::cbor, subtype_to_ignore);
   9933                                break;
   9934                            }
   9935                            case 0xDB:
   9936                            {
   9937                                std::uint64_t subtype_to_ignore{};
   9938                                get_number(input_format_t::cbor, subtype_to_ignore);
   9939                                break;
   9940                            }
   9941                            default:
   9942                                break;
   9943                        }
   9944                        return parse_cbor_internal(true, tag_handler);
   9945                    }
   9946 
   9947                    case cbor_tag_handler_t::store:
   9948                    {
   9949                        binary_t b;
   9950                        // use binary subtype and store in binary container
   9951                        switch (current)
   9952                        {
   9953                            case 0xD8:
   9954                            {
   9955                                std::uint8_t subtype{};
   9956                                get_number(input_format_t::cbor, subtype);
   9957                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9958                                break;
   9959                            }
   9960                            case 0xD9:
   9961                            {
   9962                                std::uint16_t subtype{};
   9963                                get_number(input_format_t::cbor, subtype);
   9964                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9965                                break;
   9966                            }
   9967                            case 0xDA:
   9968                            {
   9969                                std::uint32_t subtype{};
   9970                                get_number(input_format_t::cbor, subtype);
   9971                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9972                                break;
   9973                            }
   9974                            case 0xDB:
   9975                            {
   9976                                std::uint64_t subtype{};
   9977                                get_number(input_format_t::cbor, subtype);
   9978                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
   9979                                break;
   9980                            }
   9981                            default:
   9982                                return parse_cbor_internal(true, tag_handler);
   9983                        }
   9984                        get();
   9985                        return get_cbor_binary(b) && sax->binary(b);
   9986                    }
   9987 
   9988                    default:                 // LCOV_EXCL_LINE
   9989                        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
   9990                        return false;        // LCOV_EXCL_LINE
   9991                }
   9992            }
   9993 
   9994            case 0xF4: // false
   9995                return sax->boolean(false);
   9996 
   9997            case 0xF5: // true
   9998                return sax->boolean(true);
   9999 
  10000            case 0xF6: // null
  10001                return sax->null();
  10002 
  10003            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
  10004            {
  10005                const auto byte1_raw = get();
  10006                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
  10007                {
  10008                    return false;
  10009                }
  10010                const auto byte2_raw = get();
  10011                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
  10012                {
  10013                    return false;
  10014                }
  10015 
  10016                const auto byte1 = static_cast<unsigned char>(byte1_raw);
  10017                const auto byte2 = static_cast<unsigned char>(byte2_raw);
  10018 
  10019                // code from RFC 7049, Appendix D, Figure 3:
  10020                // As half-precision floating-point numbers were only added
  10021                // to IEEE 754 in 2008, today's programming platforms often
  10022                // still only have limited support for them. It is very
  10023                // easy to include at least decoding support for them even
  10024                // without such support. An example of a small decoder for
  10025                // half-precision floating-point numbers in the C language
  10026                // is shown in Fig. 3.
  10027                const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
  10028                const double val = [&half]
  10029                {
  10030                    const int exp = (half >> 10u) & 0x1Fu;
  10031                    const unsigned int mant = half & 0x3FFu;
  10032                    JSON_ASSERT(0 <= exp&& exp <= 32);
  10033                    JSON_ASSERT(mant <= 1024);
  10034                    switch (exp)
  10035                    {
  10036                        case 0:
  10037                            return std::ldexp(mant, -24);
  10038                        case 31:
  10039                            return (mant == 0)
  10040                            ? std::numeric_limits<double>::infinity()
  10041                            : std::numeric_limits<double>::quiet_NaN();
  10042                        default:
  10043                            return std::ldexp(mant + 1024, exp - 25);
  10044                    }
  10045                }();
  10046                return sax->number_float((half & 0x8000u) != 0
  10047                                         ? static_cast<number_float_t>(-val)
  10048                                         : static_cast<number_float_t>(val), "");
  10049            }
  10050 
  10051            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
  10052            {
  10053                float number{};
  10054                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
  10055            }
  10056 
  10057            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
  10058            {
  10059                double number{};
  10060                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
  10061            }
  10062 
  10063            default: // anything else (0xFF is handled inside the other types)
  10064            {
  10065                auto last_token = get_token_string();
  10066                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  10067                                        exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
  10068            }
  10069        }
  10070    }
  10071 
  10072    /*!
  10073    @brief reads a CBOR string
  10074 
  10075    This function first reads starting bytes to determine the expected
  10076    string length and then copies this number of bytes into a string.
  10077    Additionally, CBOR's strings with indefinite lengths are supported.
  10078 
  10079    @param[out] result  created string
  10080 
  10081    @return whether string creation completed
  10082    */
  10083    bool get_cbor_string(string_t& result)
  10084    {
  10085        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
  10086        {
  10087            return false;
  10088        }
  10089 
  10090        switch (current)
  10091        {
  10092            // UTF-8 string (0x00..0x17 bytes follow)
  10093            case 0x60:
  10094            case 0x61:
  10095            case 0x62:
  10096            case 0x63:
  10097            case 0x64:
  10098            case 0x65:
  10099            case 0x66:
  10100            case 0x67:
  10101            case 0x68:
  10102            case 0x69:
  10103            case 0x6A:
  10104            case 0x6B:
  10105            case 0x6C:
  10106            case 0x6D:
  10107            case 0x6E:
  10108            case 0x6F:
  10109            case 0x70:
  10110            case 0x71:
  10111            case 0x72:
  10112            case 0x73:
  10113            case 0x74:
  10114            case 0x75:
  10115            case 0x76:
  10116            case 0x77:
  10117            {
  10118                return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
  10119            }
  10120 
  10121            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
  10122            {
  10123                std::uint8_t len{};
  10124                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10125            }
  10126 
  10127            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
  10128            {
  10129                std::uint16_t len{};
  10130                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10131            }
  10132 
  10133            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
  10134            {
  10135                std::uint32_t len{};
  10136                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10137            }
  10138 
  10139            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
  10140            {
  10141                std::uint64_t len{};
  10142                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
  10143            }
  10144 
  10145            case 0x7F: // UTF-8 string (indefinite length)
  10146            {
  10147                while (get() != 0xFF)
  10148                {
  10149                    string_t chunk;
  10150                    if (!get_cbor_string(chunk))
  10151                    {
  10152                        return false;
  10153                    }
  10154                    result.append(chunk);
  10155                }
  10156                return true;
  10157            }
  10158 
  10159            default:
  10160            {
  10161                auto last_token = get_token_string();
  10162                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  10163                                        exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
  10164            }
  10165        }
  10166    }
  10167 
  10168    /*!
  10169    @brief reads a CBOR byte array
  10170 
  10171    This function first reads starting bytes to determine the expected
  10172    byte array length and then copies this number of bytes into the byte array.
  10173    Additionally, CBOR's byte arrays with indefinite lengths are supported.
  10174 
  10175    @param[out] result  created byte array
  10176 
  10177    @return whether byte array creation completed
  10178    */
  10179    bool get_cbor_binary(binary_t& result)
  10180    {
  10181        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
  10182        {
  10183            return false;
  10184        }
  10185 
  10186        switch (current)
  10187        {
  10188            // Binary data (0x00..0x17 bytes follow)
  10189            case 0x40:
  10190            case 0x41:
  10191            case 0x42:
  10192            case 0x43:
  10193            case 0x44:
  10194            case 0x45:
  10195            case 0x46:
  10196            case 0x47:
  10197            case 0x48:
  10198            case 0x49:
  10199            case 0x4A:
  10200            case 0x4B:
  10201            case 0x4C:
  10202            case 0x4D:
  10203            case 0x4E:
  10204            case 0x4F:
  10205            case 0x50:
  10206            case 0x51:
  10207            case 0x52:
  10208            case 0x53:
  10209            case 0x54:
  10210            case 0x55:
  10211            case 0x56:
  10212            case 0x57:
  10213            {
  10214                return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
  10215            }
  10216 
  10217            case 0x58: // Binary data (one-byte uint8_t for n follows)
  10218            {
  10219                std::uint8_t len{};
  10220                return get_number(input_format_t::cbor, len) &&
  10221                       get_binary(input_format_t::cbor, len, result);
  10222            }
  10223 
  10224            case 0x59: // Binary data (two-byte uint16_t for n follow)
  10225            {
  10226                std::uint16_t len{};
  10227                return get_number(input_format_t::cbor, len) &&
  10228                       get_binary(input_format_t::cbor, len, result);
  10229            }
  10230 
  10231            case 0x5A: // Binary data (four-byte uint32_t for n follow)
  10232            {
  10233                std::uint32_t len{};
  10234                return get_number(input_format_t::cbor, len) &&
  10235                       get_binary(input_format_t::cbor, len, result);
  10236            }
  10237 
  10238            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
  10239            {
  10240                std::uint64_t len{};
  10241                return get_number(input_format_t::cbor, len) &&
  10242                       get_binary(input_format_t::cbor, len, result);
  10243            }
  10244 
  10245            case 0x5F: // Binary data (indefinite length)
  10246            {
  10247                while (get() != 0xFF)
  10248                {
  10249                    binary_t chunk;
  10250                    if (!get_cbor_binary(chunk))
  10251                    {
  10252                        return false;
  10253                    }
  10254                    result.insert(result.end(), chunk.begin(), chunk.end());
  10255                }
  10256                return true;
  10257            }
  10258 
  10259            default:
  10260            {
  10261                auto last_token = get_token_string();
  10262                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  10263                                        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));
  10264            }
  10265        }
  10266    }
  10267 
  10268    /*!
  10269    @param[in] len  the length of the array or static_cast<std::size_t>(-1) for an
  10270                    array of indefinite size
  10271    @param[in] tag_handler how CBOR tags should be treated
  10272    @return whether array creation completed
  10273    */
  10274    bool get_cbor_array(const std::size_t len,
  10275                        const cbor_tag_handler_t tag_handler)
  10276    {
  10277        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
  10278        {
  10279            return false;
  10280        }
  10281 
  10282        if (len != static_cast<std::size_t>(-1))
  10283        {
  10284            for (std::size_t i = 0; i < len; ++i)
  10285            {
  10286                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
  10287                {
  10288                    return false;
  10289                }
  10290            }
  10291        }
  10292        else
  10293        {
  10294            while (get() != 0xFF)
  10295            {
  10296                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
  10297                {
  10298                    return false;
  10299                }
  10300            }
  10301        }
  10302 
  10303        return sax->end_array();
  10304    }
  10305 
  10306    /*!
  10307    @param[in] len  the length of the object or static_cast<std::size_t>(-1) for an
  10308                    object of indefinite size
  10309    @param[in] tag_handler how CBOR tags should be treated
  10310    @return whether object creation completed
  10311    */
  10312    bool get_cbor_object(const std::size_t len,
  10313                         const cbor_tag_handler_t tag_handler)
  10314    {
  10315        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
  10316        {
  10317            return false;
  10318        }
  10319 
  10320        if (len != 0)
  10321        {
  10322            string_t key;
  10323            if (len != static_cast<std::size_t>(-1))
  10324            {
  10325                for (std::size_t i = 0; i < len; ++i)
  10326                {
  10327                    get();
  10328                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
  10329                    {
  10330                        return false;
  10331                    }
  10332 
  10333                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
  10334                    {
  10335                        return false;
  10336                    }
  10337                    key.clear();
  10338                }
  10339            }
  10340            else
  10341            {
  10342                while (get() != 0xFF)
  10343                {
  10344                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
  10345                    {
  10346                        return false;
  10347                    }
  10348 
  10349                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
  10350                    {
  10351                        return false;
  10352                    }
  10353                    key.clear();
  10354                }
  10355            }
  10356        }
  10357 
  10358        return sax->end_object();
  10359    }
  10360 
  10361    /////////////
  10362    // MsgPack //
  10363    /////////////
  10364 
  10365    /*!
  10366    @return whether a valid MessagePack value was passed to the SAX parser
  10367    */
  10368    bool parse_msgpack_internal()
  10369    {
  10370        switch (get())
  10371        {
  10372            // EOF
  10373            case char_traits<char_type>::eof():
  10374                return unexpect_eof(input_format_t::msgpack, "value");
  10375 
  10376            // positive fixint
  10377            case 0x00:
  10378            case 0x01:
  10379            case 0x02:
  10380            case 0x03:
  10381            case 0x04:
  10382            case 0x05:
  10383            case 0x06:
  10384            case 0x07:
  10385            case 0x08:
  10386            case 0x09:
  10387            case 0x0A:
  10388            case 0x0B:
  10389            case 0x0C:
  10390            case 0x0D:
  10391            case 0x0E:
  10392            case 0x0F:
  10393            case 0x10:
  10394            case 0x11:
  10395            case 0x12:
  10396            case 0x13:
  10397            case 0x14:
  10398            case 0x15:
  10399            case 0x16:
  10400            case 0x17:
  10401            case 0x18:
  10402            case 0x19:
  10403            case 0x1A:
  10404            case 0x1B:
  10405            case 0x1C:
  10406            case 0x1D:
  10407            case 0x1E:
  10408            case 0x1F:
  10409            case 0x20:
  10410            case 0x21:
  10411            case 0x22:
  10412            case 0x23:
  10413            case 0x24:
  10414            case 0x25:
  10415            case 0x26:
  10416            case 0x27:
  10417            case 0x28:
  10418            case 0x29:
  10419            case 0x2A:
  10420            case 0x2B:
  10421            case 0x2C:
  10422            case 0x2D:
  10423            case 0x2E:
  10424            case 0x2F:
  10425            case 0x30:
  10426            case 0x31:
  10427            case 0x32:
  10428            case 0x33:
  10429            case 0x34:
  10430            case 0x35:
  10431            case 0x36:
  10432            case 0x37:
  10433            case 0x38:
  10434            case 0x39:
  10435            case 0x3A:
  10436            case 0x3B:
  10437            case 0x3C:
  10438            case 0x3D:
  10439            case 0x3E:
  10440            case 0x3F:
  10441            case 0x40:
  10442            case 0x41:
  10443            case 0x42:
  10444            case 0x43:
  10445            case 0x44:
  10446            case 0x45:
  10447            case 0x46:
  10448            case 0x47:
  10449            case 0x48:
  10450            case 0x49:
  10451            case 0x4A:
  10452            case 0x4B:
  10453            case 0x4C:
  10454            case 0x4D:
  10455            case 0x4E:
  10456            case 0x4F:
  10457            case 0x50:
  10458            case 0x51:
  10459            case 0x52:
  10460            case 0x53:
  10461            case 0x54:
  10462            case 0x55:
  10463            case 0x56:
  10464            case 0x57:
  10465            case 0x58:
  10466            case 0x59:
  10467            case 0x5A:
  10468            case 0x5B:
  10469            case 0x5C:
  10470            case 0x5D:
  10471            case 0x5E:
  10472            case 0x5F:
  10473            case 0x60:
  10474            case 0x61:
  10475            case 0x62:
  10476            case 0x63:
  10477            case 0x64:
  10478            case 0x65:
  10479            case 0x66:
  10480            case 0x67:
  10481            case 0x68:
  10482            case 0x69:
  10483            case 0x6A:
  10484            case 0x6B:
  10485            case 0x6C:
  10486            case 0x6D:
  10487            case 0x6E:
  10488            case 0x6F:
  10489            case 0x70:
  10490            case 0x71:
  10491            case 0x72:
  10492            case 0x73:
  10493            case 0x74:
  10494            case 0x75:
  10495            case 0x76:
  10496            case 0x77:
  10497            case 0x78:
  10498            case 0x79:
  10499            case 0x7A:
  10500            case 0x7B:
  10501            case 0x7C:
  10502            case 0x7D:
  10503            case 0x7E:
  10504            case 0x7F:
  10505                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
  10506 
  10507            // fixmap
  10508            case 0x80:
  10509            case 0x81:
  10510            case 0x82:
  10511            case 0x83:
  10512            case 0x84:
  10513            case 0x85:
  10514            case 0x86:
  10515            case 0x87:
  10516            case 0x88:
  10517            case 0x89:
  10518            case 0x8A:
  10519            case 0x8B:
  10520            case 0x8C:
  10521            case 0x8D:
  10522            case 0x8E:
  10523            case 0x8F:
  10524                return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
  10525 
  10526            // fixarray
  10527            case 0x90:
  10528            case 0x91:
  10529            case 0x92:
  10530            case 0x93:
  10531            case 0x94:
  10532            case 0x95:
  10533            case 0x96:
  10534            case 0x97:
  10535            case 0x98:
  10536            case 0x99:
  10537            case 0x9A:
  10538            case 0x9B:
  10539            case 0x9C:
  10540            case 0x9D:
  10541            case 0x9E:
  10542            case 0x9F:
  10543                return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
  10544 
  10545            // fixstr
  10546            case 0xA0:
  10547            case 0xA1:
  10548            case 0xA2:
  10549            case 0xA3:
  10550            case 0xA4:
  10551            case 0xA5:
  10552            case 0xA6:
  10553            case 0xA7:
  10554            case 0xA8:
  10555            case 0xA9:
  10556            case 0xAA:
  10557            case 0xAB:
  10558            case 0xAC:
  10559            case 0xAD:
  10560            case 0xAE:
  10561            case 0xAF:
  10562            case 0xB0:
  10563            case 0xB1:
  10564            case 0xB2:
  10565            case 0xB3:
  10566            case 0xB4:
  10567            case 0xB5:
  10568            case 0xB6:
  10569            case 0xB7:
  10570            case 0xB8:
  10571            case 0xB9:
  10572            case 0xBA:
  10573            case 0xBB:
  10574            case 0xBC:
  10575            case 0xBD:
  10576            case 0xBE:
  10577            case 0xBF:
  10578            case 0xD9: // str 8
  10579            case 0xDA: // str 16
  10580            case 0xDB: // str 32
  10581            {
  10582                string_t s;
  10583                return get_msgpack_string(s) && sax->string(s);
  10584            }
  10585 
  10586            case 0xC0: // nil
  10587                return sax->null();
  10588 
  10589            case 0xC2: // false
  10590                return sax->boolean(false);
  10591 
  10592            case 0xC3: // true
  10593                return sax->boolean(true);
  10594 
  10595            case 0xC4: // bin 8
  10596            case 0xC5: // bin 16
  10597            case 0xC6: // bin 32
  10598            case 0xC7: // ext 8
  10599            case 0xC8: // ext 16
  10600            case 0xC9: // ext 32
  10601            case 0xD4: // fixext 1
  10602            case 0xD5: // fixext 2
  10603            case 0xD6: // fixext 4
  10604            case 0xD7: // fixext 8
  10605            case 0xD8: // fixext 16
  10606            {
  10607                binary_t b;
  10608                return get_msgpack_binary(b) && sax->binary(b);
  10609            }
  10610 
  10611            case 0xCA: // float 32
  10612            {
  10613                float number{};
  10614                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
  10615            }
  10616 
  10617            case 0xCB: // float 64
  10618            {
  10619                double number{};
  10620                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
  10621            }
  10622 
  10623            case 0xCC: // uint 8
  10624            {
  10625                std::uint8_t number{};
  10626                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10627            }
  10628 
  10629            case 0xCD: // uint 16
  10630            {
  10631                std::uint16_t number{};
  10632                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10633            }
  10634 
  10635            case 0xCE: // uint 32
  10636            {
  10637                std::uint32_t number{};
  10638                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10639            }
  10640 
  10641            case 0xCF: // uint 64
  10642            {
  10643                std::uint64_t number{};
  10644                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
  10645            }
  10646 
  10647            case 0xD0: // int 8
  10648            {
  10649                std::int8_t number{};
  10650                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10651            }
  10652 
  10653            case 0xD1: // int 16
  10654            {
  10655                std::int16_t number{};
  10656                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10657            }
  10658 
  10659            case 0xD2: // int 32
  10660            {
  10661                std::int32_t number{};
  10662                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10663            }
  10664 
  10665            case 0xD3: // int 64
  10666            {
  10667                std::int64_t number{};
  10668                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
  10669            }
  10670 
  10671            case 0xDC: // array 16
  10672            {
  10673                std::uint16_t len{};
  10674                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
  10675            }
  10676 
  10677            case 0xDD: // array 32
  10678            {
  10679                std::uint32_t len{};
  10680                return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
  10681            }
  10682 
  10683            case 0xDE: // map 16
  10684            {
  10685                std::uint16_t len{};
  10686                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
  10687            }
  10688 
  10689            case 0xDF: // map 32
  10690            {
  10691                std::uint32_t len{};
  10692                return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
  10693            }
  10694 
  10695            // negative fixint
  10696            case 0xE0:
  10697            case 0xE1:
  10698            case 0xE2:
  10699            case 0xE3:
  10700            case 0xE4:
  10701            case 0xE5:
  10702            case 0xE6:
  10703            case 0xE7:
  10704            case 0xE8:
  10705            case 0xE9:
  10706            case 0xEA:
  10707            case 0xEB:
  10708            case 0xEC:
  10709            case 0xED:
  10710            case 0xEE:
  10711            case 0xEF:
  10712            case 0xF0:
  10713            case 0xF1:
  10714            case 0xF2:
  10715            case 0xF3:
  10716            case 0xF4:
  10717            case 0xF5:
  10718            case 0xF6:
  10719            case 0xF7:
  10720            case 0xF8:
  10721            case 0xF9:
  10722            case 0xFA:
  10723            case 0xFB:
  10724            case 0xFC:
  10725            case 0xFD:
  10726            case 0xFE:
  10727            case 0xFF:
  10728                return sax->number_integer(static_cast<std::int8_t>(current));
  10729 
  10730            default: // anything else
  10731            {
  10732                auto last_token = get_token_string();
  10733                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  10734                                        exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
  10735            }
  10736        }
  10737    }
  10738 
  10739    /*!
  10740    @brief reads a MessagePack string
  10741 
  10742    This function first reads starting bytes to determine the expected
  10743    string length and then copies this number of bytes into a string.
  10744 
  10745    @param[out] result  created string
  10746 
  10747    @return whether string creation completed
  10748    */
  10749    bool get_msgpack_string(string_t& result)
  10750    {
  10751        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
  10752        {
  10753            return false;
  10754        }
  10755 
  10756        switch (current)
  10757        {
  10758            // fixstr
  10759            case 0xA0:
  10760            case 0xA1:
  10761            case 0xA2:
  10762            case 0xA3:
  10763            case 0xA4:
  10764            case 0xA5:
  10765            case 0xA6:
  10766            case 0xA7:
  10767            case 0xA8:
  10768            case 0xA9:
  10769            case 0xAA:
  10770            case 0xAB:
  10771            case 0xAC:
  10772            case 0xAD:
  10773            case 0xAE:
  10774            case 0xAF:
  10775            case 0xB0:
  10776            case 0xB1:
  10777            case 0xB2:
  10778            case 0xB3:
  10779            case 0xB4:
  10780            case 0xB5:
  10781            case 0xB6:
  10782            case 0xB7:
  10783            case 0xB8:
  10784            case 0xB9:
  10785            case 0xBA:
  10786            case 0xBB:
  10787            case 0xBC:
  10788            case 0xBD:
  10789            case 0xBE:
  10790            case 0xBF:
  10791            {
  10792                return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
  10793            }
  10794 
  10795            case 0xD9: // str 8
  10796            {
  10797                std::uint8_t len{};
  10798                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
  10799            }
  10800 
  10801            case 0xDA: // str 16
  10802            {
  10803                std::uint16_t len{};
  10804                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
  10805            }
  10806 
  10807            case 0xDB: // str 32
  10808            {
  10809                std::uint32_t len{};
  10810                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
  10811            }
  10812 
  10813            default:
  10814            {
  10815                auto last_token = get_token_string();
  10816                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  10817                                        exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
  10818            }
  10819        }
  10820    }
  10821 
  10822    /*!
  10823    @brief reads a MessagePack byte array
  10824 
  10825    This function first reads starting bytes to determine the expected
  10826    byte array length and then copies this number of bytes into a byte array.
  10827 
  10828    @param[out] result  created byte array
  10829 
  10830    @return whether byte array creation completed
  10831    */
  10832    bool get_msgpack_binary(binary_t& result)
  10833    {
  10834        // helper function to set the subtype
  10835        auto assign_and_return_true = [&result](std::int8_t subtype)
  10836        {
  10837            result.set_subtype(static_cast<std::uint8_t>(subtype));
  10838            return true;
  10839        };
  10840 
  10841        switch (current)
  10842        {
  10843            case 0xC4: // bin 8
  10844            {
  10845                std::uint8_t len{};
  10846                return get_number(input_format_t::msgpack, len) &&
  10847                       get_binary(input_format_t::msgpack, len, result);
  10848            }
  10849 
  10850            case 0xC5: // bin 16
  10851            {
  10852                std::uint16_t len{};
  10853                return get_number(input_format_t::msgpack, len) &&
  10854                       get_binary(input_format_t::msgpack, len, result);
  10855            }
  10856 
  10857            case 0xC6: // bin 32
  10858            {
  10859                std::uint32_t len{};
  10860                return get_number(input_format_t::msgpack, len) &&
  10861                       get_binary(input_format_t::msgpack, len, result);
  10862            }
  10863 
  10864            case 0xC7: // ext 8
  10865            {
  10866                std::uint8_t len{};
  10867                std::int8_t subtype{};
  10868                return get_number(input_format_t::msgpack, len) &&
  10869                       get_number(input_format_t::msgpack, subtype) &&
  10870                       get_binary(input_format_t::msgpack, len, result) &&
  10871                       assign_and_return_true(subtype);
  10872            }
  10873 
  10874            case 0xC8: // ext 16
  10875            {
  10876                std::uint16_t len{};
  10877                std::int8_t subtype{};
  10878                return get_number(input_format_t::msgpack, len) &&
  10879                       get_number(input_format_t::msgpack, subtype) &&
  10880                       get_binary(input_format_t::msgpack, len, result) &&
  10881                       assign_and_return_true(subtype);
  10882            }
  10883 
  10884            case 0xC9: // ext 32
  10885            {
  10886                std::uint32_t len{};
  10887                std::int8_t subtype{};
  10888                return get_number(input_format_t::msgpack, len) &&
  10889                       get_number(input_format_t::msgpack, subtype) &&
  10890                       get_binary(input_format_t::msgpack, len, result) &&
  10891                       assign_and_return_true(subtype);
  10892            }
  10893 
  10894            case 0xD4: // fixext 1
  10895            {
  10896                std::int8_t subtype{};
  10897                return get_number(input_format_t::msgpack, subtype) &&
  10898                       get_binary(input_format_t::msgpack, 1, result) &&
  10899                       assign_and_return_true(subtype);
  10900            }
  10901 
  10902            case 0xD5: // fixext 2
  10903            {
  10904                std::int8_t subtype{};
  10905                return get_number(input_format_t::msgpack, subtype) &&
  10906                       get_binary(input_format_t::msgpack, 2, result) &&
  10907                       assign_and_return_true(subtype);
  10908            }
  10909 
  10910            case 0xD6: // fixext 4
  10911            {
  10912                std::int8_t subtype{};
  10913                return get_number(input_format_t::msgpack, subtype) &&
  10914                       get_binary(input_format_t::msgpack, 4, result) &&
  10915                       assign_and_return_true(subtype);
  10916            }
  10917 
  10918            case 0xD7: // fixext 8
  10919            {
  10920                std::int8_t subtype{};
  10921                return get_number(input_format_t::msgpack, subtype) &&
  10922                       get_binary(input_format_t::msgpack, 8, result) &&
  10923                       assign_and_return_true(subtype);
  10924            }
  10925 
  10926            case 0xD8: // fixext 16
  10927            {
  10928                std::int8_t subtype{};
  10929                return get_number(input_format_t::msgpack, subtype) &&
  10930                       get_binary(input_format_t::msgpack, 16, result) &&
  10931                       assign_and_return_true(subtype);
  10932            }
  10933 
  10934            default:           // LCOV_EXCL_LINE
  10935                return false;  // LCOV_EXCL_LINE
  10936        }
  10937    }
  10938 
  10939    /*!
  10940    @param[in] len  the length of the array
  10941    @return whether array creation completed
  10942    */
  10943    bool get_msgpack_array(const std::size_t len)
  10944    {
  10945        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
  10946        {
  10947            return false;
  10948        }
  10949 
  10950        for (std::size_t i = 0; i < len; ++i)
  10951        {
  10952            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
  10953            {
  10954                return false;
  10955            }
  10956        }
  10957 
  10958        return sax->end_array();
  10959    }
  10960 
  10961    /*!
  10962    @param[in] len  the length of the object
  10963    @return whether object creation completed
  10964    */
  10965    bool get_msgpack_object(const std::size_t len)
  10966    {
  10967        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
  10968        {
  10969            return false;
  10970        }
  10971 
  10972        string_t key;
  10973        for (std::size_t i = 0; i < len; ++i)
  10974        {
  10975            get();
  10976            if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
  10977            {
  10978                return false;
  10979            }
  10980 
  10981            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
  10982            {
  10983                return false;
  10984            }
  10985            key.clear();
  10986        }
  10987 
  10988        return sax->end_object();
  10989    }
  10990 
  10991    ////////////
  10992    // UBJSON //
  10993    ////////////
  10994 
  10995    /*!
  10996    @param[in] get_char  whether a new character should be retrieved from the
  10997                         input (true, default) or whether the last read
  10998                         character should be considered instead
  10999 
  11000    @return whether a valid UBJSON value was passed to the SAX parser
  11001    */
  11002    bool parse_ubjson_internal(const bool get_char = true)
  11003    {
  11004        return get_ubjson_value(get_char ? get_ignore_noop() : current);
  11005    }
  11006 
  11007    /*!
  11008    @brief reads a UBJSON string
  11009 
  11010    This function is either called after reading the 'S' byte explicitly
  11011    indicating a string, or in case of an object key where the 'S' byte can be
  11012    left out.
  11013 
  11014    @param[out] result   created string
  11015    @param[in] get_char  whether a new character should be retrieved from the
  11016                         input (true, default) or whether the last read
  11017                         character should be considered instead
  11018 
  11019    @return whether string creation completed
  11020    */
  11021    bool get_ubjson_string(string_t& result, const bool get_char = true)
  11022    {
  11023        if (get_char)
  11024        {
  11025            get();  // TODO(niels): may we ignore N here?
  11026        }
  11027 
  11028        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
  11029        {
  11030            return false;
  11031        }
  11032 
  11033        switch (current)
  11034        {
  11035            case 'U':
  11036            {
  11037                std::uint8_t len{};
  11038                return get_number(input_format, len) && get_string(input_format, len, result);
  11039            }
  11040 
  11041            case 'i':
  11042            {
  11043                std::int8_t len{};
  11044                return get_number(input_format, len) && get_string(input_format, len, result);
  11045            }
  11046 
  11047            case 'I':
  11048            {
  11049                std::int16_t len{};
  11050                return get_number(input_format, len) && get_string(input_format, len, result);
  11051            }
  11052 
  11053            case 'l':
  11054            {
  11055                std::int32_t len{};
  11056                return get_number(input_format, len) && get_string(input_format, len, result);
  11057            }
  11058 
  11059            case 'L':
  11060            {
  11061                std::int64_t len{};
  11062                return get_number(input_format, len) && get_string(input_format, len, result);
  11063            }
  11064 
  11065            case 'u':
  11066            {
  11067                if (input_format != input_format_t::bjdata)
  11068                {
  11069                    break;
  11070                }
  11071                std::uint16_t len{};
  11072                return get_number(input_format, len) && get_string(input_format, len, result);
  11073            }
  11074 
  11075            case 'm':
  11076            {
  11077                if (input_format != input_format_t::bjdata)
  11078                {
  11079                    break;
  11080                }
  11081                std::uint32_t len{};
  11082                return get_number(input_format, len) && get_string(input_format, len, result);
  11083            }
  11084 
  11085            case 'M':
  11086            {
  11087                if (input_format != input_format_t::bjdata)
  11088                {
  11089                    break;
  11090                }
  11091                std::uint64_t len{};
  11092                return get_number(input_format, len) && get_string(input_format, len, result);
  11093            }
  11094 
  11095            default:
  11096                break;
  11097        }
  11098        auto last_token = get_token_string();
  11099        std::string message;
  11100 
  11101        if (input_format != input_format_t::bjdata)
  11102        {
  11103            message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
  11104        }
  11105        else
  11106        {
  11107            message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
  11108        }
  11109        return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
  11110    }
  11111 
  11112    /*!
  11113    @param[out] dim  an integer vector storing the ND array dimensions
  11114    @return whether reading ND array size vector is successful
  11115    */
  11116    bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
  11117    {
  11118        std::pair<std::size_t, char_int_type> size_and_type;
  11119        size_t dimlen = 0;
  11120        bool no_ndarray = true;
  11121 
  11122        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
  11123        {
  11124            return false;
  11125        }
  11126 
  11127        if (size_and_type.first != npos)
  11128        {
  11129            if (size_and_type.second != 0)
  11130            {
  11131                if (size_and_type.second != 'N')
  11132                {
  11133                    for (std::size_t i = 0; i < size_and_type.first; ++i)
  11134                    {
  11135                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
  11136                        {
  11137                            return false;
  11138                        }
  11139                        dim.push_back(dimlen);
  11140                    }
  11141                }
  11142            }
  11143            else
  11144            {
  11145                for (std::size_t i = 0; i < size_and_type.first; ++i)
  11146                {
  11147                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
  11148                    {
  11149                        return false;
  11150                    }
  11151                    dim.push_back(dimlen);
  11152                }
  11153            }
  11154        }
  11155        else
  11156        {
  11157            while (current != ']')
  11158            {
  11159                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
  11160                {
  11161                    return false;
  11162                }
  11163                dim.push_back(dimlen);
  11164                get_ignore_noop();
  11165            }
  11166        }
  11167        return true;
  11168    }
  11169 
  11170    /*!
  11171    @param[out] result  determined size
  11172    @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector
  11173                               or ndarray dimension is not allowed; `false` means ndarray
  11174                               is allowed; for output, `true` means an ndarray is found;
  11175                               is_ndarray can only return `true` when its initial value
  11176                               is `false`
  11177    @param[in] prefix  type marker if already read, otherwise set to 0
  11178 
  11179    @return whether size determination completed
  11180    */
  11181    bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
  11182    {
  11183        if (prefix == 0)
  11184        {
  11185            prefix = get_ignore_noop();
  11186        }
  11187 
  11188        switch (prefix)
  11189        {
  11190            case 'U':
  11191            {
  11192                std::uint8_t number{};
  11193                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11194                {
  11195                    return false;
  11196                }
  11197                result = static_cast<std::size_t>(number);
  11198                return true;
  11199            }
  11200 
  11201            case 'i':
  11202            {
  11203                std::int8_t number{};
  11204                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11205                {
  11206                    return false;
  11207                }
  11208                if (number < 0)
  11209                {
  11210                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11211                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11212                }
  11213                result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
  11214                return true;
  11215            }
  11216 
  11217            case 'I':
  11218            {
  11219                std::int16_t number{};
  11220                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11221                {
  11222                    return false;
  11223                }
  11224                if (number < 0)
  11225                {
  11226                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11227                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11228                }
  11229                result = static_cast<std::size_t>(number);
  11230                return true;
  11231            }
  11232 
  11233            case 'l':
  11234            {
  11235                std::int32_t number{};
  11236                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11237                {
  11238                    return false;
  11239                }
  11240                if (number < 0)
  11241                {
  11242                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11243                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11244                }
  11245                result = static_cast<std::size_t>(number);
  11246                return true;
  11247            }
  11248 
  11249            case 'L':
  11250            {
  11251                std::int64_t number{};
  11252                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11253                {
  11254                    return false;
  11255                }
  11256                if (number < 0)
  11257                {
  11258                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
  11259                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
  11260                }
  11261                if (!value_in_range_of<std::size_t>(number))
  11262                {
  11263                    return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
  11264                                            exception_message(input_format, "integer value overflow", "size"), nullptr));
  11265                }
  11266                result = static_cast<std::size_t>(number);
  11267                return true;
  11268            }
  11269 
  11270            case 'u':
  11271            {
  11272                if (input_format != input_format_t::bjdata)
  11273                {
  11274                    break;
  11275                }
  11276                std::uint16_t number{};
  11277                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11278                {
  11279                    return false;
  11280                }
  11281                result = static_cast<std::size_t>(number);
  11282                return true;
  11283            }
  11284 
  11285            case 'm':
  11286            {
  11287                if (input_format != input_format_t::bjdata)
  11288                {
  11289                    break;
  11290                }
  11291                std::uint32_t number{};
  11292                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11293                {
  11294                    return false;
  11295                }
  11296                result = conditional_static_cast<std::size_t>(number);
  11297                return true;
  11298            }
  11299 
  11300            case 'M':
  11301            {
  11302                if (input_format != input_format_t::bjdata)
  11303                {
  11304                    break;
  11305                }
  11306                std::uint64_t number{};
  11307                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
  11308                {
  11309                    return false;
  11310                }
  11311                if (!value_in_range_of<std::size_t>(number))
  11312                {
  11313                    return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
  11314                                            exception_message(input_format, "integer value overflow", "size"), nullptr));
  11315                }
  11316                result = detail::conditional_static_cast<std::size_t>(number);
  11317                return true;
  11318            }
  11319 
  11320            case '[':
  11321            {
  11322                if (input_format != input_format_t::bjdata)
  11323                {
  11324                    break;
  11325                }
  11326                if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
  11327                {
  11328                    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));
  11329                }
  11330                std::vector<size_t> dim;
  11331                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
  11332                {
  11333                    return false;
  11334                }
  11335                if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
  11336                {
  11337                    result = dim.at(dim.size() - 1);
  11338                    return true;
  11339                }
  11340                if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
  11341                {
  11342                    for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
  11343                    {
  11344                        if ( i == 0 )
  11345                        {
  11346                            result = 0;
  11347                            return true;
  11348                        }
  11349                    }
  11350 
  11351                    string_t key = "_ArraySize_";
  11352                    if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
  11353                    {
  11354                        return false;
  11355                    }
  11356                    result = 1;
  11357                    for (auto i : dim)
  11358                    {
  11359                        result *= i;
  11360                        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()
  11361                        {
  11362                            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));
  11363                        }
  11364                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
  11365                        {
  11366                            return false;
  11367                        }
  11368                    }
  11369                    is_ndarray = true;
  11370                    return sax->end_array();
  11371                }
  11372                result = 0;
  11373                return true;
  11374            }
  11375 
  11376            default:
  11377                break;
  11378        }
  11379        auto last_token = get_token_string();
  11380        std::string message;
  11381 
  11382        if (input_format != input_format_t::bjdata)
  11383        {
  11384            message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
  11385        }
  11386        else
  11387        {
  11388            message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
  11389        }
  11390        return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
  11391    }
  11392 
  11393    /*!
  11394    @brief determine the type and size for a container
  11395 
  11396    In the optimized UBJSON format, a type and a size can be provided to allow
  11397    for a more compact representation.
  11398 
  11399    @param[out] result  pair of the size and the type
  11400    @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector
  11401 
  11402    @return whether pair creation completed
  11403    */
  11404    bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
  11405    {
  11406        result.first = npos; // size
  11407        result.second = 0; // type
  11408        bool is_ndarray = false;
  11409 
  11410        get_ignore_noop();
  11411 
  11412        if (current == '$')
  11413        {
  11414            result.second = get();  // must not ignore 'N', because 'N' maybe the type
  11415            if (input_format == input_format_t::bjdata
  11416                    && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
  11417            {
  11418                auto last_token = get_token_string();
  11419                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11420                                        exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
  11421            }
  11422 
  11423            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
  11424            {
  11425                return false;
  11426            }
  11427 
  11428            get_ignore_noop();
  11429            if (JSON_HEDLEY_UNLIKELY(current != '#'))
  11430            {
  11431                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
  11432                {
  11433                    return false;
  11434                }
  11435                auto last_token = get_token_string();
  11436                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11437                                        exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
  11438            }
  11439 
  11440            const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
  11441            if (input_format == input_format_t::bjdata && is_ndarray)
  11442            {
  11443                if (inside_ndarray)
  11444                {
  11445                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
  11446                                            exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
  11447                }
  11448                result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
  11449            }
  11450            return is_error;
  11451        }
  11452 
  11453        if (current == '#')
  11454        {
  11455            const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
  11456            if (input_format == input_format_t::bjdata && is_ndarray)
  11457            {
  11458                return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
  11459                                        exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
  11460            }
  11461            return is_error;
  11462        }
  11463 
  11464        return true;
  11465    }
  11466 
  11467    /*!
  11468    @param prefix  the previously read or set type prefix
  11469    @return whether value creation completed
  11470    */
  11471    bool get_ubjson_value(const char_int_type prefix)
  11472    {
  11473        switch (prefix)
  11474        {
  11475            case char_traits<char_type>::eof():  // EOF
  11476                return unexpect_eof(input_format, "value");
  11477 
  11478            case 'T':  // true
  11479                return sax->boolean(true);
  11480            case 'F':  // false
  11481                return sax->boolean(false);
  11482 
  11483            case 'Z':  // null
  11484                return sax->null();
  11485 
  11486            case 'U':
  11487            {
  11488                std::uint8_t number{};
  11489                return get_number(input_format, number) && sax->number_unsigned(number);
  11490            }
  11491 
  11492            case 'i':
  11493            {
  11494                std::int8_t number{};
  11495                return get_number(input_format, number) && sax->number_integer(number);
  11496            }
  11497 
  11498            case 'I':
  11499            {
  11500                std::int16_t number{};
  11501                return get_number(input_format, number) && sax->number_integer(number);
  11502            }
  11503 
  11504            case 'l':
  11505            {
  11506                std::int32_t number{};
  11507                return get_number(input_format, number) && sax->number_integer(number);
  11508            }
  11509 
  11510            case 'L':
  11511            {
  11512                std::int64_t number{};
  11513                return get_number(input_format, number) && sax->number_integer(number);
  11514            }
  11515 
  11516            case 'u':
  11517            {
  11518                if (input_format != input_format_t::bjdata)
  11519                {
  11520                    break;
  11521                }
  11522                std::uint16_t number{};
  11523                return get_number(input_format, number) && sax->number_unsigned(number);
  11524            }
  11525 
  11526            case 'm':
  11527            {
  11528                if (input_format != input_format_t::bjdata)
  11529                {
  11530                    break;
  11531                }
  11532                std::uint32_t number{};
  11533                return get_number(input_format, number) && sax->number_unsigned(number);
  11534            }
  11535 
  11536            case 'M':
  11537            {
  11538                if (input_format != input_format_t::bjdata)
  11539                {
  11540                    break;
  11541                }
  11542                std::uint64_t number{};
  11543                return get_number(input_format, number) && sax->number_unsigned(number);
  11544            }
  11545 
  11546            case 'h':
  11547            {
  11548                if (input_format != input_format_t::bjdata)
  11549                {
  11550                    break;
  11551                }
  11552                const auto byte1_raw = get();
  11553                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
  11554                {
  11555                    return false;
  11556                }
  11557                const auto byte2_raw = get();
  11558                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
  11559                {
  11560                    return false;
  11561                }
  11562 
  11563                const auto byte1 = static_cast<unsigned char>(byte1_raw);
  11564                const auto byte2 = static_cast<unsigned char>(byte2_raw);
  11565 
  11566                // code from RFC 7049, Appendix D, Figure 3:
  11567                // As half-precision floating-point numbers were only added
  11568                // to IEEE 754 in 2008, today's programming platforms often
  11569                // still only have limited support for them. It is very
  11570                // easy to include at least decoding support for them even
  11571                // without such support. An example of a small decoder for
  11572                // half-precision floating-point numbers in the C language
  11573                // is shown in Fig. 3.
  11574                const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
  11575                const double val = [&half]
  11576                {
  11577                    const int exp = (half >> 10u) & 0x1Fu;
  11578                    const unsigned int mant = half & 0x3FFu;
  11579                    JSON_ASSERT(0 <= exp&& exp <= 32);
  11580                    JSON_ASSERT(mant <= 1024);
  11581                    switch (exp)
  11582                    {
  11583                        case 0:
  11584                            return std::ldexp(mant, -24);
  11585                        case 31:
  11586                            return (mant == 0)
  11587                            ? std::numeric_limits<double>::infinity()
  11588                            : std::numeric_limits<double>::quiet_NaN();
  11589                        default:
  11590                            return std::ldexp(mant + 1024, exp - 25);
  11591                    }
  11592                }();
  11593                return sax->number_float((half & 0x8000u) != 0
  11594                                         ? static_cast<number_float_t>(-val)
  11595                                         : static_cast<number_float_t>(val), "");
  11596            }
  11597 
  11598            case 'd':
  11599            {
  11600                float number{};
  11601                return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
  11602            }
  11603 
  11604            case 'D':
  11605            {
  11606                double number{};
  11607                return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
  11608            }
  11609 
  11610            case 'H':
  11611            {
  11612                return get_ubjson_high_precision_number();
  11613            }
  11614 
  11615            case 'C':  // char
  11616            {
  11617                get();
  11618                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
  11619                {
  11620                    return false;
  11621                }
  11622                if (JSON_HEDLEY_UNLIKELY(current > 127))
  11623                {
  11624                    auto last_token = get_token_string();
  11625                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
  11626                                            exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
  11627                }
  11628                string_t s(1, static_cast<typename string_t::value_type>(current));
  11629                return sax->string(s);
  11630            }
  11631 
  11632            case 'S':  // string
  11633            {
  11634                string_t s;
  11635                return get_ubjson_string(s) && sax->string(s);
  11636            }
  11637 
  11638            case '[':  // array
  11639                return get_ubjson_array();
  11640 
  11641            case '{':  // object
  11642                return get_ubjson_object();
  11643 
  11644            default: // anything else
  11645                break;
  11646        }
  11647        auto last_token = get_token_string();
  11648        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));
  11649    }
  11650 
  11651    /*!
  11652    @return whether array creation completed
  11653    */
  11654    bool get_ubjson_array()
  11655    {
  11656        std::pair<std::size_t, char_int_type> size_and_type;
  11657        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
  11658        {
  11659            return false;
  11660        }
  11661 
  11662        // 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):
  11663        // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
  11664 
  11665        if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
  11666        {
  11667            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
  11668            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)
  11669            {
  11670                return p.first < t;
  11671            });
  11672            string_t key = "_ArrayType_";
  11673            if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
  11674            {
  11675                auto last_token = get_token_string();
  11676                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11677                                        exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
  11678            }
  11679 
  11680            string_t type = it->second; // sax->string() takes a reference
  11681            if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
  11682            {
  11683                return false;
  11684            }
  11685 
  11686            if (size_and_type.second == 'C')
  11687            {
  11688                size_and_type.second = 'U';
  11689            }
  11690 
  11691            key = "_ArrayData_";
  11692            if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
  11693            {
  11694                return false;
  11695            }
  11696 
  11697            for (std::size_t i = 0; i < size_and_type.first; ++i)
  11698            {
  11699                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
  11700                {
  11701                    return false;
  11702                }
  11703            }
  11704 
  11705            return (sax->end_array() && sax->end_object());
  11706        }
  11707 
  11708        if (size_and_type.first != npos)
  11709        {
  11710            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
  11711            {
  11712                return false;
  11713            }
  11714 
  11715            if (size_and_type.second != 0)
  11716            {
  11717                if (size_and_type.second != 'N')
  11718                {
  11719                    for (std::size_t i = 0; i < size_and_type.first; ++i)
  11720                    {
  11721                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
  11722                        {
  11723                            return false;
  11724                        }
  11725                    }
  11726                }
  11727            }
  11728            else
  11729            {
  11730                for (std::size_t i = 0; i < size_and_type.first; ++i)
  11731                {
  11732                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
  11733                    {
  11734                        return false;
  11735                    }
  11736                }
  11737            }
  11738        }
  11739        else
  11740        {
  11741            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
  11742            {
  11743                return false;
  11744            }
  11745 
  11746            while (current != ']')
  11747            {
  11748                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
  11749                {
  11750                    return false;
  11751                }
  11752                get_ignore_noop();
  11753            }
  11754        }
  11755 
  11756        return sax->end_array();
  11757    }
  11758 
  11759    /*!
  11760    @return whether object creation completed
  11761    */
  11762    bool get_ubjson_object()
  11763    {
  11764        std::pair<std::size_t, char_int_type> size_and_type;
  11765        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
  11766        {
  11767            return false;
  11768        }
  11769 
  11770        // do not accept ND-array size in objects in BJData
  11771        if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
  11772        {
  11773            auto last_token = get_token_string();
  11774            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
  11775                                    exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
  11776        }
  11777 
  11778        string_t key;
  11779        if (size_and_type.first != npos)
  11780        {
  11781            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
  11782            {
  11783                return false;
  11784            }
  11785 
  11786            if (size_and_type.second != 0)
  11787            {
  11788                for (std::size_t i = 0; i < size_and_type.first; ++i)
  11789                {
  11790                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
  11791                    {
  11792                        return false;
  11793                    }
  11794                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
  11795                    {
  11796                        return false;
  11797                    }
  11798                    key.clear();
  11799                }
  11800            }
  11801            else
  11802            {
  11803                for (std::size_t i = 0; i < size_and_type.first; ++i)
  11804                {
  11805                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
  11806                    {
  11807                        return false;
  11808                    }
  11809                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
  11810                    {
  11811                        return false;
  11812                    }
  11813                    key.clear();
  11814                }
  11815            }
  11816        }
  11817        else
  11818        {
  11819            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
  11820            {
  11821                return false;
  11822            }
  11823 
  11824            while (current != '}')
  11825            {
  11826                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
  11827                {
  11828                    return false;
  11829                }
  11830                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
  11831                {
  11832                    return false;
  11833                }
  11834                get_ignore_noop();
  11835                key.clear();
  11836            }
  11837        }
  11838 
  11839        return sax->end_object();
  11840    }
  11841 
  11842    // Note, no reader for UBJSON binary types is implemented because they do
  11843    // not exist
  11844 
  11845    bool get_ubjson_high_precision_number()
  11846    {
  11847        // get size of following number string
  11848        std::size_t size{};
  11849        bool no_ndarray = true;
  11850        auto res = get_ubjson_size_value(size, no_ndarray);
  11851        if (JSON_HEDLEY_UNLIKELY(!res))
  11852        {
  11853            return res;
  11854        }
  11855 
  11856        // get number string
  11857        std::vector<char> number_vector;
  11858        for (std::size_t i = 0; i < size; ++i)
  11859        {
  11860            get();
  11861            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
  11862            {
  11863                return false;
  11864            }
  11865            number_vector.push_back(static_cast<char>(current));
  11866        }
  11867 
  11868        // parse number string
  11869        using ia_type = decltype(detail::input_adapter(number_vector));
  11870        auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
  11871        const auto result_number = number_lexer.scan();
  11872        const auto number_string = number_lexer.get_token_string();
  11873        const auto result_remainder = number_lexer.scan();
  11874 
  11875        using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
  11876 
  11877        if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
  11878        {
  11879            return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
  11880                                    exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
  11881        }
  11882 
  11883        switch (result_number)
  11884        {
  11885            case token_type::value_integer:
  11886                return sax->number_integer(number_lexer.get_number_integer());
  11887            case token_type::value_unsigned:
  11888                return sax->number_unsigned(number_lexer.get_number_unsigned());
  11889            case token_type::value_float:
  11890                return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
  11891            case token_type::uninitialized:
  11892            case token_type::literal_true:
  11893            case token_type::literal_false:
  11894            case token_type::literal_null:
  11895            case token_type::value_string:
  11896            case token_type::begin_array:
  11897            case token_type::begin_object:
  11898            case token_type::end_array:
  11899            case token_type::end_object:
  11900            case token_type::name_separator:
  11901            case token_type::value_separator:
  11902            case token_type::parse_error:
  11903            case token_type::end_of_input:
  11904            case token_type::literal_or_value:
  11905            default:
  11906                return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
  11907                                        exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
  11908        }
  11909    }
  11910 
  11911    ///////////////////////
  11912    // Utility functions //
  11913    ///////////////////////
  11914 
  11915    /*!
  11916    @brief get next character from the input
  11917 
  11918    This function provides the interface to the used input adapter. It does
  11919    not throw in case the input reached EOF, but returns a -'ve valued
  11920    `char_traits<char_type>::eof()` in that case.
  11921 
  11922    @return character read from the input
  11923    */
  11924    char_int_type get()
  11925    {
  11926        ++chars_read;
  11927        return current = ia.get_character();
  11928    }
  11929 
  11930    /*!
  11931    @return character read from the input after ignoring all 'N' entries
  11932    */
  11933    char_int_type get_ignore_noop()
  11934    {
  11935        do
  11936        {
  11937            get();
  11938        }
  11939        while (current == 'N');
  11940 
  11941        return current;
  11942    }
  11943 
  11944    /*
  11945    @brief read a number from the input
  11946 
  11947    @tparam NumberType the type of the number
  11948    @param[in] format   the current format (for diagnostics)
  11949    @param[out] result  number of type @a NumberType
  11950 
  11951    @return whether conversion completed
  11952 
  11953    @note This function needs to respect the system's endianness, because
  11954          bytes in CBOR, MessagePack, and UBJSON are stored in network order
  11955          (big endian) and therefore need reordering on little endian systems.
  11956          On the other hand, BSON and BJData use little endian and should reorder
  11957          on big endian systems.
  11958    */
  11959    template<typename NumberType, bool InputIsLittleEndian = false>
  11960    bool get_number(const input_format_t format, NumberType& result)
  11961    {
  11962        // step 1: read input into array with system's byte order
  11963        std::array<std::uint8_t, sizeof(NumberType)> vec{};
  11964        for (std::size_t i = 0; i < sizeof(NumberType); ++i)
  11965        {
  11966            get();
  11967            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "number")))
  11968            {
  11969                return false;
  11970            }
  11971 
  11972            // reverse byte order prior to conversion if necessary
  11973            if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
  11974            {
  11975                vec[sizeof(NumberType) - i - 1] = static_cast<std::uint8_t>(current);
  11976            }
  11977            else
  11978            {
  11979                vec[i] = static_cast<std::uint8_t>(current); // LCOV_EXCL_LINE
  11980            }
  11981        }
  11982 
  11983        // step 2: convert array into number of type T and return
  11984        std::memcpy(&result, vec.data(), sizeof(NumberType));
  11985        return true;
  11986    }
  11987 
  11988    /*!
  11989    @brief create a string by reading characters from the input
  11990 
  11991    @tparam NumberType the type of the number
  11992    @param[in] format the current format (for diagnostics)
  11993    @param[in] len number of characters to read
  11994    @param[out] result string created by reading @a len bytes
  11995 
  11996    @return whether string creation completed
  11997 
  11998    @note We can not reserve @a len bytes for the result, because @a len
  11999          may be too large. Usually, @ref unexpect_eof() detects the end of
  12000          the input before we run out of string memory.
  12001    */
  12002    template<typename NumberType>
  12003    bool get_string(const input_format_t format,
  12004                    const NumberType len,
  12005                    string_t& result)
  12006    {
  12007        bool success = true;
  12008        for (NumberType i = 0; i < len; i++)
  12009        {
  12010            get();
  12011            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
  12012            {
  12013                success = false;
  12014                break;
  12015            }
  12016            result.push_back(static_cast<typename string_t::value_type>(current));
  12017        }
  12018        return success;
  12019    }
  12020 
  12021    /*!
  12022    @brief create a byte array by reading bytes from the input
  12023 
  12024    @tparam NumberType the type of the number
  12025    @param[in] format the current format (for diagnostics)
  12026    @param[in] len number of bytes to read
  12027    @param[out] result byte array created by reading @a len bytes
  12028 
  12029    @return whether byte array creation completed
  12030 
  12031    @note We can not reserve @a len bytes for the result, because @a len
  12032          may be too large. Usually, @ref unexpect_eof() detects the end of
  12033          the input before we run out of memory.
  12034    */
  12035    template<typename NumberType>
  12036    bool get_binary(const input_format_t format,
  12037                    const NumberType len,
  12038                    binary_t& result)
  12039    {
  12040        bool success = true;
  12041        for (NumberType i = 0; i < len; i++)
  12042        {
  12043            get();
  12044            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
  12045            {
  12046                success = false;
  12047                break;
  12048            }
  12049            result.push_back(static_cast<std::uint8_t>(current));
  12050        }
  12051        return success;
  12052    }
  12053 
  12054    /*!
  12055    @param[in] format   the current format (for diagnostics)
  12056    @param[in] context  further context information (for diagnostics)
  12057    @return whether the last read character is not EOF
  12058    */
  12059    JSON_HEDLEY_NON_NULL(3)
  12060    bool unexpect_eof(const input_format_t format, const char* context) const
  12061    {
  12062        if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
  12063        {
  12064            return sax->parse_error(chars_read, "<end of file>",
  12065                                    parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
  12066        }
  12067        return true;
  12068    }
  12069 
  12070    /*!
  12071    @return a string representation of the last read byte
  12072    */
  12073    std::string get_token_string() const
  12074    {
  12075        std::array<char, 3> cr{{}};
  12076        static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  12077        return std::string{cr.data()};
  12078    }
  12079 
  12080    /*!
  12081    @param[in] format   the current format
  12082    @param[in] detail   a detailed error message
  12083    @param[in] context  further context information
  12084    @return a message string to use in the parse_error exceptions
  12085    */
  12086    std::string exception_message(const input_format_t format,
  12087                                  const std::string& detail,
  12088                                  const std::string& context) const
  12089    {
  12090        std::string error_msg = "syntax error while parsing ";
  12091 
  12092        switch (format)
  12093        {
  12094            case input_format_t::cbor:
  12095                error_msg += "CBOR";
  12096                break;
  12097 
  12098            case input_format_t::msgpack:
  12099                error_msg += "MessagePack";
  12100                break;
  12101 
  12102            case input_format_t::ubjson:
  12103                error_msg += "UBJSON";
  12104                break;
  12105 
  12106            case input_format_t::bson:
  12107                error_msg += "BSON";
  12108                break;
  12109 
  12110            case input_format_t::bjdata:
  12111                error_msg += "BJData";
  12112                break;
  12113 
  12114            case input_format_t::json: // LCOV_EXCL_LINE
  12115            default:            // LCOV_EXCL_LINE
  12116                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  12117        }
  12118 
  12119        return concat(error_msg, ' ', context, ": ", detail);
  12120    }
  12121 
  12122  private:
  12123    static JSON_INLINE_VARIABLE constexpr std::size_t npos = static_cast<std::size_t>(-1);
  12124 
  12125    /// input adapter
  12126    InputAdapterType ia;
  12127 
  12128    /// the current character
  12129    char_int_type current = char_traits<char_type>::eof();
  12130 
  12131    /// the number of characters read
  12132    std::size_t chars_read = 0;
  12133 
  12134    /// whether we can assume little endianness
  12135    const bool is_little_endian = little_endianness();
  12136 
  12137    /// input format
  12138    const input_format_t input_format = input_format_t::json;
  12139 
  12140    /// the SAX parser
  12141    json_sax_t* sax = nullptr;
  12142 
  12143    // excluded markers in bjdata optimized type
  12144 #define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
  12145    make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
  12146 
  12147 #define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
  12148    make_array<bjd_type>(                      \
  12149    bjd_type{'C', "char"},                     \
  12150    bjd_type{'D', "double"},                   \
  12151    bjd_type{'I', "int16"},                    \
  12152    bjd_type{'L', "int64"},                    \
  12153    bjd_type{'M', "uint64"},                   \
  12154    bjd_type{'U', "uint8"},                    \
  12155    bjd_type{'d', "single"},                   \
  12156    bjd_type{'i', "int8"},                     \
  12157    bjd_type{'l', "int32"},                    \
  12158    bjd_type{'m', "uint32"},                   \
  12159    bjd_type{'u', "uint16"})
  12160 
  12161  JSON_PRIVATE_UNLESS_TESTED:
  12162    // lookup tables
  12163    // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
  12164    const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
  12165        JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
  12166 
  12167    using bjd_type = std::pair<char_int_type, string_t>;
  12168    // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
  12169    const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
  12170        JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
  12171 
  12172 #undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
  12173 #undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
  12174 };
  12175 
  12176 #ifndef JSON_HAS_CPP_17
  12177    template<typename BasicJsonType, typename InputAdapterType, typename SAX>
  12178    constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
  12179 #endif
  12180 
  12181 }  // namespace detail
  12182 NLOHMANN_JSON_NAMESPACE_END
  12183 
  12184 // #include <nlohmann/detail/input/input_adapters.hpp>
  12185 
  12186 // #include <nlohmann/detail/input/lexer.hpp>
  12187 
  12188 // #include <nlohmann/detail/input/parser.hpp>
  12189 //     __ _____ _____ _____
  12190 //  __|  |   __|     |   | |  JSON for Modern C++
  12191 // |  |  |__   |  |  | | | |  version 3.11.3
  12192 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12193 //
  12194 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  12195 // SPDX-License-Identifier: MIT
  12196 
  12197 
  12198 
  12199 #include <cmath> // isfinite
  12200 #include <cstdint> // uint8_t
  12201 #include <functional> // function
  12202 #include <string> // string
  12203 #include <utility> // move
  12204 #include <vector> // vector
  12205 
  12206 // #include <nlohmann/detail/exceptions.hpp>
  12207 
  12208 // #include <nlohmann/detail/input/input_adapters.hpp>
  12209 
  12210 // #include <nlohmann/detail/input/json_sax.hpp>
  12211 
  12212 // #include <nlohmann/detail/input/lexer.hpp>
  12213 
  12214 // #include <nlohmann/detail/macro_scope.hpp>
  12215 
  12216 // #include <nlohmann/detail/meta/is_sax.hpp>
  12217 
  12218 // #include <nlohmann/detail/string_concat.hpp>
  12219 
  12220 // #include <nlohmann/detail/value_t.hpp>
  12221 
  12222 
  12223 NLOHMANN_JSON_NAMESPACE_BEGIN
  12224 namespace detail
  12225 {
  12226 ////////////
  12227 // parser //
  12228 ////////////
  12229 
  12230 enum class parse_event_t : std::uint8_t
  12231 {
  12232    /// the parser read `{` and started to process a JSON object
  12233    object_start,
  12234    /// the parser read `}` and finished processing a JSON object
  12235    object_end,
  12236    /// the parser read `[` and started to process a JSON array
  12237    array_start,
  12238    /// the parser read `]` and finished processing a JSON array
  12239    array_end,
  12240    /// the parser read a key of a value in an object
  12241    key,
  12242    /// the parser finished reading a JSON value
  12243    value
  12244 };
  12245 
  12246 template<typename BasicJsonType>
  12247 using parser_callback_t =
  12248    std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
  12249 
  12250 /*!
  12251 @brief syntax analysis
  12252 
  12253 This class implements a recursive descent parser.
  12254 */
  12255 template<typename BasicJsonType, typename InputAdapterType>
  12256 class parser
  12257 {
  12258    using number_integer_t = typename BasicJsonType::number_integer_t;
  12259    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  12260    using number_float_t = typename BasicJsonType::number_float_t;
  12261    using string_t = typename BasicJsonType::string_t;
  12262    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
  12263    using token_type = typename lexer_t::token_type;
  12264 
  12265  public:
  12266    /// a parser reading from an input adapter
  12267    explicit parser(InputAdapterType&& adapter,
  12268                    const parser_callback_t<BasicJsonType> cb = nullptr,
  12269                    const bool allow_exceptions_ = true,
  12270                    const bool skip_comments = false)
  12271        : callback(cb)
  12272        , m_lexer(std::move(adapter), skip_comments)
  12273        , allow_exceptions(allow_exceptions_)
  12274    {
  12275        // read first token
  12276        get_token();
  12277    }
  12278 
  12279    /*!
  12280    @brief public parser interface
  12281 
  12282    @param[in] strict      whether to expect the last token to be EOF
  12283    @param[in,out] result  parsed JSON value
  12284 
  12285    @throw parse_error.101 in case of an unexpected token
  12286    @throw parse_error.102 if to_unicode fails or surrogate error
  12287    @throw parse_error.103 if to_unicode fails
  12288    */
  12289    void parse(const bool strict, BasicJsonType& result)
  12290    {
  12291        if (callback)
  12292        {
  12293            json_sax_dom_callback_parser<BasicJsonType> sdp(result, callback, allow_exceptions);
  12294            sax_parse_internal(&sdp);
  12295 
  12296            // in strict mode, input must be completely read
  12297            if (strict && (get_token() != token_type::end_of_input))
  12298            {
  12299                sdp.parse_error(m_lexer.get_position(),
  12300                                m_lexer.get_token_string(),
  12301                                parse_error::create(101, m_lexer.get_position(),
  12302                                                    exception_message(token_type::end_of_input, "value"), nullptr));
  12303            }
  12304 
  12305            // in case of an error, return discarded value
  12306            if (sdp.is_errored())
  12307            {
  12308                result = value_t::discarded;
  12309                return;
  12310            }
  12311 
  12312            // set top-level value to null if it was discarded by the callback
  12313            // function
  12314            if (result.is_discarded())
  12315            {
  12316                result = nullptr;
  12317            }
  12318        }
  12319        else
  12320        {
  12321            json_sax_dom_parser<BasicJsonType> sdp(result, allow_exceptions);
  12322            sax_parse_internal(&sdp);
  12323 
  12324            // in strict mode, input must be completely read
  12325            if (strict && (get_token() != token_type::end_of_input))
  12326            {
  12327                sdp.parse_error(m_lexer.get_position(),
  12328                                m_lexer.get_token_string(),
  12329                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
  12330            }
  12331 
  12332            // in case of an error, return discarded value
  12333            if (sdp.is_errored())
  12334            {
  12335                result = value_t::discarded;
  12336                return;
  12337            }
  12338        }
  12339 
  12340        result.assert_invariant();
  12341    }
  12342 
  12343    /*!
  12344    @brief public accept interface
  12345 
  12346    @param[in] strict  whether to expect the last token to be EOF
  12347    @return whether the input is a proper JSON text
  12348    */
  12349    bool accept(const bool strict = true)
  12350    {
  12351        json_sax_acceptor<BasicJsonType> sax_acceptor;
  12352        return sax_parse(&sax_acceptor, strict);
  12353    }
  12354 
  12355    template<typename SAX>
  12356    JSON_HEDLEY_NON_NULL(2)
  12357    bool sax_parse(SAX* sax, const bool strict = true)
  12358    {
  12359        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
  12360        const bool result = sax_parse_internal(sax);
  12361 
  12362        // strict mode: next byte must be EOF
  12363        if (result && strict && (get_token() != token_type::end_of_input))
  12364        {
  12365            return sax->parse_error(m_lexer.get_position(),
  12366                                    m_lexer.get_token_string(),
  12367                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
  12368        }
  12369 
  12370        return result;
  12371    }
  12372 
  12373  private:
  12374    template<typename SAX>
  12375    JSON_HEDLEY_NON_NULL(2)
  12376    bool sax_parse_internal(SAX* sax)
  12377    {
  12378        // stack to remember the hierarchy of structured values we are parsing
  12379        // true = array; false = object
  12380        std::vector<bool> states;
  12381        // value to avoid a goto (see comment where set to true)
  12382        bool skip_to_state_evaluation = false;
  12383 
  12384        while (true)
  12385        {
  12386            if (!skip_to_state_evaluation)
  12387            {
  12388                // invariant: get_token() was called before each iteration
  12389                switch (last_token)
  12390                {
  12391                    case token_type::begin_object:
  12392                    {
  12393                        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(static_cast<std::size_t>(-1))))
  12394                        {
  12395                            return false;
  12396                        }
  12397 
  12398                        // closing } -> we are done
  12399                        if (get_token() == token_type::end_object)
  12400                        {
  12401                            if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
  12402                            {
  12403                                return false;
  12404                            }
  12405                            break;
  12406                        }
  12407 
  12408                        // parse key
  12409                        if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
  12410                        {
  12411                            return sax->parse_error(m_lexer.get_position(),
  12412                                                    m_lexer.get_token_string(),
  12413                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
  12414                        }
  12415                        if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
  12416                        {
  12417                            return false;
  12418                        }
  12419 
  12420                        // parse separator (:)
  12421                        if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
  12422                        {
  12423                            return sax->parse_error(m_lexer.get_position(),
  12424                                                    m_lexer.get_token_string(),
  12425                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
  12426                        }
  12427 
  12428                        // remember we are now inside an object
  12429                        states.push_back(false);
  12430 
  12431                        // parse values
  12432                        get_token();
  12433                        continue;
  12434                    }
  12435 
  12436                    case token_type::begin_array:
  12437                    {
  12438                        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(static_cast<std::size_t>(-1))))
  12439                        {
  12440                            return false;
  12441                        }
  12442 
  12443                        // closing ] -> we are done
  12444                        if (get_token() == token_type::end_array)
  12445                        {
  12446                            if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
  12447                            {
  12448                                return false;
  12449                            }
  12450                            break;
  12451                        }
  12452 
  12453                        // remember we are now inside an array
  12454                        states.push_back(true);
  12455 
  12456                        // parse values (no need to call get_token)
  12457                        continue;
  12458                    }
  12459 
  12460                    case token_type::value_float:
  12461                    {
  12462                        const auto res = m_lexer.get_number_float();
  12463 
  12464                        if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
  12465                        {
  12466                            return sax->parse_error(m_lexer.get_position(),
  12467                                                    m_lexer.get_token_string(),
  12468                                                    out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
  12469                        }
  12470 
  12471                        if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
  12472                        {
  12473                            return false;
  12474                        }
  12475 
  12476                        break;
  12477                    }
  12478 
  12479                    case token_type::literal_false:
  12480                    {
  12481                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
  12482                        {
  12483                            return false;
  12484                        }
  12485                        break;
  12486                    }
  12487 
  12488                    case token_type::literal_null:
  12489                    {
  12490                        if (JSON_HEDLEY_UNLIKELY(!sax->null()))
  12491                        {
  12492                            return false;
  12493                        }
  12494                        break;
  12495                    }
  12496 
  12497                    case token_type::literal_true:
  12498                    {
  12499                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
  12500                        {
  12501                            return false;
  12502                        }
  12503                        break;
  12504                    }
  12505 
  12506                    case token_type::value_integer:
  12507                    {
  12508                        if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
  12509                        {
  12510                            return false;
  12511                        }
  12512                        break;
  12513                    }
  12514 
  12515                    case token_type::value_string:
  12516                    {
  12517                        if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
  12518                        {
  12519                            return false;
  12520                        }
  12521                        break;
  12522                    }
  12523 
  12524                    case token_type::value_unsigned:
  12525                    {
  12526                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
  12527                        {
  12528                            return false;
  12529                        }
  12530                        break;
  12531                    }
  12532 
  12533                    case token_type::parse_error:
  12534                    {
  12535                        // using "uninitialized" to avoid "expected" message
  12536                        return sax->parse_error(m_lexer.get_position(),
  12537                                                m_lexer.get_token_string(),
  12538                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
  12539                    }
  12540                    case token_type::end_of_input:
  12541                    {
  12542                        if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
  12543                        {
  12544                            return sax->parse_error(m_lexer.get_position(),
  12545                                                    m_lexer.get_token_string(),
  12546                                                    parse_error::create(101, m_lexer.get_position(),
  12547                                                            "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
  12548                        }
  12549 
  12550                        return sax->parse_error(m_lexer.get_position(),
  12551                                                m_lexer.get_token_string(),
  12552                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
  12553                    }
  12554                    case token_type::uninitialized:
  12555                    case token_type::end_array:
  12556                    case token_type::end_object:
  12557                    case token_type::name_separator:
  12558                    case token_type::value_separator:
  12559                    case token_type::literal_or_value:
  12560                    default: // the last token was unexpected
  12561                    {
  12562                        return sax->parse_error(m_lexer.get_position(),
  12563                                                m_lexer.get_token_string(),
  12564                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
  12565                    }
  12566                }
  12567            }
  12568            else
  12569            {
  12570                skip_to_state_evaluation = false;
  12571            }
  12572 
  12573            // we reached this line after we successfully parsed a value
  12574            if (states.empty())
  12575            {
  12576                // empty stack: we reached the end of the hierarchy: done
  12577                return true;
  12578            }
  12579 
  12580            if (states.back())  // array
  12581            {
  12582                // comma -> next value
  12583                if (get_token() == token_type::value_separator)
  12584                {
  12585                    // parse a new value
  12586                    get_token();
  12587                    continue;
  12588                }
  12589 
  12590                // closing ]
  12591                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
  12592                {
  12593                    if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
  12594                    {
  12595                        return false;
  12596                    }
  12597 
  12598                    // We are done with this array. Before we can parse a
  12599                    // new value, we need to evaluate the new state first.
  12600                    // By setting skip_to_state_evaluation to false, we
  12601                    // are effectively jumping to the beginning of this if.
  12602                    JSON_ASSERT(!states.empty());
  12603                    states.pop_back();
  12604                    skip_to_state_evaluation = true;
  12605                    continue;
  12606                }
  12607 
  12608                return sax->parse_error(m_lexer.get_position(),
  12609                                        m_lexer.get_token_string(),
  12610                                        parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
  12611            }
  12612 
  12613            // states.back() is false -> object
  12614 
  12615            // comma -> next value
  12616            if (get_token() == token_type::value_separator)
  12617            {
  12618                // parse key
  12619                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
  12620                {
  12621                    return sax->parse_error(m_lexer.get_position(),
  12622                                            m_lexer.get_token_string(),
  12623                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
  12624                }
  12625 
  12626                if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
  12627                {
  12628                    return false;
  12629                }
  12630 
  12631                // parse separator (:)
  12632                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
  12633                {
  12634                    return sax->parse_error(m_lexer.get_position(),
  12635                                            m_lexer.get_token_string(),
  12636                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
  12637                }
  12638 
  12639                // parse values
  12640                get_token();
  12641                continue;
  12642            }
  12643 
  12644            // closing }
  12645            if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
  12646            {
  12647                if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
  12648                {
  12649                    return false;
  12650                }
  12651 
  12652                // We are done with this object. Before we can parse a
  12653                // new value, we need to evaluate the new state first.
  12654                // By setting skip_to_state_evaluation to false, we
  12655                // are effectively jumping to the beginning of this if.
  12656                JSON_ASSERT(!states.empty());
  12657                states.pop_back();
  12658                skip_to_state_evaluation = true;
  12659                continue;
  12660            }
  12661 
  12662            return sax->parse_error(m_lexer.get_position(),
  12663                                    m_lexer.get_token_string(),
  12664                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
  12665        }
  12666    }
  12667 
  12668    /// get next token from lexer
  12669    token_type get_token()
  12670    {
  12671        return last_token = m_lexer.scan();
  12672    }
  12673 
  12674    std::string exception_message(const token_type expected, const std::string& context)
  12675    {
  12676        std::string error_msg = "syntax error ";
  12677 
  12678        if (!context.empty())
  12679        {
  12680            error_msg += concat("while parsing ", context, ' ');
  12681        }
  12682 
  12683        error_msg += "- ";
  12684 
  12685        if (last_token == token_type::parse_error)
  12686        {
  12687            error_msg += concat(m_lexer.get_error_message(), "; last read: '",
  12688                                m_lexer.get_token_string(), '\'');
  12689        }
  12690        else
  12691        {
  12692            error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
  12693        }
  12694 
  12695        if (expected != token_type::uninitialized)
  12696        {
  12697            error_msg += concat("; expected ", lexer_t::token_type_name(expected));
  12698        }
  12699 
  12700        return error_msg;
  12701    }
  12702 
  12703  private:
  12704    /// callback function
  12705    const parser_callback_t<BasicJsonType> callback = nullptr;
  12706    /// the type of the last read token
  12707    token_type last_token = token_type::uninitialized;
  12708    /// the lexer
  12709    lexer_t m_lexer;
  12710    /// whether to throw exceptions in case of errors
  12711    const bool allow_exceptions = true;
  12712 };
  12713 
  12714 }  // namespace detail
  12715 NLOHMANN_JSON_NAMESPACE_END
  12716 
  12717 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
  12718 //     __ _____ _____ _____
  12719 //  __|  |   __|     |   | |  JSON for Modern C++
  12720 // |  |  |__   |  |  | | | |  version 3.11.3
  12721 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12722 //
  12723 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  12724 // SPDX-License-Identifier: MIT
  12725 
  12726 
  12727 
  12728 // #include <nlohmann/detail/abi_macros.hpp>
  12729 
  12730 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  12731 //     __ _____ _____ _____
  12732 //  __|  |   __|     |   | |  JSON for Modern C++
  12733 // |  |  |__   |  |  | | | |  version 3.11.3
  12734 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12735 //
  12736 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  12737 // SPDX-License-Identifier: MIT
  12738 
  12739 
  12740 
  12741 #include <cstddef> // ptrdiff_t
  12742 #include <limits>  // numeric_limits
  12743 
  12744 // #include <nlohmann/detail/macro_scope.hpp>
  12745 
  12746 
  12747 NLOHMANN_JSON_NAMESPACE_BEGIN
  12748 namespace detail
  12749 {
  12750 
  12751 /*
  12752 @brief an iterator for primitive JSON types
  12753 
  12754 This class models an iterator for primitive JSON types (boolean, number,
  12755 string). It's only purpose is to allow the iterator/const_iterator classes
  12756 to "iterate" over primitive values. Internally, the iterator is modeled by
  12757 a `difference_type` variable. Value begin_value (`0`) models the begin,
  12758 end_value (`1`) models past the end.
  12759 */
  12760 class primitive_iterator_t
  12761 {
  12762  private:
  12763    using difference_type = std::ptrdiff_t;
  12764    static constexpr difference_type begin_value = 0;
  12765    static constexpr difference_type end_value = begin_value + 1;
  12766 
  12767  JSON_PRIVATE_UNLESS_TESTED:
  12768    /// iterator as signed integer type
  12769    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
  12770 
  12771  public:
  12772    constexpr difference_type get_value() const noexcept
  12773    {
  12774        return m_it;
  12775    }
  12776 
  12777    /// set iterator to a defined beginning
  12778    void set_begin() noexcept
  12779    {
  12780        m_it = begin_value;
  12781    }
  12782 
  12783    /// set iterator to a defined past the end
  12784    void set_end() noexcept
  12785    {
  12786        m_it = end_value;
  12787    }
  12788 
  12789    /// return whether the iterator can be dereferenced
  12790    constexpr bool is_begin() const noexcept
  12791    {
  12792        return m_it == begin_value;
  12793    }
  12794 
  12795    /// return whether the iterator is at end
  12796    constexpr bool is_end() const noexcept
  12797    {
  12798        return m_it == end_value;
  12799    }
  12800 
  12801    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
  12802    {
  12803        return lhs.m_it == rhs.m_it;
  12804    }
  12805 
  12806    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
  12807    {
  12808        return lhs.m_it < rhs.m_it;
  12809    }
  12810 
  12811    primitive_iterator_t operator+(difference_type n) noexcept
  12812    {
  12813        auto result = *this;
  12814        result += n;
  12815        return result;
  12816    }
  12817 
  12818    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
  12819    {
  12820        return lhs.m_it - rhs.m_it;
  12821    }
  12822 
  12823    primitive_iterator_t& operator++() noexcept
  12824    {
  12825        ++m_it;
  12826        return *this;
  12827    }
  12828 
  12829    primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
  12830    {
  12831        auto result = *this;
  12832        ++m_it;
  12833        return result;
  12834    }
  12835 
  12836    primitive_iterator_t& operator--() noexcept
  12837    {
  12838        --m_it;
  12839        return *this;
  12840    }
  12841 
  12842    primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
  12843    {
  12844        auto result = *this;
  12845        --m_it;
  12846        return result;
  12847    }
  12848 
  12849    primitive_iterator_t& operator+=(difference_type n) noexcept
  12850    {
  12851        m_it += n;
  12852        return *this;
  12853    }
  12854 
  12855    primitive_iterator_t& operator-=(difference_type n) noexcept
  12856    {
  12857        m_it -= n;
  12858        return *this;
  12859    }
  12860 };
  12861 
  12862 }  // namespace detail
  12863 NLOHMANN_JSON_NAMESPACE_END
  12864 
  12865 
  12866 NLOHMANN_JSON_NAMESPACE_BEGIN
  12867 namespace detail
  12868 {
  12869 
  12870 /*!
  12871 @brief an iterator value
  12872 
  12873 @note This structure could easily be a union, but MSVC currently does not allow
  12874 unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
  12875 */
  12876 template<typename BasicJsonType> struct internal_iterator
  12877 {
  12878    /// iterator for JSON objects
  12879    typename BasicJsonType::object_t::iterator object_iterator {};
  12880    /// iterator for JSON arrays
  12881    typename BasicJsonType::array_t::iterator array_iterator {};
  12882    /// generic iterator for all other types
  12883    primitive_iterator_t primitive_iterator {};
  12884 };
  12885 
  12886 }  // namespace detail
  12887 NLOHMANN_JSON_NAMESPACE_END
  12888 
  12889 // #include <nlohmann/detail/iterators/iter_impl.hpp>
  12890 //     __ _____ _____ _____
  12891 //  __|  |   __|     |   | |  JSON for Modern C++
  12892 // |  |  |__   |  |  | | | |  version 3.11.3
  12893 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  12894 //
  12895 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  12896 // SPDX-License-Identifier: MIT
  12897 
  12898 
  12899 
  12900 #include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
  12901 #include <type_traits> // conditional, is_const, remove_const
  12902 
  12903 // #include <nlohmann/detail/exceptions.hpp>
  12904 
  12905 // #include <nlohmann/detail/iterators/internal_iterator.hpp>
  12906 
  12907 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  12908 
  12909 // #include <nlohmann/detail/macro_scope.hpp>
  12910 
  12911 // #include <nlohmann/detail/meta/cpp_future.hpp>
  12912 
  12913 // #include <nlohmann/detail/meta/type_traits.hpp>
  12914 
  12915 // #include <nlohmann/detail/value_t.hpp>
  12916 
  12917 
  12918 NLOHMANN_JSON_NAMESPACE_BEGIN
  12919 namespace detail
  12920 {
  12921 
  12922 // forward declare, to be able to friend it later on
  12923 template<typename IteratorType> class iteration_proxy;
  12924 template<typename IteratorType> class iteration_proxy_value;
  12925 
  12926 /*!
  12927 @brief a template for a bidirectional iterator for the @ref basic_json class
  12928 This class implements a both iterators (iterator and const_iterator) for the
  12929 @ref basic_json class.
  12930 @note An iterator is called *initialized* when a pointer to a JSON value has
  12931      been set (e.g., by a constructor or a copy assignment). If the iterator is
  12932      default-constructed, it is *uninitialized* and most methods are undefined.
  12933      **The library uses assertions to detect calls on uninitialized iterators.**
  12934 @requirement The class satisfies the following concept requirements:
  12935 -
  12936 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
  12937  The iterator that can be moved can be moved in both directions (i.e.
  12938  incremented and decremented).
  12939 @since version 1.0.0, simplified in version 2.0.9, change to bidirectional
  12940       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
  12941 */
  12942 template<typename BasicJsonType>
  12943 class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
  12944 {
  12945    /// the iterator with BasicJsonType of different const-ness
  12946    using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
  12947    /// allow basic_json to access private members
  12948    friend other_iter_impl;
  12949    friend BasicJsonType;
  12950    friend iteration_proxy<iter_impl>;
  12951    friend iteration_proxy_value<iter_impl>;
  12952 
  12953    using object_t = typename BasicJsonType::object_t;
  12954    using array_t = typename BasicJsonType::array_t;
  12955    // make sure BasicJsonType is basic_json or const basic_json
  12956    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
  12957                  "iter_impl only accepts (const) basic_json");
  12958    // superficial check for the LegacyBidirectionalIterator named requirement
  12959    static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
  12960                  &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
  12961                  "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
  12962 
  12963  public:
  12964    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
  12965    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
  12966    /// A user-defined iterator should provide publicly accessible typedefs named
  12967    /// iterator_category, value_type, difference_type, pointer, and reference.
  12968    /// Note that value_type is required to be non-const, even for constant iterators.
  12969    using iterator_category = std::bidirectional_iterator_tag;
  12970 
  12971    /// the type of the values when the iterator is dereferenced
  12972    using value_type = typename BasicJsonType::value_type;
  12973    /// a type to represent differences between iterators
  12974    using difference_type = typename BasicJsonType::difference_type;
  12975    /// defines a pointer to the type iterated over (value_type)
  12976    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
  12977          typename BasicJsonType::const_pointer,
  12978          typename BasicJsonType::pointer>::type;
  12979    /// defines a reference to the type iterated over (value_type)
  12980    using reference =
  12981        typename std::conditional<std::is_const<BasicJsonType>::value,
  12982        typename BasicJsonType::const_reference,
  12983        typename BasicJsonType::reference>::type;
  12984 
  12985    iter_impl() = default;
  12986    ~iter_impl() = default;
  12987    iter_impl(iter_impl&&) noexcept = default;
  12988    iter_impl& operator=(iter_impl&&) noexcept = default;
  12989 
  12990    /*!
  12991    @brief constructor for a given JSON instance
  12992    @param[in] object  pointer to a JSON object for this iterator
  12993    @pre object != nullptr
  12994    @post The iterator is initialized; i.e. `m_object != nullptr`.
  12995    */
  12996    explicit iter_impl(pointer object) noexcept : m_object(object)
  12997    {
  12998        JSON_ASSERT(m_object != nullptr);
  12999 
  13000        switch (m_object->m_data.m_type)
  13001        {
  13002            case value_t::object:
  13003            {
  13004                m_it.object_iterator = typename object_t::iterator();
  13005                break;
  13006            }
  13007 
  13008            case value_t::array:
  13009            {
  13010                m_it.array_iterator = typename array_t::iterator();
  13011                break;
  13012            }
  13013 
  13014            case value_t::null:
  13015            case value_t::string:
  13016            case value_t::boolean:
  13017            case value_t::number_integer:
  13018            case value_t::number_unsigned:
  13019            case value_t::number_float:
  13020            case value_t::binary:
  13021            case value_t::discarded:
  13022            default:
  13023            {
  13024                m_it.primitive_iterator = primitive_iterator_t();
  13025                break;
  13026            }
  13027        }
  13028    }
  13029 
  13030    /*!
  13031    @note The conventional copy constructor and copy assignment are implicitly
  13032          defined. Combined with the following converting constructor and
  13033          assignment, they support: (1) copy from iterator to iterator, (2)
  13034          copy from const iterator to const iterator, and (3) conversion from
  13035          iterator to const iterator. However conversion from const iterator
  13036          to iterator is not defined.
  13037    */
  13038 
  13039    /*!
  13040    @brief const copy constructor
  13041    @param[in] other const iterator to copy from
  13042    @note This copy constructor had to be defined explicitly to circumvent a bug
  13043          occurring on msvc v19.0 compiler (VS 2015) debug build. For more
  13044          information refer to: https://github.com/nlohmann/json/issues/1608
  13045    */
  13046    iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
  13047        : m_object(other.m_object), m_it(other.m_it)
  13048    {}
  13049 
  13050    /*!
  13051    @brief converting assignment
  13052    @param[in] other const iterator to copy from
  13053    @return const/non-const iterator
  13054    @note It is not checked whether @a other is initialized.
  13055    */
  13056    iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
  13057    {
  13058        if (&other != this)
  13059        {
  13060            m_object = other.m_object;
  13061            m_it = other.m_it;
  13062        }
  13063        return *this;
  13064    }
  13065 
  13066    /*!
  13067    @brief converting constructor
  13068    @param[in] other  non-const iterator to copy from
  13069    @note It is not checked whether @a other is initialized.
  13070    */
  13071    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
  13072        : m_object(other.m_object), m_it(other.m_it)
  13073    {}
  13074 
  13075    /*!
  13076    @brief converting assignment
  13077    @param[in] other  non-const iterator to copy from
  13078    @return const/non-const iterator
  13079    @note It is not checked whether @a other is initialized.
  13080    */
  13081    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
  13082    {
  13083        m_object = other.m_object;
  13084        m_it = other.m_it;
  13085        return *this;
  13086    }
  13087 
  13088  JSON_PRIVATE_UNLESS_TESTED:
  13089    /*!
  13090    @brief set the iterator to the first value
  13091    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13092    */
  13093    void set_begin() noexcept
  13094    {
  13095        JSON_ASSERT(m_object != nullptr);
  13096 
  13097        switch (m_object->m_data.m_type)
  13098        {
  13099            case value_t::object:
  13100            {
  13101                m_it.object_iterator = m_object->m_data.m_value.object->begin();
  13102                break;
  13103            }
  13104 
  13105            case value_t::array:
  13106            {
  13107                m_it.array_iterator = m_object->m_data.m_value.array->begin();
  13108                break;
  13109            }
  13110 
  13111            case value_t::null:
  13112            {
  13113                // set to end so begin()==end() is true: null is empty
  13114                m_it.primitive_iterator.set_end();
  13115                break;
  13116            }
  13117 
  13118            case value_t::string:
  13119            case value_t::boolean:
  13120            case value_t::number_integer:
  13121            case value_t::number_unsigned:
  13122            case value_t::number_float:
  13123            case value_t::binary:
  13124            case value_t::discarded:
  13125            default:
  13126            {
  13127                m_it.primitive_iterator.set_begin();
  13128                break;
  13129            }
  13130        }
  13131    }
  13132 
  13133    /*!
  13134    @brief set the iterator past the last value
  13135    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13136    */
  13137    void set_end() noexcept
  13138    {
  13139        JSON_ASSERT(m_object != nullptr);
  13140 
  13141        switch (m_object->m_data.m_type)
  13142        {
  13143            case value_t::object:
  13144            {
  13145                m_it.object_iterator = m_object->m_data.m_value.object->end();
  13146                break;
  13147            }
  13148 
  13149            case value_t::array:
  13150            {
  13151                m_it.array_iterator = m_object->m_data.m_value.array->end();
  13152                break;
  13153            }
  13154 
  13155            case value_t::null:
  13156            case value_t::string:
  13157            case value_t::boolean:
  13158            case value_t::number_integer:
  13159            case value_t::number_unsigned:
  13160            case value_t::number_float:
  13161            case value_t::binary:
  13162            case value_t::discarded:
  13163            default:
  13164            {
  13165                m_it.primitive_iterator.set_end();
  13166                break;
  13167            }
  13168        }
  13169    }
  13170 
  13171  public:
  13172    /*!
  13173    @brief return a reference to the value pointed to by the iterator
  13174    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13175    */
  13176    reference operator*() const
  13177    {
  13178        JSON_ASSERT(m_object != nullptr);
  13179 
  13180        switch (m_object->m_data.m_type)
  13181        {
  13182            case value_t::object:
  13183            {
  13184                JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
  13185                return m_it.object_iterator->second;
  13186            }
  13187 
  13188            case value_t::array:
  13189            {
  13190                JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
  13191                return *m_it.array_iterator;
  13192            }
  13193 
  13194            case value_t::null:
  13195                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13196 
  13197            case value_t::string:
  13198            case value_t::boolean:
  13199            case value_t::number_integer:
  13200            case value_t::number_unsigned:
  13201            case value_t::number_float:
  13202            case value_t::binary:
  13203            case value_t::discarded:
  13204            default:
  13205            {
  13206                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
  13207                {
  13208                    return *m_object;
  13209                }
  13210 
  13211                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13212            }
  13213        }
  13214    }
  13215 
  13216    /*!
  13217    @brief dereference the iterator
  13218    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13219    */
  13220    pointer operator->() const
  13221    {
  13222        JSON_ASSERT(m_object != nullptr);
  13223 
  13224        switch (m_object->m_data.m_type)
  13225        {
  13226            case value_t::object:
  13227            {
  13228                JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
  13229                return &(m_it.object_iterator->second);
  13230            }
  13231 
  13232            case value_t::array:
  13233            {
  13234                JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
  13235                return &*m_it.array_iterator;
  13236            }
  13237 
  13238            case value_t::null:
  13239            case value_t::string:
  13240            case value_t::boolean:
  13241            case value_t::number_integer:
  13242            case value_t::number_unsigned:
  13243            case value_t::number_float:
  13244            case value_t::binary:
  13245            case value_t::discarded:
  13246            default:
  13247            {
  13248                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
  13249                {
  13250                    return m_object;
  13251                }
  13252 
  13253                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13254            }
  13255        }
  13256    }
  13257 
  13258    /*!
  13259    @brief post-increment (it++)
  13260    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13261    */
  13262    iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
  13263    {
  13264        auto result = *this;
  13265        ++(*this);
  13266        return result;
  13267    }
  13268 
  13269    /*!
  13270    @brief pre-increment (++it)
  13271    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13272    */
  13273    iter_impl& operator++()
  13274    {
  13275        JSON_ASSERT(m_object != nullptr);
  13276 
  13277        switch (m_object->m_data.m_type)
  13278        {
  13279            case value_t::object:
  13280            {
  13281                std::advance(m_it.object_iterator, 1);
  13282                break;
  13283            }
  13284 
  13285            case value_t::array:
  13286            {
  13287                std::advance(m_it.array_iterator, 1);
  13288                break;
  13289            }
  13290 
  13291            case value_t::null:
  13292            case value_t::string:
  13293            case value_t::boolean:
  13294            case value_t::number_integer:
  13295            case value_t::number_unsigned:
  13296            case value_t::number_float:
  13297            case value_t::binary:
  13298            case value_t::discarded:
  13299            default:
  13300            {
  13301                ++m_it.primitive_iterator;
  13302                break;
  13303            }
  13304        }
  13305 
  13306        return *this;
  13307    }
  13308 
  13309    /*!
  13310    @brief post-decrement (it--)
  13311    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13312    */
  13313    iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
  13314    {
  13315        auto result = *this;
  13316        --(*this);
  13317        return result;
  13318    }
  13319 
  13320    /*!
  13321    @brief pre-decrement (--it)
  13322    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13323    */
  13324    iter_impl& operator--()
  13325    {
  13326        JSON_ASSERT(m_object != nullptr);
  13327 
  13328        switch (m_object->m_data.m_type)
  13329        {
  13330            case value_t::object:
  13331            {
  13332                std::advance(m_it.object_iterator, -1);
  13333                break;
  13334            }
  13335 
  13336            case value_t::array:
  13337            {
  13338                std::advance(m_it.array_iterator, -1);
  13339                break;
  13340            }
  13341 
  13342            case value_t::null:
  13343            case value_t::string:
  13344            case value_t::boolean:
  13345            case value_t::number_integer:
  13346            case value_t::number_unsigned:
  13347            case value_t::number_float:
  13348            case value_t::binary:
  13349            case value_t::discarded:
  13350            default:
  13351            {
  13352                --m_it.primitive_iterator;
  13353                break;
  13354            }
  13355        }
  13356 
  13357        return *this;
  13358    }
  13359 
  13360    /*!
  13361    @brief comparison: equal
  13362    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13363    */
  13364    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 >
  13365    bool operator==(const IterImpl& other) const
  13366    {
  13367        // if objects are not the same, the comparison is undefined
  13368        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
  13369        {
  13370            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
  13371        }
  13372 
  13373        JSON_ASSERT(m_object != nullptr);
  13374 
  13375        switch (m_object->m_data.m_type)
  13376        {
  13377            case value_t::object:
  13378                return (m_it.object_iterator == other.m_it.object_iterator);
  13379 
  13380            case value_t::array:
  13381                return (m_it.array_iterator == other.m_it.array_iterator);
  13382 
  13383            case value_t::null:
  13384            case value_t::string:
  13385            case value_t::boolean:
  13386            case value_t::number_integer:
  13387            case value_t::number_unsigned:
  13388            case value_t::number_float:
  13389            case value_t::binary:
  13390            case value_t::discarded:
  13391            default:
  13392                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
  13393        }
  13394    }
  13395 
  13396    /*!
  13397    @brief comparison: not equal
  13398    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13399    */
  13400    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 >
  13401    bool operator!=(const IterImpl& other) const
  13402    {
  13403        return !operator==(other);
  13404    }
  13405 
  13406    /*!
  13407    @brief comparison: smaller
  13408    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13409    */
  13410    bool operator<(const iter_impl& other) const
  13411    {
  13412        // if objects are not the same, the comparison is undefined
  13413        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
  13414        {
  13415            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
  13416        }
  13417 
  13418        JSON_ASSERT(m_object != nullptr);
  13419 
  13420        switch (m_object->m_data.m_type)
  13421        {
  13422            case value_t::object:
  13423                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
  13424 
  13425            case value_t::array:
  13426                return (m_it.array_iterator < other.m_it.array_iterator);
  13427 
  13428            case value_t::null:
  13429            case value_t::string:
  13430            case value_t::boolean:
  13431            case value_t::number_integer:
  13432            case value_t::number_unsigned:
  13433            case value_t::number_float:
  13434            case value_t::binary:
  13435            case value_t::discarded:
  13436            default:
  13437                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
  13438        }
  13439    }
  13440 
  13441    /*!
  13442    @brief comparison: less than or equal
  13443    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13444    */
  13445    bool operator<=(const iter_impl& other) const
  13446    {
  13447        return !other.operator < (*this);
  13448    }
  13449 
  13450    /*!
  13451    @brief comparison: greater than
  13452    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13453    */
  13454    bool operator>(const iter_impl& other) const
  13455    {
  13456        return !operator<=(other);
  13457    }
  13458 
  13459    /*!
  13460    @brief comparison: greater than or equal
  13461    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13462    */
  13463    bool operator>=(const iter_impl& other) const
  13464    {
  13465        return !operator<(other);
  13466    }
  13467 
  13468    /*!
  13469    @brief add to iterator
  13470    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13471    */
  13472    iter_impl& operator+=(difference_type i)
  13473    {
  13474        JSON_ASSERT(m_object != nullptr);
  13475 
  13476        switch (m_object->m_data.m_type)
  13477        {
  13478            case value_t::object:
  13479                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
  13480 
  13481            case value_t::array:
  13482            {
  13483                std::advance(m_it.array_iterator, i);
  13484                break;
  13485            }
  13486 
  13487            case value_t::null:
  13488            case value_t::string:
  13489            case value_t::boolean:
  13490            case value_t::number_integer:
  13491            case value_t::number_unsigned:
  13492            case value_t::number_float:
  13493            case value_t::binary:
  13494            case value_t::discarded:
  13495            default:
  13496            {
  13497                m_it.primitive_iterator += i;
  13498                break;
  13499            }
  13500        }
  13501 
  13502        return *this;
  13503    }
  13504 
  13505    /*!
  13506    @brief subtract from iterator
  13507    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13508    */
  13509    iter_impl& operator-=(difference_type i)
  13510    {
  13511        return operator+=(-i);
  13512    }
  13513 
  13514    /*!
  13515    @brief add to iterator
  13516    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13517    */
  13518    iter_impl operator+(difference_type i) const
  13519    {
  13520        auto result = *this;
  13521        result += i;
  13522        return result;
  13523    }
  13524 
  13525    /*!
  13526    @brief addition of distance and iterator
  13527    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13528    */
  13529    friend iter_impl operator+(difference_type i, const iter_impl& it)
  13530    {
  13531        auto result = it;
  13532        result += i;
  13533        return result;
  13534    }
  13535 
  13536    /*!
  13537    @brief subtract from iterator
  13538    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13539    */
  13540    iter_impl operator-(difference_type i) const
  13541    {
  13542        auto result = *this;
  13543        result -= i;
  13544        return result;
  13545    }
  13546 
  13547    /*!
  13548    @brief return difference
  13549    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13550    */
  13551    difference_type operator-(const iter_impl& other) const
  13552    {
  13553        JSON_ASSERT(m_object != nullptr);
  13554 
  13555        switch (m_object->m_data.m_type)
  13556        {
  13557            case value_t::object:
  13558                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
  13559 
  13560            case value_t::array:
  13561                return m_it.array_iterator - other.m_it.array_iterator;
  13562 
  13563            case value_t::null:
  13564            case value_t::string:
  13565            case value_t::boolean:
  13566            case value_t::number_integer:
  13567            case value_t::number_unsigned:
  13568            case value_t::number_float:
  13569            case value_t::binary:
  13570            case value_t::discarded:
  13571            default:
  13572                return m_it.primitive_iterator - other.m_it.primitive_iterator;
  13573        }
  13574    }
  13575 
  13576    /*!
  13577    @brief access to successor
  13578    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13579    */
  13580    reference operator[](difference_type n) const
  13581    {
  13582        JSON_ASSERT(m_object != nullptr);
  13583 
  13584        switch (m_object->m_data.m_type)
  13585        {
  13586            case value_t::object:
  13587                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
  13588 
  13589            case value_t::array:
  13590                return *std::next(m_it.array_iterator, n);
  13591 
  13592            case value_t::null:
  13593                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13594 
  13595            case value_t::string:
  13596            case value_t::boolean:
  13597            case value_t::number_integer:
  13598            case value_t::number_unsigned:
  13599            case value_t::number_float:
  13600            case value_t::binary:
  13601            case value_t::discarded:
  13602            default:
  13603            {
  13604                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
  13605                {
  13606                    return *m_object;
  13607                }
  13608 
  13609                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
  13610            }
  13611        }
  13612    }
  13613 
  13614    /*!
  13615    @brief return the key of an object iterator
  13616    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13617    */
  13618    const typename object_t::key_type& key() const
  13619    {
  13620        JSON_ASSERT(m_object != nullptr);
  13621 
  13622        if (JSON_HEDLEY_LIKELY(m_object->is_object()))
  13623        {
  13624            return m_it.object_iterator->first;
  13625        }
  13626 
  13627        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
  13628    }
  13629 
  13630    /*!
  13631    @brief return the value of an iterator
  13632    @pre The iterator is initialized; i.e. `m_object != nullptr`.
  13633    */
  13634    reference value() const
  13635    {
  13636        return operator*();
  13637    }
  13638 
  13639  JSON_PRIVATE_UNLESS_TESTED:
  13640    /// associated JSON instance
  13641    pointer m_object = nullptr;
  13642    /// the actual iterator of the associated instance
  13643    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
  13644 };
  13645 
  13646 }  // namespace detail
  13647 NLOHMANN_JSON_NAMESPACE_END
  13648 
  13649 // #include <nlohmann/detail/iterators/iteration_proxy.hpp>
  13650 
  13651 // #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
  13652 //     __ _____ _____ _____
  13653 //  __|  |   __|     |   | |  JSON for Modern C++
  13654 // |  |  |__   |  |  | | | |  version 3.11.3
  13655 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  13656 //
  13657 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  13658 // SPDX-License-Identifier: MIT
  13659 
  13660 
  13661 
  13662 #include <cstddef> // ptrdiff_t
  13663 #include <iterator> // reverse_iterator
  13664 #include <utility> // declval
  13665 
  13666 // #include <nlohmann/detail/abi_macros.hpp>
  13667 
  13668 
  13669 NLOHMANN_JSON_NAMESPACE_BEGIN
  13670 namespace detail
  13671 {
  13672 
  13673 //////////////////////
  13674 // reverse_iterator //
  13675 //////////////////////
  13676 
  13677 /*!
  13678 @brief a template for a reverse iterator class
  13679 
  13680 @tparam Base the base iterator type to reverse. Valid types are @ref
  13681 iterator (to create @ref reverse_iterator) and @ref const_iterator (to
  13682 create @ref const_reverse_iterator).
  13683 
  13684 @requirement The class satisfies the following concept requirements:
  13685 -
  13686 [BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
  13687  The iterator that can be moved can be moved in both directions (i.e.
  13688  incremented and decremented).
  13689 - [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
  13690  It is possible to write to the pointed-to element (only if @a Base is
  13691  @ref iterator).
  13692 
  13693 @since version 1.0.0
  13694 */
  13695 template<typename Base>
  13696 class json_reverse_iterator : public std::reverse_iterator<Base>
  13697 {
  13698  public:
  13699    using difference_type = std::ptrdiff_t;
  13700    /// shortcut to the reverse iterator adapter
  13701    using base_iterator = std::reverse_iterator<Base>;
  13702    /// the reference type for the pointed-to element
  13703    using reference = typename Base::reference;
  13704 
  13705    /// create reverse iterator from iterator
  13706    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
  13707        : base_iterator(it) {}
  13708 
  13709    /// create reverse iterator from base class
  13710    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
  13711 
  13712    /// post-increment (it++)
  13713    json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
  13714    {
  13715        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
  13716    }
  13717 
  13718    /// pre-increment (++it)
  13719    json_reverse_iterator& operator++()
  13720    {
  13721        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
  13722    }
  13723 
  13724    /// post-decrement (it--)
  13725    json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
  13726    {
  13727        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
  13728    }
  13729 
  13730    /// pre-decrement (--it)
  13731    json_reverse_iterator& operator--()
  13732    {
  13733        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
  13734    }
  13735 
  13736    /// add to iterator
  13737    json_reverse_iterator& operator+=(difference_type i)
  13738    {
  13739        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
  13740    }
  13741 
  13742    /// add to iterator
  13743    json_reverse_iterator operator+(difference_type i) const
  13744    {
  13745        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
  13746    }
  13747 
  13748    /// subtract from iterator
  13749    json_reverse_iterator operator-(difference_type i) const
  13750    {
  13751        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
  13752    }
  13753 
  13754    /// return difference
  13755    difference_type operator-(const json_reverse_iterator& other) const
  13756    {
  13757        return base_iterator(*this) - base_iterator(other);
  13758    }
  13759 
  13760    /// access to successor
  13761    reference operator[](difference_type n) const
  13762    {
  13763        return *(this->operator+(n));
  13764    }
  13765 
  13766    /// return the key of an object iterator
  13767    auto key() const -> decltype(std::declval<Base>().key())
  13768    {
  13769        auto it = --this->base();
  13770        return it.key();
  13771    }
  13772 
  13773    /// return the value of an iterator
  13774    reference value() const
  13775    {
  13776        auto it = --this->base();
  13777        return it.operator * ();
  13778    }
  13779 };
  13780 
  13781 }  // namespace detail
  13782 NLOHMANN_JSON_NAMESPACE_END
  13783 
  13784 // #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  13785 
  13786 // #include <nlohmann/detail/json_custom_base_class.hpp>
  13787 //     __ _____ _____ _____
  13788 //  __|  |   __|     |   | |  JSON for Modern C++
  13789 // |  |  |__   |  |  | | | |  version 3.11.3
  13790 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  13791 //
  13792 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  13793 // SPDX-License-Identifier: MIT
  13794 
  13795 
  13796 
  13797 #include <type_traits> // conditional, is_same
  13798 
  13799 // #include <nlohmann/detail/abi_macros.hpp>
  13800 
  13801 
  13802 NLOHMANN_JSON_NAMESPACE_BEGIN
  13803 namespace detail
  13804 {
  13805 
  13806 /*!
  13807 @brief Default base class of the @ref basic_json class.
  13808 
  13809 So that the correct implementations of the copy / move ctors / assign operators
  13810 of @ref basic_json do not require complex case distinctions
  13811 (no base class / custom base class used as customization point),
  13812 @ref basic_json always has a base class.
  13813 By default, this class is used because it is empty and thus has no effect
  13814 on the behavior of @ref basic_json.
  13815 */
  13816 struct json_default_base {};
  13817 
  13818 template<class T>
  13819 using json_base_class = typename std::conditional <
  13820                        std::is_same<T, void>::value,
  13821                        json_default_base,
  13822                        T
  13823                        >::type;
  13824 
  13825 }  // namespace detail
  13826 NLOHMANN_JSON_NAMESPACE_END
  13827 
  13828 // #include <nlohmann/detail/json_pointer.hpp>
  13829 //     __ _____ _____ _____
  13830 //  __|  |   __|     |   | |  JSON for Modern C++
  13831 // |  |  |__   |  |  | | | |  version 3.11.3
  13832 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  13833 //
  13834 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  13835 // SPDX-License-Identifier: MIT
  13836 
  13837 
  13838 
  13839 #include <algorithm> // all_of
  13840 #include <cctype> // isdigit
  13841 #include <cerrno> // errno, ERANGE
  13842 #include <cstdlib> // strtoull
  13843 #ifndef JSON_NO_IO
  13844    #include <iosfwd> // ostream
  13845 #endif  // JSON_NO_IO
  13846 #include <limits> // max
  13847 #include <numeric> // accumulate
  13848 #include <string> // string
  13849 #include <utility> // move
  13850 #include <vector> // vector
  13851 
  13852 // #include <nlohmann/detail/exceptions.hpp>
  13853 
  13854 // #include <nlohmann/detail/macro_scope.hpp>
  13855 
  13856 // #include <nlohmann/detail/string_concat.hpp>
  13857 
  13858 // #include <nlohmann/detail/string_escape.hpp>
  13859 
  13860 // #include <nlohmann/detail/value_t.hpp>
  13861 
  13862 
  13863 NLOHMANN_JSON_NAMESPACE_BEGIN
  13864 
  13865 /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
  13866 /// @sa https://json.nlohmann.me/api/json_pointer/
  13867 template<typename RefStringType>
  13868 class json_pointer
  13869 {
  13870    // allow basic_json to access private members
  13871    NLOHMANN_BASIC_JSON_TPL_DECLARATION
  13872    friend class basic_json;
  13873 
  13874    template<typename>
  13875    friend class json_pointer;
  13876 
  13877    template<typename T>
  13878    struct string_t_helper
  13879    {
  13880        using type = T;
  13881    };
  13882 
  13883    NLOHMANN_BASIC_JSON_TPL_DECLARATION
  13884    struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
  13885    {
  13886        using type = StringType;
  13887    };
  13888 
  13889  public:
  13890    // for backwards compatibility accept BasicJsonType
  13891    using string_t = typename string_t_helper<RefStringType>::type;
  13892 
  13893    /// @brief create JSON pointer
  13894    /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
  13895    explicit json_pointer(const string_t& s = "")
  13896        : reference_tokens(split(s))
  13897    {}
  13898 
  13899    /// @brief return a string representation of the JSON pointer
  13900    /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
  13901    string_t to_string() const
  13902    {
  13903        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
  13904                               string_t{},
  13905                               [](const string_t& a, const string_t& b)
  13906        {
  13907            return detail::concat(a, '/', detail::escape(b));
  13908        });
  13909    }
  13910 
  13911    /// @brief return a string representation of the JSON pointer
  13912    /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
  13913    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
  13914    operator string_t() const
  13915    {
  13916        return to_string();
  13917    }
  13918 
  13919 #ifndef JSON_NO_IO
  13920    /// @brief write string representation of the JSON pointer to stream
  13921    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
  13922    friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
  13923    {
  13924        o << ptr.to_string();
  13925        return o;
  13926    }
  13927 #endif
  13928 
  13929    /// @brief append another JSON pointer at the end of this JSON pointer
  13930    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
  13931    json_pointer& operator/=(const json_pointer& ptr)
  13932    {
  13933        reference_tokens.insert(reference_tokens.end(),
  13934                                ptr.reference_tokens.begin(),
  13935                                ptr.reference_tokens.end());
  13936        return *this;
  13937    }
  13938 
  13939    /// @brief append an unescaped reference token at the end of this JSON pointer
  13940    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
  13941    json_pointer& operator/=(string_t token)
  13942    {
  13943        push_back(std::move(token));
  13944        return *this;
  13945    }
  13946 
  13947    /// @brief append an array index at the end of this JSON pointer
  13948    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
  13949    json_pointer& operator/=(std::size_t array_idx)
  13950    {
  13951        return *this /= std::to_string(array_idx);
  13952    }
  13953 
  13954    /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
  13955    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
  13956    friend json_pointer operator/(const json_pointer& lhs,
  13957                                  const json_pointer& rhs)
  13958    {
  13959        return json_pointer(lhs) /= rhs;
  13960    }
  13961 
  13962    /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
  13963    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
  13964    friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
  13965    {
  13966        return json_pointer(lhs) /= std::move(token);
  13967    }
  13968 
  13969    /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
  13970    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
  13971    friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
  13972    {
  13973        return json_pointer(lhs) /= array_idx;
  13974    }
  13975 
  13976    /// @brief returns the parent of this JSON pointer
  13977    /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
  13978    json_pointer parent_pointer() const
  13979    {
  13980        if (empty())
  13981        {
  13982            return *this;
  13983        }
  13984 
  13985        json_pointer res = *this;
  13986        res.pop_back();
  13987        return res;
  13988    }
  13989 
  13990    /// @brief remove last reference token
  13991    /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
  13992    void pop_back()
  13993    {
  13994        if (JSON_HEDLEY_UNLIKELY(empty()))
  13995        {
  13996            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
  13997        }
  13998 
  13999        reference_tokens.pop_back();
  14000    }
  14001 
  14002    /// @brief return last reference token
  14003    /// @sa https://json.nlohmann.me/api/json_pointer/back/
  14004    const string_t& back() const
  14005    {
  14006        if (JSON_HEDLEY_UNLIKELY(empty()))
  14007        {
  14008            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
  14009        }
  14010 
  14011        return reference_tokens.back();
  14012    }
  14013 
  14014    /// @brief append an unescaped token at the end of the reference pointer
  14015    /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
  14016    void push_back(const string_t& token)
  14017    {
  14018        reference_tokens.push_back(token);
  14019    }
  14020 
  14021    /// @brief append an unescaped token at the end of the reference pointer
  14022    /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
  14023    void push_back(string_t&& token)
  14024    {
  14025        reference_tokens.push_back(std::move(token));
  14026    }
  14027 
  14028    /// @brief return whether pointer points to the root document
  14029    /// @sa https://json.nlohmann.me/api/json_pointer/empty/
  14030    bool empty() const noexcept
  14031    {
  14032        return reference_tokens.empty();
  14033    }
  14034 
  14035  private:
  14036    /*!
  14037    @param[in] s  reference token to be converted into an array index
  14038 
  14039    @return integer representation of @a s
  14040 
  14041    @throw parse_error.106  if an array index begins with '0'
  14042    @throw parse_error.109  if an array index begins not with a digit
  14043    @throw out_of_range.404 if string @a s could not be converted to an integer
  14044    @throw out_of_range.410 if an array index exceeds size_type
  14045    */
  14046    template<typename BasicJsonType>
  14047    static typename BasicJsonType::size_type array_index(const string_t& s)
  14048    {
  14049        using size_type = typename BasicJsonType::size_type;
  14050 
  14051        // error condition (cf. RFC 6901, Sect. 4)
  14052        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
  14053        {
  14054            JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
  14055        }
  14056 
  14057        // error condition (cf. RFC 6901, Sect. 4)
  14058        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
  14059        {
  14060            JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
  14061        }
  14062 
  14063        const char* p = s.c_str();
  14064        char* p_end = nullptr;
  14065        errno = 0; // strtoull doesn't reset errno
  14066        const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
  14067        if (p == p_end // invalid input or empty string
  14068                || errno == ERANGE // out of range
  14069                || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
  14070        {
  14071            JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
  14072        }
  14073 
  14074        // only triggered on special platforms (like 32bit), see also
  14075        // https://github.com/nlohmann/json/pull/2203
  14076        if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
  14077        {
  14078            JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
  14079        }
  14080 
  14081        return static_cast<size_type>(res);
  14082    }
  14083 
  14084  JSON_PRIVATE_UNLESS_TESTED:
  14085    json_pointer top() const
  14086    {
  14087        if (JSON_HEDLEY_UNLIKELY(empty()))
  14088        {
  14089            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
  14090        }
  14091 
  14092        json_pointer result = *this;
  14093        result.reference_tokens = {reference_tokens[0]};
  14094        return result;
  14095    }
  14096 
  14097  private:
  14098    /*!
  14099    @brief create and return a reference to the pointed to value
  14100 
  14101    @complexity Linear in the number of reference tokens.
  14102 
  14103    @throw parse_error.109 if array index is not a number
  14104    @throw type_error.313 if value cannot be unflattened
  14105    */
  14106    template<typename BasicJsonType>
  14107    BasicJsonType& get_and_create(BasicJsonType& j) const
  14108    {
  14109        auto* result = &j;
  14110 
  14111        // in case no reference tokens exist, return a reference to the JSON value
  14112        // j which will be overwritten by a primitive value
  14113        for (const auto& reference_token : reference_tokens)
  14114        {
  14115            switch (result->type())
  14116            {
  14117                case detail::value_t::null:
  14118                {
  14119                    if (reference_token == "0")
  14120                    {
  14121                        // start a new array if reference token is 0
  14122                        result = &result->operator[](0);
  14123                    }
  14124                    else
  14125                    {
  14126                        // start a new object otherwise
  14127                        result = &result->operator[](reference_token);
  14128                    }
  14129                    break;
  14130                }
  14131 
  14132                case detail::value_t::object:
  14133                {
  14134                    // create an entry in the object
  14135                    result = &result->operator[](reference_token);
  14136                    break;
  14137                }
  14138 
  14139                case detail::value_t::array:
  14140                {
  14141                    // create an entry in the array
  14142                    result = &result->operator[](array_index<BasicJsonType>(reference_token));
  14143                    break;
  14144                }
  14145 
  14146                /*
  14147                The following code is only reached if there exists a reference
  14148                token _and_ the current value is primitive. In this case, we have
  14149                an error situation, because primitive values may only occur as
  14150                single value; that is, with an empty list of reference tokens.
  14151                */
  14152                case detail::value_t::string:
  14153                case detail::value_t::boolean:
  14154                case detail::value_t::number_integer:
  14155                case detail::value_t::number_unsigned:
  14156                case detail::value_t::number_float:
  14157                case detail::value_t::binary:
  14158                case detail::value_t::discarded:
  14159                default:
  14160                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
  14161            }
  14162        }
  14163 
  14164        return *result;
  14165    }
  14166 
  14167    /*!
  14168    @brief return a reference to the pointed to value
  14169 
  14170    @note This version does not throw if a value is not present, but tries to
  14171          create nested values instead. For instance, calling this function
  14172          with pointer `"/this/that"` on a null value is equivalent to calling
  14173          `operator[]("this").operator[]("that")` on that value, effectively
  14174          changing the null value to an object.
  14175 
  14176    @param[in] ptr  a JSON value
  14177 
  14178    @return reference to the JSON value pointed to by the JSON pointer
  14179 
  14180    @complexity Linear in the length of the JSON pointer.
  14181 
  14182    @throw parse_error.106   if an array index begins with '0'
  14183    @throw parse_error.109   if an array index was not a number
  14184    @throw out_of_range.404  if the JSON pointer can not be resolved
  14185    */
  14186    template<typename BasicJsonType>
  14187    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
  14188    {
  14189        for (const auto& reference_token : reference_tokens)
  14190        {
  14191            // convert null values to arrays or objects before continuing
  14192            if (ptr->is_null())
  14193            {
  14194                // check if reference token is a number
  14195                const bool nums =
  14196                    std::all_of(reference_token.begin(), reference_token.end(),
  14197                                [](const unsigned char x)
  14198                {
  14199                    return std::isdigit(x);
  14200                });
  14201 
  14202                // change value to array for numbers or "-" or to object otherwise
  14203                *ptr = (nums || reference_token == "-")
  14204                       ? detail::value_t::array
  14205                       : detail::value_t::object;
  14206            }
  14207 
  14208            switch (ptr->type())
  14209            {
  14210                case detail::value_t::object:
  14211                {
  14212                    // use unchecked object access
  14213                    ptr = &ptr->operator[](reference_token);
  14214                    break;
  14215                }
  14216 
  14217                case detail::value_t::array:
  14218                {
  14219                    if (reference_token == "-")
  14220                    {
  14221                        // explicitly treat "-" as index beyond the end
  14222                        ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
  14223                    }
  14224                    else
  14225                    {
  14226                        // convert array index to number; unchecked access
  14227                        ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
  14228                    }
  14229                    break;
  14230                }
  14231 
  14232                case detail::value_t::null:
  14233                case detail::value_t::string:
  14234                case detail::value_t::boolean:
  14235                case detail::value_t::number_integer:
  14236                case detail::value_t::number_unsigned:
  14237                case detail::value_t::number_float:
  14238                case detail::value_t::binary:
  14239                case detail::value_t::discarded:
  14240                default:
  14241                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14242            }
  14243        }
  14244 
  14245        return *ptr;
  14246    }
  14247 
  14248    /*!
  14249    @throw parse_error.106   if an array index begins with '0'
  14250    @throw parse_error.109   if an array index was not a number
  14251    @throw out_of_range.402  if the array index '-' is used
  14252    @throw out_of_range.404  if the JSON pointer can not be resolved
  14253    */
  14254    template<typename BasicJsonType>
  14255    BasicJsonType& get_checked(BasicJsonType* ptr) const
  14256    {
  14257        for (const auto& reference_token : reference_tokens)
  14258        {
  14259            switch (ptr->type())
  14260            {
  14261                case detail::value_t::object:
  14262                {
  14263                    // note: at performs range check
  14264                    ptr = &ptr->at(reference_token);
  14265                    break;
  14266                }
  14267 
  14268                case detail::value_t::array:
  14269                {
  14270                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14271                    {
  14272                        // "-" always fails the range check
  14273                        JSON_THROW(detail::out_of_range::create(402, detail::concat(
  14274                                "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
  14275                                ") is out of range"), ptr));
  14276                    }
  14277 
  14278                    // note: at performs range check
  14279                    ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
  14280                    break;
  14281                }
  14282 
  14283                case detail::value_t::null:
  14284                case detail::value_t::string:
  14285                case detail::value_t::boolean:
  14286                case detail::value_t::number_integer:
  14287                case detail::value_t::number_unsigned:
  14288                case detail::value_t::number_float:
  14289                case detail::value_t::binary:
  14290                case detail::value_t::discarded:
  14291                default:
  14292                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14293            }
  14294        }
  14295 
  14296        return *ptr;
  14297    }
  14298 
  14299    /*!
  14300    @brief return a const reference to the pointed to value
  14301 
  14302    @param[in] ptr  a JSON value
  14303 
  14304    @return const reference to the JSON value pointed to by the JSON
  14305    pointer
  14306 
  14307    @throw parse_error.106   if an array index begins with '0'
  14308    @throw parse_error.109   if an array index was not a number
  14309    @throw out_of_range.402  if the array index '-' is used
  14310    @throw out_of_range.404  if the JSON pointer can not be resolved
  14311    */
  14312    template<typename BasicJsonType>
  14313    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
  14314    {
  14315        for (const auto& reference_token : reference_tokens)
  14316        {
  14317            switch (ptr->type())
  14318            {
  14319                case detail::value_t::object:
  14320                {
  14321                    // use unchecked object access
  14322                    ptr = &ptr->operator[](reference_token);
  14323                    break;
  14324                }
  14325 
  14326                case detail::value_t::array:
  14327                {
  14328                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14329                    {
  14330                        // "-" cannot be used for const access
  14331                        JSON_THROW(detail::out_of_range::create(402, detail::concat("array index '-' (", std::to_string(ptr->m_data.m_value.array->size()), ") is out of range"), ptr));
  14332                    }
  14333 
  14334                    // use unchecked array access
  14335                    ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
  14336                    break;
  14337                }
  14338 
  14339                case detail::value_t::null:
  14340                case detail::value_t::string:
  14341                case detail::value_t::boolean:
  14342                case detail::value_t::number_integer:
  14343                case detail::value_t::number_unsigned:
  14344                case detail::value_t::number_float:
  14345                case detail::value_t::binary:
  14346                case detail::value_t::discarded:
  14347                default:
  14348                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14349            }
  14350        }
  14351 
  14352        return *ptr;
  14353    }
  14354 
  14355    /*!
  14356    @throw parse_error.106   if an array index begins with '0'
  14357    @throw parse_error.109   if an array index was not a number
  14358    @throw out_of_range.402  if the array index '-' is used
  14359    @throw out_of_range.404  if the JSON pointer can not be resolved
  14360    */
  14361    template<typename BasicJsonType>
  14362    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
  14363    {
  14364        for (const auto& reference_token : reference_tokens)
  14365        {
  14366            switch (ptr->type())
  14367            {
  14368                case detail::value_t::object:
  14369                {
  14370                    // note: at performs range check
  14371                    ptr = &ptr->at(reference_token);
  14372                    break;
  14373                }
  14374 
  14375                case detail::value_t::array:
  14376                {
  14377                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14378                    {
  14379                        // "-" always fails the range check
  14380                        JSON_THROW(detail::out_of_range::create(402, detail::concat(
  14381                                "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
  14382                                ") is out of range"), ptr));
  14383                    }
  14384 
  14385                    // note: at performs range check
  14386                    ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
  14387                    break;
  14388                }
  14389 
  14390                case detail::value_t::null:
  14391                case detail::value_t::string:
  14392                case detail::value_t::boolean:
  14393                case detail::value_t::number_integer:
  14394                case detail::value_t::number_unsigned:
  14395                case detail::value_t::number_float:
  14396                case detail::value_t::binary:
  14397                case detail::value_t::discarded:
  14398                default:
  14399                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
  14400            }
  14401        }
  14402 
  14403        return *ptr;
  14404    }
  14405 
  14406    /*!
  14407    @throw parse_error.106   if an array index begins with '0'
  14408    @throw parse_error.109   if an array index was not a number
  14409    */
  14410    template<typename BasicJsonType>
  14411    bool contains(const BasicJsonType* ptr) const
  14412    {
  14413        for (const auto& reference_token : reference_tokens)
  14414        {
  14415            switch (ptr->type())
  14416            {
  14417                case detail::value_t::object:
  14418                {
  14419                    if (!ptr->contains(reference_token))
  14420                    {
  14421                        // we did not find the key in the object
  14422                        return false;
  14423                    }
  14424 
  14425                    ptr = &ptr->operator[](reference_token);
  14426                    break;
  14427                }
  14428 
  14429                case detail::value_t::array:
  14430                {
  14431                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
  14432                    {
  14433                        // "-" always fails the range check
  14434                        return false;
  14435                    }
  14436                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
  14437                    {
  14438                        // invalid char
  14439                        return false;
  14440                    }
  14441                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
  14442                    {
  14443                        if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
  14444                        {
  14445                            // first char should be between '1' and '9'
  14446                            return false;
  14447                        }
  14448                        for (std::size_t i = 1; i < reference_token.size(); i++)
  14449                        {
  14450                            if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
  14451                            {
  14452                                // other char should be between '0' and '9'
  14453                                return false;
  14454                            }
  14455                        }
  14456                    }
  14457 
  14458                    const auto idx = array_index<BasicJsonType>(reference_token);
  14459                    if (idx >= ptr->size())
  14460                    {
  14461                        // index out of range
  14462                        return false;
  14463                    }
  14464 
  14465                    ptr = &ptr->operator[](idx);
  14466                    break;
  14467                }
  14468 
  14469                case detail::value_t::null:
  14470                case detail::value_t::string:
  14471                case detail::value_t::boolean:
  14472                case detail::value_t::number_integer:
  14473                case detail::value_t::number_unsigned:
  14474                case detail::value_t::number_float:
  14475                case detail::value_t::binary:
  14476                case detail::value_t::discarded:
  14477                default:
  14478                {
  14479                    // we do not expect primitive values if there is still a
  14480                    // reference token to process
  14481                    return false;
  14482                }
  14483            }
  14484        }
  14485 
  14486        // no reference token left means we found a primitive value
  14487        return true;
  14488    }
  14489 
  14490    /*!
  14491    @brief split the string input to reference tokens
  14492 
  14493    @note This function is only called by the json_pointer constructor.
  14494          All exceptions below are documented there.
  14495 
  14496    @throw parse_error.107  if the pointer is not empty or begins with '/'
  14497    @throw parse_error.108  if character '~' is not followed by '0' or '1'
  14498    */
  14499    static std::vector<string_t> split(const string_t& reference_string)
  14500    {
  14501        std::vector<string_t> result;
  14502 
  14503        // special case: empty reference string -> no reference tokens
  14504        if (reference_string.empty())
  14505        {
  14506            return result;
  14507        }
  14508 
  14509        // check if nonempty reference string begins with slash
  14510        if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
  14511        {
  14512            JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
  14513        }
  14514 
  14515        // extract the reference tokens:
  14516        // - slash: position of the last read slash (or end of string)
  14517        // - start: position after the previous slash
  14518        for (
  14519            // search for the first slash after the first character
  14520            std::size_t slash = reference_string.find_first_of('/', 1),
  14521            // set the beginning of the first reference token
  14522            start = 1;
  14523            // we can stop if start == 0 (if slash == string_t::npos)
  14524            start != 0;
  14525            // set the beginning of the next reference token
  14526            // (will eventually be 0 if slash == string_t::npos)
  14527            start = (slash == string_t::npos) ? 0 : slash + 1,
  14528            // find next slash
  14529            slash = reference_string.find_first_of('/', start))
  14530        {
  14531            // use the text between the beginning of the reference token
  14532            // (start) and the last slash (slash).
  14533            auto reference_token = reference_string.substr(start, slash - start);
  14534 
  14535            // check reference tokens are properly escaped
  14536            for (std::size_t pos = reference_token.find_first_of('~');
  14537                    pos != string_t::npos;
  14538                    pos = reference_token.find_first_of('~', pos + 1))
  14539            {
  14540                JSON_ASSERT(reference_token[pos] == '~');
  14541 
  14542                // ~ must be followed by 0 or 1
  14543                if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
  14544                                         (reference_token[pos + 1] != '0' &&
  14545                                          reference_token[pos + 1] != '1')))
  14546                {
  14547                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
  14548                }
  14549            }
  14550 
  14551            // finally, store the reference token
  14552            detail::unescape(reference_token);
  14553            result.push_back(reference_token);
  14554        }
  14555 
  14556        return result;
  14557    }
  14558 
  14559  private:
  14560    /*!
  14561    @param[in] reference_string  the reference string to the current value
  14562    @param[in] value             the value to consider
  14563    @param[in,out] result        the result object to insert values to
  14564 
  14565    @note Empty objects or arrays are flattened to `null`.
  14566    */
  14567    template<typename BasicJsonType>
  14568    static void flatten(const string_t& reference_string,
  14569                        const BasicJsonType& value,
  14570                        BasicJsonType& result)
  14571    {
  14572        switch (value.type())
  14573        {
  14574            case detail::value_t::array:
  14575            {
  14576                if (value.m_data.m_value.array->empty())
  14577                {
  14578                    // flatten empty array as null
  14579                    result[reference_string] = nullptr;
  14580                }
  14581                else
  14582                {
  14583                    // iterate array and use index as reference string
  14584                    for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
  14585                    {
  14586                        flatten(detail::concat(reference_string, '/', std::to_string(i)),
  14587                                value.m_data.m_value.array->operator[](i), result);
  14588                    }
  14589                }
  14590                break;
  14591            }
  14592 
  14593            case detail::value_t::object:
  14594            {
  14595                if (value.m_data.m_value.object->empty())
  14596                {
  14597                    // flatten empty object as null
  14598                    result[reference_string] = nullptr;
  14599                }
  14600                else
  14601                {
  14602                    // iterate object and use keys as reference string
  14603                    for (const auto& element : *value.m_data.m_value.object)
  14604                    {
  14605                        flatten(detail::concat(reference_string, '/', detail::escape(element.first)), element.second, result);
  14606                    }
  14607                }
  14608                break;
  14609            }
  14610 
  14611            case detail::value_t::null:
  14612            case detail::value_t::string:
  14613            case detail::value_t::boolean:
  14614            case detail::value_t::number_integer:
  14615            case detail::value_t::number_unsigned:
  14616            case detail::value_t::number_float:
  14617            case detail::value_t::binary:
  14618            case detail::value_t::discarded:
  14619            default:
  14620            {
  14621                // add primitive value with its reference string
  14622                result[reference_string] = value;
  14623                break;
  14624            }
  14625        }
  14626    }
  14627 
  14628    /*!
  14629    @param[in] value  flattened JSON
  14630 
  14631    @return unflattened JSON
  14632 
  14633    @throw parse_error.109 if array index is not a number
  14634    @throw type_error.314  if value is not an object
  14635    @throw type_error.315  if object values are not primitive
  14636    @throw type_error.313  if value cannot be unflattened
  14637    */
  14638    template<typename BasicJsonType>
  14639    static BasicJsonType
  14640    unflatten(const BasicJsonType& value)
  14641    {
  14642        if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
  14643        {
  14644            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
  14645        }
  14646 
  14647        BasicJsonType result;
  14648 
  14649        // iterate the JSON object values
  14650        for (const auto& element : *value.m_data.m_value.object)
  14651        {
  14652            if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
  14653            {
  14654                JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
  14655            }
  14656 
  14657            // assign value to reference pointed to by JSON pointer; Note that if
  14658            // the JSON pointer is "" (i.e., points to the whole value), function
  14659            // get_and_create returns a reference to result itself. An assignment
  14660            // will then create a primitive value.
  14661            json_pointer(element.first).get_and_create(result) = element.second;
  14662        }
  14663 
  14664        return result;
  14665    }
  14666 
  14667    // can't use conversion operator because of ambiguity
  14668    json_pointer<string_t> convert() const&
  14669    {
  14670        json_pointer<string_t> result;
  14671        result.reference_tokens = reference_tokens;
  14672        return result;
  14673    }
  14674 
  14675    json_pointer<string_t> convert()&&
  14676    {
  14677        json_pointer<string_t> result;
  14678        result.reference_tokens = std::move(reference_tokens);
  14679        return result;
  14680    }
  14681 
  14682  public:
  14683 #if JSON_HAS_THREE_WAY_COMPARISON
  14684    /// @brief compares two JSON pointers for equality
  14685    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14686    template<typename RefStringTypeRhs>
  14687    bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
  14688    {
  14689        return reference_tokens == rhs.reference_tokens;
  14690    }
  14691 
  14692    /// @brief compares JSON pointer and string for equality
  14693    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14694    JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
  14695    bool operator==(const string_t& rhs) const
  14696    {
  14697        return *this == json_pointer(rhs);
  14698    }
  14699 
  14700    /// @brief 3-way compares two JSON pointers
  14701    template<typename RefStringTypeRhs>
  14702    std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
  14703    {
  14704        return  reference_tokens <=> rhs.reference_tokens; // *NOPAD*
  14705    }
  14706 #else
  14707    /// @brief compares two JSON pointers for equality
  14708    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14709    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14710    // NOLINTNEXTLINE(readability-redundant-declaration)
  14711    friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14712                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
  14713 
  14714    /// @brief compares JSON pointer and string for equality
  14715    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14716    template<typename RefStringTypeLhs, typename StringType>
  14717    // NOLINTNEXTLINE(readability-redundant-declaration)
  14718    friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14719                           const StringType& rhs);
  14720 
  14721    /// @brief compares string and JSON pointer for equality
  14722    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
  14723    template<typename RefStringTypeRhs, typename StringType>
  14724    // NOLINTNEXTLINE(readability-redundant-declaration)
  14725    friend bool operator==(const StringType& lhs,
  14726                           const json_pointer<RefStringTypeRhs>& rhs);
  14727 
  14728    /// @brief compares two JSON pointers for inequality
  14729    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
  14730    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14731    // NOLINTNEXTLINE(readability-redundant-declaration)
  14732    friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14733                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
  14734 
  14735    /// @brief compares JSON pointer and string for inequality
  14736    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
  14737    template<typename RefStringTypeLhs, typename StringType>
  14738    // NOLINTNEXTLINE(readability-redundant-declaration)
  14739    friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14740                           const StringType& rhs);
  14741 
  14742    /// @brief compares string and JSON pointer for inequality
  14743    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
  14744    template<typename RefStringTypeRhs, typename StringType>
  14745    // NOLINTNEXTLINE(readability-redundant-declaration)
  14746    friend bool operator!=(const StringType& lhs,
  14747                           const json_pointer<RefStringTypeRhs>& rhs);
  14748 
  14749    /// @brief compares two JSON pointer for less-than
  14750    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14751    // NOLINTNEXTLINE(readability-redundant-declaration)
  14752    friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
  14753                          const json_pointer<RefStringTypeRhs>& rhs) noexcept;
  14754 #endif
  14755 
  14756  private:
  14757    /// the reference tokens
  14758    std::vector<string_t> reference_tokens;
  14759 };
  14760 
  14761 #if !JSON_HAS_THREE_WAY_COMPARISON
  14762 // functions cannot be defined inside class due to ODR violations
  14763 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14764 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14765                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
  14766 {
  14767    return lhs.reference_tokens == rhs.reference_tokens;
  14768 }
  14769 
  14770 template<typename RefStringTypeLhs,
  14771         typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
  14772 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
  14773 inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
  14774                       const StringType& rhs)
  14775 {
  14776    return lhs == json_pointer<RefStringTypeLhs>(rhs);
  14777 }
  14778 
  14779 template<typename RefStringTypeRhs,
  14780         typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
  14781 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
  14782 inline bool operator==(const StringType& lhs,
  14783                       const json_pointer<RefStringTypeRhs>& rhs)
  14784 {
  14785    return json_pointer<RefStringTypeRhs>(lhs) == rhs;
  14786 }
  14787 
  14788 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14789 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14790                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
  14791 {
  14792    return !(lhs == rhs);
  14793 }
  14794 
  14795 template<typename RefStringTypeLhs,
  14796         typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
  14797 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
  14798 inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
  14799                       const StringType& rhs)
  14800 {
  14801    return !(lhs == rhs);
  14802 }
  14803 
  14804 template<typename RefStringTypeRhs,
  14805         typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
  14806 JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
  14807 inline bool operator!=(const StringType& lhs,
  14808                       const json_pointer<RefStringTypeRhs>& rhs)
  14809 {
  14810    return !(lhs == rhs);
  14811 }
  14812 
  14813 template<typename RefStringTypeLhs, typename RefStringTypeRhs>
  14814 inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
  14815                      const json_pointer<RefStringTypeRhs>& rhs) noexcept
  14816 {
  14817    return lhs.reference_tokens < rhs.reference_tokens;
  14818 }
  14819 #endif
  14820 
  14821 NLOHMANN_JSON_NAMESPACE_END
  14822 
  14823 // #include <nlohmann/detail/json_ref.hpp>
  14824 //     __ _____ _____ _____
  14825 //  __|  |   __|     |   | |  JSON for Modern C++
  14826 // |  |  |__   |  |  | | | |  version 3.11.3
  14827 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  14828 //
  14829 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  14830 // SPDX-License-Identifier: MIT
  14831 
  14832 
  14833 
  14834 #include <initializer_list>
  14835 #include <utility>
  14836 
  14837 // #include <nlohmann/detail/abi_macros.hpp>
  14838 
  14839 // #include <nlohmann/detail/meta/type_traits.hpp>
  14840 
  14841 
  14842 NLOHMANN_JSON_NAMESPACE_BEGIN
  14843 namespace detail
  14844 {
  14845 
  14846 template<typename BasicJsonType>
  14847 class json_ref
  14848 {
  14849  public:
  14850    using value_type = BasicJsonType;
  14851 
  14852    json_ref(value_type&& value)
  14853        : owned_value(std::move(value))
  14854    {}
  14855 
  14856    json_ref(const value_type& value)
  14857        : value_ref(&value)
  14858    {}
  14859 
  14860    json_ref(std::initializer_list<json_ref> init)
  14861        : owned_value(init)
  14862    {}
  14863 
  14864    template <
  14865        class... Args,
  14866        enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
  14867    json_ref(Args && ... args)
  14868        : owned_value(std::forward<Args>(args)...)
  14869    {}
  14870 
  14871    // class should be movable only
  14872    json_ref(json_ref&&) noexcept = default;
  14873    json_ref(const json_ref&) = delete;
  14874    json_ref& operator=(const json_ref&) = delete;
  14875    json_ref& operator=(json_ref&&) = delete;
  14876    ~json_ref() = default;
  14877 
  14878    value_type moved_or_copied() const
  14879    {
  14880        if (value_ref == nullptr)
  14881        {
  14882            return std::move(owned_value);
  14883        }
  14884        return *value_ref;
  14885    }
  14886 
  14887    value_type const& operator*() const
  14888    {
  14889        return value_ref ? *value_ref : owned_value;
  14890    }
  14891 
  14892    value_type const* operator->() const
  14893    {
  14894        return &** this;
  14895    }
  14896 
  14897  private:
  14898    mutable value_type owned_value = nullptr;
  14899    value_type const* value_ref = nullptr;
  14900 };
  14901 
  14902 }  // namespace detail
  14903 NLOHMANN_JSON_NAMESPACE_END
  14904 
  14905 // #include <nlohmann/detail/macro_scope.hpp>
  14906 
  14907 // #include <nlohmann/detail/string_concat.hpp>
  14908 
  14909 // #include <nlohmann/detail/string_escape.hpp>
  14910 
  14911 // #include <nlohmann/detail/meta/cpp_future.hpp>
  14912 
  14913 // #include <nlohmann/detail/meta/type_traits.hpp>
  14914 
  14915 // #include <nlohmann/detail/output/binary_writer.hpp>
  14916 //     __ _____ _____ _____
  14917 //  __|  |   __|     |   | |  JSON for Modern C++
  14918 // |  |  |__   |  |  | | | |  version 3.11.3
  14919 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  14920 //
  14921 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  14922 // SPDX-License-Identifier: MIT
  14923 
  14924 
  14925 
  14926 #include <algorithm> // reverse
  14927 #include <array> // array
  14928 #include <map> // map
  14929 #include <cmath> // isnan, isinf
  14930 #include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
  14931 #include <cstring> // memcpy
  14932 #include <limits> // numeric_limits
  14933 #include <string> // string
  14934 #include <utility> // move
  14935 #include <vector> // vector
  14936 
  14937 // #include <nlohmann/detail/input/binary_reader.hpp>
  14938 
  14939 // #include <nlohmann/detail/macro_scope.hpp>
  14940 
  14941 // #include <nlohmann/detail/output/output_adapters.hpp>
  14942 //     __ _____ _____ _____
  14943 //  __|  |   __|     |   | |  JSON for Modern C++
  14944 // |  |  |__   |  |  | | | |  version 3.11.3
  14945 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  14946 //
  14947 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  14948 // SPDX-License-Identifier: MIT
  14949 
  14950 
  14951 
  14952 #include <algorithm> // copy
  14953 #include <cstddef> // size_t
  14954 #include <iterator> // back_inserter
  14955 #include <memory> // shared_ptr, make_shared
  14956 #include <string> // basic_string
  14957 #include <vector> // vector
  14958 
  14959 #ifndef JSON_NO_IO
  14960    #include <ios>      // streamsize
  14961    #include <ostream>  // basic_ostream
  14962 #endif  // JSON_NO_IO
  14963 
  14964 // #include <nlohmann/detail/macro_scope.hpp>
  14965 
  14966 
  14967 NLOHMANN_JSON_NAMESPACE_BEGIN
  14968 namespace detail
  14969 {
  14970 
  14971 /// abstract output adapter interface
  14972 template<typename CharType> struct output_adapter_protocol
  14973 {
  14974    virtual void write_character(CharType c) = 0;
  14975    virtual void write_characters(const CharType* s, std::size_t length) = 0;
  14976    virtual ~output_adapter_protocol() = default;
  14977 
  14978    output_adapter_protocol() = default;
  14979    output_adapter_protocol(const output_adapter_protocol&) = default;
  14980    output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
  14981    output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
  14982    output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
  14983 };
  14984 
  14985 /// a type to simplify interfaces
  14986 template<typename CharType>
  14987 using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
  14988 
  14989 /// output adapter for byte vectors
  14990 template<typename CharType, typename AllocatorType = std::allocator<CharType>>
  14991 class output_vector_adapter : public output_adapter_protocol<CharType>
  14992 {
  14993  public:
  14994    explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
  14995        : v(vec)
  14996    {}
  14997 
  14998    void write_character(CharType c) override
  14999    {
  15000        v.push_back(c);
  15001    }
  15002 
  15003    JSON_HEDLEY_NON_NULL(2)
  15004    void write_characters(const CharType* s, std::size_t length) override
  15005    {
  15006        v.insert(v.end(), s, s + length);
  15007    }
  15008 
  15009  private:
  15010    std::vector<CharType, AllocatorType>& v;
  15011 };
  15012 
  15013 #ifndef JSON_NO_IO
  15014 /// output adapter for output streams
  15015 template<typename CharType>
  15016 class output_stream_adapter : public output_adapter_protocol<CharType>
  15017 {
  15018  public:
  15019    explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
  15020        : stream(s)
  15021    {}
  15022 
  15023    void write_character(CharType c) override
  15024    {
  15025        stream.put(c);
  15026    }
  15027 
  15028    JSON_HEDLEY_NON_NULL(2)
  15029    void write_characters(const CharType* s, std::size_t length) override
  15030    {
  15031        stream.write(s, static_cast<std::streamsize>(length));
  15032    }
  15033 
  15034  private:
  15035    std::basic_ostream<CharType>& stream;
  15036 };
  15037 #endif  // JSON_NO_IO
  15038 
  15039 /// output adapter for basic_string
  15040 template<typename CharType, typename StringType = std::basic_string<CharType>>
  15041 class output_string_adapter : public output_adapter_protocol<CharType>
  15042 {
  15043  public:
  15044    explicit output_string_adapter(StringType& s) noexcept
  15045        : str(s)
  15046    {}
  15047 
  15048    void write_character(CharType c) override
  15049    {
  15050        str.push_back(c);
  15051    }
  15052 
  15053    JSON_HEDLEY_NON_NULL(2)
  15054    void write_characters(const CharType* s, std::size_t length) override
  15055    {
  15056        str.append(s, length);
  15057    }
  15058 
  15059  private:
  15060    StringType& str;
  15061 };
  15062 
  15063 template<typename CharType, typename StringType = std::basic_string<CharType>>
  15064 class output_adapter
  15065 {
  15066  public:
  15067    template<typename AllocatorType = std::allocator<CharType>>
  15068    output_adapter(std::vector<CharType, AllocatorType>& vec)
  15069        : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
  15070 
  15071 #ifndef JSON_NO_IO
  15072    output_adapter(std::basic_ostream<CharType>& s)
  15073        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
  15074 #endif  // JSON_NO_IO
  15075 
  15076    output_adapter(StringType& s)
  15077        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
  15078 
  15079    operator output_adapter_t<CharType>()
  15080    {
  15081        return oa;
  15082    }
  15083 
  15084  private:
  15085    output_adapter_t<CharType> oa = nullptr;
  15086 };
  15087 
  15088 }  // namespace detail
  15089 NLOHMANN_JSON_NAMESPACE_END
  15090 
  15091 // #include <nlohmann/detail/string_concat.hpp>
  15092 
  15093 
  15094 NLOHMANN_JSON_NAMESPACE_BEGIN
  15095 namespace detail
  15096 {
  15097 
  15098 ///////////////////
  15099 // binary writer //
  15100 ///////////////////
  15101 
  15102 /*!
  15103 @brief serialization to CBOR and MessagePack values
  15104 */
  15105 template<typename BasicJsonType, typename CharType>
  15106 class binary_writer
  15107 {
  15108    using string_t = typename BasicJsonType::string_t;
  15109    using binary_t = typename BasicJsonType::binary_t;
  15110    using number_float_t = typename BasicJsonType::number_float_t;
  15111 
  15112  public:
  15113    /*!
  15114    @brief create a binary writer
  15115 
  15116    @param[in] adapter  output adapter to write to
  15117    */
  15118    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
  15119    {
  15120        JSON_ASSERT(oa);
  15121    }
  15122 
  15123    /*!
  15124    @param[in] j  JSON value to serialize
  15125    @pre       j.type() == value_t::object
  15126    */
  15127    void write_bson(const BasicJsonType& j)
  15128    {
  15129        switch (j.type())
  15130        {
  15131            case value_t::object:
  15132            {
  15133                write_bson_object(*j.m_data.m_value.object);
  15134                break;
  15135            }
  15136 
  15137            case value_t::null:
  15138            case value_t::array:
  15139            case value_t::string:
  15140            case value_t::boolean:
  15141            case value_t::number_integer:
  15142            case value_t::number_unsigned:
  15143            case value_t::number_float:
  15144            case value_t::binary:
  15145            case value_t::discarded:
  15146            default:
  15147            {
  15148                JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
  15149            }
  15150        }
  15151    }
  15152 
  15153    /*!
  15154    @param[in] j  JSON value to serialize
  15155    */
  15156    void write_cbor(const BasicJsonType& j)
  15157    {
  15158        switch (j.type())
  15159        {
  15160            case value_t::null:
  15161            {
  15162                oa->write_character(to_char_type(0xF6));
  15163                break;
  15164            }
  15165 
  15166            case value_t::boolean:
  15167            {
  15168                oa->write_character(j.m_data.m_value.boolean
  15169                                    ? to_char_type(0xF5)
  15170                                    : to_char_type(0xF4));
  15171                break;
  15172            }
  15173 
  15174            case value_t::number_integer:
  15175            {
  15176                if (j.m_data.m_value.number_integer >= 0)
  15177                {
  15178                    // CBOR does not differentiate between positive signed
  15179                    // integers and unsigned integers. Therefore, we used the
  15180                    // code from the value_t::number_unsigned case here.
  15181                    if (j.m_data.m_value.number_integer <= 0x17)
  15182                    {
  15183                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
  15184                    }
  15185                    else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
  15186                    {
  15187                        oa->write_character(to_char_type(0x18));
  15188                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
  15189                    }
  15190                    else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
  15191                    {
  15192                        oa->write_character(to_char_type(0x19));
  15193                        write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
  15194                    }
  15195                    else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
  15196                    {
  15197                        oa->write_character(to_char_type(0x1A));
  15198                        write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
  15199                    }
  15200                    else
  15201                    {
  15202                        oa->write_character(to_char_type(0x1B));
  15203                        write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
  15204                    }
  15205                }
  15206                else
  15207                {
  15208                    // The conversions below encode the sign in the first
  15209                    // byte, and the value is converted to a positive number.
  15210                    const auto positive_number = -1 - j.m_data.m_value.number_integer;
  15211                    if (j.m_data.m_value.number_integer >= -24)
  15212                    {
  15213                        write_number(static_cast<std::uint8_t>(0x20 + positive_number));
  15214                    }
  15215                    else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
  15216                    {
  15217                        oa->write_character(to_char_type(0x38));
  15218                        write_number(static_cast<std::uint8_t>(positive_number));
  15219                    }
  15220                    else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
  15221                    {
  15222                        oa->write_character(to_char_type(0x39));
  15223                        write_number(static_cast<std::uint16_t>(positive_number));
  15224                    }
  15225                    else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
  15226                    {
  15227                        oa->write_character(to_char_type(0x3A));
  15228                        write_number(static_cast<std::uint32_t>(positive_number));
  15229                    }
  15230                    else
  15231                    {
  15232                        oa->write_character(to_char_type(0x3B));
  15233                        write_number(static_cast<std::uint64_t>(positive_number));
  15234                    }
  15235                }
  15236                break;
  15237            }
  15238 
  15239            case value_t::number_unsigned:
  15240            {
  15241                if (j.m_data.m_value.number_unsigned <= 0x17)
  15242                {
  15243                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
  15244                }
  15245                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  15246                {
  15247                    oa->write_character(to_char_type(0x18));
  15248                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
  15249                }
  15250                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  15251                {
  15252                    oa->write_character(to_char_type(0x19));
  15253                    write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
  15254                }
  15255                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  15256                {
  15257                    oa->write_character(to_char_type(0x1A));
  15258                    write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
  15259                }
  15260                else
  15261                {
  15262                    oa->write_character(to_char_type(0x1B));
  15263                    write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
  15264                }
  15265                break;
  15266            }
  15267 
  15268            case value_t::number_float:
  15269            {
  15270                if (std::isnan(j.m_data.m_value.number_float))
  15271                {
  15272                    // NaN is 0xf97e00 in CBOR
  15273                    oa->write_character(to_char_type(0xF9));
  15274                    oa->write_character(to_char_type(0x7E));
  15275                    oa->write_character(to_char_type(0x00));
  15276                }
  15277                else if (std::isinf(j.m_data.m_value.number_float))
  15278                {
  15279                    // Infinity is 0xf97c00, -Infinity is 0xf9fc00
  15280                    oa->write_character(to_char_type(0xf9));
  15281                    oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
  15282                    oa->write_character(to_char_type(0x00));
  15283                }
  15284                else
  15285                {
  15286                    write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
  15287                }
  15288                break;
  15289            }
  15290 
  15291            case value_t::string:
  15292            {
  15293                // step 1: write control byte and the string length
  15294                const auto N = j.m_data.m_value.string->size();
  15295                if (N <= 0x17)
  15296                {
  15297                    write_number(static_cast<std::uint8_t>(0x60 + N));
  15298                }
  15299                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15300                {
  15301                    oa->write_character(to_char_type(0x78));
  15302                    write_number(static_cast<std::uint8_t>(N));
  15303                }
  15304                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15305                {
  15306                    oa->write_character(to_char_type(0x79));
  15307                    write_number(static_cast<std::uint16_t>(N));
  15308                }
  15309                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15310                {
  15311                    oa->write_character(to_char_type(0x7A));
  15312                    write_number(static_cast<std::uint32_t>(N));
  15313                }
  15314                // LCOV_EXCL_START
  15315                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15316                {
  15317                    oa->write_character(to_char_type(0x7B));
  15318                    write_number(static_cast<std::uint64_t>(N));
  15319                }
  15320                // LCOV_EXCL_STOP
  15321 
  15322                // step 2: write the string
  15323                oa->write_characters(
  15324                    reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
  15325                    j.m_data.m_value.string->size());
  15326                break;
  15327            }
  15328 
  15329            case value_t::array:
  15330            {
  15331                // step 1: write control byte and the array size
  15332                const auto N = j.m_data.m_value.array->size();
  15333                if (N <= 0x17)
  15334                {
  15335                    write_number(static_cast<std::uint8_t>(0x80 + N));
  15336                }
  15337                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15338                {
  15339                    oa->write_character(to_char_type(0x98));
  15340                    write_number(static_cast<std::uint8_t>(N));
  15341                }
  15342                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15343                {
  15344                    oa->write_character(to_char_type(0x99));
  15345                    write_number(static_cast<std::uint16_t>(N));
  15346                }
  15347                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15348                {
  15349                    oa->write_character(to_char_type(0x9A));
  15350                    write_number(static_cast<std::uint32_t>(N));
  15351                }
  15352                // LCOV_EXCL_START
  15353                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15354                {
  15355                    oa->write_character(to_char_type(0x9B));
  15356                    write_number(static_cast<std::uint64_t>(N));
  15357                }
  15358                // LCOV_EXCL_STOP
  15359 
  15360                // step 2: write each element
  15361                for (const auto& el : *j.m_data.m_value.array)
  15362                {
  15363                    write_cbor(el);
  15364                }
  15365                break;
  15366            }
  15367 
  15368            case value_t::binary:
  15369            {
  15370                if (j.m_data.m_value.binary->has_subtype())
  15371                {
  15372                    if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
  15373                    {
  15374                        write_number(static_cast<std::uint8_t>(0xd8));
  15375                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
  15376                    }
  15377                    else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
  15378                    {
  15379                        write_number(static_cast<std::uint8_t>(0xd9));
  15380                        write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
  15381                    }
  15382                    else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
  15383                    {
  15384                        write_number(static_cast<std::uint8_t>(0xda));
  15385                        write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
  15386                    }
  15387                    else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
  15388                    {
  15389                        write_number(static_cast<std::uint8_t>(0xdb));
  15390                        write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
  15391                    }
  15392                }
  15393 
  15394                // step 1: write control byte and the binary array size
  15395                const auto N = j.m_data.m_value.binary->size();
  15396                if (N <= 0x17)
  15397                {
  15398                    write_number(static_cast<std::uint8_t>(0x40 + N));
  15399                }
  15400                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15401                {
  15402                    oa->write_character(to_char_type(0x58));
  15403                    write_number(static_cast<std::uint8_t>(N));
  15404                }
  15405                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15406                {
  15407                    oa->write_character(to_char_type(0x59));
  15408                    write_number(static_cast<std::uint16_t>(N));
  15409                }
  15410                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15411                {
  15412                    oa->write_character(to_char_type(0x5A));
  15413                    write_number(static_cast<std::uint32_t>(N));
  15414                }
  15415                // LCOV_EXCL_START
  15416                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15417                {
  15418                    oa->write_character(to_char_type(0x5B));
  15419                    write_number(static_cast<std::uint64_t>(N));
  15420                }
  15421                // LCOV_EXCL_STOP
  15422 
  15423                // step 2: write each element
  15424                oa->write_characters(
  15425                    reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
  15426                    N);
  15427 
  15428                break;
  15429            }
  15430 
  15431            case value_t::object:
  15432            {
  15433                // step 1: write control byte and the object size
  15434                const auto N = j.m_data.m_value.object->size();
  15435                if (N <= 0x17)
  15436                {
  15437                    write_number(static_cast<std::uint8_t>(0xA0 + N));
  15438                }
  15439                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15440                {
  15441                    oa->write_character(to_char_type(0xB8));
  15442                    write_number(static_cast<std::uint8_t>(N));
  15443                }
  15444                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15445                {
  15446                    oa->write_character(to_char_type(0xB9));
  15447                    write_number(static_cast<std::uint16_t>(N));
  15448                }
  15449                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15450                {
  15451                    oa->write_character(to_char_type(0xBA));
  15452                    write_number(static_cast<std::uint32_t>(N));
  15453                }
  15454                // LCOV_EXCL_START
  15455                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
  15456                {
  15457                    oa->write_character(to_char_type(0xBB));
  15458                    write_number(static_cast<std::uint64_t>(N));
  15459                }
  15460                // LCOV_EXCL_STOP
  15461 
  15462                // step 2: write each element
  15463                for (const auto& el : *j.m_data.m_value.object)
  15464                {
  15465                    write_cbor(el.first);
  15466                    write_cbor(el.second);
  15467                }
  15468                break;
  15469            }
  15470 
  15471            case value_t::discarded:
  15472            default:
  15473                break;
  15474        }
  15475    }
  15476 
  15477    /*!
  15478    @param[in] j  JSON value to serialize
  15479    */
  15480    void write_msgpack(const BasicJsonType& j)
  15481    {
  15482        switch (j.type())
  15483        {
  15484            case value_t::null: // nil
  15485            {
  15486                oa->write_character(to_char_type(0xC0));
  15487                break;
  15488            }
  15489 
  15490            case value_t::boolean: // true and false
  15491            {
  15492                oa->write_character(j.m_data.m_value.boolean
  15493                                    ? to_char_type(0xC3)
  15494                                    : to_char_type(0xC2));
  15495                break;
  15496            }
  15497 
  15498            case value_t::number_integer:
  15499            {
  15500                if (j.m_data.m_value.number_integer >= 0)
  15501                {
  15502                    // MessagePack does not differentiate between positive
  15503                    // signed integers and unsigned integers. Therefore, we used
  15504                    // the code from the value_t::number_unsigned case here.
  15505                    if (j.m_data.m_value.number_unsigned < 128)
  15506                    {
  15507                        // positive fixnum
  15508                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
  15509                    }
  15510                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  15511                    {
  15512                        // uint 8
  15513                        oa->write_character(to_char_type(0xCC));
  15514                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
  15515                    }
  15516                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  15517                    {
  15518                        // uint 16
  15519                        oa->write_character(to_char_type(0xCD));
  15520                        write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
  15521                    }
  15522                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  15523                    {
  15524                        // uint 32
  15525                        oa->write_character(to_char_type(0xCE));
  15526                        write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
  15527                    }
  15528                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  15529                    {
  15530                        // uint 64
  15531                        oa->write_character(to_char_type(0xCF));
  15532                        write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
  15533                    }
  15534                }
  15535                else
  15536                {
  15537                    if (j.m_data.m_value.number_integer >= -32)
  15538                    {
  15539                        // negative fixnum
  15540                        write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
  15541                    }
  15542                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
  15543                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
  15544                    {
  15545                        // int 8
  15546                        oa->write_character(to_char_type(0xD0));
  15547                        write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
  15548                    }
  15549                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
  15550                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
  15551                    {
  15552                        // int 16
  15553                        oa->write_character(to_char_type(0xD1));
  15554                        write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
  15555                    }
  15556                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
  15557                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
  15558                    {
  15559                        // int 32
  15560                        oa->write_character(to_char_type(0xD2));
  15561                        write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
  15562                    }
  15563                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
  15564                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
  15565                    {
  15566                        // int 64
  15567                        oa->write_character(to_char_type(0xD3));
  15568                        write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
  15569                    }
  15570                }
  15571                break;
  15572            }
  15573 
  15574            case value_t::number_unsigned:
  15575            {
  15576                if (j.m_data.m_value.number_unsigned < 128)
  15577                {
  15578                    // positive fixnum
  15579                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
  15580                }
  15581                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
  15582                {
  15583                    // uint 8
  15584                    oa->write_character(to_char_type(0xCC));
  15585                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
  15586                }
  15587                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
  15588                {
  15589                    // uint 16
  15590                    oa->write_character(to_char_type(0xCD));
  15591                    write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
  15592                }
  15593                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
  15594                {
  15595                    // uint 32
  15596                    oa->write_character(to_char_type(0xCE));
  15597                    write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
  15598                }
  15599                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  15600                {
  15601                    // uint 64
  15602                    oa->write_character(to_char_type(0xCF));
  15603                    write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
  15604                }
  15605                break;
  15606            }
  15607 
  15608            case value_t::number_float:
  15609            {
  15610                write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
  15611                break;
  15612            }
  15613 
  15614            case value_t::string:
  15615            {
  15616                // step 1: write control byte and the string length
  15617                const auto N = j.m_data.m_value.string->size();
  15618                if (N <= 31)
  15619                {
  15620                    // fixstr
  15621                    write_number(static_cast<std::uint8_t>(0xA0 | N));
  15622                }
  15623                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15624                {
  15625                    // str 8
  15626                    oa->write_character(to_char_type(0xD9));
  15627                    write_number(static_cast<std::uint8_t>(N));
  15628                }
  15629                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15630                {
  15631                    // str 16
  15632                    oa->write_character(to_char_type(0xDA));
  15633                    write_number(static_cast<std::uint16_t>(N));
  15634                }
  15635                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15636                {
  15637                    // str 32
  15638                    oa->write_character(to_char_type(0xDB));
  15639                    write_number(static_cast<std::uint32_t>(N));
  15640                }
  15641 
  15642                // step 2: write the string
  15643                oa->write_characters(
  15644                    reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
  15645                    j.m_data.m_value.string->size());
  15646                break;
  15647            }
  15648 
  15649            case value_t::array:
  15650            {
  15651                // step 1: write control byte and the array size
  15652                const auto N = j.m_data.m_value.array->size();
  15653                if (N <= 15)
  15654                {
  15655                    // fixarray
  15656                    write_number(static_cast<std::uint8_t>(0x90 | N));
  15657                }
  15658                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15659                {
  15660                    // array 16
  15661                    oa->write_character(to_char_type(0xDC));
  15662                    write_number(static_cast<std::uint16_t>(N));
  15663                }
  15664                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15665                {
  15666                    // array 32
  15667                    oa->write_character(to_char_type(0xDD));
  15668                    write_number(static_cast<std::uint32_t>(N));
  15669                }
  15670 
  15671                // step 2: write each element
  15672                for (const auto& el : *j.m_data.m_value.array)
  15673                {
  15674                    write_msgpack(el);
  15675                }
  15676                break;
  15677            }
  15678 
  15679            case value_t::binary:
  15680            {
  15681                // step 0: determine if the binary type has a set subtype to
  15682                // determine whether or not to use the ext or fixext types
  15683                const bool use_ext = j.m_data.m_value.binary->has_subtype();
  15684 
  15685                // step 1: write control byte and the byte string length
  15686                const auto N = j.m_data.m_value.binary->size();
  15687                if (N <= (std::numeric_limits<std::uint8_t>::max)())
  15688                {
  15689                    std::uint8_t output_type{};
  15690                    bool fixed = true;
  15691                    if (use_ext)
  15692                    {
  15693                        switch (N)
  15694                        {
  15695                            case 1:
  15696                                output_type = 0xD4; // fixext 1
  15697                                break;
  15698                            case 2:
  15699                                output_type = 0xD5; // fixext 2
  15700                                break;
  15701                            case 4:
  15702                                output_type = 0xD6; // fixext 4
  15703                                break;
  15704                            case 8:
  15705                                output_type = 0xD7; // fixext 8
  15706                                break;
  15707                            case 16:
  15708                                output_type = 0xD8; // fixext 16
  15709                                break;
  15710                            default:
  15711                                output_type = 0xC7; // ext 8
  15712                                fixed = false;
  15713                                break;
  15714                        }
  15715 
  15716                    }
  15717                    else
  15718                    {
  15719                        output_type = 0xC4; // bin 8
  15720                        fixed = false;
  15721                    }
  15722 
  15723                    oa->write_character(to_char_type(output_type));
  15724                    if (!fixed)
  15725                    {
  15726                        write_number(static_cast<std::uint8_t>(N));
  15727                    }
  15728                }
  15729                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15730                {
  15731                    const std::uint8_t output_type = use_ext
  15732                                                     ? 0xC8 // ext 16
  15733                                                     : 0xC5; // bin 16
  15734 
  15735                    oa->write_character(to_char_type(output_type));
  15736                    write_number(static_cast<std::uint16_t>(N));
  15737                }
  15738                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15739                {
  15740                    const std::uint8_t output_type = use_ext
  15741                                                     ? 0xC9 // ext 32
  15742                                                     : 0xC6; // bin 32
  15743 
  15744                    oa->write_character(to_char_type(output_type));
  15745                    write_number(static_cast<std::uint32_t>(N));
  15746                }
  15747 
  15748                // step 1.5: if this is an ext type, write the subtype
  15749                if (use_ext)
  15750                {
  15751                    write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
  15752                }
  15753 
  15754                // step 2: write the byte string
  15755                oa->write_characters(
  15756                    reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
  15757                    N);
  15758 
  15759                break;
  15760            }
  15761 
  15762            case value_t::object:
  15763            {
  15764                // step 1: write control byte and the object size
  15765                const auto N = j.m_data.m_value.object->size();
  15766                if (N <= 15)
  15767                {
  15768                    // fixmap
  15769                    write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
  15770                }
  15771                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
  15772                {
  15773                    // map 16
  15774                    oa->write_character(to_char_type(0xDE));
  15775                    write_number(static_cast<std::uint16_t>(N));
  15776                }
  15777                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
  15778                {
  15779                    // map 32
  15780                    oa->write_character(to_char_type(0xDF));
  15781                    write_number(static_cast<std::uint32_t>(N));
  15782                }
  15783 
  15784                // step 2: write each element
  15785                for (const auto& el : *j.m_data.m_value.object)
  15786                {
  15787                    write_msgpack(el.first);
  15788                    write_msgpack(el.second);
  15789                }
  15790                break;
  15791            }
  15792 
  15793            case value_t::discarded:
  15794            default:
  15795                break;
  15796        }
  15797    }
  15798 
  15799    /*!
  15800    @param[in] j  JSON value to serialize
  15801    @param[in] use_count   whether to use '#' prefixes (optimized format)
  15802    @param[in] use_type    whether to use '$' prefixes (optimized format)
  15803    @param[in] add_prefix  whether prefixes need to be used for this value
  15804    @param[in] use_bjdata  whether write in BJData format, default is false
  15805    */
  15806    void write_ubjson(const BasicJsonType& j, const bool use_count,
  15807                      const bool use_type, const bool add_prefix = true,
  15808                      const bool use_bjdata = false)
  15809    {
  15810        switch (j.type())
  15811        {
  15812            case value_t::null:
  15813            {
  15814                if (add_prefix)
  15815                {
  15816                    oa->write_character(to_char_type('Z'));
  15817                }
  15818                break;
  15819            }
  15820 
  15821            case value_t::boolean:
  15822            {
  15823                if (add_prefix)
  15824                {
  15825                    oa->write_character(j.m_data.m_value.boolean
  15826                                        ? to_char_type('T')
  15827                                        : to_char_type('F'));
  15828                }
  15829                break;
  15830            }
  15831 
  15832            case value_t::number_integer:
  15833            {
  15834                write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
  15835                break;
  15836            }
  15837 
  15838            case value_t::number_unsigned:
  15839            {
  15840                write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
  15841                break;
  15842            }
  15843 
  15844            case value_t::number_float:
  15845            {
  15846                write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
  15847                break;
  15848            }
  15849 
  15850            case value_t::string:
  15851            {
  15852                if (add_prefix)
  15853                {
  15854                    oa->write_character(to_char_type('S'));
  15855                }
  15856                write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
  15857                oa->write_characters(
  15858                    reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
  15859                    j.m_data.m_value.string->size());
  15860                break;
  15861            }
  15862 
  15863            case value_t::array:
  15864            {
  15865                if (add_prefix)
  15866                {
  15867                    oa->write_character(to_char_type('['));
  15868                }
  15869 
  15870                bool prefix_required = true;
  15871                if (use_type && !j.m_data.m_value.array->empty())
  15872                {
  15873                    JSON_ASSERT(use_count);
  15874                    const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
  15875                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
  15876                                                         [this, first_prefix, use_bjdata](const BasicJsonType & v)
  15877                    {
  15878                        return ubjson_prefix(v, use_bjdata) == first_prefix;
  15879                    });
  15880 
  15881                    std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
  15882 
  15883                    if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
  15884                    {
  15885                        prefix_required = false;
  15886                        oa->write_character(to_char_type('$'));
  15887                        oa->write_character(first_prefix);
  15888                    }
  15889                }
  15890 
  15891                if (use_count)
  15892                {
  15893                    oa->write_character(to_char_type('#'));
  15894                    write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
  15895                }
  15896 
  15897                for (const auto& el : *j.m_data.m_value.array)
  15898                {
  15899                    write_ubjson(el, use_count, use_type, prefix_required, use_bjdata);
  15900                }
  15901 
  15902                if (!use_count)
  15903                {
  15904                    oa->write_character(to_char_type(']'));
  15905                }
  15906 
  15907                break;
  15908            }
  15909 
  15910            case value_t::binary:
  15911            {
  15912                if (add_prefix)
  15913                {
  15914                    oa->write_character(to_char_type('['));
  15915                }
  15916 
  15917                if (use_type && !j.m_data.m_value.binary->empty())
  15918                {
  15919                    JSON_ASSERT(use_count);
  15920                    oa->write_character(to_char_type('$'));
  15921                    oa->write_character('U');
  15922                }
  15923 
  15924                if (use_count)
  15925                {
  15926                    oa->write_character(to_char_type('#'));
  15927                    write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
  15928                }
  15929 
  15930                if (use_type)
  15931                {
  15932                    oa->write_characters(
  15933                        reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
  15934                        j.m_data.m_value.binary->size());
  15935                }
  15936                else
  15937                {
  15938                    for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
  15939                    {
  15940                        oa->write_character(to_char_type('U'));
  15941                        oa->write_character(j.m_data.m_value.binary->data()[i]);
  15942                    }
  15943                }
  15944 
  15945                if (!use_count)
  15946                {
  15947                    oa->write_character(to_char_type(']'));
  15948                }
  15949 
  15950                break;
  15951            }
  15952 
  15953            case value_t::object:
  15954            {
  15955                if (use_bjdata && j.m_data.m_value.object->size() == 3 && j.m_data.m_value.object->find("_ArrayType_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArraySize_") != j.m_data.m_value.object->end() && j.m_data.m_value.object->find("_ArrayData_") != j.m_data.m_value.object->end())
  15956                {
  15957                    if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
  15958                    {
  15959                        break;
  15960                    }
  15961                }
  15962 
  15963                if (add_prefix)
  15964                {
  15965                    oa->write_character(to_char_type('{'));
  15966                }
  15967 
  15968                bool prefix_required = true;
  15969                if (use_type && !j.m_data.m_value.object->empty())
  15970                {
  15971                    JSON_ASSERT(use_count);
  15972                    const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
  15973                    const bool same_prefix = std::all_of(j.begin(), j.end(),
  15974                                                         [this, first_prefix, use_bjdata](const BasicJsonType & v)
  15975                    {
  15976                        return ubjson_prefix(v, use_bjdata) == first_prefix;
  15977                    });
  15978 
  15979                    std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
  15980 
  15981                    if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
  15982                    {
  15983                        prefix_required = false;
  15984                        oa->write_character(to_char_type('$'));
  15985                        oa->write_character(first_prefix);
  15986                    }
  15987                }
  15988 
  15989                if (use_count)
  15990                {
  15991                    oa->write_character(to_char_type('#'));
  15992                    write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
  15993                }
  15994 
  15995                for (const auto& el : *j.m_data.m_value.object)
  15996                {
  15997                    write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
  15998                    oa->write_characters(
  15999                        reinterpret_cast<const CharType*>(el.first.c_str()),
  16000                        el.first.size());
  16001                    write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata);
  16002                }
  16003 
  16004                if (!use_count)
  16005                {
  16006                    oa->write_character(to_char_type('}'));
  16007                }
  16008 
  16009                break;
  16010            }
  16011 
  16012            case value_t::discarded:
  16013            default:
  16014                break;
  16015        }
  16016    }
  16017 
  16018  private:
  16019    //////////
  16020    // BSON //
  16021    //////////
  16022 
  16023    /*!
  16024    @return The size of a BSON document entry header, including the id marker
  16025            and the entry name size (and its null-terminator).
  16026    */
  16027    static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
  16028    {
  16029        const auto it = name.find(static_cast<typename string_t::value_type>(0));
  16030        if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
  16031        {
  16032            JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
  16033            static_cast<void>(j);
  16034        }
  16035 
  16036        return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
  16037    }
  16038 
  16039    /*!
  16040    @brief Writes the given @a element_type and @a name to the output adapter
  16041    */
  16042    void write_bson_entry_header(const string_t& name,
  16043                                 const std::uint8_t element_type)
  16044    {
  16045        oa->write_character(to_char_type(element_type)); // boolean
  16046        oa->write_characters(
  16047            reinterpret_cast<const CharType*>(name.c_str()),
  16048            name.size() + 1u);
  16049    }
  16050 
  16051    /*!
  16052    @brief Writes a BSON element with key @a name and boolean value @a value
  16053    */
  16054    void write_bson_boolean(const string_t& name,
  16055                            const bool value)
  16056    {
  16057        write_bson_entry_header(name, 0x08);
  16058        oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
  16059    }
  16060 
  16061    /*!
  16062    @brief Writes a BSON element with key @a name and double value @a value
  16063    */
  16064    void write_bson_double(const string_t& name,
  16065                           const double value)
  16066    {
  16067        write_bson_entry_header(name, 0x01);
  16068        write_number<double>(value, true);
  16069    }
  16070 
  16071    /*!
  16072    @return The size of the BSON-encoded string in @a value
  16073    */
  16074    static std::size_t calc_bson_string_size(const string_t& value)
  16075    {
  16076        return sizeof(std::int32_t) + value.size() + 1ul;
  16077    }
  16078 
  16079    /*!
  16080    @brief Writes a BSON element with key @a name and string value @a value
  16081    */
  16082    void write_bson_string(const string_t& name,
  16083                           const string_t& value)
  16084    {
  16085        write_bson_entry_header(name, 0x02);
  16086 
  16087        write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
  16088        oa->write_characters(
  16089            reinterpret_cast<const CharType*>(value.c_str()),
  16090            value.size() + 1);
  16091    }
  16092 
  16093    /*!
  16094    @brief Writes a BSON element with key @a name and null value
  16095    */
  16096    void write_bson_null(const string_t& name)
  16097    {
  16098        write_bson_entry_header(name, 0x0A);
  16099    }
  16100 
  16101    /*!
  16102    @return The size of the BSON-encoded integer @a value
  16103    */
  16104    static std::size_t calc_bson_integer_size(const std::int64_t value)
  16105    {
  16106        return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
  16107               ? sizeof(std::int32_t)
  16108               : sizeof(std::int64_t);
  16109    }
  16110 
  16111    /*!
  16112    @brief Writes a BSON element with key @a name and integer @a value
  16113    */
  16114    void write_bson_integer(const string_t& name,
  16115                            const std::int64_t value)
  16116    {
  16117        if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
  16118        {
  16119            write_bson_entry_header(name, 0x10); // int32
  16120            write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
  16121        }
  16122        else
  16123        {
  16124            write_bson_entry_header(name, 0x12); // int64
  16125            write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
  16126        }
  16127    }
  16128 
  16129    /*!
  16130    @return The size of the BSON-encoded unsigned integer in @a j
  16131    */
  16132    static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
  16133    {
  16134        return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16135               ? sizeof(std::int32_t)
  16136               : sizeof(std::int64_t);
  16137    }
  16138 
  16139    /*!
  16140    @brief Writes a BSON element with key @a name and unsigned @a value
  16141    */
  16142    void write_bson_unsigned(const string_t& name,
  16143                             const BasicJsonType& j)
  16144    {
  16145        if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16146        {
  16147            write_bson_entry_header(name, 0x10 /* int32 */);
  16148            write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
  16149        }
  16150        else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  16151        {
  16152            write_bson_entry_header(name, 0x12 /* int64 */);
  16153            write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
  16154        }
  16155        else
  16156        {
  16157            JSON_THROW(out_of_range::create(407, concat("integer number ", std::to_string(j.m_data.m_value.number_unsigned), " cannot be represented by BSON as it does not fit int64"), &j));
  16158        }
  16159    }
  16160 
  16161    /*!
  16162    @brief Writes a BSON element with key @a name and object @a value
  16163    */
  16164    void write_bson_object_entry(const string_t& name,
  16165                                 const typename BasicJsonType::object_t& value)
  16166    {
  16167        write_bson_entry_header(name, 0x03); // object
  16168        write_bson_object(value);
  16169    }
  16170 
  16171    /*!
  16172    @return The size of the BSON-encoded array @a value
  16173    */
  16174    static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
  16175    {
  16176        std::size_t array_index = 0ul;
  16177 
  16178        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)
  16179        {
  16180            return result + calc_bson_element_size(std::to_string(array_index++), el);
  16181        });
  16182 
  16183        return sizeof(std::int32_t) + embedded_document_size + 1ul;
  16184    }
  16185 
  16186    /*!
  16187    @return The size of the BSON-encoded binary array @a value
  16188    */
  16189    static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
  16190    {
  16191        return sizeof(std::int32_t) + value.size() + 1ul;
  16192    }
  16193 
  16194    /*!
  16195    @brief Writes a BSON element with key @a name and array @a value
  16196    */
  16197    void write_bson_array(const string_t& name,
  16198                          const typename BasicJsonType::array_t& value)
  16199    {
  16200        write_bson_entry_header(name, 0x04); // array
  16201        write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
  16202 
  16203        std::size_t array_index = 0ul;
  16204 
  16205        for (const auto& el : value)
  16206        {
  16207            write_bson_element(std::to_string(array_index++), el);
  16208        }
  16209 
  16210        oa->write_character(to_char_type(0x00));
  16211    }
  16212 
  16213    /*!
  16214    @brief Writes a BSON element with key @a name and binary value @a value
  16215    */
  16216    void write_bson_binary(const string_t& name,
  16217                           const binary_t& value)
  16218    {
  16219        write_bson_entry_header(name, 0x05);
  16220 
  16221        write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
  16222        write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
  16223 
  16224        oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
  16225    }
  16226 
  16227    /*!
  16228    @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
  16229    @return The calculated size for the BSON document entry for @a j with the given @a name.
  16230    */
  16231    static std::size_t calc_bson_element_size(const string_t& name,
  16232            const BasicJsonType& j)
  16233    {
  16234        const auto header_size = calc_bson_entry_header_size(name, j);
  16235        switch (j.type())
  16236        {
  16237            case value_t::object:
  16238                return header_size + calc_bson_object_size(*j.m_data.m_value.object);
  16239 
  16240            case value_t::array:
  16241                return header_size + calc_bson_array_size(*j.m_data.m_value.array);
  16242 
  16243            case value_t::binary:
  16244                return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
  16245 
  16246            case value_t::boolean:
  16247                return header_size + 1ul;
  16248 
  16249            case value_t::number_float:
  16250                return header_size + 8ul;
  16251 
  16252            case value_t::number_integer:
  16253                return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
  16254 
  16255            case value_t::number_unsigned:
  16256                return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
  16257 
  16258            case value_t::string:
  16259                return header_size + calc_bson_string_size(*j.m_data.m_value.string);
  16260 
  16261            case value_t::null:
  16262                return header_size + 0ul;
  16263 
  16264            // LCOV_EXCL_START
  16265            case value_t::discarded:
  16266            default:
  16267                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
  16268                return 0ul;
  16269                // LCOV_EXCL_STOP
  16270        }
  16271    }
  16272 
  16273    /*!
  16274    @brief Serializes the JSON value @a j to BSON and associates it with the
  16275           key @a name.
  16276    @param name The name to associate with the JSON entity @a j within the
  16277                current BSON document
  16278    */
  16279    void write_bson_element(const string_t& name,
  16280                            const BasicJsonType& j)
  16281    {
  16282        switch (j.type())
  16283        {
  16284            case value_t::object:
  16285                return write_bson_object_entry(name, *j.m_data.m_value.object);
  16286 
  16287            case value_t::array:
  16288                return write_bson_array(name, *j.m_data.m_value.array);
  16289 
  16290            case value_t::binary:
  16291                return write_bson_binary(name, *j.m_data.m_value.binary);
  16292 
  16293            case value_t::boolean:
  16294                return write_bson_boolean(name, j.m_data.m_value.boolean);
  16295 
  16296            case value_t::number_float:
  16297                return write_bson_double(name, j.m_data.m_value.number_float);
  16298 
  16299            case value_t::number_integer:
  16300                return write_bson_integer(name, j.m_data.m_value.number_integer);
  16301 
  16302            case value_t::number_unsigned:
  16303                return write_bson_unsigned(name, j);
  16304 
  16305            case value_t::string:
  16306                return write_bson_string(name, *j.m_data.m_value.string);
  16307 
  16308            case value_t::null:
  16309                return write_bson_null(name);
  16310 
  16311            // LCOV_EXCL_START
  16312            case value_t::discarded:
  16313            default:
  16314                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
  16315                return;
  16316                // LCOV_EXCL_STOP
  16317        }
  16318    }
  16319 
  16320    /*!
  16321    @brief Calculates the size of the BSON serialization of the given
  16322           JSON-object @a j.
  16323    @param[in] value  JSON value to serialize
  16324    @pre       value.type() == value_t::object
  16325    */
  16326    static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
  16327    {
  16328        const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
  16329                                          [](size_t result, const typename BasicJsonType::object_t::value_type & el)
  16330        {
  16331            return result += calc_bson_element_size(el.first, el.second);
  16332        });
  16333 
  16334        return sizeof(std::int32_t) + document_size + 1ul;
  16335    }
  16336 
  16337    /*!
  16338    @param[in] value  JSON value to serialize
  16339    @pre       value.type() == value_t::object
  16340    */
  16341    void write_bson_object(const typename BasicJsonType::object_t& value)
  16342    {
  16343        write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
  16344 
  16345        for (const auto& el : value)
  16346        {
  16347            write_bson_element(el.first, el.second);
  16348        }
  16349 
  16350        oa->write_character(to_char_type(0x00));
  16351    }
  16352 
  16353    //////////
  16354    // CBOR //
  16355    //////////
  16356 
  16357    static constexpr CharType get_cbor_float_prefix(float /*unused*/)
  16358    {
  16359        return to_char_type(0xFA);  // Single-Precision Float
  16360    }
  16361 
  16362    static constexpr CharType get_cbor_float_prefix(double /*unused*/)
  16363    {
  16364        return to_char_type(0xFB);  // Double-Precision Float
  16365    }
  16366 
  16367    /////////////
  16368    // MsgPack //
  16369    /////////////
  16370 
  16371    static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
  16372    {
  16373        return to_char_type(0xCA);  // float 32
  16374    }
  16375 
  16376    static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
  16377    {
  16378        return to_char_type(0xCB);  // float 64
  16379    }
  16380 
  16381    ////////////
  16382    // UBJSON //
  16383    ////////////
  16384 
  16385    // UBJSON: write number (floating point)
  16386    template<typename NumberType, typename std::enable_if<
  16387                 std::is_floating_point<NumberType>::value, int>::type = 0>
  16388    void write_number_with_ubjson_prefix(const NumberType n,
  16389                                         const bool add_prefix,
  16390                                         const bool use_bjdata)
  16391    {
  16392        if (add_prefix)
  16393        {
  16394            oa->write_character(get_ubjson_float_prefix(n));
  16395        }
  16396        write_number(n, use_bjdata);
  16397    }
  16398 
  16399    // UBJSON: write number (unsigned integer)
  16400    template<typename NumberType, typename std::enable_if<
  16401                 std::is_unsigned<NumberType>::value, int>::type = 0>
  16402    void write_number_with_ubjson_prefix(const NumberType n,
  16403                                         const bool add_prefix,
  16404                                         const bool use_bjdata)
  16405    {
  16406        if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
  16407        {
  16408            if (add_prefix)
  16409            {
  16410                oa->write_character(to_char_type('i'));  // int8
  16411            }
  16412            write_number(static_cast<std::uint8_t>(n), use_bjdata);
  16413        }
  16414        else if (n <= (std::numeric_limits<std::uint8_t>::max)())
  16415        {
  16416            if (add_prefix)
  16417            {
  16418                oa->write_character(to_char_type('U'));  // uint8
  16419            }
  16420            write_number(static_cast<std::uint8_t>(n), use_bjdata);
  16421        }
  16422        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
  16423        {
  16424            if (add_prefix)
  16425            {
  16426                oa->write_character(to_char_type('I'));  // int16
  16427            }
  16428            write_number(static_cast<std::int16_t>(n), use_bjdata);
  16429        }
  16430        else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
  16431        {
  16432            if (add_prefix)
  16433            {
  16434                oa->write_character(to_char_type('u'));  // uint16 - bjdata only
  16435            }
  16436            write_number(static_cast<std::uint16_t>(n), use_bjdata);
  16437        }
  16438        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16439        {
  16440            if (add_prefix)
  16441            {
  16442                oa->write_character(to_char_type('l'));  // int32
  16443            }
  16444            write_number(static_cast<std::int32_t>(n), use_bjdata);
  16445        }
  16446        else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
  16447        {
  16448            if (add_prefix)
  16449            {
  16450                oa->write_character(to_char_type('m'));  // uint32 - bjdata only
  16451            }
  16452            write_number(static_cast<std::uint32_t>(n), use_bjdata);
  16453        }
  16454        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  16455        {
  16456            if (add_prefix)
  16457            {
  16458                oa->write_character(to_char_type('L'));  // int64
  16459            }
  16460            write_number(static_cast<std::int64_t>(n), use_bjdata);
  16461        }
  16462        else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
  16463        {
  16464            if (add_prefix)
  16465            {
  16466                oa->write_character(to_char_type('M'));  // uint64 - bjdata only
  16467            }
  16468            write_number(static_cast<std::uint64_t>(n), use_bjdata);
  16469        }
  16470        else
  16471        {
  16472            if (add_prefix)
  16473            {
  16474                oa->write_character(to_char_type('H'));  // high-precision number
  16475            }
  16476 
  16477            const auto number = BasicJsonType(n).dump();
  16478            write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
  16479            for (std::size_t i = 0; i < number.size(); ++i)
  16480            {
  16481                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
  16482            }
  16483        }
  16484    }
  16485 
  16486    // UBJSON: write number (signed integer)
  16487    template < typename NumberType, typename std::enable_if <
  16488                   std::is_signed<NumberType>::value&&
  16489                   !std::is_floating_point<NumberType>::value, int >::type = 0 >
  16490    void write_number_with_ubjson_prefix(const NumberType n,
  16491                                         const bool add_prefix,
  16492                                         const bool use_bjdata)
  16493    {
  16494        if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
  16495        {
  16496            if (add_prefix)
  16497            {
  16498                oa->write_character(to_char_type('i'));  // int8
  16499            }
  16500            write_number(static_cast<std::int8_t>(n), use_bjdata);
  16501        }
  16502        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)()))
  16503        {
  16504            if (add_prefix)
  16505            {
  16506                oa->write_character(to_char_type('U'));  // uint8
  16507            }
  16508            write_number(static_cast<std::uint8_t>(n), use_bjdata);
  16509        }
  16510        else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
  16511        {
  16512            if (add_prefix)
  16513            {
  16514                oa->write_character(to_char_type('I'));  // int16
  16515            }
  16516            write_number(static_cast<std::int16_t>(n), use_bjdata);
  16517        }
  16518        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)())))
  16519        {
  16520            if (add_prefix)
  16521            {
  16522                oa->write_character(to_char_type('u'));  // uint16 - bjdata only
  16523            }
  16524            write_number(static_cast<uint16_t>(n), use_bjdata);
  16525        }
  16526        else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
  16527        {
  16528            if (add_prefix)
  16529            {
  16530                oa->write_character(to_char_type('l'));  // int32
  16531            }
  16532            write_number(static_cast<std::int32_t>(n), use_bjdata);
  16533        }
  16534        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)())))
  16535        {
  16536            if (add_prefix)
  16537            {
  16538                oa->write_character(to_char_type('m'));  // uint32 - bjdata only
  16539            }
  16540            write_number(static_cast<uint32_t>(n), use_bjdata);
  16541        }
  16542        else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
  16543        {
  16544            if (add_prefix)
  16545            {
  16546                oa->write_character(to_char_type('L'));  // int64
  16547            }
  16548            write_number(static_cast<std::int64_t>(n), use_bjdata);
  16549        }
  16550        // LCOV_EXCL_START
  16551        else
  16552        {
  16553            if (add_prefix)
  16554            {
  16555                oa->write_character(to_char_type('H'));  // high-precision number
  16556            }
  16557 
  16558            const auto number = BasicJsonType(n).dump();
  16559            write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
  16560            for (std::size_t i = 0; i < number.size(); ++i)
  16561            {
  16562                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
  16563            }
  16564        }
  16565        // LCOV_EXCL_STOP
  16566    }
  16567 
  16568    /*!
  16569    @brief determine the type prefix of container values
  16570    */
  16571    CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
  16572    {
  16573        switch (j.type())
  16574        {
  16575            case value_t::null:
  16576                return 'Z';
  16577 
  16578            case value_t::boolean:
  16579                return j.m_data.m_value.boolean ? 'T' : 'F';
  16580 
  16581            case value_t::number_integer:
  16582            {
  16583                if ((std::numeric_limits<std::int8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
  16584                {
  16585                    return 'i';
  16586                }
  16587                if ((std::numeric_limits<std::uint8_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
  16588                {
  16589                    return 'U';
  16590                }
  16591                if ((std::numeric_limits<std::int16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
  16592                {
  16593                    return 'I';
  16594                }
  16595                if (use_bjdata && ((std::numeric_limits<std::uint16_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)()))
  16596                {
  16597                    return 'u';
  16598                }
  16599                if ((std::numeric_limits<std::int32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
  16600                {
  16601                    return 'l';
  16602                }
  16603                if (use_bjdata && ((std::numeric_limits<std::uint32_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)()))
  16604                {
  16605                    return 'm';
  16606                }
  16607                if ((std::numeric_limits<std::int64_t>::min)() <= j.m_data.m_value.number_integer && j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
  16608                {
  16609                    return 'L';
  16610                }
  16611                // anything else is treated as high-precision number
  16612                return 'H'; // LCOV_EXCL_LINE
  16613            }
  16614 
  16615            case value_t::number_unsigned:
  16616            {
  16617                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
  16618                {
  16619                    return 'i';
  16620                }
  16621                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
  16622                {
  16623                    return 'U';
  16624                }
  16625                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
  16626                {
  16627                    return 'I';
  16628                }
  16629                if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
  16630                {
  16631                    return 'u';
  16632                }
  16633                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
  16634                {
  16635                    return 'l';
  16636                }
  16637                if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
  16638                {
  16639                    return 'm';
  16640                }
  16641                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
  16642                {
  16643                    return 'L';
  16644                }
  16645                if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
  16646                {
  16647                    return 'M';
  16648                }
  16649                // anything else is treated as high-precision number
  16650                return 'H'; // LCOV_EXCL_LINE
  16651            }
  16652 
  16653            case value_t::number_float:
  16654                return get_ubjson_float_prefix(j.m_data.m_value.number_float);
  16655 
  16656            case value_t::string:
  16657                return 'S';
  16658 
  16659            case value_t::array: // fallthrough
  16660            case value_t::binary:
  16661                return '[';
  16662 
  16663            case value_t::object:
  16664                return '{';
  16665 
  16666            case value_t::discarded:
  16667            default:  // discarded values
  16668                return 'N';
  16669        }
  16670    }
  16671 
  16672    static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
  16673    {
  16674        return 'd';  // float 32
  16675    }
  16676 
  16677    static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
  16678    {
  16679        return 'D';  // float 64
  16680    }
  16681 
  16682    /*!
  16683    @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
  16684    */
  16685    bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type)
  16686    {
  16687        std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
  16688            {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'}, {"char", 'C'}
  16689        };
  16690 
  16691        string_t key = "_ArrayType_";
  16692        auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
  16693        if (it == bjdtype.end())
  16694        {
  16695            return true;
  16696        }
  16697        CharType dtype = it->second;
  16698 
  16699        key = "_ArraySize_";
  16700        std::size_t len = (value.at(key).empty() ? 0 : 1);
  16701        for (const auto& el : value.at(key))
  16702        {
  16703            len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
  16704        }
  16705 
  16706        key = "_ArrayData_";
  16707        if (value.at(key).size() != len)
  16708        {
  16709            return true;
  16710        }
  16711 
  16712        oa->write_character('[');
  16713        oa->write_character('$');
  16714        oa->write_character(dtype);
  16715        oa->write_character('#');
  16716 
  16717        key = "_ArraySize_";
  16718        write_ubjson(value.at(key), use_count, use_type, true,  true);
  16719 
  16720        key = "_ArrayData_";
  16721        if (dtype == 'U' || dtype == 'C')
  16722        {
  16723            for (const auto& el : value.at(key))
  16724            {
  16725                write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
  16726            }
  16727        }
  16728        else if (dtype == 'i')
  16729        {
  16730            for (const auto& el : value.at(key))
  16731            {
  16732                write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
  16733            }
  16734        }
  16735        else if (dtype == 'u')
  16736        {
  16737            for (const auto& el : value.at(key))
  16738            {
  16739                write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
  16740            }
  16741        }
  16742        else if (dtype == 'I')
  16743        {
  16744            for (const auto& el : value.at(key))
  16745            {
  16746                write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
  16747            }
  16748        }
  16749        else if (dtype == 'm')
  16750        {
  16751            for (const auto& el : value.at(key))
  16752            {
  16753                write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
  16754            }
  16755        }
  16756        else if (dtype == 'l')
  16757        {
  16758            for (const auto& el : value.at(key))
  16759            {
  16760                write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
  16761            }
  16762        }
  16763        else if (dtype == 'M')
  16764        {
  16765            for (const auto& el : value.at(key))
  16766            {
  16767                write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
  16768            }
  16769        }
  16770        else if (dtype == 'L')
  16771        {
  16772            for (const auto& el : value.at(key))
  16773            {
  16774                write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
  16775            }
  16776        }
  16777        else if (dtype == 'd')
  16778        {
  16779            for (const auto& el : value.at(key))
  16780            {
  16781                write_number(static_cast<float>(el.m_data.m_value.number_float), true);
  16782            }
  16783        }
  16784        else if (dtype == 'D')
  16785        {
  16786            for (const auto& el : value.at(key))
  16787            {
  16788                write_number(static_cast<double>(el.m_data.m_value.number_float), true);
  16789            }
  16790        }
  16791        return false;
  16792    }
  16793 
  16794    ///////////////////////
  16795    // Utility functions //
  16796    ///////////////////////
  16797 
  16798    /*
  16799    @brief write a number to output input
  16800    @param[in] n number of type @a NumberType
  16801    @param[in] OutputIsLittleEndian Set to true if output data is
  16802                                 required to be little endian
  16803    @tparam NumberType the type of the number
  16804 
  16805    @note This function needs to respect the system's endianness, because bytes
  16806          in CBOR, MessagePack, and UBJSON are stored in network order (big
  16807          endian) and therefore need reordering on little endian systems.
  16808          On the other hand, BSON and BJData use little endian and should reorder
  16809          on big endian systems.
  16810    */
  16811    template<typename NumberType>
  16812    void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
  16813    {
  16814        // step 1: write number to array of length NumberType
  16815        std::array<CharType, sizeof(NumberType)> vec{};
  16816        std::memcpy(vec.data(), &n, sizeof(NumberType));
  16817 
  16818        // step 2: write array to output (with possible reordering)
  16819        if (is_little_endian != OutputIsLittleEndian)
  16820        {
  16821            // reverse byte order prior to conversion if necessary
  16822            std::reverse(vec.begin(), vec.end());
  16823        }
  16824 
  16825        oa->write_characters(vec.data(), sizeof(NumberType));
  16826    }
  16827 
  16828    void write_compact_float(const number_float_t n, detail::input_format_t format)
  16829    {
  16830 #ifdef __GNUC__
  16831 #pragma GCC diagnostic push
  16832 #pragma GCC diagnostic ignored "-Wfloat-equal"
  16833 #endif
  16834        if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
  16835                static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
  16836                static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
  16837        {
  16838            oa->write_character(format == detail::input_format_t::cbor
  16839                                ? get_cbor_float_prefix(static_cast<float>(n))
  16840                                : get_msgpack_float_prefix(static_cast<float>(n)));
  16841            write_number(static_cast<float>(n));
  16842        }
  16843        else
  16844        {
  16845            oa->write_character(format == detail::input_format_t::cbor
  16846                                ? get_cbor_float_prefix(n)
  16847                                : get_msgpack_float_prefix(n));
  16848            write_number(n);
  16849        }
  16850 #ifdef __GNUC__
  16851 #pragma GCC diagnostic pop
  16852 #endif
  16853    }
  16854 
  16855  public:
  16856    // The following to_char_type functions are implement the conversion
  16857    // between uint8_t and CharType. In case CharType is not unsigned,
  16858    // such a conversion is required to allow values greater than 128.
  16859    // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
  16860    template < typename C = CharType,
  16861               enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
  16862    static constexpr CharType to_char_type(std::uint8_t x) noexcept
  16863    {
  16864        return *reinterpret_cast<char*>(&x);
  16865    }
  16866 
  16867    template < typename C = CharType,
  16868               enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
  16869    static CharType to_char_type(std::uint8_t x) noexcept
  16870    {
  16871        static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
  16872        static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
  16873        CharType result;
  16874        std::memcpy(&result, &x, sizeof(x));
  16875        return result;
  16876    }
  16877 
  16878    template<typename C = CharType,
  16879             enable_if_t<std::is_unsigned<C>::value>* = nullptr>
  16880    static constexpr CharType to_char_type(std::uint8_t x) noexcept
  16881    {
  16882        return x;
  16883    }
  16884 
  16885    template < typename InputCharType, typename C = CharType,
  16886               enable_if_t <
  16887                   std::is_signed<C>::value &&
  16888                   std::is_signed<char>::value &&
  16889                   std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
  16890                   > * = nullptr >
  16891    static constexpr CharType to_char_type(InputCharType x) noexcept
  16892    {
  16893        return x;
  16894    }
  16895 
  16896  private:
  16897    /// whether we can assume little endianness
  16898    const bool is_little_endian = little_endianness();
  16899 
  16900    /// the output
  16901    output_adapter_t<CharType> oa = nullptr;
  16902 };
  16903 
  16904 }  // namespace detail
  16905 NLOHMANN_JSON_NAMESPACE_END
  16906 
  16907 // #include <nlohmann/detail/output/output_adapters.hpp>
  16908 
  16909 // #include <nlohmann/detail/output/serializer.hpp>
  16910 //     __ _____ _____ _____
  16911 //  __|  |   __|     |   | |  JSON for Modern C++
  16912 // |  |  |__   |  |  | | | |  version 3.11.3
  16913 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  16914 //
  16915 // SPDX-FileCopyrightText: 2008-2009 Björn Hoehrmann <bjoern@hoehrmann.de>
  16916 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  16917 // SPDX-License-Identifier: MIT
  16918 
  16919 
  16920 
  16921 #include <algorithm> // reverse, remove, fill, find, none_of
  16922 #include <array> // array
  16923 #include <clocale> // localeconv, lconv
  16924 #include <cmath> // labs, isfinite, isnan, signbit
  16925 #include <cstddef> // size_t, ptrdiff_t
  16926 #include <cstdint> // uint8_t
  16927 #include <cstdio> // snprintf
  16928 #include <limits> // numeric_limits
  16929 #include <string> // string, char_traits
  16930 #include <iomanip> // setfill, setw
  16931 #include <type_traits> // is_same
  16932 #include <utility> // move
  16933 
  16934 // #include <nlohmann/detail/conversions/to_chars.hpp>
  16935 //     __ _____ _____ _____
  16936 //  __|  |   __|     |   | |  JSON for Modern C++
  16937 // |  |  |__   |  |  | | | |  version 3.11.3
  16938 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  16939 //
  16940 // SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
  16941 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  16942 // SPDX-License-Identifier: MIT
  16943 
  16944 
  16945 
  16946 #include <array> // array
  16947 #include <cmath>   // signbit, isfinite
  16948 #include <cstdint> // intN_t, uintN_t
  16949 #include <cstring> // memcpy, memmove
  16950 #include <limits> // numeric_limits
  16951 #include <type_traits> // conditional
  16952 
  16953 // #include <nlohmann/detail/macro_scope.hpp>
  16954 
  16955 
  16956 NLOHMANN_JSON_NAMESPACE_BEGIN
  16957 namespace detail
  16958 {
  16959 
  16960 /*!
  16961 @brief implements the Grisu2 algorithm for binary to decimal floating-point
  16962 conversion.
  16963 
  16964 This implementation is a slightly modified version of the reference
  16965 implementation which may be obtained from
  16966 http://florian.loitsch.com/publications (bench.tar.gz).
  16967 
  16968 The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
  16969 
  16970 For a detailed description of the algorithm see:
  16971 
  16972 [1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
  16973    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
  16974    Language Design and Implementation, PLDI 2010
  16975 [2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
  16976    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
  16977    Design and Implementation, PLDI 1996
  16978 */
  16979 namespace dtoa_impl
  16980 {
  16981 
  16982 template<typename Target, typename Source>
  16983 Target reinterpret_bits(const Source source)
  16984 {
  16985    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
  16986 
  16987    Target target;
  16988    std::memcpy(&target, &source, sizeof(Source));
  16989    return target;
  16990 }
  16991 
  16992 struct diyfp // f * 2^e
  16993 {
  16994    static constexpr int kPrecision = 64; // = q
  16995 
  16996    std::uint64_t f = 0;
  16997    int e = 0;
  16998 
  16999    constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
  17000 
  17001    /*!
  17002    @brief returns x - y
  17003    @pre x.e == y.e and x.f >= y.f
  17004    */
  17005    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
  17006    {
  17007        JSON_ASSERT(x.e == y.e);
  17008        JSON_ASSERT(x.f >= y.f);
  17009 
  17010        return {x.f - y.f, x.e};
  17011    }
  17012 
  17013    /*!
  17014    @brief returns x * y
  17015    @note The result is rounded. (Only the upper q bits are returned.)
  17016    */
  17017    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
  17018    {
  17019        static_assert(kPrecision == 64, "internal error");
  17020 
  17021        // Computes:
  17022        //  f = round((x.f * y.f) / 2^q)
  17023        //  e = x.e + y.e + q
  17024 
  17025        // Emulate the 64-bit * 64-bit multiplication:
  17026        //
  17027        // p = u * v
  17028        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
  17029        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
  17030        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
  17031        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
  17032        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
  17033        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
  17034        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
  17035        //
  17036        // (Since Q might be larger than 2^32 - 1)
  17037        //
  17038        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
  17039        //
  17040        // (Q_hi + H does not overflow a 64-bit int)
  17041        //
  17042        //   = p_lo + 2^64 p_hi
  17043 
  17044        const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
  17045        const std::uint64_t u_hi = x.f >> 32u;
  17046        const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
  17047        const std::uint64_t v_hi = y.f >> 32u;
  17048 
  17049        const std::uint64_t p0 = u_lo * v_lo;
  17050        const std::uint64_t p1 = u_lo * v_hi;
  17051        const std::uint64_t p2 = u_hi * v_lo;
  17052        const std::uint64_t p3 = u_hi * v_hi;
  17053 
  17054        const std::uint64_t p0_hi = p0 >> 32u;
  17055        const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
  17056        const std::uint64_t p1_hi = p1 >> 32u;
  17057        const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
  17058        const std::uint64_t p2_hi = p2 >> 32u;
  17059 
  17060        std::uint64_t Q = p0_hi + p1_lo + p2_lo;
  17061 
  17062        // The full product might now be computed as
  17063        //
  17064        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
  17065        // p_lo = p0_lo + (Q << 32)
  17066        //
  17067        // But in this particular case here, the full p_lo is not required.
  17068        // Effectively we only need to add the highest bit in p_lo to p_hi (and
  17069        // Q_hi + 1 does not overflow).
  17070 
  17071        Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
  17072 
  17073        const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
  17074 
  17075        return {h, x.e + y.e + 64};
  17076    }
  17077 
  17078    /*!
  17079    @brief normalize x such that the significand is >= 2^(q-1)
  17080    @pre x.f != 0
  17081    */
  17082    static diyfp normalize(diyfp x) noexcept
  17083    {
  17084        JSON_ASSERT(x.f != 0);
  17085 
  17086        while ((x.f >> 63u) == 0)
  17087        {
  17088            x.f <<= 1u;
  17089            x.e--;
  17090        }
  17091 
  17092        return x;
  17093    }
  17094 
  17095    /*!
  17096    @brief normalize x such that the result has the exponent E
  17097    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
  17098    */
  17099    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
  17100    {
  17101        const int delta = x.e - target_exponent;
  17102 
  17103        JSON_ASSERT(delta >= 0);
  17104        JSON_ASSERT(((x.f << delta) >> delta) == x.f);
  17105 
  17106        return {x.f << delta, target_exponent};
  17107    }
  17108 };
  17109 
  17110 struct boundaries
  17111 {
  17112    diyfp w;
  17113    diyfp minus;
  17114    diyfp plus;
  17115 };
  17116 
  17117 /*!
  17118 Compute the (normalized) diyfp representing the input number 'value' and its
  17119 boundaries.
  17120 
  17121 @pre value must be finite and positive
  17122 */
  17123 template<typename FloatType>
  17124 boundaries compute_boundaries(FloatType value)
  17125 {
  17126    JSON_ASSERT(std::isfinite(value));
  17127    JSON_ASSERT(value > 0);
  17128 
  17129    // Convert the IEEE representation into a diyfp.
  17130    //
  17131    // If v is denormal:
  17132    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
  17133    // If v is normalized:
  17134    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
  17135 
  17136    static_assert(std::numeric_limits<FloatType>::is_iec559,
  17137                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
  17138 
  17139    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
  17140    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
  17141    constexpr int      kMinExp    = 1 - kBias;
  17142    constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
  17143 
  17144    using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
  17145 
  17146    const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
  17147    const std::uint64_t E = bits >> (kPrecision - 1);
  17148    const std::uint64_t F = bits & (kHiddenBit - 1);
  17149 
  17150    const bool is_denormal = E == 0;
  17151    const diyfp v = is_denormal
  17152                    ? diyfp(F, kMinExp)
  17153                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
  17154 
  17155    // Compute the boundaries m- and m+ of the floating-point value
  17156    // v = f * 2^e.
  17157    //
  17158    // Determine v- and v+, the floating-point predecessor and successor if v,
  17159    // respectively.
  17160    //
  17161    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
  17162    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
  17163    //
  17164    //      v+ = v + 2^e
  17165    //
  17166    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
  17167    // between m- and m+ round to v, regardless of how the input rounding
  17168    // algorithm breaks ties.
  17169    //
  17170    //      ---+-------------+-------------+-------------+-------------+---  (A)
  17171    //         v-            m-            v             m+            v+
  17172    //
  17173    //      -----------------+------+------+-------------+-------------+---  (B)
  17174    //                       v-     m-     v             m+            v+
  17175 
  17176    const bool lower_boundary_is_closer = F == 0 && E > 1;
  17177    const diyfp m_plus = diyfp(2 * v.f + 1, v.e - 1);
  17178    const diyfp m_minus = lower_boundary_is_closer
  17179                          ? diyfp(4 * v.f - 1, v.e - 2)  // (B)
  17180                          : diyfp(2 * v.f - 1, v.e - 1); // (A)
  17181 
  17182    // Determine the normalized w+ = m+.
  17183    const diyfp w_plus = diyfp::normalize(m_plus);
  17184 
  17185    // Determine w- = m- such that e_(w-) = e_(w+).
  17186    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
  17187 
  17188    return {diyfp::normalize(v), w_minus, w_plus};
  17189 }
  17190 
  17191 // Given normalized diyfp w, Grisu needs to find a (normalized) cached
  17192 // power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
  17193 // within a certain range [alpha, gamma] (Definition 3.2 from [1])
  17194 //
  17195 //      alpha <= e = e_c + e_w + q <= gamma
  17196 //
  17197 // or
  17198 //
  17199 //      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
  17200 //                          <= f_c * f_w * 2^gamma
  17201 //
  17202 // Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
  17203 //
  17204 //      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
  17205 //
  17206 // or
  17207 //
  17208 //      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
  17209 //
  17210 // The choice of (alpha,gamma) determines the size of the table and the form of
  17211 // the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
  17212 // in practice:
  17213 //
  17214 // The idea is to cut the number c * w = f * 2^e into two parts, which can be
  17215 // processed independently: An integral part p1, and a fractional part p2:
  17216 //
  17217 //      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
  17218 //              = (f div 2^-e) + (f mod 2^-e) * 2^e
  17219 //              = p1 + p2 * 2^e
  17220 //
  17221 // The conversion of p1 into decimal form requires a series of divisions and
  17222 // modulos by (a power of) 10. These operations are faster for 32-bit than for
  17223 // 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
  17224 // achieved by choosing
  17225 //
  17226 //      -e >= 32   or   e <= -32 := gamma
  17227 //
  17228 // In order to convert the fractional part
  17229 //
  17230 //      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
  17231 //
  17232 // into decimal form, the fraction is repeatedly multiplied by 10 and the digits
  17233 // d[-i] are extracted in order:
  17234 //
  17235 //      (10 * p2) div 2^-e = d[-1]
  17236 //      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
  17237 //
  17238 // The multiplication by 10 must not overflow. It is sufficient to choose
  17239 //
  17240 //      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
  17241 //
  17242 // Since p2 = f mod 2^-e < 2^-e,
  17243 //
  17244 //      -e <= 60   or   e >= -60 := alpha
  17245 
  17246 constexpr int kAlpha = -60;
  17247 constexpr int kGamma = -32;
  17248 
  17249 struct cached_power // c = f * 2^e ~= 10^k
  17250 {
  17251    std::uint64_t f;
  17252    int e;
  17253    int k;
  17254 };
  17255 
  17256 /*!
  17257 For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
  17258 power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
  17259 satisfies (Definition 3.2 from [1])
  17260 
  17261     alpha <= e_c + e + q <= gamma.
  17262 */
  17263 inline cached_power get_cached_power_for_binary_exponent(int e)
  17264 {
  17265    // Now
  17266    //
  17267    //      alpha <= e_c + e + q <= gamma                                    (1)
  17268    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
  17269    //
  17270    // and since the c's are normalized, 2^(q-1) <= f_c,
  17271    //
  17272    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
  17273    //      ==> 2^(alpha - e - 1) <= c
  17274    //
  17275    // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
  17276    //
  17277    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
  17278    //        = ceil( (alpha - e - 1) * log_10(2) )
  17279    //
  17280    // From the paper:
  17281    // "In theory the result of the procedure could be wrong since c is rounded,
  17282    //  and the computation itself is approximated [...]. In practice, however,
  17283    //  this simple function is sufficient."
  17284    //
  17285    // For IEEE double precision floating-point numbers converted into
  17286    // normalized diyfp's w = f * 2^e, with q = 64,
  17287    //
  17288    //      e >= -1022      (min IEEE exponent)
  17289    //           -52        (p - 1)
  17290    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
  17291    //           -11        (normalize the diyfp)
  17292    //         = -1137
  17293    //
  17294    // and
  17295    //
  17296    //      e <= +1023      (max IEEE exponent)
  17297    //           -52        (p - 1)
  17298    //           -11        (normalize the diyfp)
  17299    //         = 960
  17300    //
  17301    // This binary exponent range [-1137,960] results in a decimal exponent
  17302    // range [-307,324]. One does not need to store a cached power for each
  17303    // k in this range. For each such k it suffices to find a cached power
  17304    // such that the exponent of the product lies in [alpha,gamma].
  17305    // This implies that the difference of the decimal exponents of adjacent
  17306    // table entries must be less than or equal to
  17307    //
  17308    //      floor( (gamma - alpha) * log_10(2) ) = 8.
  17309    //
  17310    // (A smaller distance gamma-alpha would require a larger table.)
  17311 
  17312    // NB:
  17313    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
  17314 
  17315    constexpr int kCachedPowersMinDecExp = -300;
  17316    constexpr int kCachedPowersDecStep = 8;
  17317 
  17318    static constexpr std::array<cached_power, 79> kCachedPowers =
  17319    {
  17320        {
  17321            { 0xAB70FE17C79AC6CA, -1060, -300 },
  17322            { 0xFF77B1FCBEBCDC4F, -1034, -292 },
  17323            { 0xBE5691EF416BD60C, -1007, -284 },
  17324            { 0x8DD01FAD907FFC3C,  -980, -276 },
  17325            { 0xD3515C2831559A83,  -954, -268 },
  17326            { 0x9D71AC8FADA6C9B5,  -927, -260 },
  17327            { 0xEA9C227723EE8BCB,  -901, -252 },
  17328            { 0xAECC49914078536D,  -874, -244 },
  17329            { 0x823C12795DB6CE57,  -847, -236 },
  17330            { 0xC21094364DFB5637,  -821, -228 },
  17331            { 0x9096EA6F3848984F,  -794, -220 },
  17332            { 0xD77485CB25823AC7,  -768, -212 },
  17333            { 0xA086CFCD97BF97F4,  -741, -204 },
  17334            { 0xEF340A98172AACE5,  -715, -196 },
  17335            { 0xB23867FB2A35B28E,  -688, -188 },
  17336            { 0x84C8D4DFD2C63F3B,  -661, -180 },
  17337            { 0xC5DD44271AD3CDBA,  -635, -172 },
  17338            { 0x936B9FCEBB25C996,  -608, -164 },
  17339            { 0xDBAC6C247D62A584,  -582, -156 },
  17340            { 0xA3AB66580D5FDAF6,  -555, -148 },
  17341            { 0xF3E2F893DEC3F126,  -529, -140 },
  17342            { 0xB5B5ADA8AAFF80B8,  -502, -132 },
  17343            { 0x87625F056C7C4A8B,  -475, -124 },
  17344            { 0xC9BCFF6034C13053,  -449, -116 },
  17345            { 0x964E858C91BA2655,  -422, -108 },
  17346            { 0xDFF9772470297EBD,  -396, -100 },
  17347            { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
  17348            { 0xF8A95FCF88747D94,  -343,  -84 },
  17349            { 0xB94470938FA89BCF,  -316,  -76 },
  17350            { 0x8A08F0F8BF0F156B,  -289,  -68 },
  17351            { 0xCDB02555653131B6,  -263,  -60 },
  17352            { 0x993FE2C6D07B7FAC,  -236,  -52 },
  17353            { 0xE45C10C42A2B3B06,  -210,  -44 },
  17354            { 0xAA242499697392D3,  -183,  -36 },
  17355            { 0xFD87B5F28300CA0E,  -157,  -28 },
  17356            { 0xBCE5086492111AEB,  -130,  -20 },
  17357            { 0x8CBCCC096F5088CC,  -103,  -12 },
  17358            { 0xD1B71758E219652C,   -77,   -4 },
  17359            { 0x9C40000000000000,   -50,    4 },
  17360            { 0xE8D4A51000000000,   -24,   12 },
  17361            { 0xAD78EBC5AC620000,     3,   20 },
  17362            { 0x813F3978F8940984,    30,   28 },
  17363            { 0xC097CE7BC90715B3,    56,   36 },
  17364            { 0x8F7E32CE7BEA5C70,    83,   44 },
  17365            { 0xD5D238A4ABE98068,   109,   52 },
  17366            { 0x9F4F2726179A2245,   136,   60 },
  17367            { 0xED63A231D4C4FB27,   162,   68 },
  17368            { 0xB0DE65388CC8ADA8,   189,   76 },
  17369            { 0x83C7088E1AAB65DB,   216,   84 },
  17370            { 0xC45D1DF942711D9A,   242,   92 },
  17371            { 0x924D692CA61BE758,   269,  100 },
  17372            { 0xDA01EE641A708DEA,   295,  108 },
  17373            { 0xA26DA3999AEF774A,   322,  116 },
  17374            { 0xF209787BB47D6B85,   348,  124 },
  17375            { 0xB454E4A179DD1877,   375,  132 },
  17376            { 0x865B86925B9BC5C2,   402,  140 },
  17377            { 0xC83553C5C8965D3D,   428,  148 },
  17378            { 0x952AB45CFA97A0B3,   455,  156 },
  17379            { 0xDE469FBD99A05FE3,   481,  164 },
  17380            { 0xA59BC234DB398C25,   508,  172 },
  17381            { 0xF6C69A72A3989F5C,   534,  180 },
  17382            { 0xB7DCBF5354E9BECE,   561,  188 },
  17383            { 0x88FCF317F22241E2,   588,  196 },
  17384            { 0xCC20CE9BD35C78A5,   614,  204 },
  17385            { 0x98165AF37B2153DF,   641,  212 },
  17386            { 0xE2A0B5DC971F303A,   667,  220 },
  17387            { 0xA8D9D1535CE3B396,   694,  228 },
  17388            { 0xFB9B7CD9A4A7443C,   720,  236 },
  17389            { 0xBB764C4CA7A44410,   747,  244 },
  17390            { 0x8BAB8EEFB6409C1A,   774,  252 },
  17391            { 0xD01FEF10A657842C,   800,  260 },
  17392            { 0x9B10A4E5E9913129,   827,  268 },
  17393            { 0xE7109BFBA19C0C9D,   853,  276 },
  17394            { 0xAC2820D9623BF429,   880,  284 },
  17395            { 0x80444B5E7AA7CF85,   907,  292 },
  17396            { 0xBF21E44003ACDD2D,   933,  300 },
  17397            { 0x8E679C2F5E44FF8F,   960,  308 },
  17398            { 0xD433179D9C8CB841,   986,  316 },
  17399            { 0x9E19DB92B4E31BA9,  1013,  324 },
  17400        }
  17401    };
  17402 
  17403    // This computation gives exactly the same results for k as
  17404    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
  17405    // for |e| <= 1500, but doesn't require floating-point operations.
  17406    // NB: log_10(2) ~= 78913 / 2^18
  17407    JSON_ASSERT(e >= -1500);
  17408    JSON_ASSERT(e <=  1500);
  17409    const int f = kAlpha - e - 1;
  17410    const int k = (f * 78913) / (1 << 18) + static_cast<int>(f > 0);
  17411 
  17412    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
  17413    JSON_ASSERT(index >= 0);
  17414    JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
  17415 
  17416    const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
  17417    JSON_ASSERT(kAlpha <= cached.e + e + 64);
  17418    JSON_ASSERT(kGamma >= cached.e + e + 64);
  17419 
  17420    return cached;
  17421 }
  17422 
  17423 /*!
  17424 For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
  17425 For n == 0, returns 1 and sets pow10 := 1.
  17426 */
  17427 inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
  17428 {
  17429    // LCOV_EXCL_START
  17430    if (n >= 1000000000)
  17431    {
  17432        pow10 = 1000000000;
  17433        return 10;
  17434    }
  17435    // LCOV_EXCL_STOP
  17436    if (n >= 100000000)
  17437    {
  17438        pow10 = 100000000;
  17439        return  9;
  17440    }
  17441    if (n >= 10000000)
  17442    {
  17443        pow10 = 10000000;
  17444        return  8;
  17445    }
  17446    if (n >= 1000000)
  17447    {
  17448        pow10 = 1000000;
  17449        return  7;
  17450    }
  17451    if (n >= 100000)
  17452    {
  17453        pow10 = 100000;
  17454        return  6;
  17455    }
  17456    if (n >= 10000)
  17457    {
  17458        pow10 = 10000;
  17459        return  5;
  17460    }
  17461    if (n >= 1000)
  17462    {
  17463        pow10 = 1000;
  17464        return  4;
  17465    }
  17466    if (n >= 100)
  17467    {
  17468        pow10 = 100;
  17469        return  3;
  17470    }
  17471    if (n >= 10)
  17472    {
  17473        pow10 = 10;
  17474        return  2;
  17475    }
  17476 
  17477    pow10 = 1;
  17478    return 1;
  17479 }
  17480 
  17481 inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
  17482                         std::uint64_t rest, std::uint64_t ten_k)
  17483 {
  17484    JSON_ASSERT(len >= 1);
  17485    JSON_ASSERT(dist <= delta);
  17486    JSON_ASSERT(rest <= delta);
  17487    JSON_ASSERT(ten_k > 0);
  17488 
  17489    //               <--------------------------- delta ---->
  17490    //                                  <---- dist --------->
  17491    // --------------[------------------+-------------------]--------------
  17492    //               M-                 w                   M+
  17493    //
  17494    //                                  ten_k
  17495    //                                <------>
  17496    //                                       <---- rest ---->
  17497    // --------------[------------------+----+--------------]--------------
  17498    //                                  w    V
  17499    //                                       = buf * 10^k
  17500    //
  17501    // ten_k represents a unit-in-the-last-place in the decimal representation
  17502    // stored in buf.
  17503    // Decrement buf by ten_k while this takes buf closer to w.
  17504 
  17505    // The tests are written in this order to avoid overflow in unsigned
  17506    // integer arithmetic.
  17507 
  17508    while (rest < dist
  17509            && delta - rest >= ten_k
  17510            && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
  17511    {
  17512        JSON_ASSERT(buf[len - 1] != '0');
  17513        buf[len - 1]--;
  17514        rest += ten_k;
  17515    }
  17516 }
  17517 
  17518 /*!
  17519 Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
  17520 M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
  17521 */
  17522 inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
  17523                             diyfp M_minus, diyfp w, diyfp M_plus)
  17524 {
  17525    static_assert(kAlpha >= -60, "internal error");
  17526    static_assert(kGamma <= -32, "internal error");
  17527 
  17528    // Generates the digits (and the exponent) of a decimal floating-point
  17529    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
  17530    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
  17531    //
  17532    //               <--------------------------- delta ---->
  17533    //                                  <---- dist --------->
  17534    // --------------[------------------+-------------------]--------------
  17535    //               M-                 w                   M+
  17536    //
  17537    // Grisu2 generates the digits of M+ from left to right and stops as soon as
  17538    // V is in [M-,M+].
  17539 
  17540    JSON_ASSERT(M_plus.e >= kAlpha);
  17541    JSON_ASSERT(M_plus.e <= kGamma);
  17542 
  17543    std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
  17544    std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
  17545 
  17546    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
  17547    //
  17548    //      M+ = f * 2^e
  17549    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
  17550    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
  17551    //         = p1 + p2 * 2^e
  17552 
  17553    const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
  17554 
  17555    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.)
  17556    std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
  17557 
  17558    // 1)
  17559    //
  17560    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
  17561 
  17562    JSON_ASSERT(p1 > 0);
  17563 
  17564    std::uint32_t pow10{};
  17565    const int k = find_largest_pow10(p1, pow10);
  17566 
  17567    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
  17568    //
  17569    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
  17570    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
  17571    //
  17572    //      M+ = p1                                             + p2 * 2^e
  17573    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
  17574    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
  17575    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
  17576    //
  17577    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
  17578    //
  17579    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
  17580    //
  17581    // but stop as soon as
  17582    //
  17583    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
  17584 
  17585    int n = k;
  17586    while (n > 0)
  17587    {
  17588        // Invariants:
  17589        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
  17590        //      pow10 = 10^(n-1) <= p1 < 10^n
  17591        //
  17592        const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
  17593        const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
  17594        //
  17595        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
  17596        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
  17597        //
  17598        JSON_ASSERT(d <= 9);
  17599        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
  17600        //
  17601        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
  17602        //
  17603        p1 = r;
  17604        n--;
  17605        //
  17606        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
  17607        //      pow10 = 10^n
  17608        //
  17609 
  17610        // Now check if enough digits have been generated.
  17611        // Compute
  17612        //
  17613        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
  17614        //
  17615        // Note:
  17616        // Since rest and delta share the same exponent e, it suffices to
  17617        // compare the significands.
  17618        const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
  17619        if (rest <= delta)
  17620        {
  17621            // V = buffer * 10^n, with M- <= V <= M+.
  17622 
  17623            decimal_exponent += n;
  17624 
  17625            // We may now just stop. But instead look if the buffer could be
  17626            // decremented to bring V closer to w.
  17627            //
  17628            // pow10 = 10^n is now 1 ulp in the decimal representation V.
  17629            // The rounding procedure works with diyfp's with an implicit
  17630            // exponent of e.
  17631            //
  17632            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
  17633            //
  17634            const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
  17635            grisu2_round(buffer, length, dist, delta, rest, ten_n);
  17636 
  17637            return;
  17638        }
  17639 
  17640        pow10 /= 10;
  17641        //
  17642        //      pow10 = 10^(n-1) <= p1 < 10^n
  17643        // Invariants restored.
  17644    }
  17645 
  17646    // 2)
  17647    //
  17648    // The digits of the integral part have been generated:
  17649    //
  17650    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
  17651    //         = buffer            + p2 * 2^e
  17652    //
  17653    // Now generate the digits of the fractional part p2 * 2^e.
  17654    //
  17655    // Note:
  17656    // No decimal point is generated: the exponent is adjusted instead.
  17657    //
  17658    // p2 actually represents the fraction
  17659    //
  17660    //      p2 * 2^e
  17661    //          = p2 / 2^-e
  17662    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
  17663    //
  17664    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
  17665    //
  17666    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
  17667    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
  17668    //
  17669    // using
  17670    //
  17671    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
  17672    //                = (                   d) * 2^-e + (                   r)
  17673    //
  17674    // or
  17675    //      10^m * p2 * 2^e = d + r * 2^e
  17676    //
  17677    // i.e.
  17678    //
  17679    //      M+ = buffer + p2 * 2^e
  17680    //         = buffer + 10^-m * (d + r * 2^e)
  17681    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
  17682    //
  17683    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
  17684 
  17685    JSON_ASSERT(p2 > delta);
  17686 
  17687    int m = 0;
  17688    for (;;)
  17689    {
  17690        // Invariant:
  17691        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
  17692        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
  17693        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
  17694        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
  17695        //
  17696        JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
  17697        p2 *= 10;
  17698        const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
  17699        const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
  17700        //
  17701        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
  17702        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
  17703        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
  17704        //
  17705        JSON_ASSERT(d <= 9);
  17706        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
  17707        //
  17708        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
  17709        //
  17710        p2 = r;
  17711        m++;
  17712        //
  17713        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
  17714        // Invariant restored.
  17715 
  17716        // Check if enough digits have been generated.
  17717        //
  17718        //      10^-m * p2 * 2^e <= delta * 2^e
  17719        //              p2 * 2^e <= 10^m * delta * 2^e
  17720        //                    p2 <= 10^m * delta
  17721        delta *= 10;
  17722        dist  *= 10;
  17723        if (p2 <= delta)
  17724        {
  17725            break;
  17726        }
  17727    }
  17728 
  17729    // V = buffer * 10^-m, with M- <= V <= M+.
  17730 
  17731    decimal_exponent -= m;
  17732 
  17733    // 1 ulp in the decimal representation is now 10^-m.
  17734    // Since delta and dist are now scaled by 10^m, we need to do the
  17735    // same with ulp in order to keep the units in sync.
  17736    //
  17737    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
  17738    //
  17739    const std::uint64_t ten_m = one.f;
  17740    grisu2_round(buffer, length, dist, delta, p2, ten_m);
  17741 
  17742    // By construction this algorithm generates the shortest possible decimal
  17743    // number (Loitsch, Theorem 6.2) which rounds back to w.
  17744    // For an input number of precision p, at least
  17745    //
  17746    //      N = 1 + ceil(p * log_10(2))
  17747    //
  17748    // decimal digits are sufficient to identify all binary floating-point
  17749    // numbers (Matula, "In-and-Out conversions").
  17750    // This implies that the algorithm does not produce more than N decimal
  17751    // digits.
  17752    //
  17753    //      N = 17 for p = 53 (IEEE double precision)
  17754    //      N = 9  for p = 24 (IEEE single precision)
  17755 }
  17756 
  17757 /*!
  17758 v = buf * 10^decimal_exponent
  17759 len is the length of the buffer (number of decimal digits)
  17760 The buffer must be large enough, i.e. >= max_digits10.
  17761 */
  17762 JSON_HEDLEY_NON_NULL(1)
  17763 inline void grisu2(char* buf, int& len, int& decimal_exponent,
  17764                   diyfp m_minus, diyfp v, diyfp m_plus)
  17765 {
  17766    JSON_ASSERT(m_plus.e == m_minus.e);
  17767    JSON_ASSERT(m_plus.e == v.e);
  17768 
  17769    //  --------(-----------------------+-----------------------)--------    (A)
  17770    //          m-                      v                       m+
  17771    //
  17772    //  --------------------(-----------+-----------------------)--------    (B)
  17773    //                      m-          v                       m+
  17774    //
  17775    // First scale v (and m- and m+) such that the exponent is in the range
  17776    // [alpha, gamma].
  17777 
  17778    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
  17779 
  17780    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
  17781 
  17782    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
  17783    const diyfp w       = diyfp::mul(v,       c_minus_k);
  17784    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
  17785    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
  17786 
  17787    //  ----(---+---)---------------(---+---)---------------(---+---)----
  17788    //          w-                      w                       w+
  17789    //          = c*m-                  = c*v                   = c*m+
  17790    //
  17791    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
  17792    // w+ are now off by a small amount.
  17793    // In fact:
  17794    //
  17795    //      w - v * 10^k < 1 ulp
  17796    //
  17797    // To account for this inaccuracy, add resp. subtract 1 ulp.
  17798    //
  17799    //  --------+---[---------------(---+---)---------------]---+--------
  17800    //          w-  M-                  w                   M+  w+
  17801    //
  17802    // Now any number in [M-, M+] (bounds included) will round to w when input,
  17803    // regardless of how the input rounding algorithm breaks ties.
  17804    //
  17805    // And digit_gen generates the shortest possible such number in [M-, M+].
  17806    // Note that this does not mean that Grisu2 always generates the shortest
  17807    // possible number in the interval (m-, m+).
  17808    const diyfp M_minus(w_minus.f + 1, w_minus.e);
  17809    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
  17810 
  17811    decimal_exponent = -cached.k; // = -(-k) = k
  17812 
  17813    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
  17814 }
  17815 
  17816 /*!
  17817 v = buf * 10^decimal_exponent
  17818 len is the length of the buffer (number of decimal digits)
  17819 The buffer must be large enough, i.e. >= max_digits10.
  17820 */
  17821 template<typename FloatType>
  17822 JSON_HEDLEY_NON_NULL(1)
  17823 void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
  17824 {
  17825    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
  17826                  "internal error: not enough precision");
  17827 
  17828    JSON_ASSERT(std::isfinite(value));
  17829    JSON_ASSERT(value > 0);
  17830 
  17831    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
  17832    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
  17833    // decimal representations are not exactly "short".
  17834    //
  17835    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
  17836    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
  17837    // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
  17838    // does.
  17839    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
  17840    // representation using the corresponding std::from_chars function recovers value exactly". That
  17841    // indicates that single precision floating-point numbers should be recovered using
  17842    // 'std::strtof'.
  17843    //
  17844    // NB: If the neighbors are computed for single-precision numbers, there is a single float
  17845    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
  17846    //     value is off by 1 ulp.
  17847 #if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
  17848    const boundaries w = compute_boundaries(static_cast<double>(value));
  17849 #else
  17850    const boundaries w = compute_boundaries(value);
  17851 #endif
  17852 
  17853    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
  17854 }
  17855 
  17856 /*!
  17857 @brief appends a decimal representation of e to buf
  17858 @return a pointer to the element following the exponent.
  17859 @pre -1000 < e < 1000
  17860 */
  17861 JSON_HEDLEY_NON_NULL(1)
  17862 JSON_HEDLEY_RETURNS_NON_NULL
  17863 inline char* append_exponent(char* buf, int e)
  17864 {
  17865    JSON_ASSERT(e > -1000);
  17866    JSON_ASSERT(e <  1000);
  17867 
  17868    if (e < 0)
  17869    {
  17870        e = -e;
  17871        *buf++ = '-';
  17872    }
  17873    else
  17874    {
  17875        *buf++ = '+';
  17876    }
  17877 
  17878    auto k = static_cast<std::uint32_t>(e);
  17879    if (k < 10)
  17880    {
  17881        // Always print at least two digits in the exponent.
  17882        // This is for compatibility with printf("%g").
  17883        *buf++ = '0';
  17884        *buf++ = static_cast<char>('0' + k);
  17885    }
  17886    else if (k < 100)
  17887    {
  17888        *buf++ = static_cast<char>('0' + k / 10);
  17889        k %= 10;
  17890        *buf++ = static_cast<char>('0' + k);
  17891    }
  17892    else
  17893    {
  17894        *buf++ = static_cast<char>('0' + k / 100);
  17895        k %= 100;
  17896        *buf++ = static_cast<char>('0' + k / 10);
  17897        k %= 10;
  17898        *buf++ = static_cast<char>('0' + k);
  17899    }
  17900 
  17901    return buf;
  17902 }
  17903 
  17904 /*!
  17905 @brief prettify v = buf * 10^decimal_exponent
  17906 
  17907 If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
  17908 notation. Otherwise it will be printed in exponential notation.
  17909 
  17910 @pre min_exp < 0
  17911 @pre max_exp > 0
  17912 */
  17913 JSON_HEDLEY_NON_NULL(1)
  17914 JSON_HEDLEY_RETURNS_NON_NULL
  17915 inline char* format_buffer(char* buf, int len, int decimal_exponent,
  17916                           int min_exp, int max_exp)
  17917 {
  17918    JSON_ASSERT(min_exp < 0);
  17919    JSON_ASSERT(max_exp > 0);
  17920 
  17921    const int k = len;
  17922    const int n = len + decimal_exponent;
  17923 
  17924    // v = buf * 10^(n-k)
  17925    // k is the length of the buffer (number of decimal digits)
  17926    // n is the position of the decimal point relative to the start of the buffer.
  17927 
  17928    if (k <= n && n <= max_exp)
  17929    {
  17930        // digits[000]
  17931        // len <= max_exp + 2
  17932 
  17933        std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
  17934        // Make it look like a floating-point number (#362, #378)
  17935        buf[n + 0] = '.';
  17936        buf[n + 1] = '0';
  17937        return buf + (static_cast<size_t>(n) + 2);
  17938    }
  17939 
  17940    if (0 < n && n <= max_exp)
  17941    {
  17942        // dig.its
  17943        // len <= max_digits10 + 1
  17944 
  17945        JSON_ASSERT(k > n);
  17946 
  17947        std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
  17948        buf[n] = '.';
  17949        return buf + (static_cast<size_t>(k) + 1U);
  17950    }
  17951 
  17952    if (min_exp < n && n <= 0)
  17953    {
  17954        // 0.[000]digits
  17955        // len <= 2 + (-min_exp - 1) + max_digits10
  17956 
  17957        std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
  17958        buf[0] = '0';
  17959        buf[1] = '.';
  17960        std::memset(buf + 2, '0', static_cast<size_t>(-n));
  17961        return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
  17962    }
  17963 
  17964    if (k == 1)
  17965    {
  17966        // dE+123
  17967        // len <= 1 + 5
  17968 
  17969        buf += 1;
  17970    }
  17971    else
  17972    {
  17973        // d.igitsE+123
  17974        // len <= max_digits10 + 1 + 5
  17975 
  17976        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
  17977        buf[1] = '.';
  17978        buf += 1 + static_cast<size_t>(k);
  17979    }
  17980 
  17981    *buf++ = 'e';
  17982    return append_exponent(buf, n - 1);
  17983 }
  17984 
  17985 }  // namespace dtoa_impl
  17986 
  17987 /*!
  17988 @brief generates a decimal representation of the floating-point number value in [first, last).
  17989 
  17990 The format of the resulting decimal representation is similar to printf's %g
  17991 format. Returns an iterator pointing past-the-end of the decimal representation.
  17992 
  17993 @note The input number must be finite, i.e. NaN's and Inf's are not supported.
  17994 @note The buffer must be large enough.
  17995 @note The result is NOT null-terminated.
  17996 */
  17997 template<typename FloatType>
  17998 JSON_HEDLEY_NON_NULL(1, 2)
  17999 JSON_HEDLEY_RETURNS_NON_NULL
  18000 char* to_chars(char* first, const char* last, FloatType value)
  18001 {
  18002    static_cast<void>(last); // maybe unused - fix warning
  18003    JSON_ASSERT(std::isfinite(value));
  18004 
  18005    // Use signbit(value) instead of (value < 0) since signbit works for -0.
  18006    if (std::signbit(value))
  18007    {
  18008        value = -value;
  18009        *first++ = '-';
  18010    }
  18011 
  18012 #ifdef __GNUC__
  18013 #pragma GCC diagnostic push
  18014 #pragma GCC diagnostic ignored "-Wfloat-equal"
  18015 #endif
  18016    if (value == 0) // +-0
  18017    {
  18018        *first++ = '0';
  18019        // Make it look like a floating-point number (#362, #378)
  18020        *first++ = '.';
  18021        *first++ = '0';
  18022        return first;
  18023    }
  18024 #ifdef __GNUC__
  18025 #pragma GCC diagnostic pop
  18026 #endif
  18027 
  18028    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
  18029 
  18030    // Compute v = buffer * 10^decimal_exponent.
  18031    // The decimal digits are stored in the buffer, which needs to be interpreted
  18032    // as an unsigned decimal integer.
  18033    // len is the length of the buffer, i.e. the number of decimal digits.
  18034    int len = 0;
  18035    int decimal_exponent = 0;
  18036    dtoa_impl::grisu2(first, len, decimal_exponent, value);
  18037 
  18038    JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
  18039 
  18040    // Format the buffer like printf("%.*g", prec, value)
  18041    constexpr int kMinExp = -4;
  18042    // Use digits10 here to increase compatibility with version 2.
  18043    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
  18044 
  18045    JSON_ASSERT(last - first >= kMaxExp + 2);
  18046    JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
  18047    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
  18048 
  18049    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
  18050 }
  18051 
  18052 }  // namespace detail
  18053 NLOHMANN_JSON_NAMESPACE_END
  18054 
  18055 // #include <nlohmann/detail/exceptions.hpp>
  18056 
  18057 // #include <nlohmann/detail/macro_scope.hpp>
  18058 
  18059 // #include <nlohmann/detail/meta/cpp_future.hpp>
  18060 
  18061 // #include <nlohmann/detail/output/binary_writer.hpp>
  18062 
  18063 // #include <nlohmann/detail/output/output_adapters.hpp>
  18064 
  18065 // #include <nlohmann/detail/string_concat.hpp>
  18066 
  18067 // #include <nlohmann/detail/value_t.hpp>
  18068 
  18069 
  18070 NLOHMANN_JSON_NAMESPACE_BEGIN
  18071 namespace detail
  18072 {
  18073 
  18074 ///////////////////
  18075 // serialization //
  18076 ///////////////////
  18077 
  18078 /// how to treat decoding errors
  18079 enum class error_handler_t
  18080 {
  18081    strict,  ///< throw a type_error exception in case of invalid UTF-8
  18082    replace, ///< replace invalid UTF-8 sequences with U+FFFD
  18083    ignore   ///< ignore invalid UTF-8 sequences
  18084 };
  18085 
  18086 template<typename BasicJsonType>
  18087 class serializer
  18088 {
  18089    using string_t = typename BasicJsonType::string_t;
  18090    using number_float_t = typename BasicJsonType::number_float_t;
  18091    using number_integer_t = typename BasicJsonType::number_integer_t;
  18092    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  18093    using binary_char_t = typename BasicJsonType::binary_t::value_type;
  18094    static constexpr std::uint8_t UTF8_ACCEPT = 0;
  18095    static constexpr std::uint8_t UTF8_REJECT = 1;
  18096 
  18097  public:
  18098    /*!
  18099    @param[in] s  output stream to serialize to
  18100    @param[in] ichar  indentation character to use
  18101    @param[in] error_handler_  how to react on decoding errors
  18102    */
  18103    serializer(output_adapter_t<char> s, const char ichar,
  18104               error_handler_t error_handler_ = error_handler_t::strict)
  18105        : o(std::move(s))
  18106        , loc(std::localeconv())
  18107        , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
  18108        , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
  18109        , indent_char(ichar)
  18110        , indent_string(512, indent_char)
  18111        , error_handler(error_handler_)
  18112    {}
  18113 
  18114    // delete because of pointer members
  18115    serializer(const serializer&) = delete;
  18116    serializer& operator=(const serializer&) = delete;
  18117    serializer(serializer&&) = delete;
  18118    serializer& operator=(serializer&&) = delete;
  18119    ~serializer() = default;
  18120 
  18121    /*!
  18122    @brief internal implementation of the serialization function
  18123 
  18124    This function is called by the public member function dump and organizes
  18125    the serialization internally. The indentation level is propagated as
  18126    additional parameter. In case of arrays and objects, the function is
  18127    called recursively.
  18128 
  18129    - strings and object keys are escaped using `escape_string()`
  18130    - integer numbers are converted implicitly via `operator<<`
  18131    - floating-point numbers are converted to a string using `"%g"` format
  18132    - binary values are serialized as objects containing the subtype and the
  18133      byte array
  18134 
  18135    @param[in] val               value to serialize
  18136    @param[in] pretty_print      whether the output shall be pretty-printed
  18137    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
  18138    in the output are escaped with `\uXXXX` sequences, and the result consists
  18139    of ASCII characters only.
  18140    @param[in] indent_step       the indent level
  18141    @param[in] current_indent    the current indent level (only used internally)
  18142    */
  18143    void dump(const BasicJsonType& val,
  18144              const bool pretty_print,
  18145              const bool ensure_ascii,
  18146              const unsigned int indent_step,
  18147              const unsigned int current_indent = 0)
  18148    {
  18149        switch (val.m_data.m_type)
  18150        {
  18151            case value_t::object:
  18152            {
  18153                if (val.m_data.m_value.object->empty())
  18154                {
  18155                    o->write_characters("{}", 2);
  18156                    return;
  18157                }
  18158 
  18159                if (pretty_print)
  18160                {
  18161                    o->write_characters("{\n", 2);
  18162 
  18163                    // variable to hold indentation for recursive calls
  18164                    const auto new_indent = current_indent + indent_step;
  18165                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  18166                    {
  18167                        indent_string.resize(indent_string.size() * 2, ' ');
  18168                    }
  18169 
  18170                    // first n-1 elements
  18171                    auto i = val.m_data.m_value.object->cbegin();
  18172                    for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
  18173                    {
  18174                        o->write_characters(indent_string.c_str(), new_indent);
  18175                        o->write_character('\"');
  18176                        dump_escaped(i->first, ensure_ascii);
  18177                        o->write_characters("\": ", 3);
  18178                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
  18179                        o->write_characters(",\n", 2);
  18180                    }
  18181 
  18182                    // last element
  18183                    JSON_ASSERT(i != val.m_data.m_value.object->cend());
  18184                    JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
  18185                    o->write_characters(indent_string.c_str(), new_indent);
  18186                    o->write_character('\"');
  18187                    dump_escaped(i->first, ensure_ascii);
  18188                    o->write_characters("\": ", 3);
  18189                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
  18190 
  18191                    o->write_character('\n');
  18192                    o->write_characters(indent_string.c_str(), current_indent);
  18193                    o->write_character('}');
  18194                }
  18195                else
  18196                {
  18197                    o->write_character('{');
  18198 
  18199                    // first n-1 elements
  18200                    auto i = val.m_data.m_value.object->cbegin();
  18201                    for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
  18202                    {
  18203                        o->write_character('\"');
  18204                        dump_escaped(i->first, ensure_ascii);
  18205                        o->write_characters("\":", 2);
  18206                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
  18207                        o->write_character(',');
  18208                    }
  18209 
  18210                    // last element
  18211                    JSON_ASSERT(i != val.m_data.m_value.object->cend());
  18212                    JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
  18213                    o->write_character('\"');
  18214                    dump_escaped(i->first, ensure_ascii);
  18215                    o->write_characters("\":", 2);
  18216                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
  18217 
  18218                    o->write_character('}');
  18219                }
  18220 
  18221                return;
  18222            }
  18223 
  18224            case value_t::array:
  18225            {
  18226                if (val.m_data.m_value.array->empty())
  18227                {
  18228                    o->write_characters("[]", 2);
  18229                    return;
  18230                }
  18231 
  18232                if (pretty_print)
  18233                {
  18234                    o->write_characters("[\n", 2);
  18235 
  18236                    // variable to hold indentation for recursive calls
  18237                    const auto new_indent = current_indent + indent_step;
  18238                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  18239                    {
  18240                        indent_string.resize(indent_string.size() * 2, ' ');
  18241                    }
  18242 
  18243                    // first n-1 elements
  18244                    for (auto i = val.m_data.m_value.array->cbegin();
  18245                            i != val.m_data.m_value.array->cend() - 1; ++i)
  18246                    {
  18247                        o->write_characters(indent_string.c_str(), new_indent);
  18248                        dump(*i, true, ensure_ascii, indent_step, new_indent);
  18249                        o->write_characters(",\n", 2);
  18250                    }
  18251 
  18252                    // last element
  18253                    JSON_ASSERT(!val.m_data.m_value.array->empty());
  18254                    o->write_characters(indent_string.c_str(), new_indent);
  18255                    dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
  18256 
  18257                    o->write_character('\n');
  18258                    o->write_characters(indent_string.c_str(), current_indent);
  18259                    o->write_character(']');
  18260                }
  18261                else
  18262                {
  18263                    o->write_character('[');
  18264 
  18265                    // first n-1 elements
  18266                    for (auto i = val.m_data.m_value.array->cbegin();
  18267                            i != val.m_data.m_value.array->cend() - 1; ++i)
  18268                    {
  18269                        dump(*i, false, ensure_ascii, indent_step, current_indent);
  18270                        o->write_character(',');
  18271                    }
  18272 
  18273                    // last element
  18274                    JSON_ASSERT(!val.m_data.m_value.array->empty());
  18275                    dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
  18276 
  18277                    o->write_character(']');
  18278                }
  18279 
  18280                return;
  18281            }
  18282 
  18283            case value_t::string:
  18284            {
  18285                o->write_character('\"');
  18286                dump_escaped(*val.m_data.m_value.string, ensure_ascii);
  18287                o->write_character('\"');
  18288                return;
  18289            }
  18290 
  18291            case value_t::binary:
  18292            {
  18293                if (pretty_print)
  18294                {
  18295                    o->write_characters("{\n", 2);
  18296 
  18297                    // variable to hold indentation for recursive calls
  18298                    const auto new_indent = current_indent + indent_step;
  18299                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
  18300                    {
  18301                        indent_string.resize(indent_string.size() * 2, ' ');
  18302                    }
  18303 
  18304                    o->write_characters(indent_string.c_str(), new_indent);
  18305 
  18306                    o->write_characters("\"bytes\": [", 10);
  18307 
  18308                    if (!val.m_data.m_value.binary->empty())
  18309                    {
  18310                        for (auto i = val.m_data.m_value.binary->cbegin();
  18311                                i != val.m_data.m_value.binary->cend() - 1; ++i)
  18312                        {
  18313                            dump_integer(*i);
  18314                            o->write_characters(", ", 2);
  18315                        }
  18316                        dump_integer(val.m_data.m_value.binary->back());
  18317                    }
  18318 
  18319                    o->write_characters("],\n", 3);
  18320                    o->write_characters(indent_string.c_str(), new_indent);
  18321 
  18322                    o->write_characters("\"subtype\": ", 11);
  18323                    if (val.m_data.m_value.binary->has_subtype())
  18324                    {
  18325                        dump_integer(val.m_data.m_value.binary->subtype());
  18326                    }
  18327                    else
  18328                    {
  18329                        o->write_characters("null", 4);
  18330                    }
  18331                    o->write_character('\n');
  18332                    o->write_characters(indent_string.c_str(), current_indent);
  18333                    o->write_character('}');
  18334                }
  18335                else
  18336                {
  18337                    o->write_characters("{\"bytes\":[", 10);
  18338 
  18339                    if (!val.m_data.m_value.binary->empty())
  18340                    {
  18341                        for (auto i = val.m_data.m_value.binary->cbegin();
  18342                                i != val.m_data.m_value.binary->cend() - 1; ++i)
  18343                        {
  18344                            dump_integer(*i);
  18345                            o->write_character(',');
  18346                        }
  18347                        dump_integer(val.m_data.m_value.binary->back());
  18348                    }
  18349 
  18350                    o->write_characters("],\"subtype\":", 12);
  18351                    if (val.m_data.m_value.binary->has_subtype())
  18352                    {
  18353                        dump_integer(val.m_data.m_value.binary->subtype());
  18354                        o->write_character('}');
  18355                    }
  18356                    else
  18357                    {
  18358                        o->write_characters("null}", 5);
  18359                    }
  18360                }
  18361                return;
  18362            }
  18363 
  18364            case value_t::boolean:
  18365            {
  18366                if (val.m_data.m_value.boolean)
  18367                {
  18368                    o->write_characters("true", 4);
  18369                }
  18370                else
  18371                {
  18372                    o->write_characters("false", 5);
  18373                }
  18374                return;
  18375            }
  18376 
  18377            case value_t::number_integer:
  18378            {
  18379                dump_integer(val.m_data.m_value.number_integer);
  18380                return;
  18381            }
  18382 
  18383            case value_t::number_unsigned:
  18384            {
  18385                dump_integer(val.m_data.m_value.number_unsigned);
  18386                return;
  18387            }
  18388 
  18389            case value_t::number_float:
  18390            {
  18391                dump_float(val.m_data.m_value.number_float);
  18392                return;
  18393            }
  18394 
  18395            case value_t::discarded:
  18396            {
  18397                o->write_characters("<discarded>", 11);
  18398                return;
  18399            }
  18400 
  18401            case value_t::null:
  18402            {
  18403                o->write_characters("null", 4);
  18404                return;
  18405            }
  18406 
  18407            default:            // LCOV_EXCL_LINE
  18408                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18409        }
  18410    }
  18411 
  18412  JSON_PRIVATE_UNLESS_TESTED:
  18413    /*!
  18414    @brief dump escaped string
  18415 
  18416    Escape a string by replacing certain special characters by a sequence of an
  18417    escape character (backslash) and another character and other control
  18418    characters by a sequence of "\u" followed by a four-digit hex
  18419    representation. The escaped string is written to output stream @a o.
  18420 
  18421    @param[in] s  the string to escape
  18422    @param[in] ensure_ascii  whether to escape non-ASCII characters with
  18423                             \uXXXX sequences
  18424 
  18425    @complexity Linear in the length of string @a s.
  18426    */
  18427    void dump_escaped(const string_t& s, const bool ensure_ascii)
  18428    {
  18429        std::uint32_t codepoint{};
  18430        std::uint8_t state = UTF8_ACCEPT;
  18431        std::size_t bytes = 0;  // number of bytes written to string_buffer
  18432 
  18433        // number of bytes written at the point of the last valid byte
  18434        std::size_t bytes_after_last_accept = 0;
  18435        std::size_t undumped_chars = 0;
  18436 
  18437        for (std::size_t i = 0; i < s.size(); ++i)
  18438        {
  18439            const auto byte = static_cast<std::uint8_t>(s[i]);
  18440 
  18441            switch (decode(state, codepoint, byte))
  18442            {
  18443                case UTF8_ACCEPT:  // decode found a new code point
  18444                {
  18445                    switch (codepoint)
  18446                    {
  18447                        case 0x08: // backspace
  18448                        {
  18449                            string_buffer[bytes++] = '\\';
  18450                            string_buffer[bytes++] = 'b';
  18451                            break;
  18452                        }
  18453 
  18454                        case 0x09: // horizontal tab
  18455                        {
  18456                            string_buffer[bytes++] = '\\';
  18457                            string_buffer[bytes++] = 't';
  18458                            break;
  18459                        }
  18460 
  18461                        case 0x0A: // newline
  18462                        {
  18463                            string_buffer[bytes++] = '\\';
  18464                            string_buffer[bytes++] = 'n';
  18465                            break;
  18466                        }
  18467 
  18468                        case 0x0C: // formfeed
  18469                        {
  18470                            string_buffer[bytes++] = '\\';
  18471                            string_buffer[bytes++] = 'f';
  18472                            break;
  18473                        }
  18474 
  18475                        case 0x0D: // carriage return
  18476                        {
  18477                            string_buffer[bytes++] = '\\';
  18478                            string_buffer[bytes++] = 'r';
  18479                            break;
  18480                        }
  18481 
  18482                        case 0x22: // quotation mark
  18483                        {
  18484                            string_buffer[bytes++] = '\\';
  18485                            string_buffer[bytes++] = '\"';
  18486                            break;
  18487                        }
  18488 
  18489                        case 0x5C: // reverse solidus
  18490                        {
  18491                            string_buffer[bytes++] = '\\';
  18492                            string_buffer[bytes++] = '\\';
  18493                            break;
  18494                        }
  18495 
  18496                        default:
  18497                        {
  18498                            // escape control characters (0x00..0x1F) or, if
  18499                            // ensure_ascii parameter is used, non-ASCII characters
  18500                            if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
  18501                            {
  18502                                if (codepoint <= 0xFFFF)
  18503                                {
  18504                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18505                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
  18506                                                                      static_cast<std::uint16_t>(codepoint)));
  18507                                    bytes += 6;
  18508                                }
  18509                                else
  18510                                {
  18511                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18512                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
  18513                                                                      static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
  18514                                                                      static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
  18515                                    bytes += 12;
  18516                                }
  18517                            }
  18518                            else
  18519                            {
  18520                                // copy byte to buffer (all previous bytes
  18521                                // been copied have in default case above)
  18522                                string_buffer[bytes++] = s[i];
  18523                            }
  18524                            break;
  18525                        }
  18526                    }
  18527 
  18528                    // write buffer and reset index; there must be 13 bytes
  18529                    // left, as this is the maximal number of bytes to be
  18530                    // written ("\uxxxx\uxxxx\0") for one code point
  18531                    if (string_buffer.size() - bytes < 13)
  18532                    {
  18533                        o->write_characters(string_buffer.data(), bytes);
  18534                        bytes = 0;
  18535                    }
  18536 
  18537                    // remember the byte position of this accept
  18538                    bytes_after_last_accept = bytes;
  18539                    undumped_chars = 0;
  18540                    break;
  18541                }
  18542 
  18543                case UTF8_REJECT:  // decode found invalid UTF-8 byte
  18544                {
  18545                    switch (error_handler)
  18546                    {
  18547                        case error_handler_t::strict:
  18548                        {
  18549                            JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
  18550                        }
  18551 
  18552                        case error_handler_t::ignore:
  18553                        case error_handler_t::replace:
  18554                        {
  18555                            // in case we saw this character the first time, we
  18556                            // would like to read it again, because the byte
  18557                            // may be OK for itself, but just not OK for the
  18558                            // previous sequence
  18559                            if (undumped_chars > 0)
  18560                            {
  18561                                --i;
  18562                            }
  18563 
  18564                            // reset length buffer to the last accepted index;
  18565                            // thus removing/ignoring the invalid characters
  18566                            bytes = bytes_after_last_accept;
  18567 
  18568                            if (error_handler == error_handler_t::replace)
  18569                            {
  18570                                // add a replacement character
  18571                                if (ensure_ascii)
  18572                                {
  18573                                    string_buffer[bytes++] = '\\';
  18574                                    string_buffer[bytes++] = 'u';
  18575                                    string_buffer[bytes++] = 'f';
  18576                                    string_buffer[bytes++] = 'f';
  18577                                    string_buffer[bytes++] = 'f';
  18578                                    string_buffer[bytes++] = 'd';
  18579                                }
  18580                                else
  18581                                {
  18582                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
  18583                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
  18584                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
  18585                                }
  18586 
  18587                                // write buffer and reset index; there must be 13 bytes
  18588                                // left, as this is the maximal number of bytes to be
  18589                                // written ("\uxxxx\uxxxx\0") for one code point
  18590                                if (string_buffer.size() - bytes < 13)
  18591                                {
  18592                                    o->write_characters(string_buffer.data(), bytes);
  18593                                    bytes = 0;
  18594                                }
  18595 
  18596                                bytes_after_last_accept = bytes;
  18597                            }
  18598 
  18599                            undumped_chars = 0;
  18600 
  18601                            // continue processing the string
  18602                            state = UTF8_ACCEPT;
  18603                            break;
  18604                        }
  18605 
  18606                        default:            // LCOV_EXCL_LINE
  18607                            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18608                    }
  18609                    break;
  18610                }
  18611 
  18612                default:  // decode found yet incomplete multi-byte code point
  18613                {
  18614                    if (!ensure_ascii)
  18615                    {
  18616                        // code point will not be escaped - copy byte to buffer
  18617                        string_buffer[bytes++] = s[i];
  18618                    }
  18619                    ++undumped_chars;
  18620                    break;
  18621                }
  18622            }
  18623        }
  18624 
  18625        // we finished processing the string
  18626        if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
  18627        {
  18628            // write buffer
  18629            if (bytes > 0)
  18630            {
  18631                o->write_characters(string_buffer.data(), bytes);
  18632            }
  18633        }
  18634        else
  18635        {
  18636            // we finish reading, but do not accept: string was incomplete
  18637            switch (error_handler)
  18638            {
  18639                case error_handler_t::strict:
  18640                {
  18641                    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));
  18642                }
  18643 
  18644                case error_handler_t::ignore:
  18645                {
  18646                    // write all accepted bytes
  18647                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
  18648                    break;
  18649                }
  18650 
  18651                case error_handler_t::replace:
  18652                {
  18653                    // write all accepted bytes
  18654                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
  18655                    // add a replacement character
  18656                    if (ensure_ascii)
  18657                    {
  18658                        o->write_characters("\\ufffd", 6);
  18659                    }
  18660                    else
  18661                    {
  18662                        o->write_characters("\xEF\xBF\xBD", 3);
  18663                    }
  18664                    break;
  18665                }
  18666 
  18667                default:            // LCOV_EXCL_LINE
  18668                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18669            }
  18670        }
  18671    }
  18672 
  18673  private:
  18674    /*!
  18675    @brief count digits
  18676 
  18677    Count the number of decimal (base 10) digits for an input unsigned integer.
  18678 
  18679    @param[in] x  unsigned integer number to count its digits
  18680    @return    number of decimal digits
  18681    */
  18682    inline unsigned int count_digits(number_unsigned_t x) noexcept
  18683    {
  18684        unsigned int n_digits = 1;
  18685        for (;;)
  18686        {
  18687            if (x < 10)
  18688            {
  18689                return n_digits;
  18690            }
  18691            if (x < 100)
  18692            {
  18693                return n_digits + 1;
  18694            }
  18695            if (x < 1000)
  18696            {
  18697                return n_digits + 2;
  18698            }
  18699            if (x < 10000)
  18700            {
  18701                return n_digits + 3;
  18702            }
  18703            x = x / 10000u;
  18704            n_digits += 4;
  18705        }
  18706    }
  18707 
  18708    /*!
  18709     * @brief convert a byte to a uppercase hex representation
  18710     * @param[in] byte byte to represent
  18711     * @return representation ("00".."FF")
  18712     */
  18713    static std::string hex_bytes(std::uint8_t byte)
  18714    {
  18715        std::string result = "FF";
  18716        constexpr const char* nibble_to_hex = "0123456789ABCDEF";
  18717        result[0] = nibble_to_hex[byte / 16];
  18718        result[1] = nibble_to_hex[byte % 16];
  18719        return result;
  18720    }
  18721 
  18722    // templates to avoid warnings about useless casts
  18723    template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
  18724    bool is_negative_number(NumberType x)
  18725    {
  18726        return x < 0;
  18727    }
  18728 
  18729    template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
  18730    bool is_negative_number(NumberType /*unused*/)
  18731    {
  18732        return false;
  18733    }
  18734 
  18735    /*!
  18736    @brief dump an integer
  18737 
  18738    Dump a given integer to output stream @a o. Works internally with
  18739    @a number_buffer.
  18740 
  18741    @param[in] x  integer number (signed or unsigned) to dump
  18742    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
  18743    */
  18744    template < typename NumberType, detail::enable_if_t <
  18745                   std::is_integral<NumberType>::value ||
  18746                   std::is_same<NumberType, number_unsigned_t>::value ||
  18747                   std::is_same<NumberType, number_integer_t>::value ||
  18748                   std::is_same<NumberType, binary_char_t>::value,
  18749                   int > = 0 >
  18750    void dump_integer(NumberType x)
  18751    {
  18752        static constexpr std::array<std::array<char, 2>, 100> digits_to_99
  18753        {
  18754            {
  18755                {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
  18756                {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
  18757                {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
  18758                {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
  18759                {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
  18760                {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
  18761                {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
  18762                {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
  18763                {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
  18764                {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
  18765            }
  18766        };
  18767 
  18768        // special case for "0"
  18769        if (x == 0)
  18770        {
  18771            o->write_character('0');
  18772            return;
  18773        }
  18774 
  18775        // use a pointer to fill the buffer
  18776        auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18777 
  18778        number_unsigned_t abs_value;
  18779 
  18780        unsigned int n_chars{};
  18781 
  18782        if (is_negative_number(x))
  18783        {
  18784            *buffer_ptr = '-';
  18785            abs_value = remove_sign(static_cast<number_integer_t>(x));
  18786 
  18787            // account one more byte for the minus sign
  18788            n_chars = 1 + count_digits(abs_value);
  18789        }
  18790        else
  18791        {
  18792            abs_value = static_cast<number_unsigned_t>(x);
  18793            n_chars = count_digits(abs_value);
  18794        }
  18795 
  18796        // spare 1 byte for '\0'
  18797        JSON_ASSERT(n_chars < number_buffer.size() - 1);
  18798 
  18799        // jump to the end to generate the string from backward,
  18800        // so we later avoid reversing the result
  18801        buffer_ptr += n_chars;
  18802 
  18803        // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
  18804        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
  18805        while (abs_value >= 100)
  18806        {
  18807            const auto digits_index = static_cast<unsigned>((abs_value % 100));
  18808            abs_value /= 100;
  18809            *(--buffer_ptr) = digits_to_99[digits_index][1];
  18810            *(--buffer_ptr) = digits_to_99[digits_index][0];
  18811        }
  18812 
  18813        if (abs_value >= 10)
  18814        {
  18815            const auto digits_index = static_cast<unsigned>(abs_value);
  18816            *(--buffer_ptr) = digits_to_99[digits_index][1];
  18817            *(--buffer_ptr) = digits_to_99[digits_index][0];
  18818        }
  18819        else
  18820        {
  18821            *(--buffer_ptr) = static_cast<char>('0' + abs_value);
  18822        }
  18823 
  18824        o->write_characters(number_buffer.data(), n_chars);
  18825    }
  18826 
  18827    /*!
  18828    @brief dump a floating-point number
  18829 
  18830    Dump a given floating-point number to output stream @a o. Works internally
  18831    with @a number_buffer.
  18832 
  18833    @param[in] x  floating-point number to dump
  18834    */
  18835    void dump_float(number_float_t x)
  18836    {
  18837        // NaN / inf
  18838        if (!std::isfinite(x))
  18839        {
  18840            o->write_characters("null", 4);
  18841            return;
  18842        }
  18843 
  18844        // If number_float_t is an IEEE-754 single or double precision number,
  18845        // use the Grisu2 algorithm to produce short numbers which are
  18846        // guaranteed to round-trip, using strtof and strtod, resp.
  18847        //
  18848        // NB: The test below works if <long double> == <double>.
  18849        static constexpr bool is_ieee_single_or_double
  18850            = (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) ||
  18851              (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);
  18852 
  18853        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
  18854    }
  18855 
  18856    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
  18857    {
  18858        auto* begin = number_buffer.data();
  18859        auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
  18860 
  18861        o->write_characters(begin, static_cast<size_t>(end - begin));
  18862    }
  18863 
  18864    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
  18865    {
  18866        // get number of digits for a float -> text -> float round-trip
  18867        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
  18868 
  18869        // the actual conversion
  18870        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
  18871        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
  18872 
  18873        // negative value indicates an error
  18874        JSON_ASSERT(len > 0);
  18875        // check if buffer was large enough
  18876        JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
  18877 
  18878        // erase thousands separator
  18879        if (thousands_sep != '\0')
  18880        {
  18881            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
  18882            const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
  18883            std::fill(end, number_buffer.end(), '\0');
  18884            JSON_ASSERT((end - number_buffer.begin()) <= len);
  18885            len = (end - number_buffer.begin());
  18886        }
  18887 
  18888        // convert decimal point to '.'
  18889        if (decimal_point != '\0' && decimal_point != '.')
  18890        {
  18891            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
  18892            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
  18893            if (dec_pos != number_buffer.end())
  18894            {
  18895                *dec_pos = '.';
  18896            }
  18897        }
  18898 
  18899        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
  18900 
  18901        // determine if we need to append ".0"
  18902        const bool value_is_int_like =
  18903            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
  18904                         [](char c)
  18905        {
  18906            return c == '.' || c == 'e';
  18907        });
  18908 
  18909        if (value_is_int_like)
  18910        {
  18911            o->write_characters(".0", 2);
  18912        }
  18913    }
  18914 
  18915    /*!
  18916    @brief check whether a string is UTF-8 encoded
  18917 
  18918    The function checks each byte of a string whether it is UTF-8 encoded. The
  18919    result of the check is stored in the @a state parameter. The function must
  18920    be called initially with state 0 (accept). State 1 means the string must
  18921    be rejected, because the current byte is not allowed. If the string is
  18922    completely processed, but the state is non-zero, the string ended
  18923    prematurely; that is, the last byte indicated more bytes should have
  18924    followed.
  18925 
  18926    @param[in,out] state  the state of the decoding
  18927    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
  18928    @param[in] byte       next byte to decode
  18929    @return               new state
  18930 
  18931    @note The function has been edited: a std::array is used.
  18932 
  18933    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
  18934    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
  18935    */
  18936    static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
  18937    {
  18938        static const std::array<std::uint8_t, 400> utf8d =
  18939        {
  18940            {
  18941                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
  18942                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
  18943                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
  18944                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
  18945                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
  18946                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
  18947                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
  18948                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
  18949                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
  18950                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
  18951                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
  18952                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
  18953                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
  18954                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
  18955            }
  18956        };
  18957 
  18958        JSON_ASSERT(byte < utf8d.size());
  18959        const std::uint8_t type = utf8d[byte];
  18960 
  18961        codep = (state != UTF8_ACCEPT)
  18962                ? (byte & 0x3fu) | (codep << 6u)
  18963                : (0xFFu >> type) & (byte);
  18964 
  18965        const std::size_t index = 256u + static_cast<size_t>(state) * 16u + static_cast<size_t>(type);
  18966        JSON_ASSERT(index < utf8d.size());
  18967        state = utf8d[index];
  18968        return state;
  18969    }
  18970 
  18971    /*
  18972     * Overload to make the compiler happy while it is instantiating
  18973     * dump_integer for number_unsigned_t.
  18974     * Must never be called.
  18975     */
  18976    number_unsigned_t remove_sign(number_unsigned_t x)
  18977    {
  18978        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  18979        return x; // LCOV_EXCL_LINE
  18980    }
  18981 
  18982    /*
  18983     * Helper function for dump_integer
  18984     *
  18985     * This function takes a negative signed integer and returns its absolute
  18986     * value as unsigned integer. The plus/minus shuffling is necessary as we can
  18987     * not directly remove the sign of an arbitrary signed integer as the
  18988     * absolute values of INT_MIN and INT_MAX are usually not the same. See
  18989     * #1708 for details.
  18990     */
  18991    inline number_unsigned_t remove_sign(number_integer_t x) noexcept
  18992    {
  18993        JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
  18994        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
  18995    }
  18996 
  18997  private:
  18998    /// the output of the serializer
  18999    output_adapter_t<char> o = nullptr;
  19000 
  19001    /// a (hopefully) large enough character buffer
  19002    std::array<char, 64> number_buffer{{}};
  19003 
  19004    /// the locale
  19005    const std::lconv* loc = nullptr;
  19006    /// the locale's thousand separator character
  19007    const char thousands_sep = '\0';
  19008    /// the locale's decimal point character
  19009    const char decimal_point = '\0';
  19010 
  19011    /// string buffer
  19012    std::array<char, 512> string_buffer{{}};
  19013 
  19014    /// the indentation character
  19015    const char indent_char;
  19016    /// the indentation string
  19017    string_t indent_string;
  19018 
  19019    /// error_handler how to react on decoding errors
  19020    const error_handler_t error_handler;
  19021 };
  19022 
  19023 }  // namespace detail
  19024 NLOHMANN_JSON_NAMESPACE_END
  19025 
  19026 // #include <nlohmann/detail/value_t.hpp>
  19027 
  19028 // #include <nlohmann/json_fwd.hpp>
  19029 
  19030 // #include <nlohmann/ordered_map.hpp>
  19031 //     __ _____ _____ _____
  19032 //  __|  |   __|     |   | |  JSON for Modern C++
  19033 // |  |  |__   |  |  | | | |  version 3.11.3
  19034 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  19035 //
  19036 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  19037 // SPDX-License-Identifier: MIT
  19038 
  19039 
  19040 
  19041 #include <functional> // equal_to, less
  19042 #include <initializer_list> // initializer_list
  19043 #include <iterator> // input_iterator_tag, iterator_traits
  19044 #include <memory> // allocator
  19045 #include <stdexcept> // for out_of_range
  19046 #include <type_traits> // enable_if, is_convertible
  19047 #include <utility> // pair
  19048 #include <vector> // vector
  19049 
  19050 // #include <nlohmann/detail/macro_scope.hpp>
  19051 
  19052 // #include <nlohmann/detail/meta/type_traits.hpp>
  19053 
  19054 
  19055 NLOHMANN_JSON_NAMESPACE_BEGIN
  19056 
  19057 /// ordered_map: a minimal map-like container that preserves insertion order
  19058 /// for use within nlohmann::basic_json<ordered_map>
  19059 template <class Key, class T, class IgnoredLess = std::less<Key>,
  19060          class Allocator = std::allocator<std::pair<const Key, T>>>
  19061                  struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
  19062 {
  19063    using key_type = Key;
  19064    using mapped_type = T;
  19065    using Container = std::vector<std::pair<const Key, T>, Allocator>;
  19066    using iterator = typename Container::iterator;
  19067    using const_iterator = typename Container::const_iterator;
  19068    using size_type = typename Container::size_type;
  19069    using value_type = typename Container::value_type;
  19070 #ifdef JSON_HAS_CPP_14
  19071    using key_compare = std::equal_to<>;
  19072 #else
  19073    using key_compare = std::equal_to<Key>;
  19074 #endif
  19075 
  19076    // Explicit constructors instead of `using Container::Container`
  19077    // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
  19078    ordered_map() noexcept(noexcept(Container())) : Container{} {}
  19079    explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
  19080    template <class It>
  19081    ordered_map(It first, It last, const Allocator& alloc = Allocator())
  19082        : Container{first, last, alloc} {}
  19083    ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
  19084        : Container{init, alloc} {}
  19085 
  19086    std::pair<iterator, bool> emplace(const key_type& key, T&& t)
  19087    {
  19088        for (auto it = this->begin(); it != this->end(); ++it)
  19089        {
  19090            if (m_compare(it->first, key))
  19091            {
  19092                return {it, false};
  19093            }
  19094        }
  19095        Container::emplace_back(key, std::forward<T>(t));
  19096        return {std::prev(this->end()), true};
  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    std::pair<iterator, bool> emplace(KeyType && key, T && t)
  19102    {
  19103        for (auto it = this->begin(); it != this->end(); ++it)
  19104        {
  19105            if (m_compare(it->first, key))
  19106            {
  19107                return {it, false};
  19108            }
  19109        }
  19110        Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
  19111        return {std::prev(this->end()), true};
  19112    }
  19113 
  19114    T& operator[](const key_type& key)
  19115    {
  19116        return emplace(key, T{}).first->second;
  19117    }
  19118 
  19119    template<class KeyType, detail::enable_if_t<
  19120                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19121    T & operator[](KeyType && key)
  19122    {
  19123        return emplace(std::forward<KeyType>(key), T{}).first->second;
  19124    }
  19125 
  19126    const T& operator[](const key_type& key) const
  19127    {
  19128        return at(key);
  19129    }
  19130 
  19131    template<class KeyType, detail::enable_if_t<
  19132                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19133    const T & operator[](KeyType && key) const
  19134    {
  19135        return at(std::forward<KeyType>(key));
  19136    }
  19137 
  19138    T& at(const key_type& key)
  19139    {
  19140        for (auto it = this->begin(); it != this->end(); ++it)
  19141        {
  19142            if (m_compare(it->first, key))
  19143            {
  19144                return it->second;
  19145            }
  19146        }
  19147 
  19148        JSON_THROW(std::out_of_range("key not found"));
  19149    }
  19150 
  19151    template<class KeyType, detail::enable_if_t<
  19152                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19153    T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
  19154    {
  19155        for (auto it = this->begin(); it != this->end(); ++it)
  19156        {
  19157            if (m_compare(it->first, key))
  19158            {
  19159                return it->second;
  19160            }
  19161        }
  19162 
  19163        JSON_THROW(std::out_of_range("key not found"));
  19164    }
  19165 
  19166    const T& at(const key_type& key) const
  19167    {
  19168        for (auto it = this->begin(); it != this->end(); ++it)
  19169        {
  19170            if (m_compare(it->first, key))
  19171            {
  19172                return it->second;
  19173            }
  19174        }
  19175 
  19176        JSON_THROW(std::out_of_range("key not found"));
  19177    }
  19178 
  19179    template<class KeyType, detail::enable_if_t<
  19180                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19181    const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
  19182    {
  19183        for (auto it = this->begin(); it != this->end(); ++it)
  19184        {
  19185            if (m_compare(it->first, key))
  19186            {
  19187                return it->second;
  19188            }
  19189        }
  19190 
  19191        JSON_THROW(std::out_of_range("key not found"));
  19192    }
  19193 
  19194    size_type erase(const key_type& key)
  19195    {
  19196        for (auto it = this->begin(); it != this->end(); ++it)
  19197        {
  19198            if (m_compare(it->first, key))
  19199            {
  19200                // Since we cannot move const Keys, re-construct them in place
  19201                for (auto next = it; ++next != this->end(); ++it)
  19202                {
  19203                    it->~value_type(); // Destroy but keep allocation
  19204                    new (&*it) value_type{std::move(*next)};
  19205                }
  19206                Container::pop_back();
  19207                return 1;
  19208            }
  19209        }
  19210        return 0;
  19211    }
  19212 
  19213    template<class KeyType, detail::enable_if_t<
  19214                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19215    size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
  19216    {
  19217        for (auto it = this->begin(); it != this->end(); ++it)
  19218        {
  19219            if (m_compare(it->first, key))
  19220            {
  19221                // Since we cannot move const Keys, re-construct them in place
  19222                for (auto next = it; ++next != this->end(); ++it)
  19223                {
  19224                    it->~value_type(); // Destroy but keep allocation
  19225                    new (&*it) value_type{std::move(*next)};
  19226                }
  19227                Container::pop_back();
  19228                return 1;
  19229            }
  19230        }
  19231        return 0;
  19232    }
  19233 
  19234    iterator erase(iterator pos)
  19235    {
  19236        return erase(pos, std::next(pos));
  19237    }
  19238 
  19239    iterator erase(iterator first, iterator last)
  19240    {
  19241        if (first == last)
  19242        {
  19243            return first;
  19244        }
  19245 
  19246        const auto elements_affected = std::distance(first, last);
  19247        const auto offset = std::distance(Container::begin(), first);
  19248 
  19249        // This is the start situation. We need to delete elements_affected
  19250        // elements (3 in this example: e, f, g), and need to return an
  19251        // iterator past the last deleted element (h in this example).
  19252        // Note that offset is the distance from the start of the vector
  19253        // to first. We will need this later.
  19254 
  19255        // [ a, b, c, d, e, f, g, h, i, j ]
  19256        //               ^        ^
  19257        //             first    last
  19258 
  19259        // Since we cannot move const Keys, we re-construct them in place.
  19260        // We start at first and re-construct (viz. copy) the elements from
  19261        // the back of the vector. Example for first iteration:
  19262 
  19263        //               ,--------.
  19264        //               v        |   destroy e and re-construct with h
  19265        // [ a, b, c, d, e, f, g, h, i, j ]
  19266        //               ^        ^
  19267        //               it       it + elements_affected
  19268 
  19269        for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
  19270        {
  19271            it->~value_type(); // destroy but keep allocation
  19272            new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
  19273        }
  19274 
  19275        // [ a, b, c, d, h, i, j, h, i, j ]
  19276        //               ^        ^
  19277        //             first    last
  19278 
  19279        // remove the unneeded elements at the end of the vector
  19280        Container::resize(this->size() - static_cast<size_type>(elements_affected));
  19281 
  19282        // [ a, b, c, d, h, i, j ]
  19283        //               ^        ^
  19284        //             first    last
  19285 
  19286        // first is now pointing past the last deleted element, but we cannot
  19287        // use this iterator, because it may have been invalidated by the
  19288        // resize call. Instead, we can return begin() + offset.
  19289        return Container::begin() + offset;
  19290    }
  19291 
  19292    size_type count(const key_type& key) const
  19293    {
  19294        for (auto it = this->begin(); it != this->end(); ++it)
  19295        {
  19296            if (m_compare(it->first, key))
  19297            {
  19298                return 1;
  19299            }
  19300        }
  19301        return 0;
  19302    }
  19303 
  19304    template<class KeyType, detail::enable_if_t<
  19305                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19306    size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
  19307    {
  19308        for (auto it = this->begin(); it != this->end(); ++it)
  19309        {
  19310            if (m_compare(it->first, key))
  19311            {
  19312                return 1;
  19313            }
  19314        }
  19315        return 0;
  19316    }
  19317 
  19318    iterator find(const key_type& key)
  19319    {
  19320        for (auto it = this->begin(); it != this->end(); ++it)
  19321        {
  19322            if (m_compare(it->first, key))
  19323            {
  19324                return it;
  19325            }
  19326        }
  19327        return Container::end();
  19328    }
  19329 
  19330    template<class KeyType, detail::enable_if_t<
  19331                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
  19332    iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
  19333    {
  19334        for (auto it = this->begin(); it != this->end(); ++it)
  19335        {
  19336            if (m_compare(it->first, key))
  19337            {
  19338                return it;
  19339            }
  19340        }
  19341        return Container::end();
  19342    }
  19343 
  19344    const_iterator find(const key_type& key) const
  19345    {
  19346        for (auto it = this->begin(); it != this->end(); ++it)
  19347        {
  19348            if (m_compare(it->first, key))
  19349            {
  19350                return it;
  19351            }
  19352        }
  19353        return Container::end();
  19354    }
  19355 
  19356    std::pair<iterator, bool> insert( value_type&& value )
  19357    {
  19358        return emplace(value.first, std::move(value.second));
  19359    }
  19360 
  19361    std::pair<iterator, bool> insert( const value_type& value )
  19362    {
  19363        for (auto it = this->begin(); it != this->end(); ++it)
  19364        {
  19365            if (m_compare(it->first, value.first))
  19366            {
  19367                return {it, false};
  19368            }
  19369        }
  19370        Container::push_back(value);
  19371        return {--this->end(), true};
  19372    }
  19373 
  19374    template<typename InputIt>
  19375    using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
  19376            std::input_iterator_tag>::value>::type;
  19377 
  19378    template<typename InputIt, typename = require_input_iter<InputIt>>
  19379    void insert(InputIt first, InputIt last)
  19380    {
  19381        for (auto it = first; it != last; ++it)
  19382        {
  19383            insert(*it);
  19384        }
  19385    }
  19386 
  19387 private:
  19388    JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
  19389 };
  19390 
  19391 NLOHMANN_JSON_NAMESPACE_END
  19392 
  19393 
  19394 #if defined(JSON_HAS_CPP_17)
  19395    #if JSON_HAS_STATIC_RTTI
  19396        #include <any>
  19397    #endif
  19398    #include <string_view>
  19399 #endif
  19400 
  19401 /*!
  19402 @brief namespace for Niels Lohmann
  19403 @see https://github.com/nlohmann
  19404 @since version 1.0.0
  19405 */
  19406 NLOHMANN_JSON_NAMESPACE_BEGIN
  19407 
  19408 /*!
  19409 @brief a class to store JSON values
  19410 
  19411 @internal
  19412 @invariant The member variables @a m_value and @a m_type have the following
  19413 relationship:
  19414 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
  19415 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
  19416 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
  19417 The invariants are checked by member function assert_invariant().
  19418 
  19419 @note ObjectType trick from https://stackoverflow.com/a/9860911
  19420 @endinternal
  19421 
  19422 @since version 1.0.0
  19423 
  19424 @nosubgrouping
  19425 */
  19426 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  19427 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
  19428    : public ::nlohmann::detail::json_base_class<CustomBaseClass>
  19429 {
  19430  private:
  19431    template<detail::value_t> friend struct detail::external_constructor;
  19432 
  19433    template<typename>
  19434    friend class ::nlohmann::json_pointer;
  19435    // can be restored when json_pointer backwards compatibility is removed
  19436    // friend ::nlohmann::json_pointer<StringType>;
  19437 
  19438    template<typename BasicJsonType, typename InputType>
  19439    friend class ::nlohmann::detail::parser;
  19440    friend ::nlohmann::detail::serializer<basic_json>;
  19441    template<typename BasicJsonType>
  19442    friend class ::nlohmann::detail::iter_impl;
  19443    template<typename BasicJsonType, typename CharType>
  19444    friend class ::nlohmann::detail::binary_writer;
  19445    template<typename BasicJsonType, typename InputType, typename SAX>
  19446    friend class ::nlohmann::detail::binary_reader;
  19447    template<typename BasicJsonType>
  19448    friend class ::nlohmann::detail::json_sax_dom_parser;
  19449    template<typename BasicJsonType>
  19450    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
  19451    friend class ::nlohmann::detail::exception;
  19452 
  19453    /// workaround type for MSVC
  19454    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
  19455    using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
  19456 
  19457  JSON_PRIVATE_UNLESS_TESTED:
  19458    // convenience aliases for types residing in namespace detail;
  19459    using lexer = ::nlohmann::detail::lexer_base<basic_json>;
  19460 
  19461    template<typename InputAdapterType>
  19462    static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
  19463        InputAdapterType adapter,
  19464        detail::parser_callback_t<basic_json>cb = nullptr,
  19465        const bool allow_exceptions = true,
  19466        const bool ignore_comments = false
  19467                                 )
  19468    {
  19469        return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
  19470                std::move(cb), allow_exceptions, ignore_comments);
  19471    }
  19472 
  19473  private:
  19474    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
  19475    template<typename BasicJsonType>
  19476    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
  19477    template<typename BasicJsonType>
  19478    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
  19479    template<typename Iterator>
  19480    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
  19481    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
  19482 
  19483    template<typename CharType>
  19484    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
  19485 
  19486    template<typename InputType>
  19487    using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
  19488    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
  19489 
  19490  JSON_PRIVATE_UNLESS_TESTED:
  19491    using serializer = ::nlohmann::detail::serializer<basic_json>;
  19492 
  19493  public:
  19494    using value_t = detail::value_t;
  19495    /// JSON Pointer, see @ref nlohmann::json_pointer
  19496    using json_pointer = ::nlohmann::json_pointer<StringType>;
  19497    template<typename T, typename SFINAE>
  19498    using json_serializer = JSONSerializer<T, SFINAE>;
  19499    /// how to treat decoding errors
  19500    using error_handler_t = detail::error_handler_t;
  19501    /// how to treat CBOR tags
  19502    using cbor_tag_handler_t = detail::cbor_tag_handler_t;
  19503    /// helper type for initializer lists of basic_json values
  19504    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
  19505 
  19506    using input_format_t = detail::input_format_t;
  19507    /// SAX interface type, see @ref nlohmann::json_sax
  19508    using json_sax_t = json_sax<basic_json>;
  19509 
  19510    ////////////////
  19511    // exceptions //
  19512    ////////////////
  19513 
  19514    /// @name exceptions
  19515    /// Classes to implement user-defined exceptions.
  19516    /// @{
  19517 
  19518    using exception = detail::exception;
  19519    using parse_error = detail::parse_error;
  19520    using invalid_iterator = detail::invalid_iterator;
  19521    using type_error = detail::type_error;
  19522    using out_of_range = detail::out_of_range;
  19523    using other_error = detail::other_error;
  19524 
  19525    /// @}
  19526 
  19527    /////////////////////
  19528    // container types //
  19529    /////////////////////
  19530 
  19531    /// @name container types
  19532    /// The canonic container types to use @ref basic_json like any other STL
  19533    /// container.
  19534    /// @{
  19535 
  19536    /// the type of elements in a basic_json container
  19537    using value_type = basic_json;
  19538 
  19539    /// the type of an element reference
  19540    using reference = value_type&;
  19541    /// the type of an element const reference
  19542    using const_reference = const value_type&;
  19543 
  19544    /// a type to represent differences between iterators
  19545    using difference_type = std::ptrdiff_t;
  19546    /// a type to represent container sizes
  19547    using size_type = std::size_t;
  19548 
  19549    /// the allocator type
  19550    using allocator_type = AllocatorType<basic_json>;
  19551 
  19552    /// the type of an element pointer
  19553    using pointer = typename std::allocator_traits<allocator_type>::pointer;
  19554    /// the type of an element const pointer
  19555    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
  19556 
  19557    /// an iterator for a basic_json container
  19558    using iterator = iter_impl<basic_json>;
  19559    /// a const iterator for a basic_json container
  19560    using const_iterator = iter_impl<const basic_json>;
  19561    /// a reverse iterator for a basic_json container
  19562    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
  19563    /// a const reverse iterator for a basic_json container
  19564    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
  19565 
  19566    /// @}
  19567 
  19568    /// @brief returns the allocator associated with the container
  19569    /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
  19570    static allocator_type get_allocator()
  19571    {
  19572        return allocator_type();
  19573    }
  19574 
  19575    /// @brief returns version information on the library
  19576    /// @sa https://json.nlohmann.me/api/basic_json/meta/
  19577    JSON_HEDLEY_WARN_UNUSED_RESULT
  19578    static basic_json meta()
  19579    {
  19580        basic_json result;
  19581 
  19582        result["copyright"] = "(C) 2013-2023 Niels Lohmann";
  19583        result["name"] = "JSON for Modern C++";
  19584        result["url"] = "https://github.com/nlohmann/json";
  19585        result["version"]["string"] =
  19586            detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
  19587                           std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
  19588                           std::to_string(NLOHMANN_JSON_VERSION_PATCH));
  19589        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
  19590        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
  19591        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
  19592 
  19593 #ifdef _WIN32
  19594        result["platform"] = "win32";
  19595 #elif defined __linux__
  19596        result["platform"] = "linux";
  19597 #elif defined __APPLE__
  19598        result["platform"] = "apple";
  19599 #elif defined __unix__
  19600        result["platform"] = "unix";
  19601 #else
  19602        result["platform"] = "unknown";
  19603 #endif
  19604 
  19605 #if defined(__ICC) || defined(__INTEL_COMPILER)
  19606        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
  19607 #elif defined(__clang__)
  19608        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
  19609 #elif defined(__GNUC__) || defined(__GNUG__)
  19610        result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
  19611                    std::to_string(__GNUC__), '.',
  19612                    std::to_string(__GNUC_MINOR__), '.',
  19613                    std::to_string(__GNUC_PATCHLEVEL__))
  19614            }
  19615        };
  19616 #elif defined(__HP_cc) || defined(__HP_aCC)
  19617        result["compiler"] = "hp"
  19618 #elif defined(__IBMCPP__)
  19619        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
  19620 #elif defined(_MSC_VER)
  19621        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
  19622 #elif defined(__PGI)
  19623        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
  19624 #elif defined(__SUNPRO_CC)
  19625        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
  19626 #else
  19627        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
  19628 #endif
  19629 
  19630 #if defined(_MSVC_LANG)
  19631        result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
  19632 #elif defined(__cplusplus)
  19633        result["compiler"]["c++"] = std::to_string(__cplusplus);
  19634 #else
  19635        result["compiler"]["c++"] = "unknown";
  19636 #endif
  19637        return result;
  19638    }
  19639 
  19640    ///////////////////////////
  19641    // JSON value data types //
  19642    ///////////////////////////
  19643 
  19644    /// @name JSON value data types
  19645    /// The data types to store a JSON value. These types are derived from
  19646    /// the template arguments passed to class @ref basic_json.
  19647    /// @{
  19648 
  19649    /// @brief default object key comparator type
  19650    /// The actual object key comparator type (@ref object_comparator_t) may be
  19651    /// different.
  19652    /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
  19653 #if defined(JSON_HAS_CPP_14)
  19654    // use of transparent comparator avoids unnecessary repeated construction of temporaries
  19655    // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
  19656    using default_object_comparator_t = std::less<>;
  19657 #else
  19658    using default_object_comparator_t = std::less<StringType>;
  19659 #endif
  19660 
  19661    /// @brief a type for an object
  19662    /// @sa https://json.nlohmann.me/api/basic_json/object_t/
  19663    using object_t = ObjectType<StringType,
  19664          basic_json,
  19665          default_object_comparator_t,
  19666          AllocatorType<std::pair<const StringType,
  19667          basic_json>>>;
  19668 
  19669    /// @brief a type for an array
  19670    /// @sa https://json.nlohmann.me/api/basic_json/array_t/
  19671    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
  19672 
  19673    /// @brief a type for a string
  19674    /// @sa https://json.nlohmann.me/api/basic_json/string_t/
  19675    using string_t = StringType;
  19676 
  19677    /// @brief a type for a boolean
  19678    /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
  19679    using boolean_t = BooleanType;
  19680 
  19681    /// @brief a type for a number (integer)
  19682    /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
  19683    using number_integer_t = NumberIntegerType;
  19684 
  19685    /// @brief a type for a number (unsigned)
  19686    /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
  19687    using number_unsigned_t = NumberUnsignedType;
  19688 
  19689    /// @brief a type for a number (floating-point)
  19690    /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
  19691    using number_float_t = NumberFloatType;
  19692 
  19693    /// @brief a type for a packed binary type
  19694    /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
  19695    using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
  19696 
  19697    /// @brief object key comparator type
  19698    /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
  19699    using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
  19700 
  19701    /// @}
  19702 
  19703  private:
  19704 
  19705    /// helper for exception-safe object creation
  19706    template<typename T, typename... Args>
  19707    JSON_HEDLEY_RETURNS_NON_NULL
  19708    static T* create(Args&& ... args)
  19709    {
  19710        AllocatorType<T> alloc;
  19711        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
  19712 
  19713        auto deleter = [&](T * obj)
  19714        {
  19715            AllocatorTraits::deallocate(alloc, obj, 1);
  19716        };
  19717        std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
  19718        AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
  19719        JSON_ASSERT(obj != nullptr);
  19720        return obj.release();
  19721    }
  19722 
  19723    ////////////////////////
  19724    // JSON value storage //
  19725    ////////////////////////
  19726 
  19727  JSON_PRIVATE_UNLESS_TESTED:
  19728    /*!
  19729    @brief a JSON value
  19730 
  19731    The actual storage for a JSON value of the @ref basic_json class. This
  19732    union combines the different storage types for the JSON value types
  19733    defined in @ref value_t.
  19734 
  19735    JSON type | value_t type    | used type
  19736    --------- | --------------- | ------------------------
  19737    object    | object          | pointer to @ref object_t
  19738    array     | array           | pointer to @ref array_t
  19739    string    | string          | pointer to @ref string_t
  19740    boolean   | boolean         | @ref boolean_t
  19741    number    | number_integer  | @ref number_integer_t
  19742    number    | number_unsigned | @ref number_unsigned_t
  19743    number    | number_float    | @ref number_float_t
  19744    binary    | binary          | pointer to @ref binary_t
  19745    null      | null            | *no value is stored*
  19746 
  19747    @note Variable-length types (objects, arrays, and strings) are stored as
  19748    pointers. The size of the union should not exceed 64 bits if the default
  19749    value types are used.
  19750 
  19751    @since version 1.0.0
  19752    */
  19753    union json_value
  19754    {
  19755        /// object (stored with pointer to save storage)
  19756        object_t* object;
  19757        /// array (stored with pointer to save storage)
  19758        array_t* array;
  19759        /// string (stored with pointer to save storage)
  19760        string_t* string;
  19761        /// binary (stored with pointer to save storage)
  19762        binary_t* binary;
  19763        /// boolean
  19764        boolean_t boolean;
  19765        /// number (integer)
  19766        number_integer_t number_integer;
  19767        /// number (unsigned integer)
  19768        number_unsigned_t number_unsigned;
  19769        /// number (floating-point)
  19770        number_float_t number_float;
  19771 
  19772        /// default constructor (for null values)
  19773        json_value() = default;
  19774        /// constructor for booleans
  19775        json_value(boolean_t v) noexcept : boolean(v) {}
  19776        /// constructor for numbers (integer)
  19777        json_value(number_integer_t v) noexcept : number_integer(v) {}
  19778        /// constructor for numbers (unsigned)
  19779        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
  19780        /// constructor for numbers (floating-point)
  19781        json_value(number_float_t v) noexcept : number_float(v) {}
  19782        /// constructor for empty values of a given type
  19783        json_value(value_t t)
  19784        {
  19785            switch (t)
  19786            {
  19787                case value_t::object:
  19788                {
  19789                    object = create<object_t>();
  19790                    break;
  19791                }
  19792 
  19793                case value_t::array:
  19794                {
  19795                    array = create<array_t>();
  19796                    break;
  19797                }
  19798 
  19799                case value_t::string:
  19800                {
  19801                    string = create<string_t>("");
  19802                    break;
  19803                }
  19804 
  19805                case value_t::binary:
  19806                {
  19807                    binary = create<binary_t>();
  19808                    break;
  19809                }
  19810 
  19811                case value_t::boolean:
  19812                {
  19813                    boolean = static_cast<boolean_t>(false);
  19814                    break;
  19815                }
  19816 
  19817                case value_t::number_integer:
  19818                {
  19819                    number_integer = static_cast<number_integer_t>(0);
  19820                    break;
  19821                }
  19822 
  19823                case value_t::number_unsigned:
  19824                {
  19825                    number_unsigned = static_cast<number_unsigned_t>(0);
  19826                    break;
  19827                }
  19828 
  19829                case value_t::number_float:
  19830                {
  19831                    number_float = static_cast<number_float_t>(0.0);
  19832                    break;
  19833                }
  19834 
  19835                case value_t::null:
  19836                {
  19837                    object = nullptr;  // silence warning, see #821
  19838                    break;
  19839                }
  19840 
  19841                case value_t::discarded:
  19842                default:
  19843                {
  19844                    object = nullptr;  // silence warning, see #821
  19845                    if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
  19846                    {
  19847                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
  19848                    }
  19849                    break;
  19850                }
  19851            }
  19852        }
  19853 
  19854        /// constructor for strings
  19855        json_value(const string_t& value) : string(create<string_t>(value)) {}
  19856 
  19857        /// constructor for rvalue strings
  19858        json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
  19859 
  19860        /// constructor for objects
  19861        json_value(const object_t& value) : object(create<object_t>(value)) {}
  19862 
  19863        /// constructor for rvalue objects
  19864        json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
  19865 
  19866        /// constructor for arrays
  19867        json_value(const array_t& value) : array(create<array_t>(value)) {}
  19868 
  19869        /// constructor for rvalue arrays
  19870        json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
  19871 
  19872        /// constructor for binary arrays
  19873        json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
  19874 
  19875        /// constructor for rvalue binary arrays
  19876        json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
  19877 
  19878        /// constructor for binary arrays (internal type)
  19879        json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
  19880 
  19881        /// constructor for rvalue binary arrays (internal type)
  19882        json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
  19883 
  19884        void destroy(value_t t)
  19885        {
  19886            if (
  19887                (t == value_t::object && object == nullptr) ||
  19888                (t == value_t::array && array == nullptr) ||
  19889                (t == value_t::string && string == nullptr) ||
  19890                (t == value_t::binary && binary == nullptr)
  19891            )
  19892            {
  19893                //not initialized (e.g. due to exception in the ctor)
  19894                return;
  19895            }
  19896            if (t == value_t::array || t == value_t::object)
  19897            {
  19898                // flatten the current json_value to a heap-allocated stack
  19899                std::vector<basic_json> stack;
  19900 
  19901                // move the top-level items to stack
  19902                if (t == value_t::array)
  19903                {
  19904                    stack.reserve(array->size());
  19905                    std::move(array->begin(), array->end(), std::back_inserter(stack));
  19906                }
  19907                else
  19908                {
  19909                    stack.reserve(object->size());
  19910                    for (auto&& it : *object)
  19911                    {
  19912                        stack.push_back(std::move(it.second));
  19913                    }
  19914                }
  19915 
  19916                while (!stack.empty())
  19917                {
  19918                    // move the last item to local variable to be processed
  19919                    basic_json current_item(std::move(stack.back()));
  19920                    stack.pop_back();
  19921 
  19922                    // if current_item is array/object, move
  19923                    // its children to the stack to be processed later
  19924                    if (current_item.is_array())
  19925                    {
  19926                        std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
  19927 
  19928                        current_item.m_data.m_value.array->clear();
  19929                    }
  19930                    else if (current_item.is_object())
  19931                    {
  19932                        for (auto&& it : *current_item.m_data.m_value.object)
  19933                        {
  19934                            stack.push_back(std::move(it.second));
  19935                        }
  19936 
  19937                        current_item.m_data.m_value.object->clear();
  19938                    }
  19939 
  19940                    // it's now safe that current_item get destructed
  19941                    // since it doesn't have any children
  19942                }
  19943            }
  19944 
  19945            switch (t)
  19946            {
  19947                case value_t::object:
  19948                {
  19949                    AllocatorType<object_t> alloc;
  19950                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
  19951                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
  19952                    break;
  19953                }
  19954 
  19955                case value_t::array:
  19956                {
  19957                    AllocatorType<array_t> alloc;
  19958                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
  19959                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
  19960                    break;
  19961                }
  19962 
  19963                case value_t::string:
  19964                {
  19965                    AllocatorType<string_t> alloc;
  19966                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
  19967                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
  19968                    break;
  19969                }
  19970 
  19971                case value_t::binary:
  19972                {
  19973                    AllocatorType<binary_t> alloc;
  19974                    std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
  19975                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
  19976                    break;
  19977                }
  19978 
  19979                case value_t::null:
  19980                case value_t::boolean:
  19981                case value_t::number_integer:
  19982                case value_t::number_unsigned:
  19983                case value_t::number_float:
  19984                case value_t::discarded:
  19985                default:
  19986                {
  19987                    break;
  19988                }
  19989            }
  19990        }
  19991    };
  19992 
  19993  private:
  19994    /*!
  19995    @brief checks the class invariants
  19996 
  19997    This function asserts the class invariants. It needs to be called at the
  19998    end of every constructor to make sure that created objects respect the
  19999    invariant. Furthermore, it has to be called each time the type of a JSON
  20000    value is changed, because the invariant expresses a relationship between
  20001    @a m_type and @a m_value.
  20002 
  20003    Furthermore, the parent relation is checked for arrays and objects: If
  20004    @a check_parents true and the value is an array or object, then the
  20005    container's elements must have the current value as parent.
  20006 
  20007    @param[in] check_parents  whether the parent relation should be checked.
  20008               The value is true by default and should only be set to false
  20009               during destruction of objects when the invariant does not
  20010               need to hold.
  20011    */
  20012    void assert_invariant(bool check_parents = true) const noexcept
  20013    {
  20014        JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
  20015        JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
  20016        JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
  20017        JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
  20018 
  20019 #if JSON_DIAGNOSTICS
  20020        JSON_TRY
  20021        {
  20022            // cppcheck-suppress assertWithSideEffect
  20023            JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
  20024            {
  20025                return j.m_parent == this;
  20026            }));
  20027        }
  20028        JSON_CATCH(...) {} // LCOV_EXCL_LINE
  20029 #endif
  20030        static_cast<void>(check_parents);
  20031    }
  20032 
  20033    void set_parents()
  20034    {
  20035 #if JSON_DIAGNOSTICS
  20036        switch (m_data.m_type)
  20037        {
  20038            case value_t::array:
  20039            {
  20040                for (auto& element : *m_data.m_value.array)
  20041                {
  20042                    element.m_parent = this;
  20043                }
  20044                break;
  20045            }
  20046 
  20047            case value_t::object:
  20048            {
  20049                for (auto& element : *m_data.m_value.object)
  20050                {
  20051                    element.second.m_parent = this;
  20052                }
  20053                break;
  20054            }
  20055 
  20056            case value_t::null:
  20057            case value_t::string:
  20058            case value_t::boolean:
  20059            case value_t::number_integer:
  20060            case value_t::number_unsigned:
  20061            case value_t::number_float:
  20062            case value_t::binary:
  20063            case value_t::discarded:
  20064            default:
  20065                break;
  20066        }
  20067 #endif
  20068    }
  20069 
  20070    iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
  20071    {
  20072 #if JSON_DIAGNOSTICS
  20073        for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
  20074        {
  20075            (it + i)->m_parent = this;
  20076        }
  20077 #else
  20078        static_cast<void>(count_set_parents);
  20079 #endif
  20080        return it;
  20081    }
  20082 
  20083    reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
  20084    {
  20085 #if JSON_DIAGNOSTICS
  20086        if (old_capacity != static_cast<std::size_t>(-1))
  20087        {
  20088            // see https://github.com/nlohmann/json/issues/2838
  20089            JSON_ASSERT(type() == value_t::array);
  20090            if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
  20091            {
  20092                // capacity has changed: update all parents
  20093                set_parents();
  20094                return j;
  20095            }
  20096        }
  20097 
  20098        // ordered_json uses a vector internally, so pointers could have
  20099        // been invalidated; see https://github.com/nlohmann/json/issues/2962
  20100 #ifdef JSON_HEDLEY_MSVC_VERSION
  20101 #pragma warning(push )
  20102 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
  20103 #endif
  20104        if (detail::is_ordered_map<object_t>::value)
  20105        {
  20106            set_parents();
  20107            return j;
  20108        }
  20109 #ifdef JSON_HEDLEY_MSVC_VERSION
  20110 #pragma warning( pop )
  20111 #endif
  20112 
  20113        j.m_parent = this;
  20114 #else
  20115        static_cast<void>(j);
  20116        static_cast<void>(old_capacity);
  20117 #endif
  20118        return j;
  20119    }
  20120 
  20121  public:
  20122    //////////////////////////
  20123    // JSON parser callback //
  20124    //////////////////////////
  20125 
  20126    /// @brief parser event types
  20127    /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
  20128    using parse_event_t = detail::parse_event_t;
  20129 
  20130    /// @brief per-element parser callback type
  20131    /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
  20132    using parser_callback_t = detail::parser_callback_t<basic_json>;
  20133 
  20134    //////////////////
  20135    // constructors //
  20136    //////////////////
  20137 
  20138    /// @name constructors and destructors
  20139    /// Constructors of class @ref basic_json, copy/move constructor, copy
  20140    /// assignment, static functions creating objects, and the destructor.
  20141    /// @{
  20142 
  20143    /// @brief create an empty value with a given type
  20144    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20145    basic_json(const value_t v)
  20146        : m_data(v)
  20147    {
  20148        assert_invariant();
  20149    }
  20150 
  20151    /// @brief create a null object
  20152    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20153    basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
  20154        : basic_json(value_t::null)
  20155    {
  20156        assert_invariant();
  20157    }
  20158 
  20159    /// @brief create a JSON value from compatible types
  20160    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20161    template < typename CompatibleType,
  20162               typename U = detail::uncvref_t<CompatibleType>,
  20163               detail::enable_if_t <
  20164                   !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
  20165    basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
  20166                JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
  20167                                           std::forward<CompatibleType>(val))))
  20168    {
  20169        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
  20170        set_parents();
  20171        assert_invariant();
  20172    }
  20173 
  20174    /// @brief create a JSON value from an existing one
  20175    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20176    template < typename BasicJsonType,
  20177               detail::enable_if_t <
  20178                   detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
  20179    basic_json(const BasicJsonType& val)
  20180    {
  20181        using other_boolean_t = typename BasicJsonType::boolean_t;
  20182        using other_number_float_t = typename BasicJsonType::number_float_t;
  20183        using other_number_integer_t = typename BasicJsonType::number_integer_t;
  20184        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
  20185        using other_string_t = typename BasicJsonType::string_t;
  20186        using other_object_t = typename BasicJsonType::object_t;
  20187        using other_array_t = typename BasicJsonType::array_t;
  20188        using other_binary_t = typename BasicJsonType::binary_t;
  20189 
  20190        switch (val.type())
  20191        {
  20192            case value_t::boolean:
  20193                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
  20194                break;
  20195            case value_t::number_float:
  20196                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
  20197                break;
  20198            case value_t::number_integer:
  20199                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
  20200                break;
  20201            case value_t::number_unsigned:
  20202                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
  20203                break;
  20204            case value_t::string:
  20205                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
  20206                break;
  20207            case value_t::object:
  20208                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
  20209                break;
  20210            case value_t::array:
  20211                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
  20212                break;
  20213            case value_t::binary:
  20214                JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
  20215                break;
  20216            case value_t::null:
  20217                *this = nullptr;
  20218                break;
  20219            case value_t::discarded:
  20220                m_data.m_type = value_t::discarded;
  20221                break;
  20222            default:            // LCOV_EXCL_LINE
  20223                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  20224        }
  20225        JSON_ASSERT(m_data.m_type == val.type());
  20226        set_parents();
  20227        assert_invariant();
  20228    }
  20229 
  20230    /// @brief create a container (array or object) from an initializer list
  20231    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20232    basic_json(initializer_list_t init,
  20233               bool type_deduction = true,
  20234               value_t manual_type = value_t::array)
  20235    {
  20236        // check if each element is an array with two elements whose first
  20237        // element is a string
  20238        bool is_an_object = std::all_of(init.begin(), init.end(),
  20239                                        [](const detail::json_ref<basic_json>& element_ref)
  20240        {
  20241            // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
  20242            // (many string types can be constructed from 0 via its null-pointer guise, so we get a
  20243            // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
  20244            return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
  20245        });
  20246 
  20247        // adjust type if type deduction is not wanted
  20248        if (!type_deduction)
  20249        {
  20250            // if array is wanted, do not create an object though possible
  20251            if (manual_type == value_t::array)
  20252            {
  20253                is_an_object = false;
  20254            }
  20255 
  20256            // if object is wanted but impossible, throw an exception
  20257            if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
  20258            {
  20259                JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
  20260            }
  20261        }
  20262 
  20263        if (is_an_object)
  20264        {
  20265            // the initializer list is a list of pairs -> create object
  20266            m_data.m_type = value_t::object;
  20267            m_data.m_value = value_t::object;
  20268 
  20269            for (auto& element_ref : init)
  20270            {
  20271                auto element = element_ref.moved_or_copied();
  20272                m_data.m_value.object->emplace(
  20273                    std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
  20274                    std::move((*element.m_data.m_value.array)[1]));
  20275            }
  20276        }
  20277        else
  20278        {
  20279            // the initializer list describes an array -> create array
  20280            m_data.m_type = value_t::array;
  20281            m_data.m_value.array = create<array_t>(init.begin(), init.end());
  20282        }
  20283 
  20284        set_parents();
  20285        assert_invariant();
  20286    }
  20287 
  20288    /// @brief explicitly create a binary array (without subtype)
  20289    /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20290    JSON_HEDLEY_WARN_UNUSED_RESULT
  20291    static basic_json binary(const typename binary_t::container_type& init)
  20292    {
  20293        auto res = basic_json();
  20294        res.m_data.m_type = value_t::binary;
  20295        res.m_data.m_value = init;
  20296        return res;
  20297    }
  20298 
  20299    /// @brief explicitly create a binary array (with subtype)
  20300    /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20301    JSON_HEDLEY_WARN_UNUSED_RESULT
  20302    static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
  20303    {
  20304        auto res = basic_json();
  20305        res.m_data.m_type = value_t::binary;
  20306        res.m_data.m_value = binary_t(init, subtype);
  20307        return res;
  20308    }
  20309 
  20310    /// @brief explicitly create a binary array
  20311    /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20312    JSON_HEDLEY_WARN_UNUSED_RESULT
  20313    static basic_json binary(typename binary_t::container_type&& init)
  20314    {
  20315        auto res = basic_json();
  20316        res.m_data.m_type = value_t::binary;
  20317        res.m_data.m_value = std::move(init);
  20318        return res;
  20319    }
  20320 
  20321    /// @brief explicitly create a binary array (with subtype)
  20322    /// @sa https://json.nlohmann.me/api/basic_json/binary/
  20323    JSON_HEDLEY_WARN_UNUSED_RESULT
  20324    static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
  20325    {
  20326        auto res = basic_json();
  20327        res.m_data.m_type = value_t::binary;
  20328        res.m_data.m_value = binary_t(std::move(init), subtype);
  20329        return res;
  20330    }
  20331 
  20332    /// @brief explicitly create an array from an initializer list
  20333    /// @sa https://json.nlohmann.me/api/basic_json/array/
  20334    JSON_HEDLEY_WARN_UNUSED_RESULT
  20335    static basic_json array(initializer_list_t init = {})
  20336    {
  20337        return basic_json(init, false, value_t::array);
  20338    }
  20339 
  20340    /// @brief explicitly create an object from an initializer list
  20341    /// @sa https://json.nlohmann.me/api/basic_json/object/
  20342    JSON_HEDLEY_WARN_UNUSED_RESULT
  20343    static basic_json object(initializer_list_t init = {})
  20344    {
  20345        return basic_json(init, false, value_t::object);
  20346    }
  20347 
  20348    /// @brief construct an array with count copies of given value
  20349    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20350    basic_json(size_type cnt, const basic_json& val):
  20351        m_data{cnt, val}
  20352    {
  20353        set_parents();
  20354        assert_invariant();
  20355    }
  20356 
  20357    /// @brief construct a JSON container given an iterator range
  20358    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20359    template < class InputIT, typename std::enable_if <
  20360                   std::is_same<InputIT, typename basic_json_t::iterator>::value ||
  20361                   std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
  20362    basic_json(InputIT first, InputIT last)
  20363    {
  20364        JSON_ASSERT(first.m_object != nullptr);
  20365        JSON_ASSERT(last.m_object != nullptr);
  20366 
  20367        // make sure iterator fits the current value
  20368        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  20369        {
  20370            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
  20371        }
  20372 
  20373        // copy type from first iterator
  20374        m_data.m_type = first.m_object->m_data.m_type;
  20375 
  20376        // check if iterator range is complete for primitive values
  20377        switch (m_data.m_type)
  20378        {
  20379            case value_t::boolean:
  20380            case value_t::number_float:
  20381            case value_t::number_integer:
  20382            case value_t::number_unsigned:
  20383            case value_t::string:
  20384            {
  20385                if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
  20386                                         || !last.m_it.primitive_iterator.is_end()))
  20387                {
  20388                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
  20389                }
  20390                break;
  20391            }
  20392 
  20393            case value_t::null:
  20394            case value_t::object:
  20395            case value_t::array:
  20396            case value_t::binary:
  20397            case value_t::discarded:
  20398            default:
  20399                break;
  20400        }
  20401 
  20402        switch (m_data.m_type)
  20403        {
  20404            case value_t::number_integer:
  20405            {
  20406                m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
  20407                break;
  20408            }
  20409 
  20410            case value_t::number_unsigned:
  20411            {
  20412                m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
  20413                break;
  20414            }
  20415 
  20416            case value_t::number_float:
  20417            {
  20418                m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
  20419                break;
  20420            }
  20421 
  20422            case value_t::boolean:
  20423            {
  20424                m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
  20425                break;
  20426            }
  20427 
  20428            case value_t::string:
  20429            {
  20430                m_data.m_value = *first.m_object->m_data.m_value.string;
  20431                break;
  20432            }
  20433 
  20434            case value_t::object:
  20435            {
  20436                m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
  20437                                        last.m_it.object_iterator);
  20438                break;
  20439            }
  20440 
  20441            case value_t::array:
  20442            {
  20443                m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
  20444                                                       last.m_it.array_iterator);
  20445                break;
  20446            }
  20447 
  20448            case value_t::binary:
  20449            {
  20450                m_data.m_value = *first.m_object->m_data.m_value.binary;
  20451                break;
  20452            }
  20453 
  20454            case value_t::null:
  20455            case value_t::discarded:
  20456            default:
  20457                JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
  20458        }
  20459 
  20460        set_parents();
  20461        assert_invariant();
  20462    }
  20463 
  20464    ///////////////////////////////////////
  20465    // other constructors and destructor //
  20466    ///////////////////////////////////////
  20467 
  20468    template<typename JsonRef,
  20469             detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
  20470                                 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
  20471    basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
  20472 
  20473    /// @brief copy constructor
  20474    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20475    basic_json(const basic_json& other)
  20476        : json_base_class_t(other)
  20477    {
  20478        m_data.m_type = other.m_data.m_type;
  20479        // check of passed value is valid
  20480        other.assert_invariant();
  20481 
  20482        switch (m_data.m_type)
  20483        {
  20484            case value_t::object:
  20485            {
  20486                m_data.m_value = *other.m_data.m_value.object;
  20487                break;
  20488            }
  20489 
  20490            case value_t::array:
  20491            {
  20492                m_data.m_value = *other.m_data.m_value.array;
  20493                break;
  20494            }
  20495 
  20496            case value_t::string:
  20497            {
  20498                m_data.m_value = *other.m_data.m_value.string;
  20499                break;
  20500            }
  20501 
  20502            case value_t::boolean:
  20503            {
  20504                m_data.m_value = other.m_data.m_value.boolean;
  20505                break;
  20506            }
  20507 
  20508            case value_t::number_integer:
  20509            {
  20510                m_data.m_value = other.m_data.m_value.number_integer;
  20511                break;
  20512            }
  20513 
  20514            case value_t::number_unsigned:
  20515            {
  20516                m_data.m_value = other.m_data.m_value.number_unsigned;
  20517                break;
  20518            }
  20519 
  20520            case value_t::number_float:
  20521            {
  20522                m_data.m_value = other.m_data.m_value.number_float;
  20523                break;
  20524            }
  20525 
  20526            case value_t::binary:
  20527            {
  20528                m_data.m_value = *other.m_data.m_value.binary;
  20529                break;
  20530            }
  20531 
  20532            case value_t::null:
  20533            case value_t::discarded:
  20534            default:
  20535                break;
  20536        }
  20537 
  20538        set_parents();
  20539        assert_invariant();
  20540    }
  20541 
  20542    /// @brief move constructor
  20543    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
  20544    basic_json(basic_json&& other) noexcept
  20545        : json_base_class_t(std::forward<json_base_class_t>(other)),
  20546          m_data(std::move(other.m_data))
  20547    {
  20548        // check that passed value is valid
  20549        other.assert_invariant(false);
  20550 
  20551        // invalidate payload
  20552        other.m_data.m_type = value_t::null;
  20553        other.m_data.m_value = {};
  20554 
  20555        set_parents();
  20556        assert_invariant();
  20557    }
  20558 
  20559    /// @brief copy assignment
  20560    /// @sa https://json.nlohmann.me/api/basic_json/operator=/
  20561    basic_json& operator=(basic_json other) noexcept (
  20562        std::is_nothrow_move_constructible<value_t>::value&&
  20563        std::is_nothrow_move_assignable<value_t>::value&&
  20564        std::is_nothrow_move_constructible<json_value>::value&&
  20565        std::is_nothrow_move_assignable<json_value>::value&&
  20566        std::is_nothrow_move_assignable<json_base_class_t>::value
  20567    )
  20568    {
  20569        // check that passed value is valid
  20570        other.assert_invariant();
  20571 
  20572        using std::swap;
  20573        swap(m_data.m_type, other.m_data.m_type);
  20574        swap(m_data.m_value, other.m_data.m_value);
  20575        json_base_class_t::operator=(std::move(other));
  20576 
  20577        set_parents();
  20578        assert_invariant();
  20579        return *this;
  20580    }
  20581 
  20582    /// @brief destructor
  20583    /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
  20584    ~basic_json() noexcept
  20585    {
  20586        assert_invariant(false);
  20587    }
  20588 
  20589    /// @}
  20590 
  20591  public:
  20592    ///////////////////////
  20593    // object inspection //
  20594    ///////////////////////
  20595 
  20596    /// @name object inspection
  20597    /// Functions to inspect the type of a JSON value.
  20598    /// @{
  20599 
  20600    /// @brief serialization
  20601    /// @sa https://json.nlohmann.me/api/basic_json/dump/
  20602    string_t dump(const int indent = -1,
  20603                  const char indent_char = ' ',
  20604                  const bool ensure_ascii = false,
  20605                  const error_handler_t error_handler = error_handler_t::strict) const
  20606    {
  20607        string_t result;
  20608        serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
  20609 
  20610        if (indent >= 0)
  20611        {
  20612            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
  20613        }
  20614        else
  20615        {
  20616            s.dump(*this, false, ensure_ascii, 0);
  20617        }
  20618 
  20619        return result;
  20620    }
  20621 
  20622    /// @brief return the type of the JSON value (explicit)
  20623    /// @sa https://json.nlohmann.me/api/basic_json/type/
  20624    constexpr value_t type() const noexcept
  20625    {
  20626        return m_data.m_type;
  20627    }
  20628 
  20629    /// @brief return whether type is primitive
  20630    /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
  20631    constexpr bool is_primitive() const noexcept
  20632    {
  20633        return is_null() || is_string() || is_boolean() || is_number() || is_binary();
  20634    }
  20635 
  20636    /// @brief return whether type is structured
  20637    /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
  20638    constexpr bool is_structured() const noexcept
  20639    {
  20640        return is_array() || is_object();
  20641    }
  20642 
  20643    /// @brief return whether value is null
  20644    /// @sa https://json.nlohmann.me/api/basic_json/is_null/
  20645    constexpr bool is_null() const noexcept
  20646    {
  20647        return m_data.m_type == value_t::null;
  20648    }
  20649 
  20650    /// @brief return whether value is a boolean
  20651    /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
  20652    constexpr bool is_boolean() const noexcept
  20653    {
  20654        return m_data.m_type == value_t::boolean;
  20655    }
  20656 
  20657    /// @brief return whether value is a number
  20658    /// @sa https://json.nlohmann.me/api/basic_json/is_number/
  20659    constexpr bool is_number() const noexcept
  20660    {
  20661        return is_number_integer() || is_number_float();
  20662    }
  20663 
  20664    /// @brief return whether value is an integer number
  20665    /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
  20666    constexpr bool is_number_integer() const noexcept
  20667    {
  20668        return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
  20669    }
  20670 
  20671    /// @brief return whether value is an unsigned integer number
  20672    /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
  20673    constexpr bool is_number_unsigned() const noexcept
  20674    {
  20675        return m_data.m_type == value_t::number_unsigned;
  20676    }
  20677 
  20678    /// @brief return whether value is a floating-point number
  20679    /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
  20680    constexpr bool is_number_float() const noexcept
  20681    {
  20682        return m_data.m_type == value_t::number_float;
  20683    }
  20684 
  20685    /// @brief return whether value is an object
  20686    /// @sa https://json.nlohmann.me/api/basic_json/is_object/
  20687    constexpr bool is_object() const noexcept
  20688    {
  20689        return m_data.m_type == value_t::object;
  20690    }
  20691 
  20692    /// @brief return whether value is an array
  20693    /// @sa https://json.nlohmann.me/api/basic_json/is_array/
  20694    constexpr bool is_array() const noexcept
  20695    {
  20696        return m_data.m_type == value_t::array;
  20697    }
  20698 
  20699    /// @brief return whether value is a string
  20700    /// @sa https://json.nlohmann.me/api/basic_json/is_string/
  20701    constexpr bool is_string() const noexcept
  20702    {
  20703        return m_data.m_type == value_t::string;
  20704    }
  20705 
  20706    /// @brief return whether value is a binary array
  20707    /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
  20708    constexpr bool is_binary() const noexcept
  20709    {
  20710        return m_data.m_type == value_t::binary;
  20711    }
  20712 
  20713    /// @brief return whether value is discarded
  20714    /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
  20715    constexpr bool is_discarded() const noexcept
  20716    {
  20717        return m_data.m_type == value_t::discarded;
  20718    }
  20719 
  20720    /// @brief return the type of the JSON value (implicit)
  20721    /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
  20722    constexpr operator value_t() const noexcept
  20723    {
  20724        return m_data.m_type;
  20725    }
  20726 
  20727    /// @}
  20728 
  20729  private:
  20730    //////////////////
  20731    // value access //
  20732    //////////////////
  20733 
  20734    /// get a boolean (explicit)
  20735    boolean_t get_impl(boolean_t* /*unused*/) const
  20736    {
  20737        if (JSON_HEDLEY_LIKELY(is_boolean()))
  20738        {
  20739            return m_data.m_value.boolean;
  20740        }
  20741 
  20742        JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
  20743    }
  20744 
  20745    /// get a pointer to the value (object)
  20746    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
  20747    {
  20748        return is_object() ? m_data.m_value.object : nullptr;
  20749    }
  20750 
  20751    /// get a pointer to the value (object)
  20752    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
  20753    {
  20754        return is_object() ? m_data.m_value.object : nullptr;
  20755    }
  20756 
  20757    /// get a pointer to the value (array)
  20758    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
  20759    {
  20760        return is_array() ? m_data.m_value.array : nullptr;
  20761    }
  20762 
  20763    /// get a pointer to the value (array)
  20764    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
  20765    {
  20766        return is_array() ? m_data.m_value.array : nullptr;
  20767    }
  20768 
  20769    /// get a pointer to the value (string)
  20770    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
  20771    {
  20772        return is_string() ? m_data.m_value.string : nullptr;
  20773    }
  20774 
  20775    /// get a pointer to the value (string)
  20776    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
  20777    {
  20778        return is_string() ? m_data.m_value.string : nullptr;
  20779    }
  20780 
  20781    /// get a pointer to the value (boolean)
  20782    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
  20783    {
  20784        return is_boolean() ? &m_data.m_value.boolean : nullptr;
  20785    }
  20786 
  20787    /// get a pointer to the value (boolean)
  20788    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
  20789    {
  20790        return is_boolean() ? &m_data.m_value.boolean : nullptr;
  20791    }
  20792 
  20793    /// get a pointer to the value (integer number)
  20794    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
  20795    {
  20796        return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
  20797    }
  20798 
  20799    /// get a pointer to the value (integer number)
  20800    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
  20801    {
  20802        return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
  20803    }
  20804 
  20805    /// get a pointer to the value (unsigned number)
  20806    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
  20807    {
  20808        return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
  20809    }
  20810 
  20811    /// get a pointer to the value (unsigned number)
  20812    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
  20813    {
  20814        return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
  20815    }
  20816 
  20817    /// get a pointer to the value (floating-point number)
  20818    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
  20819    {
  20820        return is_number_float() ? &m_data.m_value.number_float : nullptr;
  20821    }
  20822 
  20823    /// get a pointer to the value (floating-point number)
  20824    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
  20825    {
  20826        return is_number_float() ? &m_data.m_value.number_float : nullptr;
  20827    }
  20828 
  20829    /// get a pointer to the value (binary)
  20830    binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
  20831    {
  20832        return is_binary() ? m_data.m_value.binary : nullptr;
  20833    }
  20834 
  20835    /// get a pointer to the value (binary)
  20836    constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
  20837    {
  20838        return is_binary() ? m_data.m_value.binary : nullptr;
  20839    }
  20840 
  20841    /*!
  20842    @brief helper function to implement get_ref()
  20843 
  20844    This function helps to implement get_ref() without code duplication for
  20845    const and non-const overloads
  20846 
  20847    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
  20848 
  20849    @throw type_error.303 if ReferenceType does not match underlying value
  20850    type of the current JSON
  20851    */
  20852    template<typename ReferenceType, typename ThisType>
  20853    static ReferenceType get_ref_impl(ThisType& obj)
  20854    {
  20855        // delegate the call to get_ptr<>()
  20856        auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
  20857 
  20858        if (JSON_HEDLEY_LIKELY(ptr != nullptr))
  20859        {
  20860            return *ptr;
  20861        }
  20862 
  20863        JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
  20864    }
  20865 
  20866  public:
  20867    /// @name value access
  20868    /// Direct access to the stored value of a JSON value.
  20869    /// @{
  20870 
  20871    /// @brief get a pointer value (implicit)
  20872    /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
  20873    template<typename PointerType, typename std::enable_if<
  20874                 std::is_pointer<PointerType>::value, int>::type = 0>
  20875    auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
  20876    {
  20877        // delegate the call to get_impl_ptr<>()
  20878        return get_impl_ptr(static_cast<PointerType>(nullptr));
  20879    }
  20880 
  20881    /// @brief get a pointer value (implicit)
  20882    /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
  20883    template < typename PointerType, typename std::enable_if <
  20884                   std::is_pointer<PointerType>::value&&
  20885                   std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
  20886    constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
  20887    {
  20888        // delegate the call to get_impl_ptr<>() const
  20889        return get_impl_ptr(static_cast<PointerType>(nullptr));
  20890    }
  20891 
  20892  private:
  20893    /*!
  20894    @brief get a value (explicit)
  20895 
  20896    Explicit type conversion between the JSON value and a compatible value
  20897    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
  20898    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
  20899    The value is converted by calling the @ref json_serializer<ValueType>
  20900    `from_json()` method.
  20901 
  20902    The function is equivalent to executing
  20903    @code {.cpp}
  20904    ValueType ret;
  20905    JSONSerializer<ValueType>::from_json(*this, ret);
  20906    return ret;
  20907    @endcode
  20908 
  20909    This overloads is chosen if:
  20910    - @a ValueType is not @ref basic_json,
  20911    - @ref json_serializer<ValueType> has a `from_json()` method of the form
  20912      `void from_json(const basic_json&, ValueType&)`, and
  20913    - @ref json_serializer<ValueType> does not have a `from_json()` method of
  20914      the form `ValueType from_json(const basic_json&)`
  20915 
  20916    @tparam ValueType the returned value type
  20917 
  20918    @return copy of the JSON value, converted to @a ValueType
  20919 
  20920    @throw what @ref json_serializer<ValueType> `from_json()` method throws
  20921 
  20922    @liveexample{The example below shows several conversions from JSON values
  20923    to other types. There a few things to note: (1) Floating-point numbers can
  20924    be converted to integers\, (2) A JSON array can be converted to a standard
  20925    `std::vector<short>`\, (3) A JSON object can be converted to C++
  20926    associative containers such as `std::unordered_map<std::string\,
  20927    json>`.,get__ValueType_const}
  20928 
  20929    @since version 2.1.0
  20930    */
  20931    template < typename ValueType,
  20932               detail::enable_if_t <
  20933                   detail::is_default_constructible<ValueType>::value&&
  20934                   detail::has_from_json<basic_json_t, ValueType>::value,
  20935                   int > = 0 >
  20936    ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
  20937                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
  20938    {
  20939        auto ret = ValueType();
  20940        JSONSerializer<ValueType>::from_json(*this, ret);
  20941        return ret;
  20942    }
  20943 
  20944    /*!
  20945    @brief get a value (explicit); special case
  20946 
  20947    Explicit type conversion between the JSON value and a compatible value
  20948    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
  20949    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
  20950    The value is converted by calling the @ref json_serializer<ValueType>
  20951    `from_json()` method.
  20952 
  20953    The function is equivalent to executing
  20954    @code {.cpp}
  20955    return JSONSerializer<ValueType>::from_json(*this);
  20956    @endcode
  20957 
  20958    This overloads is chosen if:
  20959    - @a ValueType is not @ref basic_json and
  20960    - @ref json_serializer<ValueType> has a `from_json()` method of the form
  20961      `ValueType from_json(const basic_json&)`
  20962 
  20963    @note If @ref json_serializer<ValueType> has both overloads of
  20964    `from_json()`, this one is chosen.
  20965 
  20966    @tparam ValueType the returned value type
  20967 
  20968    @return copy of the JSON value, converted to @a ValueType
  20969 
  20970    @throw what @ref json_serializer<ValueType> `from_json()` method throws
  20971 
  20972    @since version 2.1.0
  20973    */
  20974    template < typename ValueType,
  20975               detail::enable_if_t <
  20976                   detail::has_non_default_from_json<basic_json_t, ValueType>::value,
  20977                   int > = 0 >
  20978    ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
  20979                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
  20980    {
  20981        return JSONSerializer<ValueType>::from_json(*this);
  20982    }
  20983 
  20984    /*!
  20985    @brief get special-case overload
  20986 
  20987    This overloads converts the current @ref basic_json in a different
  20988    @ref basic_json type
  20989 
  20990    @tparam BasicJsonType == @ref basic_json
  20991 
  20992    @return a copy of *this, converted into @a BasicJsonType
  20993 
  20994    @complexity Depending on the implementation of the called `from_json()`
  20995                method.
  20996 
  20997    @since version 3.2.0
  20998    */
  20999    template < typename BasicJsonType,
  21000               detail::enable_if_t <
  21001                   detail::is_basic_json<BasicJsonType>::value,
  21002                   int > = 0 >
  21003    BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
  21004    {
  21005        return *this;
  21006    }
  21007 
  21008    /*!
  21009    @brief get special-case overload
  21010 
  21011    This overloads avoids a lot of template boilerplate, it can be seen as the
  21012    identity method
  21013 
  21014    @tparam BasicJsonType == @ref basic_json
  21015 
  21016    @return a copy of *this
  21017 
  21018    @complexity Constant.
  21019 
  21020    @since version 2.1.0
  21021    */
  21022    template<typename BasicJsonType,
  21023             detail::enable_if_t<
  21024                 std::is_same<BasicJsonType, basic_json_t>::value,
  21025                 int> = 0>
  21026    basic_json get_impl(detail::priority_tag<3> /*unused*/) const
  21027    {
  21028        return *this;
  21029    }
  21030 
  21031    /*!
  21032    @brief get a pointer value (explicit)
  21033    @copydoc get()
  21034    */
  21035    template<typename PointerType,
  21036             detail::enable_if_t<
  21037                 std::is_pointer<PointerType>::value,
  21038                 int> = 0>
  21039    constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
  21040    -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
  21041    {
  21042        // delegate the call to get_ptr
  21043        return get_ptr<PointerType>();
  21044    }
  21045 
  21046  public:
  21047    /*!
  21048    @brief get a (pointer) value (explicit)
  21049 
  21050    Performs explicit type conversion between the JSON value and a compatible value if required.
  21051 
  21052    - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
  21053    No copies are made.
  21054 
  21055    - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
  21056    from the current @ref basic_json.
  21057 
  21058    - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
  21059    method.
  21060 
  21061    @tparam ValueTypeCV the provided value type
  21062    @tparam ValueType the returned value type
  21063 
  21064    @return copy of the JSON value, converted to @tparam ValueType if necessary
  21065 
  21066    @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
  21067 
  21068    @since version 2.1.0
  21069    */
  21070    template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
  21071 #if defined(JSON_HAS_CPP_14)
  21072    constexpr
  21073 #endif
  21074    auto get() const noexcept(
  21075    noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
  21076    -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
  21077    {
  21078        // we cannot static_assert on ValueTypeCV being non-const, because
  21079        // there is support for get<const basic_json_t>(), which is why we
  21080        // still need the uncvref
  21081        static_assert(!std::is_reference<ValueTypeCV>::value,
  21082                      "get() cannot be used with reference types, you might want to use get_ref()");
  21083        return get_impl<ValueType>(detail::priority_tag<4> {});
  21084    }
  21085 
  21086    /*!
  21087    @brief get a pointer value (explicit)
  21088 
  21089    Explicit pointer access to the internally stored JSON value. No copies are
  21090    made.
  21091 
  21092    @warning The pointer becomes invalid if the underlying JSON object
  21093    changes.
  21094 
  21095    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
  21096    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
  21097    @ref number_unsigned_t, or @ref number_float_t.
  21098 
  21099    @return pointer to the internally stored JSON value if the requested
  21100    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
  21101 
  21102    @complexity Constant.
  21103 
  21104    @liveexample{The example below shows how pointers to internal values of a
  21105    JSON value can be requested. Note that no type conversions are made and a
  21106    `nullptr` is returned if the value and the requested pointer type does not
  21107    match.,get__PointerType}
  21108 
  21109    @sa see @ref get_ptr() for explicit pointer-member access
  21110 
  21111    @since version 1.0.0
  21112    */
  21113    template<typename PointerType, typename std::enable_if<
  21114                 std::is_pointer<PointerType>::value, int>::type = 0>
  21115    auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
  21116    {
  21117        // delegate the call to get_ptr
  21118        return get_ptr<PointerType>();
  21119    }
  21120 
  21121    /// @brief get a value (explicit)
  21122    /// @sa https://json.nlohmann.me/api/basic_json/get_to/
  21123    template < typename ValueType,
  21124               detail::enable_if_t <
  21125                   !detail::is_basic_json<ValueType>::value&&
  21126                   detail::has_from_json<basic_json_t, ValueType>::value,
  21127                   int > = 0 >
  21128    ValueType & get_to(ValueType& v) const noexcept(noexcept(
  21129                JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
  21130    {
  21131        JSONSerializer<ValueType>::from_json(*this, v);
  21132        return v;
  21133    }
  21134 
  21135    // specialization to allow calling get_to with a basic_json value
  21136    // see https://github.com/nlohmann/json/issues/2175
  21137    template<typename ValueType,
  21138             detail::enable_if_t <
  21139                 detail::is_basic_json<ValueType>::value,
  21140                 int> = 0>
  21141    ValueType & get_to(ValueType& v) const
  21142    {
  21143        v = *this;
  21144        return v;
  21145    }
  21146 
  21147    template <
  21148        typename T, std::size_t N,
  21149        typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  21150        detail::enable_if_t <
  21151            detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
  21152    Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
  21153    noexcept(noexcept(JSONSerializer<Array>::from_json(
  21154                          std::declval<const basic_json_t&>(), v)))
  21155    {
  21156        JSONSerializer<Array>::from_json(*this, v);
  21157        return v;
  21158    }
  21159 
  21160    /// @brief get a reference value (implicit)
  21161    /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
  21162    template<typename ReferenceType, typename std::enable_if<
  21163                 std::is_reference<ReferenceType>::value, int>::type = 0>
  21164    ReferenceType get_ref()
  21165    {
  21166        // delegate call to get_ref_impl
  21167        return get_ref_impl<ReferenceType>(*this);
  21168    }
  21169 
  21170    /// @brief get a reference value (implicit)
  21171    /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
  21172    template < typename ReferenceType, typename std::enable_if <
  21173                   std::is_reference<ReferenceType>::value&&
  21174                   std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
  21175    ReferenceType get_ref() const
  21176    {
  21177        // delegate call to get_ref_impl
  21178        return get_ref_impl<ReferenceType>(*this);
  21179    }
  21180 
  21181    /*!
  21182    @brief get a value (implicit)
  21183 
  21184    Implicit type conversion between the JSON value and a compatible value.
  21185    The call is realized by calling @ref get() const.
  21186 
  21187    @tparam ValueType non-pointer type compatible to the JSON value, for
  21188    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
  21189    `std::vector` types for JSON arrays. The character type of @ref string_t
  21190    as well as an initializer list of this type is excluded to avoid
  21191    ambiguities as these types implicitly convert to `std::string`.
  21192 
  21193    @return copy of the JSON value, converted to type @a ValueType
  21194 
  21195    @throw type_error.302 in case passed type @a ValueType is incompatible
  21196    to the JSON value type (e.g., the JSON value is of type boolean, but a
  21197    string is requested); see example below
  21198 
  21199    @complexity Linear in the size of the JSON value.
  21200 
  21201    @liveexample{The example below shows several conversions from JSON values
  21202    to other types. There a few things to note: (1) Floating-point numbers can
  21203    be converted to integers\, (2) A JSON array can be converted to a standard
  21204    `std::vector<short>`\, (3) A JSON object can be converted to C++
  21205    associative containers such as `std::unordered_map<std::string\,
  21206    json>`.,operator__ValueType}
  21207 
  21208    @since version 1.0.0
  21209    */
  21210    template < typename ValueType, typename std::enable_if <
  21211                   detail::conjunction <
  21212                       detail::negation<std::is_pointer<ValueType>>,
  21213                       detail::negation<std::is_same<ValueType, std::nullptr_t>>,
  21214                       detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
  21215                                        detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
  21216                                        detail::negation<detail::is_basic_json<ValueType>>,
  21217                                        detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
  21218 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
  21219                                                detail::negation<std::is_same<ValueType, std::string_view>>,
  21220 #endif
  21221 #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
  21222                                                detail::negation<std::is_same<ValueType, std::any>>,
  21223 #endif
  21224                                                detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
  21225                                                >::value, int >::type = 0 >
  21226                                        JSON_EXPLICIT operator ValueType() const
  21227    {
  21228        // delegate the call to get<>() const
  21229        return get<ValueType>();
  21230    }
  21231 
  21232    /// @brief get a binary value
  21233    /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
  21234    binary_t& get_binary()
  21235    {
  21236        if (!is_binary())
  21237        {
  21238            JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
  21239        }
  21240 
  21241        return *get_ptr<binary_t*>();
  21242    }
  21243 
  21244    /// @brief get a binary value
  21245    /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
  21246    const binary_t& get_binary() const
  21247    {
  21248        if (!is_binary())
  21249        {
  21250            JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
  21251        }
  21252 
  21253        return *get_ptr<const binary_t*>();
  21254    }
  21255 
  21256    /// @}
  21257 
  21258    ////////////////////
  21259    // element access //
  21260    ////////////////////
  21261 
  21262    /// @name element access
  21263    /// Access to the JSON value.
  21264    /// @{
  21265 
  21266    /// @brief access specified array element with bounds checking
  21267    /// @sa https://json.nlohmann.me/api/basic_json/at/
  21268    reference at(size_type idx)
  21269    {
  21270        // at only works for arrays
  21271        if (JSON_HEDLEY_LIKELY(is_array()))
  21272        {
  21273            JSON_TRY
  21274            {
  21275                return set_parent(m_data.m_value.array->at(idx));
  21276            }
  21277            JSON_CATCH (std::out_of_range&)
  21278            {
  21279                // create better exception explanation
  21280                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
  21281            }
  21282        }
  21283        else
  21284        {
  21285            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21286        }
  21287    }
  21288 
  21289    /// @brief access specified array element with bounds checking
  21290    /// @sa https://json.nlohmann.me/api/basic_json/at/
  21291    const_reference at(size_type idx) const
  21292    {
  21293        // at only works for arrays
  21294        if (JSON_HEDLEY_LIKELY(is_array()))
  21295        {
  21296            JSON_TRY
  21297            {
  21298                return m_data.m_value.array->at(idx);
  21299            }
  21300            JSON_CATCH (std::out_of_range&)
  21301            {
  21302                // create better exception explanation
  21303                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
  21304            }
  21305        }
  21306        else
  21307        {
  21308            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21309        }
  21310    }
  21311 
  21312    /// @brief access specified object element with bounds checking
  21313    /// @sa https://json.nlohmann.me/api/basic_json/at/
  21314    reference at(const typename object_t::key_type& key)
  21315    {
  21316        // at only works for objects
  21317        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21318        {
  21319            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21320        }
  21321 
  21322        auto it = m_data.m_value.object->find(key);
  21323        if (it == m_data.m_value.object->end())
  21324        {
  21325            JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
  21326        }
  21327        return set_parent(it->second);
  21328    }
  21329 
  21330    /// @brief access specified object element with bounds checking
  21331    /// @sa https://json.nlohmann.me/api/basic_json/at/
  21332    template<class KeyType, detail::enable_if_t<
  21333                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21334    reference at(KeyType && key)
  21335    {
  21336        // at only works for objects
  21337        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21338        {
  21339            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21340        }
  21341 
  21342        auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
  21343        if (it == m_data.m_value.object->end())
  21344        {
  21345            JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
  21346        }
  21347        return set_parent(it->second);
  21348    }
  21349 
  21350    /// @brief access specified object element with bounds checking
  21351    /// @sa https://json.nlohmann.me/api/basic_json/at/
  21352    const_reference at(const typename object_t::key_type& key) const
  21353    {
  21354        // at only works for objects
  21355        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21356        {
  21357            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21358        }
  21359 
  21360        auto it = m_data.m_value.object->find(key);
  21361        if (it == m_data.m_value.object->end())
  21362        {
  21363            JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
  21364        }
  21365        return it->second;
  21366    }
  21367 
  21368    /// @brief access specified object element with bounds checking
  21369    /// @sa https://json.nlohmann.me/api/basic_json/at/
  21370    template<class KeyType, detail::enable_if_t<
  21371                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21372    const_reference at(KeyType && key) const
  21373    {
  21374        // at only works for objects
  21375        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21376        {
  21377            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
  21378        }
  21379 
  21380        auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
  21381        if (it == m_data.m_value.object->end())
  21382        {
  21383            JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
  21384        }
  21385        return it->second;
  21386    }
  21387 
  21388    /// @brief access specified array element
  21389    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21390    reference operator[](size_type idx)
  21391    {
  21392        // implicitly convert null value to an empty array
  21393        if (is_null())
  21394        {
  21395            m_data.m_type = value_t::array;
  21396            m_data.m_value.array = create<array_t>();
  21397            assert_invariant();
  21398        }
  21399 
  21400        // operator[] only works for arrays
  21401        if (JSON_HEDLEY_LIKELY(is_array()))
  21402        {
  21403            // fill up array with null values if given idx is outside range
  21404            if (idx >= m_data.m_value.array->size())
  21405            {
  21406 #if JSON_DIAGNOSTICS
  21407                // remember array size & capacity before resizing
  21408                const auto old_size = m_data.m_value.array->size();
  21409                const auto old_capacity = m_data.m_value.array->capacity();
  21410 #endif
  21411                m_data.m_value.array->resize(idx + 1);
  21412 
  21413 #if JSON_DIAGNOSTICS
  21414                if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
  21415                {
  21416                    // capacity has changed: update all parents
  21417                    set_parents();
  21418                }
  21419                else
  21420                {
  21421                    // set parent for values added above
  21422                    set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
  21423                }
  21424 #endif
  21425                assert_invariant();
  21426            }
  21427 
  21428            return m_data.m_value.array->operator[](idx);
  21429        }
  21430 
  21431        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
  21432    }
  21433 
  21434    /// @brief access specified array element
  21435    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21436    const_reference operator[](size_type idx) const
  21437    {
  21438        // const operator[] only works for arrays
  21439        if (JSON_HEDLEY_LIKELY(is_array()))
  21440        {
  21441            return m_data.m_value.array->operator[](idx);
  21442        }
  21443 
  21444        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
  21445    }
  21446 
  21447    /// @brief access specified object element
  21448    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21449    reference operator[](typename object_t::key_type key)
  21450    {
  21451        // implicitly convert null value to an empty object
  21452        if (is_null())
  21453        {
  21454            m_data.m_type = value_t::object;
  21455            m_data.m_value.object = create<object_t>();
  21456            assert_invariant();
  21457        }
  21458 
  21459        // operator[] only works for objects
  21460        if (JSON_HEDLEY_LIKELY(is_object()))
  21461        {
  21462            auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
  21463            return set_parent(result.first->second);
  21464        }
  21465 
  21466        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21467    }
  21468 
  21469    /// @brief access specified object element
  21470    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21471    const_reference operator[](const typename object_t::key_type& key) const
  21472    {
  21473        // const operator[] only works for objects
  21474        if (JSON_HEDLEY_LIKELY(is_object()))
  21475        {
  21476            auto it = m_data.m_value.object->find(key);
  21477            JSON_ASSERT(it != m_data.m_value.object->end());
  21478            return it->second;
  21479        }
  21480 
  21481        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21482    }
  21483 
  21484    // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
  21485    // (they seemingly cannot be constrained to resolve the ambiguity)
  21486    template<typename T>
  21487    reference operator[](T* key)
  21488    {
  21489        return operator[](typename object_t::key_type(key));
  21490    }
  21491 
  21492    template<typename T>
  21493    const_reference operator[](T* key) const
  21494    {
  21495        return operator[](typename object_t::key_type(key));
  21496    }
  21497 
  21498    /// @brief access specified object element
  21499    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21500    template<class KeyType, detail::enable_if_t<
  21501                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21502    reference operator[](KeyType && key)
  21503    {
  21504        // implicitly convert null value to an empty object
  21505        if (is_null())
  21506        {
  21507            m_data.m_type = value_t::object;
  21508            m_data.m_value.object = create<object_t>();
  21509            assert_invariant();
  21510        }
  21511 
  21512        // operator[] only works for objects
  21513        if (JSON_HEDLEY_LIKELY(is_object()))
  21514        {
  21515            auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
  21516            return set_parent(result.first->second);
  21517        }
  21518 
  21519        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21520    }
  21521 
  21522    /// @brief access specified object element
  21523    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  21524    template<class KeyType, detail::enable_if_t<
  21525                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21526    const_reference operator[](KeyType && key) const
  21527    {
  21528        // const operator[] only works for objects
  21529        if (JSON_HEDLEY_LIKELY(is_object()))
  21530        {
  21531            auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
  21532            JSON_ASSERT(it != m_data.m_value.object->end());
  21533            return it->second;
  21534        }
  21535 
  21536        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
  21537    }
  21538 
  21539  private:
  21540    template<typename KeyType>
  21541    using is_comparable_with_object_key = detail::is_comparable <
  21542        object_comparator_t, const typename object_t::key_type&, KeyType >;
  21543 
  21544    template<typename ValueType>
  21545    using value_return_type = std::conditional <
  21546        detail::is_c_string_uncvref<ValueType>::value,
  21547        string_t, typename std::decay<ValueType>::type >;
  21548 
  21549  public:
  21550    /// @brief access specified object element with default value
  21551    /// @sa https://json.nlohmann.me/api/basic_json/value/
  21552    template < class ValueType, detail::enable_if_t <
  21553                   !detail::is_transparent<object_comparator_t>::value
  21554                   && detail::is_getable<basic_json_t, ValueType>::value
  21555                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21556    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
  21557    {
  21558        // value only works for objects
  21559        if (JSON_HEDLEY_LIKELY(is_object()))
  21560        {
  21561            // if key is found, return value and given default value otherwise
  21562            const auto it = find(key);
  21563            if (it != end())
  21564            {
  21565                return it->template get<ValueType>();
  21566            }
  21567 
  21568            return default_value;
  21569        }
  21570 
  21571        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21572    }
  21573 
  21574    /// @brief access specified object element with default value
  21575    /// @sa https://json.nlohmann.me/api/basic_json/value/
  21576    template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
  21577               detail::enable_if_t <
  21578                   !detail::is_transparent<object_comparator_t>::value
  21579                   && detail::is_getable<basic_json_t, ReturnType>::value
  21580                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21581    ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
  21582    {
  21583        // value only works for objects
  21584        if (JSON_HEDLEY_LIKELY(is_object()))
  21585        {
  21586            // if key is found, return value and given default value otherwise
  21587            const auto it = find(key);
  21588            if (it != end())
  21589            {
  21590                return it->template get<ReturnType>();
  21591            }
  21592 
  21593            return std::forward<ValueType>(default_value);
  21594        }
  21595 
  21596        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21597    }
  21598 
  21599    /// @brief access specified object element with default value
  21600    /// @sa https://json.nlohmann.me/api/basic_json/value/
  21601    template < class ValueType, class KeyType, detail::enable_if_t <
  21602                   detail::is_transparent<object_comparator_t>::value
  21603                   && !detail::is_json_pointer<KeyType>::value
  21604                   && is_comparable_with_object_key<KeyType>::value
  21605                   && detail::is_getable<basic_json_t, ValueType>::value
  21606                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21607    ValueType value(KeyType && key, const ValueType& default_value) const
  21608    {
  21609        // value only works for objects
  21610        if (JSON_HEDLEY_LIKELY(is_object()))
  21611        {
  21612            // if key is found, return value and given default value otherwise
  21613            const auto it = find(std::forward<KeyType>(key));
  21614            if (it != end())
  21615            {
  21616                return it->template get<ValueType>();
  21617            }
  21618 
  21619            return default_value;
  21620        }
  21621 
  21622        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21623    }
  21624 
  21625    /// @brief access specified object element via JSON Pointer with default value
  21626    /// @sa https://json.nlohmann.me/api/basic_json/value/
  21627    template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
  21628               detail::enable_if_t <
  21629                   detail::is_transparent<object_comparator_t>::value
  21630                   && !detail::is_json_pointer<KeyType>::value
  21631                   && is_comparable_with_object_key<KeyType>::value
  21632                   && detail::is_getable<basic_json_t, ReturnType>::value
  21633                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21634    ReturnType value(KeyType && key, ValueType && default_value) const
  21635    {
  21636        // value only works for objects
  21637        if (JSON_HEDLEY_LIKELY(is_object()))
  21638        {
  21639            // if key is found, return value and given default value otherwise
  21640            const auto it = find(std::forward<KeyType>(key));
  21641            if (it != end())
  21642            {
  21643                return it->template get<ReturnType>();
  21644            }
  21645 
  21646            return std::forward<ValueType>(default_value);
  21647        }
  21648 
  21649        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21650    }
  21651 
  21652    /// @brief access specified object element via JSON Pointer with default value
  21653    /// @sa https://json.nlohmann.me/api/basic_json/value/
  21654    template < class ValueType, detail::enable_if_t <
  21655                   detail::is_getable<basic_json_t, ValueType>::value
  21656                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21657    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
  21658    {
  21659        // value only works for objects
  21660        if (JSON_HEDLEY_LIKELY(is_object()))
  21661        {
  21662            // if pointer resolves a value, return it or use default value
  21663            JSON_TRY
  21664            {
  21665                return ptr.get_checked(this).template get<ValueType>();
  21666            }
  21667            JSON_INTERNAL_CATCH (out_of_range&)
  21668            {
  21669                return default_value;
  21670            }
  21671        }
  21672 
  21673        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21674    }
  21675 
  21676    /// @brief access specified object element via JSON Pointer with default value
  21677    /// @sa https://json.nlohmann.me/api/basic_json/value/
  21678    template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
  21679               detail::enable_if_t <
  21680                   detail::is_getable<basic_json_t, ReturnType>::value
  21681                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21682    ReturnType value(const json_pointer& ptr, ValueType && default_value) const
  21683    {
  21684        // value only works for objects
  21685        if (JSON_HEDLEY_LIKELY(is_object()))
  21686        {
  21687            // if pointer resolves a value, return it or use default value
  21688            JSON_TRY
  21689            {
  21690                return ptr.get_checked(this).template get<ReturnType>();
  21691            }
  21692            JSON_INTERNAL_CATCH (out_of_range&)
  21693            {
  21694                return std::forward<ValueType>(default_value);
  21695            }
  21696        }
  21697 
  21698        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
  21699    }
  21700 
  21701    template < class ValueType, class BasicJsonType, detail::enable_if_t <
  21702                   detail::is_basic_json<BasicJsonType>::value
  21703                   && detail::is_getable<basic_json_t, ValueType>::value
  21704                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21705    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  21706    ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
  21707    {
  21708        return value(ptr.convert(), default_value);
  21709    }
  21710 
  21711    template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
  21712               detail::enable_if_t <
  21713                   detail::is_basic_json<BasicJsonType>::value
  21714                   && detail::is_getable<basic_json_t, ReturnType>::value
  21715                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
  21716    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  21717    ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
  21718    {
  21719        return value(ptr.convert(), std::forward<ValueType>(default_value));
  21720    }
  21721 
  21722    /// @brief access the first element
  21723    /// @sa https://json.nlohmann.me/api/basic_json/front/
  21724    reference front()
  21725    {
  21726        return *begin();
  21727    }
  21728 
  21729    /// @brief access the first element
  21730    /// @sa https://json.nlohmann.me/api/basic_json/front/
  21731    const_reference front() const
  21732    {
  21733        return *cbegin();
  21734    }
  21735 
  21736    /// @brief access the last element
  21737    /// @sa https://json.nlohmann.me/api/basic_json/back/
  21738    reference back()
  21739    {
  21740        auto tmp = end();
  21741        --tmp;
  21742        return *tmp;
  21743    }
  21744 
  21745    /// @brief access the last element
  21746    /// @sa https://json.nlohmann.me/api/basic_json/back/
  21747    const_reference back() const
  21748    {
  21749        auto tmp = cend();
  21750        --tmp;
  21751        return *tmp;
  21752    }
  21753 
  21754    /// @brief remove element given an iterator
  21755    /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21756    template < class IteratorType, detail::enable_if_t <
  21757                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
  21758                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
  21759    IteratorType erase(IteratorType pos)
  21760    {
  21761        // make sure iterator fits the current value
  21762        if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
  21763        {
  21764            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  21765        }
  21766 
  21767        IteratorType result = end();
  21768 
  21769        switch (m_data.m_type)
  21770        {
  21771            case value_t::boolean:
  21772            case value_t::number_float:
  21773            case value_t::number_integer:
  21774            case value_t::number_unsigned:
  21775            case value_t::string:
  21776            case value_t::binary:
  21777            {
  21778                if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
  21779                {
  21780                    JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
  21781                }
  21782 
  21783                if (is_string())
  21784                {
  21785                    AllocatorType<string_t> alloc;
  21786                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
  21787                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
  21788                    m_data.m_value.string = nullptr;
  21789                }
  21790                else if (is_binary())
  21791                {
  21792                    AllocatorType<binary_t> alloc;
  21793                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
  21794                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
  21795                    m_data.m_value.binary = nullptr;
  21796                }
  21797 
  21798                m_data.m_type = value_t::null;
  21799                assert_invariant();
  21800                break;
  21801            }
  21802 
  21803            case value_t::object:
  21804            {
  21805                result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
  21806                break;
  21807            }
  21808 
  21809            case value_t::array:
  21810            {
  21811                result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
  21812                break;
  21813            }
  21814 
  21815            case value_t::null:
  21816            case value_t::discarded:
  21817            default:
  21818                JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21819        }
  21820 
  21821        return result;
  21822    }
  21823 
  21824    /// @brief remove elements given an iterator range
  21825    /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21826    template < class IteratorType, detail::enable_if_t <
  21827                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
  21828                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
  21829    IteratorType erase(IteratorType first, IteratorType last)
  21830    {
  21831        // make sure iterator fits the current value
  21832        if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
  21833        {
  21834            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
  21835        }
  21836 
  21837        IteratorType result = end();
  21838 
  21839        switch (m_data.m_type)
  21840        {
  21841            case value_t::boolean:
  21842            case value_t::number_float:
  21843            case value_t::number_integer:
  21844            case value_t::number_unsigned:
  21845            case value_t::string:
  21846            case value_t::binary:
  21847            {
  21848                if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
  21849                                       || !last.m_it.primitive_iterator.is_end()))
  21850                {
  21851                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
  21852                }
  21853 
  21854                if (is_string())
  21855                {
  21856                    AllocatorType<string_t> alloc;
  21857                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
  21858                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
  21859                    m_data.m_value.string = nullptr;
  21860                }
  21861                else if (is_binary())
  21862                {
  21863                    AllocatorType<binary_t> alloc;
  21864                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
  21865                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
  21866                    m_data.m_value.binary = nullptr;
  21867                }
  21868 
  21869                m_data.m_type = value_t::null;
  21870                assert_invariant();
  21871                break;
  21872            }
  21873 
  21874            case value_t::object:
  21875            {
  21876                result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
  21877                                              last.m_it.object_iterator);
  21878                break;
  21879            }
  21880 
  21881            case value_t::array:
  21882            {
  21883                result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
  21884                                             last.m_it.array_iterator);
  21885                break;
  21886            }
  21887 
  21888            case value_t::null:
  21889            case value_t::discarded:
  21890            default:
  21891                JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21892        }
  21893 
  21894        return result;
  21895    }
  21896 
  21897  private:
  21898    template < typename KeyType, detail::enable_if_t <
  21899                   detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21900    size_type erase_internal(KeyType && key)
  21901    {
  21902        // this erase only works for objects
  21903        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21904        {
  21905            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21906        }
  21907 
  21908        return m_data.m_value.object->erase(std::forward<KeyType>(key));
  21909    }
  21910 
  21911    template < typename KeyType, detail::enable_if_t <
  21912                   !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
  21913    size_type erase_internal(KeyType && key)
  21914    {
  21915        // this erase only works for objects
  21916        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  21917        {
  21918            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21919        }
  21920 
  21921        const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
  21922        if (it != m_data.m_value.object->end())
  21923        {
  21924            m_data.m_value.object->erase(it);
  21925            return 1;
  21926        }
  21927        return 0;
  21928    }
  21929 
  21930  public:
  21931 
  21932    /// @brief remove element from a JSON object given a key
  21933    /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21934    size_type erase(const typename object_t::key_type& key)
  21935    {
  21936        // the indirection via erase_internal() is added to avoid making this
  21937        // function a template and thus de-rank it during overload resolution
  21938        return erase_internal(key);
  21939    }
  21940 
  21941    /// @brief remove element from a JSON object given a key
  21942    /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21943    template<class KeyType, detail::enable_if_t<
  21944                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  21945    size_type erase(KeyType && key)
  21946    {
  21947        return erase_internal(std::forward<KeyType>(key));
  21948    }
  21949 
  21950    /// @brief remove element from a JSON array given an index
  21951    /// @sa https://json.nlohmann.me/api/basic_json/erase/
  21952    void erase(const size_type idx)
  21953    {
  21954        // this erase only works for arrays
  21955        if (JSON_HEDLEY_LIKELY(is_array()))
  21956        {
  21957            if (JSON_HEDLEY_UNLIKELY(idx >= size()))
  21958            {
  21959                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
  21960            }
  21961 
  21962            m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
  21963        }
  21964        else
  21965        {
  21966            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
  21967        }
  21968    }
  21969 
  21970    /// @}
  21971 
  21972    ////////////
  21973    // lookup //
  21974    ////////////
  21975 
  21976    /// @name lookup
  21977    /// @{
  21978 
  21979    /// @brief find an element in a JSON object
  21980    /// @sa https://json.nlohmann.me/api/basic_json/find/
  21981    iterator find(const typename object_t::key_type& key)
  21982    {
  21983        auto result = end();
  21984 
  21985        if (is_object())
  21986        {
  21987            result.m_it.object_iterator = m_data.m_value.object->find(key);
  21988        }
  21989 
  21990        return result;
  21991    }
  21992 
  21993    /// @brief find an element in a JSON object
  21994    /// @sa https://json.nlohmann.me/api/basic_json/find/
  21995    const_iterator find(const typename object_t::key_type& key) const
  21996    {
  21997        auto result = cend();
  21998 
  21999        if (is_object())
  22000        {
  22001            result.m_it.object_iterator = m_data.m_value.object->find(key);
  22002        }
  22003 
  22004        return result;
  22005    }
  22006 
  22007    /// @brief find an element in a JSON object
  22008    /// @sa https://json.nlohmann.me/api/basic_json/find/
  22009    template<class KeyType, detail::enable_if_t<
  22010                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  22011    iterator find(KeyType && key)
  22012    {
  22013        auto result = end();
  22014 
  22015        if (is_object())
  22016        {
  22017            result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
  22018        }
  22019 
  22020        return result;
  22021    }
  22022 
  22023    /// @brief find an element in a JSON object
  22024    /// @sa https://json.nlohmann.me/api/basic_json/find/
  22025    template<class KeyType, detail::enable_if_t<
  22026                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  22027    const_iterator find(KeyType && key) const
  22028    {
  22029        auto result = cend();
  22030 
  22031        if (is_object())
  22032        {
  22033            result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
  22034        }
  22035 
  22036        return result;
  22037    }
  22038 
  22039    /// @brief returns the number of occurrences of a key in a JSON object
  22040    /// @sa https://json.nlohmann.me/api/basic_json/count/
  22041    size_type count(const typename object_t::key_type& key) const
  22042    {
  22043        // return 0 for all nonobject types
  22044        return is_object() ? m_data.m_value.object->count(key) : 0;
  22045    }
  22046 
  22047    /// @brief returns the number of occurrences of a key in a JSON object
  22048    /// @sa https://json.nlohmann.me/api/basic_json/count/
  22049    template<class KeyType, detail::enable_if_t<
  22050                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  22051    size_type count(KeyType && key) const
  22052    {
  22053        // return 0 for all nonobject types
  22054        return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
  22055    }
  22056 
  22057    /// @brief check the existence of an element in a JSON object
  22058    /// @sa https://json.nlohmann.me/api/basic_json/contains/
  22059    bool contains(const typename object_t::key_type& key) const
  22060    {
  22061        return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
  22062    }
  22063 
  22064    /// @brief check the existence of an element in a JSON object
  22065    /// @sa https://json.nlohmann.me/api/basic_json/contains/
  22066    template<class KeyType, detail::enable_if_t<
  22067                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
  22068    bool contains(KeyType && key) const
  22069    {
  22070        return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
  22071    }
  22072 
  22073    /// @brief check the existence of an element in a JSON object given a JSON pointer
  22074    /// @sa https://json.nlohmann.me/api/basic_json/contains/
  22075    bool contains(const json_pointer& ptr) const
  22076    {
  22077        return ptr.contains(this);
  22078    }
  22079 
  22080    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  22081    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  22082    bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
  22083    {
  22084        return ptr.contains(this);
  22085    }
  22086 
  22087    /// @}
  22088 
  22089    ///////////////
  22090    // iterators //
  22091    ///////////////
  22092 
  22093    /// @name iterators
  22094    /// @{
  22095 
  22096    /// @brief returns an iterator to the first element
  22097    /// @sa https://json.nlohmann.me/api/basic_json/begin/
  22098    iterator begin() noexcept
  22099    {
  22100        iterator result(this);
  22101        result.set_begin();
  22102        return result;
  22103    }
  22104 
  22105    /// @brief returns an iterator to the first element
  22106    /// @sa https://json.nlohmann.me/api/basic_json/begin/
  22107    const_iterator begin() const noexcept
  22108    {
  22109        return cbegin();
  22110    }
  22111 
  22112    /// @brief returns a const iterator to the first element
  22113    /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
  22114    const_iterator cbegin() const noexcept
  22115    {
  22116        const_iterator result(this);
  22117        result.set_begin();
  22118        return result;
  22119    }
  22120 
  22121    /// @brief returns an iterator to one past the last element
  22122    /// @sa https://json.nlohmann.me/api/basic_json/end/
  22123    iterator end() noexcept
  22124    {
  22125        iterator result(this);
  22126        result.set_end();
  22127        return result;
  22128    }
  22129 
  22130    /// @brief returns an iterator to one past the last element
  22131    /// @sa https://json.nlohmann.me/api/basic_json/end/
  22132    const_iterator end() const noexcept
  22133    {
  22134        return cend();
  22135    }
  22136 
  22137    /// @brief returns an iterator to one past the last element
  22138    /// @sa https://json.nlohmann.me/api/basic_json/cend/
  22139    const_iterator cend() const noexcept
  22140    {
  22141        const_iterator result(this);
  22142        result.set_end();
  22143        return result;
  22144    }
  22145 
  22146    /// @brief returns an iterator to the reverse-beginning
  22147    /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
  22148    reverse_iterator rbegin() noexcept
  22149    {
  22150        return reverse_iterator(end());
  22151    }
  22152 
  22153    /// @brief returns an iterator to the reverse-beginning
  22154    /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
  22155    const_reverse_iterator rbegin() const noexcept
  22156    {
  22157        return crbegin();
  22158    }
  22159 
  22160    /// @brief returns an iterator to the reverse-end
  22161    /// @sa https://json.nlohmann.me/api/basic_json/rend/
  22162    reverse_iterator rend() noexcept
  22163    {
  22164        return reverse_iterator(begin());
  22165    }
  22166 
  22167    /// @brief returns an iterator to the reverse-end
  22168    /// @sa https://json.nlohmann.me/api/basic_json/rend/
  22169    const_reverse_iterator rend() const noexcept
  22170    {
  22171        return crend();
  22172    }
  22173 
  22174    /// @brief returns a const reverse iterator to the last element
  22175    /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
  22176    const_reverse_iterator crbegin() const noexcept
  22177    {
  22178        return const_reverse_iterator(cend());
  22179    }
  22180 
  22181    /// @brief returns a const reverse iterator to one before the first
  22182    /// @sa https://json.nlohmann.me/api/basic_json/crend/
  22183    const_reverse_iterator crend() const noexcept
  22184    {
  22185        return const_reverse_iterator(cbegin());
  22186    }
  22187 
  22188  public:
  22189    /// @brief wrapper to access iterator member functions in range-based for
  22190    /// @sa https://json.nlohmann.me/api/basic_json/items/
  22191    /// @deprecated This function is deprecated since 3.1.0 and will be removed in
  22192    ///             version 4.0.0 of the library. Please use @ref items() instead;
  22193    ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
  22194    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
  22195    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
  22196    {
  22197        return ref.items();
  22198    }
  22199 
  22200    /// @brief wrapper to access iterator member functions in range-based for
  22201    /// @sa https://json.nlohmann.me/api/basic_json/items/
  22202    /// @deprecated This function is deprecated since 3.1.0 and will be removed in
  22203    ///         version 4.0.0 of the library. Please use @ref items() instead;
  22204    ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
  22205    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
  22206    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
  22207    {
  22208        return ref.items();
  22209    }
  22210 
  22211    /// @brief helper to access iterator member functions in range-based for
  22212    /// @sa https://json.nlohmann.me/api/basic_json/items/
  22213    iteration_proxy<iterator> items() noexcept
  22214    {
  22215        return iteration_proxy<iterator>(*this);
  22216    }
  22217 
  22218    /// @brief helper to access iterator member functions in range-based for
  22219    /// @sa https://json.nlohmann.me/api/basic_json/items/
  22220    iteration_proxy<const_iterator> items() const noexcept
  22221    {
  22222        return iteration_proxy<const_iterator>(*this);
  22223    }
  22224 
  22225    /// @}
  22226 
  22227    //////////////
  22228    // capacity //
  22229    //////////////
  22230 
  22231    /// @name capacity
  22232    /// @{
  22233 
  22234    /// @brief checks whether the container is empty.
  22235    /// @sa https://json.nlohmann.me/api/basic_json/empty/
  22236    bool empty() const noexcept
  22237    {
  22238        switch (m_data.m_type)
  22239        {
  22240            case value_t::null:
  22241            {
  22242                // null values are empty
  22243                return true;
  22244            }
  22245 
  22246            case value_t::array:
  22247            {
  22248                // delegate call to array_t::empty()
  22249                return m_data.m_value.array->empty();
  22250            }
  22251 
  22252            case value_t::object:
  22253            {
  22254                // delegate call to object_t::empty()
  22255                return m_data.m_value.object->empty();
  22256            }
  22257 
  22258            case value_t::string:
  22259            case value_t::boolean:
  22260            case value_t::number_integer:
  22261            case value_t::number_unsigned:
  22262            case value_t::number_float:
  22263            case value_t::binary:
  22264            case value_t::discarded:
  22265            default:
  22266            {
  22267                // all other types are nonempty
  22268                return false;
  22269            }
  22270        }
  22271    }
  22272 
  22273    /// @brief returns the number of elements
  22274    /// @sa https://json.nlohmann.me/api/basic_json/size/
  22275    size_type size() const noexcept
  22276    {
  22277        switch (m_data.m_type)
  22278        {
  22279            case value_t::null:
  22280            {
  22281                // null values are empty
  22282                return 0;
  22283            }
  22284 
  22285            case value_t::array:
  22286            {
  22287                // delegate call to array_t::size()
  22288                return m_data.m_value.array->size();
  22289            }
  22290 
  22291            case value_t::object:
  22292            {
  22293                // delegate call to object_t::size()
  22294                return m_data.m_value.object->size();
  22295            }
  22296 
  22297            case value_t::string:
  22298            case value_t::boolean:
  22299            case value_t::number_integer:
  22300            case value_t::number_unsigned:
  22301            case value_t::number_float:
  22302            case value_t::binary:
  22303            case value_t::discarded:
  22304            default:
  22305            {
  22306                // all other types have size 1
  22307                return 1;
  22308            }
  22309        }
  22310    }
  22311 
  22312    /// @brief returns the maximum possible number of elements
  22313    /// @sa https://json.nlohmann.me/api/basic_json/max_size/
  22314    size_type max_size() const noexcept
  22315    {
  22316        switch (m_data.m_type)
  22317        {
  22318            case value_t::array:
  22319            {
  22320                // delegate call to array_t::max_size()
  22321                return m_data.m_value.array->max_size();
  22322            }
  22323 
  22324            case value_t::object:
  22325            {
  22326                // delegate call to object_t::max_size()
  22327                return m_data.m_value.object->max_size();
  22328            }
  22329 
  22330            case value_t::null:
  22331            case value_t::string:
  22332            case value_t::boolean:
  22333            case value_t::number_integer:
  22334            case value_t::number_unsigned:
  22335            case value_t::number_float:
  22336            case value_t::binary:
  22337            case value_t::discarded:
  22338            default:
  22339            {
  22340                // all other types have max_size() == size()
  22341                return size();
  22342            }
  22343        }
  22344    }
  22345 
  22346    /// @}
  22347 
  22348    ///////////////
  22349    // modifiers //
  22350    ///////////////
  22351 
  22352    /// @name modifiers
  22353    /// @{
  22354 
  22355    /// @brief clears the contents
  22356    /// @sa https://json.nlohmann.me/api/basic_json/clear/
  22357    void clear() noexcept
  22358    {
  22359        switch (m_data.m_type)
  22360        {
  22361            case value_t::number_integer:
  22362            {
  22363                m_data.m_value.number_integer = 0;
  22364                break;
  22365            }
  22366 
  22367            case value_t::number_unsigned:
  22368            {
  22369                m_data.m_value.number_unsigned = 0;
  22370                break;
  22371            }
  22372 
  22373            case value_t::number_float:
  22374            {
  22375                m_data.m_value.number_float = 0.0;
  22376                break;
  22377            }
  22378 
  22379            case value_t::boolean:
  22380            {
  22381                m_data.m_value.boolean = false;
  22382                break;
  22383            }
  22384 
  22385            case value_t::string:
  22386            {
  22387                m_data.m_value.string->clear();
  22388                break;
  22389            }
  22390 
  22391            case value_t::binary:
  22392            {
  22393                m_data.m_value.binary->clear();
  22394                break;
  22395            }
  22396 
  22397            case value_t::array:
  22398            {
  22399                m_data.m_value.array->clear();
  22400                break;
  22401            }
  22402 
  22403            case value_t::object:
  22404            {
  22405                m_data.m_value.object->clear();
  22406                break;
  22407            }
  22408 
  22409            case value_t::null:
  22410            case value_t::discarded:
  22411            default:
  22412                break;
  22413        }
  22414    }
  22415 
  22416    /// @brief add an object to an array
  22417    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22418    void push_back(basic_json&& val)
  22419    {
  22420        // push_back only works for null objects or arrays
  22421        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
  22422        {
  22423            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
  22424        }
  22425 
  22426        // transform null object into an array
  22427        if (is_null())
  22428        {
  22429            m_data.m_type = value_t::array;
  22430            m_data.m_value = value_t::array;
  22431            assert_invariant();
  22432        }
  22433 
  22434        // add element to array (move semantics)
  22435        const auto old_capacity = m_data.m_value.array->capacity();
  22436        m_data.m_value.array->push_back(std::move(val));
  22437        set_parent(m_data.m_value.array->back(), old_capacity);
  22438        // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
  22439    }
  22440 
  22441    /// @brief add an object to an array
  22442    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22443    reference operator+=(basic_json&& val)
  22444    {
  22445        push_back(std::move(val));
  22446        return *this;
  22447    }
  22448 
  22449    /// @brief add an object to an array
  22450    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22451    void push_back(const basic_json& val)
  22452    {
  22453        // push_back only works for null objects or arrays
  22454        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
  22455        {
  22456            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
  22457        }
  22458 
  22459        // transform null object into an array
  22460        if (is_null())
  22461        {
  22462            m_data.m_type = value_t::array;
  22463            m_data.m_value = value_t::array;
  22464            assert_invariant();
  22465        }
  22466 
  22467        // add element to array
  22468        const auto old_capacity = m_data.m_value.array->capacity();
  22469        m_data.m_value.array->push_back(val);
  22470        set_parent(m_data.m_value.array->back(), old_capacity);
  22471    }
  22472 
  22473    /// @brief add an object to an array
  22474    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22475    reference operator+=(const basic_json& val)
  22476    {
  22477        push_back(val);
  22478        return *this;
  22479    }
  22480 
  22481    /// @brief add an object to an object
  22482    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22483    void push_back(const typename object_t::value_type& val)
  22484    {
  22485        // push_back only works for null objects or objects
  22486        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
  22487        {
  22488            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
  22489        }
  22490 
  22491        // transform null object into an object
  22492        if (is_null())
  22493        {
  22494            m_data.m_type = value_t::object;
  22495            m_data.m_value = value_t::object;
  22496            assert_invariant();
  22497        }
  22498 
  22499        // add element to object
  22500        auto res = m_data.m_value.object->insert(val);
  22501        set_parent(res.first->second);
  22502    }
  22503 
  22504    /// @brief add an object to an object
  22505    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22506    reference operator+=(const typename object_t::value_type& val)
  22507    {
  22508        push_back(val);
  22509        return *this;
  22510    }
  22511 
  22512    /// @brief add an object to an object
  22513    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
  22514    void push_back(initializer_list_t init)
  22515    {
  22516        if (is_object() && init.size() == 2 && (*init.begin())->is_string())
  22517        {
  22518            basic_json&& key = init.begin()->moved_or_copied();
  22519            push_back(typename object_t::value_type(
  22520                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
  22521        }
  22522        else
  22523        {
  22524            push_back(basic_json(init));
  22525        }
  22526    }
  22527 
  22528    /// @brief add an object to an object
  22529    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
  22530    reference operator+=(initializer_list_t init)
  22531    {
  22532        push_back(init);
  22533        return *this;
  22534    }
  22535 
  22536    /// @brief add an object to an array
  22537    /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
  22538    template<class... Args>
  22539    reference emplace_back(Args&& ... args)
  22540    {
  22541        // emplace_back only works for null objects or arrays
  22542        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
  22543        {
  22544            JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
  22545        }
  22546 
  22547        // transform null object into an array
  22548        if (is_null())
  22549        {
  22550            m_data.m_type = value_t::array;
  22551            m_data.m_value = value_t::array;
  22552            assert_invariant();
  22553        }
  22554 
  22555        // add element to array (perfect forwarding)
  22556        const auto old_capacity = m_data.m_value.array->capacity();
  22557        m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
  22558        return set_parent(m_data.m_value.array->back(), old_capacity);
  22559    }
  22560 
  22561    /// @brief add an object to an object if key does not exist
  22562    /// @sa https://json.nlohmann.me/api/basic_json/emplace/
  22563    template<class... Args>
  22564    std::pair<iterator, bool> emplace(Args&& ... args)
  22565    {
  22566        // emplace only works for null objects or arrays
  22567        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
  22568        {
  22569            JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
  22570        }
  22571 
  22572        // transform null object into an object
  22573        if (is_null())
  22574        {
  22575            m_data.m_type = value_t::object;
  22576            m_data.m_value = value_t::object;
  22577            assert_invariant();
  22578        }
  22579 
  22580        // add element to array (perfect forwarding)
  22581        auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
  22582        set_parent(res.first->second);
  22583 
  22584        // create result iterator and set iterator to the result of emplace
  22585        auto it = begin();
  22586        it.m_it.object_iterator = res.first;
  22587 
  22588        // return pair of iterator and boolean
  22589        return {it, res.second};
  22590    }
  22591 
  22592    /// Helper for insertion of an iterator
  22593    /// @note: This uses std::distance to support GCC 4.8,
  22594    ///        see https://github.com/nlohmann/json/pull/1257
  22595    template<typename... Args>
  22596    iterator insert_iterator(const_iterator pos, Args&& ... args)
  22597    {
  22598        iterator result(this);
  22599        JSON_ASSERT(m_data.m_value.array != nullptr);
  22600 
  22601        auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
  22602        m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
  22603        result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
  22604 
  22605        // This could have been written as:
  22606        // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
  22607        // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
  22608 
  22609        set_parents();
  22610        return result;
  22611    }
  22612 
  22613    /// @brief inserts element into array
  22614    /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22615    iterator insert(const_iterator pos, const basic_json& val)
  22616    {
  22617        // insert only works for arrays
  22618        if (JSON_HEDLEY_LIKELY(is_array()))
  22619        {
  22620            // check if iterator pos fits to this JSON value
  22621            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22622            {
  22623                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22624            }
  22625 
  22626            // insert to array and return iterator
  22627            return insert_iterator(pos, val);
  22628        }
  22629 
  22630        JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22631    }
  22632 
  22633    /// @brief inserts element into array
  22634    /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22635    iterator insert(const_iterator pos, basic_json&& val)
  22636    {
  22637        return insert(pos, val);
  22638    }
  22639 
  22640    /// @brief inserts copies of element into array
  22641    /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22642    iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
  22643    {
  22644        // insert only works for arrays
  22645        if (JSON_HEDLEY_LIKELY(is_array()))
  22646        {
  22647            // check if iterator pos fits to this JSON value
  22648            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22649            {
  22650                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22651            }
  22652 
  22653            // insert to array and return iterator
  22654            return insert_iterator(pos, cnt, val);
  22655        }
  22656 
  22657        JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22658    }
  22659 
  22660    /// @brief inserts range of elements into array
  22661    /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22662    iterator insert(const_iterator pos, const_iterator first, const_iterator last)
  22663    {
  22664        // insert only works for arrays
  22665        if (JSON_HEDLEY_UNLIKELY(!is_array()))
  22666        {
  22667            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22668        }
  22669 
  22670        // check if iterator pos fits to this JSON value
  22671        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22672        {
  22673            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22674        }
  22675 
  22676        // check if range iterators belong to the same JSON object
  22677        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  22678        {
  22679            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
  22680        }
  22681 
  22682        if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
  22683        {
  22684            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
  22685        }
  22686 
  22687        // insert to array and return iterator
  22688        return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
  22689    }
  22690 
  22691    /// @brief inserts elements from initializer list into array
  22692    /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22693    iterator insert(const_iterator pos, initializer_list_t ilist)
  22694    {
  22695        // insert only works for arrays
  22696        if (JSON_HEDLEY_UNLIKELY(!is_array()))
  22697        {
  22698            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22699        }
  22700 
  22701        // check if iterator pos fits to this JSON value
  22702        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
  22703        {
  22704            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
  22705        }
  22706 
  22707        // insert to array and return iterator
  22708        return insert_iterator(pos, ilist.begin(), ilist.end());
  22709    }
  22710 
  22711    /// @brief inserts range of elements into object
  22712    /// @sa https://json.nlohmann.me/api/basic_json/insert/
  22713    void insert(const_iterator first, const_iterator last)
  22714    {
  22715        // insert only works for objects
  22716        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  22717        {
  22718            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
  22719        }
  22720 
  22721        // check if range iterators belong to the same JSON object
  22722        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  22723        {
  22724            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
  22725        }
  22726 
  22727        // passed iterators must belong to objects
  22728        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
  22729        {
  22730            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
  22731        }
  22732 
  22733        m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
  22734    }
  22735 
  22736    /// @brief updates a JSON object from another object, overwriting existing keys
  22737    /// @sa https://json.nlohmann.me/api/basic_json/update/
  22738    void update(const_reference j, bool merge_objects = false)
  22739    {
  22740        update(j.begin(), j.end(), merge_objects);
  22741    }
  22742 
  22743    /// @brief updates a JSON object from another object, overwriting existing keys
  22744    /// @sa https://json.nlohmann.me/api/basic_json/update/
  22745    void update(const_iterator first, const_iterator last, bool merge_objects = false)
  22746    {
  22747        // implicitly convert null value to an empty object
  22748        if (is_null())
  22749        {
  22750            m_data.m_type = value_t::object;
  22751            m_data.m_value.object = create<object_t>();
  22752            assert_invariant();
  22753        }
  22754 
  22755        if (JSON_HEDLEY_UNLIKELY(!is_object()))
  22756        {
  22757            JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
  22758        }
  22759 
  22760        // check if range iterators belong to the same JSON object
  22761        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
  22762        {
  22763            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
  22764        }
  22765 
  22766        // passed iterators must belong to objects
  22767        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
  22768        {
  22769            JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
  22770        }
  22771 
  22772        for (auto it = first; it != last; ++it)
  22773        {
  22774            if (merge_objects && it.value().is_object())
  22775            {
  22776                auto it2 = m_data.m_value.object->find(it.key());
  22777                if (it2 != m_data.m_value.object->end())
  22778                {
  22779                    it2->second.update(it.value(), true);
  22780                    continue;
  22781                }
  22782            }
  22783            m_data.m_value.object->operator[](it.key()) = it.value();
  22784 #if JSON_DIAGNOSTICS
  22785            m_data.m_value.object->operator[](it.key()).m_parent = this;
  22786 #endif
  22787        }
  22788    }
  22789 
  22790    /// @brief exchanges the values
  22791    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22792    void swap(reference other) noexcept (
  22793        std::is_nothrow_move_constructible<value_t>::value&&
  22794        std::is_nothrow_move_assignable<value_t>::value&&
  22795        std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  22796        std::is_nothrow_move_assignable<json_value>::value
  22797    )
  22798    {
  22799        std::swap(m_data.m_type, other.m_data.m_type);
  22800        std::swap(m_data.m_value, other.m_data.m_value);
  22801 
  22802        set_parents();
  22803        other.set_parents();
  22804        assert_invariant();
  22805    }
  22806 
  22807    /// @brief exchanges the values
  22808    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22809    friend void swap(reference left, reference right) noexcept (
  22810        std::is_nothrow_move_constructible<value_t>::value&&
  22811        std::is_nothrow_move_assignable<value_t>::value&&
  22812        std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  22813        std::is_nothrow_move_assignable<json_value>::value
  22814    )
  22815    {
  22816        left.swap(right);
  22817    }
  22818 
  22819    /// @brief exchanges the values
  22820    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22821    void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  22822    {
  22823        // swap only works for arrays
  22824        if (JSON_HEDLEY_LIKELY(is_array()))
  22825        {
  22826            using std::swap;
  22827            swap(*(m_data.m_value.array), other);
  22828        }
  22829        else
  22830        {
  22831            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
  22832        }
  22833    }
  22834 
  22835    /// @brief exchanges the values
  22836    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22837    void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  22838    {
  22839        // swap only works for objects
  22840        if (JSON_HEDLEY_LIKELY(is_object()))
  22841        {
  22842            using std::swap;
  22843            swap(*(m_data.m_value.object), other);
  22844        }
  22845        else
  22846        {
  22847            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
  22848        }
  22849    }
  22850 
  22851    /// @brief exchanges the values
  22852    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22853    void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  22854    {
  22855        // swap only works for strings
  22856        if (JSON_HEDLEY_LIKELY(is_string()))
  22857        {
  22858            using std::swap;
  22859            swap(*(m_data.m_value.string), other);
  22860        }
  22861        else
  22862        {
  22863            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
  22864        }
  22865    }
  22866 
  22867    /// @brief exchanges the values
  22868    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22869    void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  22870    {
  22871        // swap only works for strings
  22872        if (JSON_HEDLEY_LIKELY(is_binary()))
  22873        {
  22874            using std::swap;
  22875            swap(*(m_data.m_value.binary), other);
  22876        }
  22877        else
  22878        {
  22879            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
  22880        }
  22881    }
  22882 
  22883    /// @brief exchanges the values
  22884    /// @sa https://json.nlohmann.me/api/basic_json/swap/
  22885    void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
  22886    {
  22887        // swap only works for strings
  22888        if (JSON_HEDLEY_LIKELY(is_binary()))
  22889        {
  22890            using std::swap;
  22891            swap(*(m_data.m_value.binary), other);
  22892        }
  22893        else
  22894        {
  22895            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
  22896        }
  22897    }
  22898 
  22899    /// @}
  22900 
  22901    //////////////////////////////////////////
  22902    // lexicographical comparison operators //
  22903    //////////////////////////////////////////
  22904 
  22905    /// @name lexicographical comparison operators
  22906    /// @{
  22907 
  22908    // note parentheses around operands are necessary; see
  22909    // https://github.com/nlohmann/json/issues/1530
  22910 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
  22911    const auto lhs_type = lhs.type();                                                                    \
  22912    const auto rhs_type = rhs.type();                                                                    \
  22913    \
  22914    if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
  22915    {                                                                                                    \
  22916        switch (lhs_type)                                                                                \
  22917        {                                                                                                \
  22918            case value_t::array:                                                                         \
  22919                return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array);                                     \
  22920                \
  22921            case value_t::object:                                                                        \
  22922                return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object);                                   \
  22923                \
  22924            case value_t::null:                                                                          \
  22925                return (null_result);                                                                    \
  22926                \
  22927            case value_t::string:                                                                        \
  22928                return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string);                                   \
  22929                \
  22930            case value_t::boolean:                                                                       \
  22931                return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean);                                   \
  22932                \
  22933            case value_t::number_integer:                                                                \
  22934                return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer);                     \
  22935                \
  22936            case value_t::number_unsigned:                                                               \
  22937                return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned);                   \
  22938                \
  22939            case value_t::number_float:                                                                  \
  22940                return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float);                         \
  22941                \
  22942            case value_t::binary:                                                                        \
  22943                return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary);                                   \
  22944                \
  22945            case value_t::discarded:                                                                     \
  22946            default:                                                                                     \
  22947                return (unordered_result);                                                               \
  22948        }                                                                                                \
  22949    }                                                                                                    \
  22950    else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
  22951    {                                                                                                    \
  22952        return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float;      \
  22953    }                                                                                                    \
  22954    else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
  22955    {                                                                                                    \
  22956        return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer);      \
  22957    }                                                                                                    \
  22958    else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
  22959    {                                                                                                    \
  22960        return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float;     \
  22961    }                                                                                                    \
  22962    else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
  22963    {                                                                                                    \
  22964        return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned);     \
  22965    }                                                                                                    \
  22966    else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
  22967    {                                                                                                    \
  22968        return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
  22969    }                                                                                                    \
  22970    else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
  22971    {                                                                                                    \
  22972        return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
  22973    }                                                                                                    \
  22974    else if(compares_unordered(lhs, rhs))\
  22975    {\
  22976        return (unordered_result);\
  22977    }\
  22978    \
  22979    return (default_result);
  22980 
  22981  JSON_PRIVATE_UNLESS_TESTED:
  22982    // returns true if:
  22983    // - any operand is NaN and the other operand is of number type
  22984    // - any operand is discarded
  22985    // in legacy mode, discarded values are considered ordered if
  22986    // an operation is computed as an odd number of inverses of others
  22987    static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
  22988    {
  22989        if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
  22990                || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
  22991        {
  22992            return true;
  22993        }
  22994 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
  22995        return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
  22996 #else
  22997        static_cast<void>(inverse);
  22998        return lhs.is_discarded() || rhs.is_discarded();
  22999 #endif
  23000    }
  23001 
  23002  private:
  23003    bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
  23004    {
  23005        return compares_unordered(*this, rhs, inverse);
  23006    }
  23007 
  23008  public:
  23009 #if JSON_HAS_THREE_WAY_COMPARISON
  23010    /// @brief comparison: equal
  23011    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  23012    bool operator==(const_reference rhs) const noexcept
  23013    {
  23014 #ifdef __GNUC__
  23015 #pragma GCC diagnostic push
  23016 #pragma GCC diagnostic ignored "-Wfloat-equal"
  23017 #endif
  23018        const_reference lhs = *this;
  23019        JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
  23020 #ifdef __GNUC__
  23021 #pragma GCC diagnostic pop
  23022 #endif
  23023    }
  23024 
  23025    /// @brief comparison: equal
  23026    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  23027    template<typename ScalarType>
  23028    requires std::is_scalar_v<ScalarType>
  23029    bool operator==(ScalarType rhs) const noexcept
  23030    {
  23031        return *this == basic_json(rhs);
  23032    }
  23033 
  23034    /// @brief comparison: not equal
  23035    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  23036    bool operator!=(const_reference rhs) const noexcept
  23037    {
  23038        if (compares_unordered(rhs, true))
  23039        {
  23040            return false;
  23041        }
  23042        return !operator==(rhs);
  23043    }
  23044 
  23045    /// @brief comparison: 3-way
  23046    /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
  23047    std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
  23048    {
  23049        const_reference lhs = *this;
  23050        // default_result is used if we cannot compare values. In that case,
  23051        // we compare types.
  23052        JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
  23053                                std::partial_ordering::equivalent,
  23054                                std::partial_ordering::unordered,
  23055                                lhs_type <=> rhs_type) // *NOPAD*
  23056    }
  23057 
  23058    /// @brief comparison: 3-way
  23059    /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
  23060    template<typename ScalarType>
  23061    requires std::is_scalar_v<ScalarType>
  23062    std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
  23063    {
  23064        return *this <=> basic_json(rhs); // *NOPAD*
  23065    }
  23066 
  23067 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
  23068    // all operators that are computed as an odd number of inverses of others
  23069    // need to be overloaded to emulate the legacy comparison behavior
  23070 
  23071    /// @brief comparison: less than or equal
  23072    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23073    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
  23074    bool operator<=(const_reference rhs) const noexcept
  23075    {
  23076        if (compares_unordered(rhs, true))
  23077        {
  23078            return false;
  23079        }
  23080        return !(rhs < *this);
  23081    }
  23082 
  23083    /// @brief comparison: less than or equal
  23084    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23085    template<typename ScalarType>
  23086    requires std::is_scalar_v<ScalarType>
  23087    bool operator<=(ScalarType rhs) const noexcept
  23088    {
  23089        return *this <= basic_json(rhs);
  23090    }
  23091 
  23092    /// @brief comparison: greater than or equal
  23093    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23094    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
  23095    bool operator>=(const_reference rhs) const noexcept
  23096    {
  23097        if (compares_unordered(rhs, true))
  23098        {
  23099            return false;
  23100        }
  23101        return !(*this < rhs);
  23102    }
  23103 
  23104    /// @brief comparison: greater than or equal
  23105    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23106    template<typename ScalarType>
  23107    requires std::is_scalar_v<ScalarType>
  23108    bool operator>=(ScalarType rhs) const noexcept
  23109    {
  23110        return *this >= basic_json(rhs);
  23111    }
  23112 #endif
  23113 #else
  23114    /// @brief comparison: equal
  23115    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  23116    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
  23117    {
  23118 #ifdef __GNUC__
  23119 #pragma GCC diagnostic push
  23120 #pragma GCC diagnostic ignored "-Wfloat-equal"
  23121 #endif
  23122        JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
  23123 #ifdef __GNUC__
  23124 #pragma GCC diagnostic pop
  23125 #endif
  23126    }
  23127 
  23128    /// @brief comparison: equal
  23129    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  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: equal
  23138    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
  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: not equal
  23147    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  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: not equal
  23158    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  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: not equal
  23167    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
  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 
  23175    /// @brief comparison: less than
  23176    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
  23177    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
  23178    {
  23179        // default_result is used if we cannot compare values. In that case,
  23180        // we compare types. Note we have to call the operator explicitly,
  23181        // because MSVC has problems otherwise.
  23182        JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
  23183    }
  23184 
  23185    /// @brief comparison: less than
  23186    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
  23187    template<typename ScalarType, typename std::enable_if<
  23188                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23189    friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
  23190    {
  23191        return lhs < basic_json(rhs);
  23192    }
  23193 
  23194    /// @brief comparison: less than
  23195    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
  23196    template<typename ScalarType, typename std::enable_if<
  23197                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23198    friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
  23199    {
  23200        return basic_json(lhs) < rhs;
  23201    }
  23202 
  23203    /// @brief comparison: less than or equal
  23204    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23205    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
  23206    {
  23207        if (compares_unordered(lhs, rhs, true))
  23208        {
  23209            return false;
  23210        }
  23211        return !(rhs < lhs);
  23212    }
  23213 
  23214    /// @brief comparison: less than or equal
  23215    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23216    template<typename ScalarType, typename std::enable_if<
  23217                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23218    friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
  23219    {
  23220        return lhs <= basic_json(rhs);
  23221    }
  23222 
  23223    /// @brief comparison: less than or equal
  23224    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
  23225    template<typename ScalarType, typename std::enable_if<
  23226                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23227    friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
  23228    {
  23229        return basic_json(lhs) <= rhs;
  23230    }
  23231 
  23232    /// @brief comparison: greater than
  23233    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
  23234    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
  23235    {
  23236        // double inverse
  23237        if (compares_unordered(lhs, rhs))
  23238        {
  23239            return false;
  23240        }
  23241        return !(lhs <= rhs);
  23242    }
  23243 
  23244    /// @brief comparison: greater than
  23245    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
  23246    template<typename ScalarType, typename std::enable_if<
  23247                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23248    friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
  23249    {
  23250        return lhs > basic_json(rhs);
  23251    }
  23252 
  23253    /// @brief comparison: greater than
  23254    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
  23255    template<typename ScalarType, typename std::enable_if<
  23256                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23257    friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
  23258    {
  23259        return basic_json(lhs) > rhs;
  23260    }
  23261 
  23262    /// @brief comparison: greater than or equal
  23263    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23264    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
  23265    {
  23266        if (compares_unordered(lhs, rhs, true))
  23267        {
  23268            return false;
  23269        }
  23270        return !(lhs < rhs);
  23271    }
  23272 
  23273    /// @brief comparison: greater than or equal
  23274    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23275    template<typename ScalarType, typename std::enable_if<
  23276                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23277    friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
  23278    {
  23279        return lhs >= basic_json(rhs);
  23280    }
  23281 
  23282    /// @brief comparison: greater than or equal
  23283    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
  23284    template<typename ScalarType, typename std::enable_if<
  23285                 std::is_scalar<ScalarType>::value, int>::type = 0>
  23286    friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
  23287    {
  23288        return basic_json(lhs) >= rhs;
  23289    }
  23290 #endif
  23291 
  23292 #undef JSON_IMPLEMENT_OPERATOR
  23293 
  23294    /// @}
  23295 
  23296    ///////////////////
  23297    // serialization //
  23298    ///////////////////
  23299 
  23300    /// @name serialization
  23301    /// @{
  23302 #ifndef JSON_NO_IO
  23303    /// @brief serialize to stream
  23304    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
  23305    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
  23306    {
  23307        // read width member and use it as indentation parameter if nonzero
  23308        const bool pretty_print = o.width() > 0;
  23309        const auto indentation = pretty_print ? o.width() : 0;
  23310 
  23311        // reset width to 0 for subsequent calls to this stream
  23312        o.width(0);
  23313 
  23314        // do the actual serialization
  23315        serializer s(detail::output_adapter<char>(o), o.fill());
  23316        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
  23317        return o;
  23318    }
  23319 
  23320    /// @brief serialize to stream
  23321    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
  23322    /// @deprecated This function is deprecated since 3.0.0 and will be removed in
  23323    ///             version 4.0.0 of the library. Please use
  23324    ///             operator<<(std::ostream&, const basic_json&) instead; that is,
  23325    ///             replace calls like `j >> o;` with `o << j;`.
  23326    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
  23327    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
  23328    {
  23329        return o << j;
  23330    }
  23331 #endif  // JSON_NO_IO
  23332    /// @}
  23333 
  23334    /////////////////////
  23335    // deserialization //
  23336    /////////////////////
  23337 
  23338    /// @name deserialization
  23339    /// @{
  23340 
  23341    /// @brief deserialize from a compatible input
  23342    /// @sa https://json.nlohmann.me/api/basic_json/parse/
  23343    template<typename InputType>
  23344    JSON_HEDLEY_WARN_UNUSED_RESULT
  23345    static basic_json parse(InputType&& i,
  23346                            const parser_callback_t cb = nullptr,
  23347                            const bool allow_exceptions = true,
  23348                            const bool ignore_comments = false)
  23349    {
  23350        basic_json result;
  23351        parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
  23352        return result;
  23353    }
  23354 
  23355    /// @brief deserialize from a pair of character iterators
  23356    /// @sa https://json.nlohmann.me/api/basic_json/parse/
  23357    template<typename IteratorType>
  23358    JSON_HEDLEY_WARN_UNUSED_RESULT
  23359    static basic_json parse(IteratorType first,
  23360                            IteratorType last,
  23361                            const parser_callback_t cb = nullptr,
  23362                            const bool allow_exceptions = true,
  23363                            const bool ignore_comments = false)
  23364    {
  23365        basic_json result;
  23366        parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
  23367        return result;
  23368    }
  23369 
  23370    JSON_HEDLEY_WARN_UNUSED_RESULT
  23371    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
  23372    static basic_json parse(detail::span_input_adapter&& i,
  23373                            const parser_callback_t cb = nullptr,
  23374                            const bool allow_exceptions = true,
  23375                            const bool ignore_comments = false)
  23376    {
  23377        basic_json result;
  23378        parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
  23379        return result;
  23380    }
  23381 
  23382    /// @brief check if the input is valid JSON
  23383    /// @sa https://json.nlohmann.me/api/basic_json/accept/
  23384    template<typename InputType>
  23385    static bool accept(InputType&& i,
  23386                       const bool ignore_comments = false)
  23387    {
  23388        return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
  23389    }
  23390 
  23391    /// @brief check if the input is valid JSON
  23392    /// @sa https://json.nlohmann.me/api/basic_json/accept/
  23393    template<typename IteratorType>
  23394    static bool accept(IteratorType first, IteratorType last,
  23395                       const bool ignore_comments = false)
  23396    {
  23397        return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
  23398    }
  23399 
  23400    JSON_HEDLEY_WARN_UNUSED_RESULT
  23401    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
  23402    static bool accept(detail::span_input_adapter&& i,
  23403                       const bool ignore_comments = false)
  23404    {
  23405        return parser(i.get(), nullptr, false, ignore_comments).accept(true);
  23406    }
  23407 
  23408    /// @brief generate SAX events
  23409    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
  23410    template <typename InputType, typename SAX>
  23411    JSON_HEDLEY_NON_NULL(2)
  23412    static bool sax_parse(InputType&& i, SAX* sax,
  23413                          input_format_t format = input_format_t::json,
  23414                          const bool strict = true,
  23415                          const bool ignore_comments = false)
  23416    {
  23417        auto ia = detail::input_adapter(std::forward<InputType>(i));
  23418        return format == input_format_t::json
  23419               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
  23420               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
  23421    }
  23422 
  23423    /// @brief generate SAX events
  23424    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
  23425    template<class IteratorType, class SAX>
  23426    JSON_HEDLEY_NON_NULL(3)
  23427    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
  23428                          input_format_t format = input_format_t::json,
  23429                          const bool strict = true,
  23430                          const bool ignore_comments = false)
  23431    {
  23432        auto ia = detail::input_adapter(std::move(first), std::move(last));
  23433        return format == input_format_t::json
  23434               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
  23435               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
  23436    }
  23437 
  23438    /// @brief generate SAX events
  23439    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
  23440    /// @deprecated This function is deprecated since 3.8.0 and will be removed in
  23441    ///             version 4.0.0 of the library. Please use
  23442    ///             sax_parse(ptr, ptr + len) instead.
  23443    template <typename SAX>
  23444    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
  23445    JSON_HEDLEY_NON_NULL(2)
  23446    static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
  23447                          input_format_t format = input_format_t::json,
  23448                          const bool strict = true,
  23449                          const bool ignore_comments = false)
  23450    {
  23451        auto ia = i.get();
  23452        return format == input_format_t::json
  23453               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23454               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
  23455               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23456               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
  23457    }
  23458 #ifndef JSON_NO_IO
  23459    /// @brief deserialize from stream
  23460    /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
  23461    /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
  23462    ///             version 4.0.0 of the library. Please use
  23463    ///             operator>>(std::istream&, basic_json&) instead; that is,
  23464    ///             replace calls like `j << i;` with `i >> j;`.
  23465    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
  23466    friend std::istream& operator<<(basic_json& j, std::istream& i)
  23467    {
  23468        return operator>>(i, j);
  23469    }
  23470 
  23471    /// @brief deserialize from stream
  23472    /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
  23473    friend std::istream& operator>>(std::istream& i, basic_json& j)
  23474    {
  23475        parser(detail::input_adapter(i)).parse(false, j);
  23476        return i;
  23477    }
  23478 #endif  // JSON_NO_IO
  23479    /// @}
  23480 
  23481    ///////////////////////////
  23482    // convenience functions //
  23483    ///////////////////////////
  23484 
  23485    /// @brief return the type as string
  23486    /// @sa https://json.nlohmann.me/api/basic_json/type_name/
  23487    JSON_HEDLEY_RETURNS_NON_NULL
  23488    const char* type_name() const noexcept
  23489    {
  23490        switch (m_data.m_type)
  23491        {
  23492            case value_t::null:
  23493                return "null";
  23494            case value_t::object:
  23495                return "object";
  23496            case value_t::array:
  23497                return "array";
  23498            case value_t::string:
  23499                return "string";
  23500            case value_t::boolean:
  23501                return "boolean";
  23502            case value_t::binary:
  23503                return "binary";
  23504            case value_t::discarded:
  23505                return "discarded";
  23506            case value_t::number_integer:
  23507            case value_t::number_unsigned:
  23508            case value_t::number_float:
  23509            default:
  23510                return "number";
  23511        }
  23512    }
  23513 
  23514  JSON_PRIVATE_UNLESS_TESTED:
  23515    //////////////////////
  23516    // member variables //
  23517    //////////////////////
  23518 
  23519    struct data
  23520    {
  23521        /// the type of the current element
  23522        value_t m_type = value_t::null;
  23523 
  23524        /// the value of the current element
  23525        json_value m_value = {};
  23526 
  23527        data(const value_t v)
  23528            : m_type(v), m_value(v)
  23529        {
  23530        }
  23531 
  23532        data(size_type cnt, const basic_json& val)
  23533            : m_type(value_t::array)
  23534        {
  23535            m_value.array = create<array_t>(cnt, val);
  23536        }
  23537 
  23538        data() noexcept = default;
  23539        data(data&&) noexcept = default;
  23540        data(const data&) noexcept = delete;
  23541        data& operator=(data&&) noexcept = delete;
  23542        data& operator=(const data&) noexcept = delete;
  23543 
  23544        ~data() noexcept
  23545        {
  23546            m_value.destroy(m_type);
  23547        }
  23548    };
  23549 
  23550    data m_data = {};
  23551 
  23552 #if JSON_DIAGNOSTICS
  23553    /// a pointer to a parent value (for debugging purposes)
  23554    basic_json* m_parent = nullptr;
  23555 #endif
  23556 
  23557    //////////////////////////////////////////
  23558    // binary serialization/deserialization //
  23559    //////////////////////////////////////////
  23560 
  23561    /// @name binary serialization/deserialization support
  23562    /// @{
  23563 
  23564  public:
  23565    /// @brief create a CBOR serialization of a given JSON value
  23566    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
  23567    static std::vector<std::uint8_t> to_cbor(const basic_json& j)
  23568    {
  23569        std::vector<std::uint8_t> result;
  23570        to_cbor(j, result);
  23571        return result;
  23572    }
  23573 
  23574    /// @brief create a CBOR serialization of a given JSON value
  23575    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
  23576    static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
  23577    {
  23578        binary_writer<std::uint8_t>(o).write_cbor(j);
  23579    }
  23580 
  23581    /// @brief create a CBOR serialization of a given JSON value
  23582    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
  23583    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
  23584    {
  23585        binary_writer<char>(o).write_cbor(j);
  23586    }
  23587 
  23588    /// @brief create a MessagePack serialization of a given JSON value
  23589    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
  23590    static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
  23591    {
  23592        std::vector<std::uint8_t> result;
  23593        to_msgpack(j, result);
  23594        return result;
  23595    }
  23596 
  23597    /// @brief create a MessagePack serialization of a given JSON value
  23598    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
  23599    static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
  23600    {
  23601        binary_writer<std::uint8_t>(o).write_msgpack(j);
  23602    }
  23603 
  23604    /// @brief create a MessagePack serialization of a given JSON value
  23605    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
  23606    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
  23607    {
  23608        binary_writer<char>(o).write_msgpack(j);
  23609    }
  23610 
  23611    /// @brief create a UBJSON serialization of a given JSON value
  23612    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
  23613    static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
  23614            const bool use_size = false,
  23615            const bool use_type = false)
  23616    {
  23617        std::vector<std::uint8_t> result;
  23618        to_ubjson(j, result, use_size, use_type);
  23619        return result;
  23620    }
  23621 
  23622    /// @brief create a UBJSON serialization of a given JSON value
  23623    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
  23624    static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
  23625                          const bool use_size = false, const bool use_type = false)
  23626    {
  23627        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
  23628    }
  23629 
  23630    /// @brief create a UBJSON serialization of a given JSON value
  23631    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
  23632    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
  23633                          const bool use_size = false, const bool use_type = false)
  23634    {
  23635        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
  23636    }
  23637 
  23638    /// @brief create a BJData serialization of a given JSON value
  23639    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
  23640    static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
  23641            const bool use_size = false,
  23642            const bool use_type = false)
  23643    {
  23644        std::vector<std::uint8_t> result;
  23645        to_bjdata(j, result, use_size, use_type);
  23646        return result;
  23647    }
  23648 
  23649    /// @brief create a BJData serialization of a given JSON value
  23650    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
  23651    static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
  23652                          const bool use_size = false, const bool use_type = false)
  23653    {
  23654        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
  23655    }
  23656 
  23657    /// @brief create a BJData serialization of a given JSON value
  23658    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
  23659    static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
  23660                          const bool use_size = false, const bool use_type = false)
  23661    {
  23662        binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
  23663    }
  23664 
  23665    /// @brief create a BSON serialization of a given JSON value
  23666    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
  23667    static std::vector<std::uint8_t> to_bson(const basic_json& j)
  23668    {
  23669        std::vector<std::uint8_t> result;
  23670        to_bson(j, result);
  23671        return result;
  23672    }
  23673 
  23674    /// @brief create a BSON serialization of a given JSON value
  23675    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
  23676    static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
  23677    {
  23678        binary_writer<std::uint8_t>(o).write_bson(j);
  23679    }
  23680 
  23681    /// @brief create a BSON serialization of a given JSON value
  23682    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
  23683    static void to_bson(const basic_json& j, detail::output_adapter<char> o)
  23684    {
  23685        binary_writer<char>(o).write_bson(j);
  23686    }
  23687 
  23688    /// @brief create a JSON value from an input in CBOR format
  23689    /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
  23690    template<typename InputType>
  23691    JSON_HEDLEY_WARN_UNUSED_RESULT
  23692    static basic_json from_cbor(InputType&& i,
  23693                                const bool strict = true,
  23694                                const bool allow_exceptions = true,
  23695                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23696    {
  23697        basic_json result;
  23698        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23699        auto ia = detail::input_adapter(std::forward<InputType>(i));
  23700        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
  23701        return res ? result : basic_json(value_t::discarded);
  23702    }
  23703 
  23704    /// @brief create a JSON value from an input in CBOR format
  23705    /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
  23706    template<typename IteratorType>
  23707    JSON_HEDLEY_WARN_UNUSED_RESULT
  23708    static basic_json from_cbor(IteratorType first, IteratorType last,
  23709                                const bool strict = true,
  23710                                const bool allow_exceptions = true,
  23711                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23712    {
  23713        basic_json result;
  23714        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23715        auto ia = detail::input_adapter(std::move(first), std::move(last));
  23716        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
  23717        return res ? result : basic_json(value_t::discarded);
  23718    }
  23719 
  23720    template<typename T>
  23721    JSON_HEDLEY_WARN_UNUSED_RESULT
  23722    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
  23723    static basic_json from_cbor(const T* ptr, std::size_t len,
  23724                                const bool strict = true,
  23725                                const bool allow_exceptions = true,
  23726                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23727    {
  23728        return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
  23729    }
  23730 
  23731    JSON_HEDLEY_WARN_UNUSED_RESULT
  23732    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
  23733    static basic_json from_cbor(detail::span_input_adapter&& i,
  23734                                const bool strict = true,
  23735                                const bool allow_exceptions = true,
  23736                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
  23737    {
  23738        basic_json result;
  23739        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23740        auto ia = i.get();
  23741        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23742        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
  23743        return res ? result : basic_json(value_t::discarded);
  23744    }
  23745 
  23746    /// @brief create a JSON value from an input in MessagePack format
  23747    /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
  23748    template<typename InputType>
  23749    JSON_HEDLEY_WARN_UNUSED_RESULT
  23750    static basic_json from_msgpack(InputType&& i,
  23751                                   const bool strict = true,
  23752                                   const bool allow_exceptions = true)
  23753    {
  23754        basic_json result;
  23755        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23756        auto ia = detail::input_adapter(std::forward<InputType>(i));
  23757        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
  23758        return res ? result : basic_json(value_t::discarded);
  23759    }
  23760 
  23761    /// @brief create a JSON value from an input in MessagePack format
  23762    /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
  23763    template<typename IteratorType>
  23764    JSON_HEDLEY_WARN_UNUSED_RESULT
  23765    static basic_json from_msgpack(IteratorType first, IteratorType last,
  23766                                   const bool strict = true,
  23767                                   const bool allow_exceptions = true)
  23768    {
  23769        basic_json result;
  23770        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23771        auto ia = detail::input_adapter(std::move(first), std::move(last));
  23772        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
  23773        return res ? result : basic_json(value_t::discarded);
  23774    }
  23775 
  23776    template<typename T>
  23777    JSON_HEDLEY_WARN_UNUSED_RESULT
  23778    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
  23779    static basic_json from_msgpack(const T* ptr, std::size_t len,
  23780                                   const bool strict = true,
  23781                                   const bool allow_exceptions = true)
  23782    {
  23783        return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
  23784    }
  23785 
  23786    JSON_HEDLEY_WARN_UNUSED_RESULT
  23787    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
  23788    static basic_json from_msgpack(detail::span_input_adapter&& i,
  23789                                   const bool strict = true,
  23790                                   const bool allow_exceptions = true)
  23791    {
  23792        basic_json result;
  23793        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23794        auto ia = i.get();
  23795        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23796        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
  23797        return res ? result : basic_json(value_t::discarded);
  23798    }
  23799 
  23800    /// @brief create a JSON value from an input in UBJSON format
  23801    /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
  23802    template<typename InputType>
  23803    JSON_HEDLEY_WARN_UNUSED_RESULT
  23804    static basic_json from_ubjson(InputType&& i,
  23805                                  const bool strict = true,
  23806                                  const bool allow_exceptions = true)
  23807    {
  23808        basic_json result;
  23809        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23810        auto ia = detail::input_adapter(std::forward<InputType>(i));
  23811        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
  23812        return res ? result : basic_json(value_t::discarded);
  23813    }
  23814 
  23815    /// @brief create a JSON value from an input in UBJSON format
  23816    /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
  23817    template<typename IteratorType>
  23818    JSON_HEDLEY_WARN_UNUSED_RESULT
  23819    static basic_json from_ubjson(IteratorType first, IteratorType last,
  23820                                  const bool strict = true,
  23821                                  const bool allow_exceptions = true)
  23822    {
  23823        basic_json result;
  23824        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23825        auto ia = detail::input_adapter(std::move(first), std::move(last));
  23826        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
  23827        return res ? result : basic_json(value_t::discarded);
  23828    }
  23829 
  23830    template<typename T>
  23831    JSON_HEDLEY_WARN_UNUSED_RESULT
  23832    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
  23833    static basic_json from_ubjson(const T* ptr, std::size_t len,
  23834                                  const bool strict = true,
  23835                                  const bool allow_exceptions = true)
  23836    {
  23837        return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
  23838    }
  23839 
  23840    JSON_HEDLEY_WARN_UNUSED_RESULT
  23841    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
  23842    static basic_json from_ubjson(detail::span_input_adapter&& i,
  23843                                  const bool strict = true,
  23844                                  const bool allow_exceptions = true)
  23845    {
  23846        basic_json result;
  23847        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23848        auto ia = i.get();
  23849        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23850        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
  23851        return res ? result : basic_json(value_t::discarded);
  23852    }
  23853 
  23854    /// @brief create a JSON value from an input in BJData format
  23855    /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
  23856    template<typename InputType>
  23857    JSON_HEDLEY_WARN_UNUSED_RESULT
  23858    static basic_json from_bjdata(InputType&& i,
  23859                                  const bool strict = true,
  23860                                  const bool allow_exceptions = true)
  23861    {
  23862        basic_json result;
  23863        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23864        auto ia = detail::input_adapter(std::forward<InputType>(i));
  23865        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
  23866        return res ? result : basic_json(value_t::discarded);
  23867    }
  23868 
  23869    /// @brief create a JSON value from an input in BJData format
  23870    /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
  23871    template<typename IteratorType>
  23872    JSON_HEDLEY_WARN_UNUSED_RESULT
  23873    static basic_json from_bjdata(IteratorType first, IteratorType last,
  23874                                  const bool strict = true,
  23875                                  const bool allow_exceptions = true)
  23876    {
  23877        basic_json result;
  23878        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23879        auto ia = detail::input_adapter(std::move(first), std::move(last));
  23880        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
  23881        return res ? result : basic_json(value_t::discarded);
  23882    }
  23883 
  23884    /// @brief create a JSON value from an input in BSON format
  23885    /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
  23886    template<typename InputType>
  23887    JSON_HEDLEY_WARN_UNUSED_RESULT
  23888    static basic_json from_bson(InputType&& i,
  23889                                const bool strict = true,
  23890                                const bool allow_exceptions = true)
  23891    {
  23892        basic_json result;
  23893        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23894        auto ia = detail::input_adapter(std::forward<InputType>(i));
  23895        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
  23896        return res ? result : basic_json(value_t::discarded);
  23897    }
  23898 
  23899    /// @brief create a JSON value from an input in BSON format
  23900    /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
  23901    template<typename IteratorType>
  23902    JSON_HEDLEY_WARN_UNUSED_RESULT
  23903    static basic_json from_bson(IteratorType first, IteratorType last,
  23904                                const bool strict = true,
  23905                                const bool allow_exceptions = true)
  23906    {
  23907        basic_json result;
  23908        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23909        auto ia = detail::input_adapter(std::move(first), std::move(last));
  23910        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
  23911        return res ? result : basic_json(value_t::discarded);
  23912    }
  23913 
  23914    template<typename T>
  23915    JSON_HEDLEY_WARN_UNUSED_RESULT
  23916    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
  23917    static basic_json from_bson(const T* ptr, std::size_t len,
  23918                                const bool strict = true,
  23919                                const bool allow_exceptions = true)
  23920    {
  23921        return from_bson(ptr, ptr + len, strict, allow_exceptions);
  23922    }
  23923 
  23924    JSON_HEDLEY_WARN_UNUSED_RESULT
  23925    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
  23926    static basic_json from_bson(detail::span_input_adapter&& i,
  23927                                const bool strict = true,
  23928                                const bool allow_exceptions = true)
  23929    {
  23930        basic_json result;
  23931        detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
  23932        auto ia = i.get();
  23933        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
  23934        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
  23935        return res ? result : basic_json(value_t::discarded);
  23936    }
  23937    /// @}
  23938 
  23939    //////////////////////////
  23940    // JSON Pointer support //
  23941    //////////////////////////
  23942 
  23943    /// @name JSON Pointer functions
  23944    /// @{
  23945 
  23946    /// @brief access specified element via JSON Pointer
  23947    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  23948    reference operator[](const json_pointer& ptr)
  23949    {
  23950        return ptr.get_unchecked(this);
  23951    }
  23952 
  23953    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23954    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23955    reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
  23956    {
  23957        return ptr.get_unchecked(this);
  23958    }
  23959 
  23960    /// @brief access specified element via JSON Pointer
  23961    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
  23962    const_reference operator[](const json_pointer& ptr) const
  23963    {
  23964        return ptr.get_unchecked(this);
  23965    }
  23966 
  23967    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23968    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23969    const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
  23970    {
  23971        return ptr.get_unchecked(this);
  23972    }
  23973 
  23974    /// @brief access specified element via JSON Pointer
  23975    /// @sa https://json.nlohmann.me/api/basic_json/at/
  23976    reference at(const json_pointer& ptr)
  23977    {
  23978        return ptr.get_checked(this);
  23979    }
  23980 
  23981    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23982    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23983    reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
  23984    {
  23985        return ptr.get_checked(this);
  23986    }
  23987 
  23988    /// @brief access specified element via JSON Pointer
  23989    /// @sa https://json.nlohmann.me/api/basic_json/at/
  23990    const_reference at(const json_pointer& ptr) const
  23991    {
  23992        return ptr.get_checked(this);
  23993    }
  23994 
  23995    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
  23996    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
  23997    const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
  23998    {
  23999        return ptr.get_checked(this);
  24000    }
  24001 
  24002    /// @brief return flattened JSON value
  24003    /// @sa https://json.nlohmann.me/api/basic_json/flatten/
  24004    basic_json flatten() const
  24005    {
  24006        basic_json result(value_t::object);
  24007        json_pointer::flatten("", *this, result);
  24008        return result;
  24009    }
  24010 
  24011    /// @brief unflatten a previously flattened JSON value
  24012    /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
  24013    basic_json unflatten() const
  24014    {
  24015        return json_pointer::unflatten(*this);
  24016    }
  24017 
  24018    /// @}
  24019 
  24020    //////////////////////////
  24021    // JSON Patch functions //
  24022    //////////////////////////
  24023 
  24024    /// @name JSON Patch functions
  24025    /// @{
  24026 
  24027    /// @brief applies a JSON patch in-place without copying the object
  24028    /// @sa https://json.nlohmann.me/api/basic_json/patch/
  24029    void patch_inplace(const basic_json& json_patch)
  24030    {
  24031        basic_json& result = *this;
  24032        // the valid JSON Patch operations
  24033        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
  24034 
  24035        const auto get_op = [](const std::string & op)
  24036        {
  24037            if (op == "add")
  24038            {
  24039                return patch_operations::add;
  24040            }
  24041            if (op == "remove")
  24042            {
  24043                return patch_operations::remove;
  24044            }
  24045            if (op == "replace")
  24046            {
  24047                return patch_operations::replace;
  24048            }
  24049            if (op == "move")
  24050            {
  24051                return patch_operations::move;
  24052            }
  24053            if (op == "copy")
  24054            {
  24055                return patch_operations::copy;
  24056            }
  24057            if (op == "test")
  24058            {
  24059                return patch_operations::test;
  24060            }
  24061 
  24062            return patch_operations::invalid;
  24063        };
  24064 
  24065        // wrapper for "add" operation; add value at ptr
  24066        const auto operation_add = [&result](json_pointer & ptr, basic_json val)
  24067        {
  24068            // adding to the root of the target document means replacing it
  24069            if (ptr.empty())
  24070            {
  24071                result = val;
  24072                return;
  24073            }
  24074 
  24075            // make sure the top element of the pointer exists
  24076            json_pointer const top_pointer = ptr.top();
  24077            if (top_pointer != ptr)
  24078            {
  24079                result.at(top_pointer);
  24080            }
  24081 
  24082            // get reference to parent of JSON pointer ptr
  24083            const auto last_path = ptr.back();
  24084            ptr.pop_back();
  24085            // parent must exist when performing patch add per RFC6902 specs
  24086            basic_json& parent = result.at(ptr);
  24087 
  24088            switch (parent.m_data.m_type)
  24089            {
  24090                case value_t::null:
  24091                case value_t::object:
  24092                {
  24093                    // use operator[] to add value
  24094                    parent[last_path] = val;
  24095                    break;
  24096                }
  24097 
  24098                case value_t::array:
  24099                {
  24100                    if (last_path == "-")
  24101                    {
  24102                        // special case: append to back
  24103                        parent.push_back(val);
  24104                    }
  24105                    else
  24106                    {
  24107                        const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
  24108                        if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
  24109                        {
  24110                            // avoid undefined behavior
  24111                            JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
  24112                        }
  24113 
  24114                        // default case: insert add offset
  24115                        parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
  24116                    }
  24117                    break;
  24118                }
  24119 
  24120                // if there exists a parent it cannot be primitive
  24121                case value_t::string: // LCOV_EXCL_LINE
  24122                case value_t::boolean: // LCOV_EXCL_LINE
  24123                case value_t::number_integer: // LCOV_EXCL_LINE
  24124                case value_t::number_unsigned: // LCOV_EXCL_LINE
  24125                case value_t::number_float: // LCOV_EXCL_LINE
  24126                case value_t::binary: // LCOV_EXCL_LINE
  24127                case value_t::discarded: // LCOV_EXCL_LINE
  24128                default:            // LCOV_EXCL_LINE
  24129                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
  24130            }
  24131        };
  24132 
  24133        // wrapper for "remove" operation; remove value at ptr
  24134        const auto operation_remove = [this, & result](json_pointer & ptr)
  24135        {
  24136            // get reference to parent of JSON pointer ptr
  24137            const auto last_path = ptr.back();
  24138            ptr.pop_back();
  24139            basic_json& parent = result.at(ptr);
  24140 
  24141            // remove child
  24142            if (parent.is_object())
  24143            {
  24144                // perform range check
  24145                auto it = parent.find(last_path);
  24146                if (JSON_HEDLEY_LIKELY(it != parent.end()))
  24147                {
  24148                    parent.erase(it);
  24149                }
  24150                else
  24151                {
  24152                    JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
  24153                }
  24154            }
  24155            else if (parent.is_array())
  24156            {
  24157                // note erase performs range check
  24158                parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
  24159            }
  24160        };
  24161 
  24162        // type check: top level value must be an array
  24163        if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
  24164        {
  24165            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
  24166        }
  24167 
  24168        // iterate and apply the operations
  24169        for (const auto& val : json_patch)
  24170        {
  24171            // wrapper to get a value for an operation
  24172            const auto get_value = [&val](const std::string & op,
  24173                                          const std::string & member,
  24174                                          bool string_type) -> basic_json &
  24175            {
  24176                // find value
  24177                auto it = val.m_data.m_value.object->find(member);
  24178 
  24179                // context-sensitive error message
  24180                const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
  24181 
  24182                // check if desired value is present
  24183                if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
  24184                {
  24185                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
  24186                    JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
  24187                }
  24188 
  24189                // check if result is of type string
  24190                if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
  24191                {
  24192                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
  24193                    JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
  24194                }
  24195 
  24196                // no error: return value
  24197                return it->second;
  24198            };
  24199 
  24200            // type check: every element of the array must be an object
  24201            if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
  24202            {
  24203                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
  24204            }
  24205 
  24206            // collect mandatory members
  24207            const auto op = get_value("op", "op", true).template get<std::string>();
  24208            const auto path = get_value(op, "path", true).template get<std::string>();
  24209            json_pointer ptr(path);
  24210 
  24211            switch (get_op(op))
  24212            {
  24213                case patch_operations::add:
  24214                {
  24215                    operation_add(ptr, get_value("add", "value", false));
  24216                    break;
  24217                }
  24218 
  24219                case patch_operations::remove:
  24220                {
  24221                    operation_remove(ptr);
  24222                    break;
  24223                }
  24224 
  24225                case patch_operations::replace:
  24226                {
  24227                    // the "path" location must exist - use at()
  24228                    result.at(ptr) = get_value("replace", "value", false);
  24229                    break;
  24230                }
  24231 
  24232                case patch_operations::move:
  24233                {
  24234                    const auto from_path = get_value("move", "from", true).template get<std::string>();
  24235                    json_pointer from_ptr(from_path);
  24236 
  24237                    // the "from" location must exist - use at()
  24238                    basic_json const v = result.at(from_ptr);
  24239 
  24240                    // The move operation is functionally identical to a
  24241                    // "remove" operation on the "from" location, followed
  24242                    // immediately by an "add" operation at the target
  24243                    // location with the value that was just removed.
  24244                    operation_remove(from_ptr);
  24245                    operation_add(ptr, v);
  24246                    break;
  24247                }
  24248 
  24249                case patch_operations::copy:
  24250                {
  24251                    const auto from_path = get_value("copy", "from", true).template get<std::string>();
  24252                    const json_pointer from_ptr(from_path);
  24253 
  24254                    // the "from" location must exist - use at()
  24255                    basic_json const v = result.at(from_ptr);
  24256 
  24257                    // The copy is functionally identical to an "add"
  24258                    // operation at the target location using the value
  24259                    // specified in the "from" member.
  24260                    operation_add(ptr, v);
  24261                    break;
  24262                }
  24263 
  24264                case patch_operations::test:
  24265                {
  24266                    bool success = false;
  24267                    JSON_TRY
  24268                    {
  24269                        // check if "value" matches the one at "path"
  24270                        // the "path" location must exist - use at()
  24271                        success = (result.at(ptr) == get_value("test", "value", false));
  24272                    }
  24273                    JSON_INTERNAL_CATCH (out_of_range&)
  24274                    {
  24275                        // ignore out of range errors: success remains false
  24276                    }
  24277 
  24278                    // throw an exception if test fails
  24279                    if (JSON_HEDLEY_UNLIKELY(!success))
  24280                    {
  24281                        JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
  24282                    }
  24283 
  24284                    break;
  24285                }
  24286 
  24287                case patch_operations::invalid:
  24288                default:
  24289                {
  24290                    // op must be "add", "remove", "replace", "move", "copy", or
  24291                    // "test"
  24292                    JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
  24293                }
  24294            }
  24295        }
  24296    }
  24297 
  24298    /// @brief applies a JSON patch to a copy of the current object
  24299    /// @sa https://json.nlohmann.me/api/basic_json/patch/
  24300    basic_json patch(const basic_json& json_patch) const
  24301    {
  24302        basic_json result = *this;
  24303        result.patch_inplace(json_patch);
  24304        return result;
  24305    }
  24306 
  24307    /// @brief creates a diff as a JSON patch
  24308    /// @sa https://json.nlohmann.me/api/basic_json/diff/
  24309    JSON_HEDLEY_WARN_UNUSED_RESULT
  24310    static basic_json diff(const basic_json& source, const basic_json& target,
  24311                           const std::string& path = "")
  24312    {
  24313        // the patch
  24314        basic_json result(value_t::array);
  24315 
  24316        // if the values are the same, return empty patch
  24317        if (source == target)
  24318        {
  24319            return result;
  24320        }
  24321 
  24322        if (source.type() != target.type())
  24323        {
  24324            // different types: replace value
  24325            result.push_back(
  24326            {
  24327                {"op", "replace"}, {"path", path}, {"value", target}
  24328            });
  24329            return result;
  24330        }
  24331 
  24332        switch (source.type())
  24333        {
  24334            case value_t::array:
  24335            {
  24336                // first pass: traverse common elements
  24337                std::size_t i = 0;
  24338                while (i < source.size() && i < target.size())
  24339                {
  24340                    // recursive call to compare array values at index i
  24341                    auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
  24342                    result.insert(result.end(), temp_diff.begin(), temp_diff.end());
  24343                    ++i;
  24344                }
  24345 
  24346                // We now reached the end of at least one array
  24347                // in a second pass, traverse the remaining elements
  24348 
  24349                // remove my remaining elements
  24350                const auto end_index = static_cast<difference_type>(result.size());
  24351                while (i < source.size())
  24352                {
  24353                    // add operations in reverse order to avoid invalid
  24354                    // indices
  24355                    result.insert(result.begin() + end_index, object(
  24356                    {
  24357                        {"op", "remove"},
  24358                        {"path", detail::concat(path, '/', std::to_string(i))}
  24359                    }));
  24360                    ++i;
  24361                }
  24362 
  24363                // add other remaining elements
  24364                while (i < target.size())
  24365                {
  24366                    result.push_back(
  24367                    {
  24368                        {"op", "add"},
  24369                        {"path", detail::concat(path, "/-")},
  24370                        {"value", target[i]}
  24371                    });
  24372                    ++i;
  24373                }
  24374 
  24375                break;
  24376            }
  24377 
  24378            case value_t::object:
  24379            {
  24380                // first pass: traverse this object's elements
  24381                for (auto it = source.cbegin(); it != source.cend(); ++it)
  24382                {
  24383                    // escape the key name to be used in a JSON patch
  24384                    const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
  24385 
  24386                    if (target.find(it.key()) != target.end())
  24387                    {
  24388                        // recursive call to compare object values at key it
  24389                        auto temp_diff = diff(it.value(), target[it.key()], path_key);
  24390                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
  24391                    }
  24392                    else
  24393                    {
  24394                        // found a key that is not in o -> remove it
  24395                        result.push_back(object(
  24396                        {
  24397                            {"op", "remove"}, {"path", path_key}
  24398                        }));
  24399                    }
  24400                }
  24401 
  24402                // second pass: traverse other object's elements
  24403                for (auto it = target.cbegin(); it != target.cend(); ++it)
  24404                {
  24405                    if (source.find(it.key()) == source.end())
  24406                    {
  24407                        // found a key that is not in this -> add it
  24408                        const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
  24409                        result.push_back(
  24410                        {
  24411                            {"op", "add"}, {"path", path_key},
  24412                            {"value", it.value()}
  24413                        });
  24414                    }
  24415                }
  24416 
  24417                break;
  24418            }
  24419 
  24420            case value_t::null:
  24421            case value_t::string:
  24422            case value_t::boolean:
  24423            case value_t::number_integer:
  24424            case value_t::number_unsigned:
  24425            case value_t::number_float:
  24426            case value_t::binary:
  24427            case value_t::discarded:
  24428            default:
  24429            {
  24430                // both primitive type: replace value
  24431                result.push_back(
  24432                {
  24433                    {"op", "replace"}, {"path", path}, {"value", target}
  24434                });
  24435                break;
  24436            }
  24437        }
  24438 
  24439        return result;
  24440    }
  24441    /// @}
  24442 
  24443    ////////////////////////////////
  24444    // JSON Merge Patch functions //
  24445    ////////////////////////////////
  24446 
  24447    /// @name JSON Merge Patch functions
  24448    /// @{
  24449 
  24450    /// @brief applies a JSON Merge Patch
  24451    /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
  24452    void merge_patch(const basic_json& apply_patch)
  24453    {
  24454        if (apply_patch.is_object())
  24455        {
  24456            if (!is_object())
  24457            {
  24458                *this = object();
  24459            }
  24460            for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
  24461            {
  24462                if (it.value().is_null())
  24463                {
  24464                    erase(it.key());
  24465                }
  24466                else
  24467                {
  24468                    operator[](it.key()).merge_patch(it.value());
  24469                }
  24470            }
  24471        }
  24472        else
  24473        {
  24474            *this = apply_patch;
  24475        }
  24476    }
  24477 
  24478    /// @}
  24479 };
  24480 
  24481 /// @brief user-defined to_string function for JSON values
  24482 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
  24483 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24484 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
  24485 {
  24486    return j.dump();
  24487 }
  24488 
  24489 inline namespace literals
  24490 {
  24491 inline namespace json_literals
  24492 {
  24493 
  24494 /// @brief user-defined string literal for JSON values
  24495 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
  24496 JSON_HEDLEY_NON_NULL(1)
  24497 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
  24498    inline nlohmann::json operator ""_json(const char* s, std::size_t n)
  24499 #else
  24500    inline nlohmann::json operator "" _json(const char* s, std::size_t n)
  24501 #endif
  24502 {
  24503    return nlohmann::json::parse(s, s + n);
  24504 }
  24505 
  24506 /// @brief user-defined string literal for JSON pointer
  24507 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
  24508 JSON_HEDLEY_NON_NULL(1)
  24509 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
  24510    inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
  24511 #else
  24512    inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
  24513 #endif
  24514 {
  24515    return nlohmann::json::json_pointer(std::string(s, n));
  24516 }
  24517 
  24518 }  // namespace json_literals
  24519 }  // namespace literals
  24520 NLOHMANN_JSON_NAMESPACE_END
  24521 
  24522 ///////////////////////
  24523 // nonmember support //
  24524 ///////////////////////
  24525 
  24526 namespace std // NOLINT(cert-dcl58-cpp)
  24527 {
  24528 
  24529 /// @brief hash value for JSON objects
  24530 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
  24531 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24532 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
  24533 {
  24534    std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
  24535    {
  24536        return nlohmann::detail::hash(j);
  24537    }
  24538 };
  24539 
  24540 // specialization for std::less<value_t>
  24541 template<>
  24542 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
  24543 {
  24544    /*!
  24545    @brief compare two value_t enum values
  24546    @since version 3.0.0
  24547    */
  24548    bool operator()(::nlohmann::detail::value_t lhs,
  24549                    ::nlohmann::detail::value_t rhs) const noexcept
  24550    {
  24551 #if JSON_HAS_THREE_WAY_COMPARISON
  24552        return std::is_lt(lhs <=> rhs); // *NOPAD*
  24553 #else
  24554        return ::nlohmann::detail::operator<(lhs, rhs);
  24555 #endif
  24556    }
  24557 };
  24558 
  24559 // C++20 prohibit function specialization in the std namespace.
  24560 #ifndef JSON_HAS_CPP_20
  24561 
  24562 /// @brief exchanges the values of two JSON objects
  24563 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
  24564 NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24565 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)
  24566    is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
  24567    is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
  24568 {
  24569    j1.swap(j2);
  24570 }
  24571 
  24572 #endif
  24573 
  24574 }  // namespace std
  24575 
  24576 #if JSON_USE_GLOBAL_UDLS
  24577    #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
  24578        using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
  24579        using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
  24580    #else
  24581        using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
  24582        using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
  24583    #endif
  24584 #endif
  24585 
  24586 // #include <nlohmann/detail/macro_unscope.hpp>
  24587 //     __ _____ _____ _____
  24588 //  __|  |   __|     |   | |  JSON for Modern C++
  24589 // |  |  |__   |  |  | | | |  version 3.11.3
  24590 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  24591 //
  24592 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  24593 // SPDX-License-Identifier: MIT
  24594 
  24595 
  24596 
  24597 // restore clang diagnostic settings
  24598 #if defined(__clang__)
  24599    #pragma clang diagnostic pop
  24600 #endif
  24601 
  24602 // clean up
  24603 #undef JSON_ASSERT
  24604 #undef JSON_INTERNAL_CATCH
  24605 #undef JSON_THROW
  24606 #undef JSON_PRIVATE_UNLESS_TESTED
  24607 #undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
  24608 #undef NLOHMANN_BASIC_JSON_TPL
  24609 #undef JSON_EXPLICIT
  24610 #undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
  24611 #undef JSON_INLINE_VARIABLE
  24612 #undef JSON_NO_UNIQUE_ADDRESS
  24613 #undef JSON_DISABLE_ENUM_SERIALIZATION
  24614 #undef JSON_USE_GLOBAL_UDLS
  24615 
  24616 #ifndef JSON_TEST_KEEP_MACROS
  24617    #undef JSON_CATCH
  24618    #undef JSON_TRY
  24619    #undef JSON_HAS_CPP_11
  24620    #undef JSON_HAS_CPP_14
  24621    #undef JSON_HAS_CPP_17
  24622    #undef JSON_HAS_CPP_20
  24623    #undef JSON_HAS_FILESYSTEM
  24624    #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
  24625    #undef JSON_HAS_THREE_WAY_COMPARISON
  24626    #undef JSON_HAS_RANGES
  24627    #undef JSON_HAS_STATIC_RTTI
  24628    #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
  24629 #endif
  24630 
  24631 // #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
  24632 //     __ _____ _____ _____
  24633 //  __|  |   __|     |   | |  JSON for Modern C++
  24634 // |  |  |__   |  |  | | | |  version 3.11.3
  24635 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  24636 //
  24637 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
  24638 // SPDX-License-Identifier: MIT
  24639 
  24640 
  24641 
  24642 #undef JSON_HEDLEY_ALWAYS_INLINE
  24643 #undef JSON_HEDLEY_ARM_VERSION
  24644 #undef JSON_HEDLEY_ARM_VERSION_CHECK
  24645 #undef JSON_HEDLEY_ARRAY_PARAM
  24646 #undef JSON_HEDLEY_ASSUME
  24647 #undef JSON_HEDLEY_BEGIN_C_DECLS
  24648 #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
  24649 #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
  24650 #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
  24651 #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
  24652 #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
  24653 #undef JSON_HEDLEY_CLANG_HAS_FEATURE
  24654 #undef JSON_HEDLEY_CLANG_HAS_WARNING
  24655 #undef JSON_HEDLEY_COMPCERT_VERSION
  24656 #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
  24657 #undef JSON_HEDLEY_CONCAT
  24658 #undef JSON_HEDLEY_CONCAT3
  24659 #undef JSON_HEDLEY_CONCAT3_EX
  24660 #undef JSON_HEDLEY_CONCAT_EX
  24661 #undef JSON_HEDLEY_CONST
  24662 #undef JSON_HEDLEY_CONSTEXPR
  24663 #undef JSON_HEDLEY_CONST_CAST
  24664 #undef JSON_HEDLEY_CPP_CAST
  24665 #undef JSON_HEDLEY_CRAY_VERSION
  24666 #undef JSON_HEDLEY_CRAY_VERSION_CHECK
  24667 #undef JSON_HEDLEY_C_DECL
  24668 #undef JSON_HEDLEY_DEPRECATED
  24669 #undef JSON_HEDLEY_DEPRECATED_FOR
  24670 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
  24671 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
  24672 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
  24673 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
  24674 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
  24675 #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
  24676 #undef JSON_HEDLEY_DIAGNOSTIC_POP
  24677 #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
  24678 #undef JSON_HEDLEY_DMC_VERSION
  24679 #undef JSON_HEDLEY_DMC_VERSION_CHECK
  24680 #undef JSON_HEDLEY_EMPTY_BASES
  24681 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
  24682 #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
  24683 #undef JSON_HEDLEY_END_C_DECLS
  24684 #undef JSON_HEDLEY_FLAGS
  24685 #undef JSON_HEDLEY_FLAGS_CAST
  24686 #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
  24687 #undef JSON_HEDLEY_GCC_HAS_BUILTIN
  24688 #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
  24689 #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
  24690 #undef JSON_HEDLEY_GCC_HAS_EXTENSION
  24691 #undef JSON_HEDLEY_GCC_HAS_FEATURE
  24692 #undef JSON_HEDLEY_GCC_HAS_WARNING
  24693 #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
  24694 #undef JSON_HEDLEY_GCC_VERSION
  24695 #undef JSON_HEDLEY_GCC_VERSION_CHECK
  24696 #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
  24697 #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
  24698 #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
  24699 #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
  24700 #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
  24701 #undef JSON_HEDLEY_GNUC_HAS_FEATURE
  24702 #undef JSON_HEDLEY_GNUC_HAS_WARNING
  24703 #undef JSON_HEDLEY_GNUC_VERSION
  24704 #undef JSON_HEDLEY_GNUC_VERSION_CHECK
  24705 #undef JSON_HEDLEY_HAS_ATTRIBUTE
  24706 #undef JSON_HEDLEY_HAS_BUILTIN
  24707 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
  24708 #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
  24709 #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
  24710 #undef JSON_HEDLEY_HAS_EXTENSION
  24711 #undef JSON_HEDLEY_HAS_FEATURE
  24712 #undef JSON_HEDLEY_HAS_WARNING
  24713 #undef JSON_HEDLEY_IAR_VERSION
  24714 #undef JSON_HEDLEY_IAR_VERSION_CHECK
  24715 #undef JSON_HEDLEY_IBM_VERSION
  24716 #undef JSON_HEDLEY_IBM_VERSION_CHECK
  24717 #undef JSON_HEDLEY_IMPORT
  24718 #undef JSON_HEDLEY_INLINE
  24719 #undef JSON_HEDLEY_INTEL_CL_VERSION
  24720 #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
  24721 #undef JSON_HEDLEY_INTEL_VERSION
  24722 #undef JSON_HEDLEY_INTEL_VERSION_CHECK
  24723 #undef JSON_HEDLEY_IS_CONSTANT
  24724 #undef JSON_HEDLEY_IS_CONSTEXPR_
  24725 #undef JSON_HEDLEY_LIKELY
  24726 #undef JSON_HEDLEY_MALLOC
  24727 #undef JSON_HEDLEY_MCST_LCC_VERSION
  24728 #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
  24729 #undef JSON_HEDLEY_MESSAGE
  24730 #undef JSON_HEDLEY_MSVC_VERSION
  24731 #undef JSON_HEDLEY_MSVC_VERSION_CHECK
  24732 #undef JSON_HEDLEY_NEVER_INLINE
  24733 #undef JSON_HEDLEY_NON_NULL
  24734 #undef JSON_HEDLEY_NO_ESCAPE
  24735 #undef JSON_HEDLEY_NO_RETURN
  24736 #undef JSON_HEDLEY_NO_THROW
  24737 #undef JSON_HEDLEY_NULL
  24738 #undef JSON_HEDLEY_PELLES_VERSION
  24739 #undef JSON_HEDLEY_PELLES_VERSION_CHECK
  24740 #undef JSON_HEDLEY_PGI_VERSION
  24741 #undef JSON_HEDLEY_PGI_VERSION_CHECK
  24742 #undef JSON_HEDLEY_PREDICT
  24743 #undef JSON_HEDLEY_PRINTF_FORMAT
  24744 #undef JSON_HEDLEY_PRIVATE
  24745 #undef JSON_HEDLEY_PUBLIC
  24746 #undef JSON_HEDLEY_PURE
  24747 #undef JSON_HEDLEY_REINTERPRET_CAST
  24748 #undef JSON_HEDLEY_REQUIRE
  24749 #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
  24750 #undef JSON_HEDLEY_REQUIRE_MSG
  24751 #undef JSON_HEDLEY_RESTRICT
  24752 #undef JSON_HEDLEY_RETURNS_NON_NULL
  24753 #undef JSON_HEDLEY_SENTINEL
  24754 #undef JSON_HEDLEY_STATIC_ASSERT
  24755 #undef JSON_HEDLEY_STATIC_CAST
  24756 #undef JSON_HEDLEY_STRINGIFY
  24757 #undef JSON_HEDLEY_STRINGIFY_EX
  24758 #undef JSON_HEDLEY_SUNPRO_VERSION
  24759 #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
  24760 #undef JSON_HEDLEY_TINYC_VERSION
  24761 #undef JSON_HEDLEY_TINYC_VERSION_CHECK
  24762 #undef JSON_HEDLEY_TI_ARMCL_VERSION
  24763 #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
  24764 #undef JSON_HEDLEY_TI_CL2000_VERSION
  24765 #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
  24766 #undef JSON_HEDLEY_TI_CL430_VERSION
  24767 #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
  24768 #undef JSON_HEDLEY_TI_CL6X_VERSION
  24769 #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
  24770 #undef JSON_HEDLEY_TI_CL7X_VERSION
  24771 #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
  24772 #undef JSON_HEDLEY_TI_CLPRU_VERSION
  24773 #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
  24774 #undef JSON_HEDLEY_TI_VERSION
  24775 #undef JSON_HEDLEY_TI_VERSION_CHECK
  24776 #undef JSON_HEDLEY_UNAVAILABLE
  24777 #undef JSON_HEDLEY_UNLIKELY
  24778 #undef JSON_HEDLEY_UNPREDICTABLE
  24779 #undef JSON_HEDLEY_UNREACHABLE
  24780 #undef JSON_HEDLEY_UNREACHABLE_RETURN
  24781 #undef JSON_HEDLEY_VERSION
  24782 #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
  24783 #undef JSON_HEDLEY_VERSION_DECODE_MINOR
  24784 #undef JSON_HEDLEY_VERSION_DECODE_REVISION
  24785 #undef JSON_HEDLEY_VERSION_ENCODE
  24786 #undef JSON_HEDLEY_WARNING
  24787 #undef JSON_HEDLEY_WARN_UNUSED_RESULT
  24788 #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
  24789 #undef JSON_HEDLEY_FALL_THROUGH
  24790 
  24791 
  24792 
  24793 #endif  // INCLUDE_NLOHMANN_JSON_HPP_