1//     __ _____ _____ _____
    2//  __|  |   __|     |   | |  JSON for Modern C++
    3// |  |  |__   |  |  | | | |  version 3.12.0
    4// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
    5//
    6// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
    7// SPDX-License-Identifier: MIT
    8
    9/****************************************************************************\
   10 * Note on documentation: The source files contain links to the online      *
   11 * documentation of the public API at https://json.nlohmann.me. This URL    *
   12 * contains the most recent documentation and should also be applicable to  *
   13 * previous versions; documentation for deprecated functions is not         *
   14 * removed, but marked deprecated. See "Generate documentation" section in  *
   15 * file docs/README.md.                                                     *
   16\****************************************************************************/
   17
   18#ifndef INCLUDE_NLOHMANN_JSON_HPP_
   19#define INCLUDE_NLOHMANN_JSON_HPP_
   20
   21#include <algorithm> // all_of, find, for_each
   22#include <cstddef> // nullptr_t, ptrdiff_t, size_t
   23#include <functional> // hash, less
   24#include <initializer_list> // initializer_list
   25#ifndef JSON_NO_IO
   26    #include <iosfwd> // istream, ostream
   27#endif  // JSON_NO_IO
   28#include <iterator> // random_access_iterator_tag
   29#include <memory> // unique_ptr
   30#include <string> // string, stoi, to_string
   31#include <utility> // declval, forward, move, pair, swap
   32#include <vector> // vector
   33
   34// #include <nlohmann/adl_serializer.hpp>
   35//     __ _____ _____ _____
   36//  __|  |   __|     |   | |  JSON for Modern C++
   37// |  |  |__   |  |  | | | |  version 3.12.0
   38// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   39//
   40// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
   41// SPDX-License-Identifier: MIT
   42
   43
   44
   45#include <utility>
   46
   47// #include <nlohmann/detail/abi_macros.hpp>
   48//     __ _____ _____ _____
   49//  __|  |   __|     |   | |  JSON for Modern C++
   50// |  |  |__   |  |  | | | |  version 3.12.0
   51// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   52//
   53// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
   54// SPDX-License-Identifier: MIT
   55
   56
   57
   58// This file contains all macro definitions affecting or depending on the ABI
   59
   60#ifndef JSON_SKIP_LIBRARY_VERSION_CHECK
   61    #if defined(NLOHMANN_JSON_VERSION_MAJOR) && defined(NLOHMANN_JSON_VERSION_MINOR) && defined(NLOHMANN_JSON_VERSION_PATCH)
   62        #if NLOHMANN_JSON_VERSION_MAJOR != 3 || NLOHMANN_JSON_VERSION_MINOR != 12 || NLOHMANN_JSON_VERSION_PATCH != 0
   63            #warning "Already included a different version of the library!"
   64        #endif
   65    #endif
   66#endif
   67
   68#define NLOHMANN_JSON_VERSION_MAJOR 3   // NOLINT(modernize-macro-to-enum)
   69#define NLOHMANN_JSON_VERSION_MINOR 12  // NOLINT(modernize-macro-to-enum)
   70#define NLOHMANN_JSON_VERSION_PATCH 0   // NOLINT(modernize-macro-to-enum)
   71
   72#ifndef JSON_DIAGNOSTICS
   73    #define JSON_DIAGNOSTICS 0
   74#endif
   75
   76#ifndef JSON_DIAGNOSTIC_POSITIONS
   77    #define JSON_DIAGNOSTIC_POSITIONS 0
   78#endif
   79
   80#ifndef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
   81    #define JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON 0
   82#endif
   83
   84#if JSON_DIAGNOSTICS
   85    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS _diag
   86#else
   87    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS
   88#endif
   89
   90#if JSON_DIAGNOSTIC_POSITIONS
   91    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS _dp
   92#else
   93    #define NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS
   94#endif
   95
   96#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
   97    #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON _ldvcmp
   98#else
   99    #define NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON
  100#endif
  101
  102#ifndef NLOHMANN_JSON_NAMESPACE_NO_VERSION
  103    #define NLOHMANN_JSON_NAMESPACE_NO_VERSION 0
  104#endif
  105
  106// Construct the namespace ABI tags component
  107#define NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c) json_abi ## a ## b ## c
  108#define NLOHMANN_JSON_ABI_TAGS_CONCAT(a, b, c) \
  109    NLOHMANN_JSON_ABI_TAGS_CONCAT_EX(a, b, c)
  110
  111#define NLOHMANN_JSON_ABI_TAGS                                       \
  112    NLOHMANN_JSON_ABI_TAGS_CONCAT(                                   \
  113            NLOHMANN_JSON_ABI_TAG_DIAGNOSTICS,                       \
  114            NLOHMANN_JSON_ABI_TAG_LEGACY_DISCARDED_VALUE_COMPARISON, \
  115            NLOHMANN_JSON_ABI_TAG_DIAGNOSTIC_POSITIONS)
  116
  117// Construct the namespace version component
  118#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch) \
  119    _v ## major ## _ ## minor ## _ ## patch
  120#define NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(major, minor, patch) \
  121    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT_EX(major, minor, patch)
  122
  123#if NLOHMANN_JSON_NAMESPACE_NO_VERSION
  124#define NLOHMANN_JSON_NAMESPACE_VERSION
  125#else
  126#define NLOHMANN_JSON_NAMESPACE_VERSION                                 \
  127    NLOHMANN_JSON_NAMESPACE_VERSION_CONCAT(NLOHMANN_JSON_VERSION_MAJOR, \
  128                                           NLOHMANN_JSON_VERSION_MINOR, \
  129                                           NLOHMANN_JSON_VERSION_PATCH)
  130#endif
  131
  132// Combine namespace components
  133#define NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b) a ## b
  134#define NLOHMANN_JSON_NAMESPACE_CONCAT(a, b) \
  135    NLOHMANN_JSON_NAMESPACE_CONCAT_EX(a, b)
  136
  137#ifndef NLOHMANN_JSON_NAMESPACE
  138#define NLOHMANN_JSON_NAMESPACE               \
  139    nlohmann::NLOHMANN_JSON_NAMESPACE_CONCAT( \
  140            NLOHMANN_JSON_ABI_TAGS,           \
  141            NLOHMANN_JSON_NAMESPACE_VERSION)
  142#endif
  143
  144#ifndef NLOHMANN_JSON_NAMESPACE_BEGIN
  145#define NLOHMANN_JSON_NAMESPACE_BEGIN                \
  146    namespace nlohmann                               \
  147    {                                                \
  148    inline namespace NLOHMANN_JSON_NAMESPACE_CONCAT( \
  149                NLOHMANN_JSON_ABI_TAGS,              \
  150                NLOHMANN_JSON_NAMESPACE_VERSION)     \
  151    {
  152#endif
  153
  154#ifndef NLOHMANN_JSON_NAMESPACE_END
  155#define NLOHMANN_JSON_NAMESPACE_END                                     \
  156    }  /* namespace (inline namespace) NOLINT(readability/namespace) */ \
  157    }  // namespace nlohmann
  158#endif
  159
  160// #include <nlohmann/detail/conversions/from_json.hpp>
  161//     __ _____ _____ _____
  162//  __|  |   __|     |   | |  JSON for Modern C++
  163// |  |  |__   |  |  | | | |  version 3.12.0
  164// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  165//
  166// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  167// SPDX-License-Identifier: MIT
  168
  169
  170
  171#include <algorithm> // transform
  172#include <array> // array
  173#include <forward_list> // forward_list
  174#include <iterator> // inserter, front_inserter, end
  175#include <map> // map
  176#ifdef JSON_HAS_CPP_17
  177    #include <optional> // optional
  178#endif
  179#include <string> // string
  180#include <tuple> // tuple, make_tuple
  181#include <type_traits> // is_arithmetic, is_same, is_enum, underlying_type, is_convertible
  182#include <unordered_map> // unordered_map
  183#include <utility> // pair, declval
  184#include <valarray> // valarray
  185
  186// #include <nlohmann/detail/exceptions.hpp>
  187//     __ _____ _____ _____
  188//  __|  |   __|     |   | |  JSON for Modern C++
  189// |  |  |__   |  |  | | | |  version 3.12.0
  190// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  191//
  192// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  193// SPDX-License-Identifier: MIT
  194
  195
  196
  197#include <cstddef> // nullptr_t
  198#include <exception> // exception
  199#if JSON_DIAGNOSTICS
  200    #include <numeric> // accumulate
  201#endif
  202#include <stdexcept> // runtime_error
  203#include <string> // to_string
  204#include <vector> // vector
  205
  206// #include <nlohmann/detail/value_t.hpp>
  207//     __ _____ _____ _____
  208//  __|  |   __|     |   | |  JSON for Modern C++
  209// |  |  |__   |  |  | | | |  version 3.12.0
  210// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  211//
  212// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  213// SPDX-License-Identifier: MIT
  214
  215
  216
  217#include <array> // array
  218#include <cstddef> // size_t
  219#include <cstdint> // uint8_t
  220#include <string> // string
  221
  222// #include <nlohmann/detail/macro_scope.hpp>
  223//     __ _____ _____ _____
  224//  __|  |   __|     |   | |  JSON for Modern C++
  225// |  |  |__   |  |  | | | |  version 3.12.0
  226// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  227//
  228// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  229// SPDX-License-Identifier: MIT
  230
  231
  232
  233#include <utility> // declval, pair
  234// #include <nlohmann/detail/meta/detected.hpp>
  235//     __ _____ _____ _____
  236//  __|  |   __|     |   | |  JSON for Modern C++
  237// |  |  |__   |  |  | | | |  version 3.12.0
  238// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  239//
  240// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  241// SPDX-License-Identifier: MIT
  242
  243
  244
  245#include <type_traits>
  246
  247// #include <nlohmann/detail/meta/void_t.hpp>
  248//     __ _____ _____ _____
  249//  __|  |   __|     |   | |  JSON for Modern C++
  250// |  |  |__   |  |  | | | |  version 3.12.0
  251// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  252//
  253// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  254// SPDX-License-Identifier: MIT
  255
  256
  257
  258// #include <nlohmann/detail/abi_macros.hpp>
  259
  260
  261NLOHMANN_JSON_NAMESPACE_BEGIN
  262namespace detail
  263{
  264
  265template<typename ...Ts> struct make_void
  266{
  267    using type = void;
  268};
  269template<typename ...Ts> using void_t = typename make_void<Ts...>::type;
  270
  271}  // namespace detail
  272NLOHMANN_JSON_NAMESPACE_END
  273
  274
  275NLOHMANN_JSON_NAMESPACE_BEGIN
  276namespace detail
  277{
  278
  279// https://en.cppreference.com/w/cpp/experimental/is_detected
  280struct nonesuch
  281{
  282    nonesuch() = delete;
  283    ~nonesuch() = delete;
  284    nonesuch(nonesuch const&) = delete;
  285    nonesuch(nonesuch const&&) = delete;
  286    void operator=(nonesuch const&) = delete;
  287    void operator=(nonesuch&&) = delete;
  288};
  289
  290template<class Default,
  291         class AlwaysVoid,
  292         template<class...> class Op,
  293         class... Args>
  294struct detector
  295{
  296    using value_t = std::false_type;
  297    using type = Default;
  298};
  299
  300template<class Default, template<class...> class Op, class... Args>
  301struct detector<Default, void_t<Op<Args...>>, Op, Args...>
  302{
  303    using value_t = std::true_type;
  304    using type = Op<Args...>;
  305};
  306
  307template<template<class...> class Op, class... Args>
  308using is_detected = typename detector<nonesuch, void, Op, Args...>::value_t;
  309
  310template<template<class...> class Op, class... Args>
  311struct is_detected_lazy : is_detected<Op, Args...> { };
  312
  313template<template<class...> class Op, class... Args>
  314using detected_t = typename detector<nonesuch, void, Op, Args...>::type;
  315
  316template<class Default, template<class...> class Op, class... Args>
  317using detected_or = detector<Default, void, Op, Args...>;
  318
  319template<class Default, template<class...> class Op, class... Args>
  320using detected_or_t = typename detected_or<Default, Op, Args...>::type;
  321
  322template<class Expected, template<class...> class Op, class... Args>
  323using is_detected_exact = std::is_same<Expected, detected_t<Op, Args...>>;
  324
  325template<class To, template<class...> class Op, class... Args>
  326using is_detected_convertible =
  327    std::is_convertible<detected_t<Op, Args...>, To>;
  328
  329}  // namespace detail
  330NLOHMANN_JSON_NAMESPACE_END
  331
  332// #include <nlohmann/thirdparty/hedley/hedley.hpp>
  333
  334
  335//     __ _____ _____ _____
  336//  __|  |   __|     |   | |  JSON for Modern C++
  337// |  |  |__   |  |  | | | |  version 3.12.0
  338// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
  339//
  340// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
  341// SPDX-FileCopyrightText: 2016 - 2021 Evan Nemerson <evan@nemerson.com>
  342// SPDX-License-Identifier: MIT
  343
  344/* Hedley - https://nemequ.github.io/hedley
  345 * Created by Evan Nemerson <evan@nemerson.com>
  346 */
  347
  348#if !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < 15)
  349#if defined(JSON_HEDLEY_VERSION)
  350    #undef JSON_HEDLEY_VERSION
  351#endif
  352#define JSON_HEDLEY_VERSION 15
  353
  354#if defined(JSON_HEDLEY_STRINGIFY_EX)
  355    #undef JSON_HEDLEY_STRINGIFY_EX
  356#endif
  357#define JSON_HEDLEY_STRINGIFY_EX(x) #x
  358
  359#if defined(JSON_HEDLEY_STRINGIFY)
  360    #undef JSON_HEDLEY_STRINGIFY
  361#endif
  362#define JSON_HEDLEY_STRINGIFY(x) JSON_HEDLEY_STRINGIFY_EX(x)
  363
  364#if defined(JSON_HEDLEY_CONCAT_EX)
  365    #undef JSON_HEDLEY_CONCAT_EX
  366#endif
  367#define JSON_HEDLEY_CONCAT_EX(a,b) a##b
  368
  369#if defined(JSON_HEDLEY_CONCAT)
  370    #undef JSON_HEDLEY_CONCAT
  371#endif
  372#define JSON_HEDLEY_CONCAT(a,b) JSON_HEDLEY_CONCAT_EX(a,b)
  373
  374#if defined(JSON_HEDLEY_CONCAT3_EX)
  375    #undef JSON_HEDLEY_CONCAT3_EX
  376#endif
  377#define JSON_HEDLEY_CONCAT3_EX(a,b,c) a##b##c
  378
  379#if defined(JSON_HEDLEY_CONCAT3)
  380    #undef JSON_HEDLEY_CONCAT3
  381#endif
  382#define JSON_HEDLEY_CONCAT3(a,b,c) JSON_HEDLEY_CONCAT3_EX(a,b,c)
  383
  384#if defined(JSON_HEDLEY_VERSION_ENCODE)
  385    #undef JSON_HEDLEY_VERSION_ENCODE
  386#endif
  387#define JSON_HEDLEY_VERSION_ENCODE(major,minor,revision) (((major) * 1000000) + ((minor) * 1000) + (revision))
  388
  389#if defined(JSON_HEDLEY_VERSION_DECODE_MAJOR)
  390    #undef JSON_HEDLEY_VERSION_DECODE_MAJOR
  391#endif
  392#define JSON_HEDLEY_VERSION_DECODE_MAJOR(version) ((version) / 1000000)
  393
  394#if defined(JSON_HEDLEY_VERSION_DECODE_MINOR)
  395    #undef JSON_HEDLEY_VERSION_DECODE_MINOR
  396#endif
  397#define JSON_HEDLEY_VERSION_DECODE_MINOR(version) (((version) % 1000000) / 1000)
  398
  399#if defined(JSON_HEDLEY_VERSION_DECODE_REVISION)
  400    #undef JSON_HEDLEY_VERSION_DECODE_REVISION
  401#endif
  402#define JSON_HEDLEY_VERSION_DECODE_REVISION(version) ((version) % 1000)
  403
  404#if defined(JSON_HEDLEY_GNUC_VERSION)
  405    #undef JSON_HEDLEY_GNUC_VERSION
  406#endif
  407#if defined(__GNUC__) && defined(__GNUC_PATCHLEVEL__)
  408    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
  409#elif defined(__GNUC__)
  410    #define JSON_HEDLEY_GNUC_VERSION JSON_HEDLEY_VERSION_ENCODE(__GNUC__, __GNUC_MINOR__, 0)
  411#endif
  412
  413#if defined(JSON_HEDLEY_GNUC_VERSION_CHECK)
  414    #undef JSON_HEDLEY_GNUC_VERSION_CHECK
  415#endif
  416#if defined(JSON_HEDLEY_GNUC_VERSION)
  417    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GNUC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  418#else
  419    #define JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch) (0)
  420#endif
  421
  422#if defined(JSON_HEDLEY_MSVC_VERSION)
  423    #undef JSON_HEDLEY_MSVC_VERSION
  424#endif
  425#if defined(_MSC_FULL_VER) && (_MSC_FULL_VER >= 140000000) && !defined(__ICL)
  426    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 10000000, (_MSC_FULL_VER % 10000000) / 100000, (_MSC_FULL_VER % 100000) / 100)
  427#elif defined(_MSC_FULL_VER) && !defined(__ICL)
  428    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_FULL_VER / 1000000, (_MSC_FULL_VER % 1000000) / 10000, (_MSC_FULL_VER % 10000) / 10)
  429#elif defined(_MSC_VER) && !defined(__ICL)
  430    #define JSON_HEDLEY_MSVC_VERSION JSON_HEDLEY_VERSION_ENCODE(_MSC_VER / 100, _MSC_VER % 100, 0)
  431#endif
  432
  433#if defined(JSON_HEDLEY_MSVC_VERSION_CHECK)
  434    #undef JSON_HEDLEY_MSVC_VERSION_CHECK
  435#endif
  436#if !defined(JSON_HEDLEY_MSVC_VERSION)
  437    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (0)
  438#elif defined(_MSC_VER) && (_MSC_VER >= 1400)
  439    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 10000000) + (minor * 100000) + (patch)))
  440#elif defined(_MSC_VER) && (_MSC_VER >= 1200)
  441    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_FULL_VER >= ((major * 1000000) + (minor * 10000) + (patch)))
  442#else
  443    #define JSON_HEDLEY_MSVC_VERSION_CHECK(major,minor,patch) (_MSC_VER >= ((major * 100) + (minor)))
  444#endif
  445
  446#if defined(JSON_HEDLEY_INTEL_VERSION)
  447    #undef JSON_HEDLEY_INTEL_VERSION
  448#endif
  449#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && !defined(__ICL)
  450    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, __INTEL_COMPILER_UPDATE)
  451#elif defined(__INTEL_COMPILER) && !defined(__ICL)
  452    #define JSON_HEDLEY_INTEL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER / 100, __INTEL_COMPILER % 100, 0)
  453#endif
  454
  455#if defined(JSON_HEDLEY_INTEL_VERSION_CHECK)
  456    #undef JSON_HEDLEY_INTEL_VERSION_CHECK
  457#endif
  458#if defined(JSON_HEDLEY_INTEL_VERSION)
  459    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  460#else
  461    #define JSON_HEDLEY_INTEL_VERSION_CHECK(major,minor,patch) (0)
  462#endif
  463
  464#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
  465    #undef JSON_HEDLEY_INTEL_CL_VERSION
  466#endif
  467#if defined(__INTEL_COMPILER) && defined(__INTEL_COMPILER_UPDATE) && defined(__ICL)
  468    #define JSON_HEDLEY_INTEL_CL_VERSION JSON_HEDLEY_VERSION_ENCODE(__INTEL_COMPILER, __INTEL_COMPILER_UPDATE, 0)
  469#endif
  470
  471#if defined(JSON_HEDLEY_INTEL_CL_VERSION_CHECK)
  472    #undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
  473#endif
  474#if defined(JSON_HEDLEY_INTEL_CL_VERSION)
  475    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_INTEL_CL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  476#else
  477    #define JSON_HEDLEY_INTEL_CL_VERSION_CHECK(major,minor,patch) (0)
  478#endif
  479
  480#if defined(JSON_HEDLEY_PGI_VERSION)
  481    #undef JSON_HEDLEY_PGI_VERSION
  482#endif
  483#if defined(__PGI) && defined(__PGIC__) && defined(__PGIC_MINOR__) && defined(__PGIC_PATCHLEVEL__)
  484    #define JSON_HEDLEY_PGI_VERSION JSON_HEDLEY_VERSION_ENCODE(__PGIC__, __PGIC_MINOR__, __PGIC_PATCHLEVEL__)
  485#endif
  486
  487#if defined(JSON_HEDLEY_PGI_VERSION_CHECK)
  488    #undef JSON_HEDLEY_PGI_VERSION_CHECK
  489#endif
  490#if defined(JSON_HEDLEY_PGI_VERSION)
  491    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PGI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  492#else
  493    #define JSON_HEDLEY_PGI_VERSION_CHECK(major,minor,patch) (0)
  494#endif
  495
  496#if defined(JSON_HEDLEY_SUNPRO_VERSION)
  497    #undef JSON_HEDLEY_SUNPRO_VERSION
  498#endif
  499#if defined(__SUNPRO_C) && (__SUNPRO_C > 0x1000)
  500    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_C >> 16) & 0xf) * 10) + ((__SUNPRO_C >> 12) & 0xf), (((__SUNPRO_C >> 8) & 0xf) * 10) + ((__SUNPRO_C >> 4) & 0xf), (__SUNPRO_C & 0xf) * 10)
  501#elif defined(__SUNPRO_C)
  502    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_C >> 8) & 0xf, (__SUNPRO_C >> 4) & 0xf, (__SUNPRO_C) & 0xf)
  503#elif defined(__SUNPRO_CC) && (__SUNPRO_CC > 0x1000)
  504    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((((__SUNPRO_CC >> 16) & 0xf) * 10) + ((__SUNPRO_CC >> 12) & 0xf), (((__SUNPRO_CC >> 8) & 0xf) * 10) + ((__SUNPRO_CC >> 4) & 0xf), (__SUNPRO_CC & 0xf) * 10)
  505#elif defined(__SUNPRO_CC)
  506    #define JSON_HEDLEY_SUNPRO_VERSION JSON_HEDLEY_VERSION_ENCODE((__SUNPRO_CC >> 8) & 0xf, (__SUNPRO_CC >> 4) & 0xf, (__SUNPRO_CC) & 0xf)
  507#endif
  508
  509#if defined(JSON_HEDLEY_SUNPRO_VERSION_CHECK)
  510    #undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
  511#endif
  512#if defined(JSON_HEDLEY_SUNPRO_VERSION)
  513    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_SUNPRO_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  514#else
  515    #define JSON_HEDLEY_SUNPRO_VERSION_CHECK(major,minor,patch) (0)
  516#endif
  517
  518#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
  519    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION
  520#endif
  521#if defined(__EMSCRIPTEN__)
  522    #define JSON_HEDLEY_EMSCRIPTEN_VERSION JSON_HEDLEY_VERSION_ENCODE(__EMSCRIPTEN_major__, __EMSCRIPTEN_minor__, __EMSCRIPTEN_tiny__)
  523#endif
  524
  525#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK)
  526    #undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
  527#endif
  528#if defined(JSON_HEDLEY_EMSCRIPTEN_VERSION)
  529    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_EMSCRIPTEN_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  530#else
  531    #define JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK(major,minor,patch) (0)
  532#endif
  533
  534#if defined(JSON_HEDLEY_ARM_VERSION)
  535    #undef JSON_HEDLEY_ARM_VERSION
  536#endif
  537#if defined(__CC_ARM) && defined(__ARMCOMPILER_VERSION)
  538    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCOMPILER_VERSION / 1000000, (__ARMCOMPILER_VERSION % 1000000) / 10000, (__ARMCOMPILER_VERSION % 10000) / 100)
  539#elif defined(__CC_ARM) && defined(__ARMCC_VERSION)
  540    #define JSON_HEDLEY_ARM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ARMCC_VERSION / 1000000, (__ARMCC_VERSION % 1000000) / 10000, (__ARMCC_VERSION % 10000) / 100)
  541#endif
  542
  543#if defined(JSON_HEDLEY_ARM_VERSION_CHECK)
  544    #undef JSON_HEDLEY_ARM_VERSION_CHECK
  545#endif
  546#if defined(JSON_HEDLEY_ARM_VERSION)
  547    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_ARM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  548#else
  549    #define JSON_HEDLEY_ARM_VERSION_CHECK(major,minor,patch) (0)
  550#endif
  551
  552#if defined(JSON_HEDLEY_IBM_VERSION)
  553    #undef JSON_HEDLEY_IBM_VERSION
  554#endif
  555#if defined(__ibmxl__)
  556    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__ibmxl_version__, __ibmxl_release__, __ibmxl_modification__)
  557#elif defined(__xlC__) && defined(__xlC_ver__)
  558    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, (__xlC_ver__ >> 8) & 0xff)
  559#elif defined(__xlC__)
  560    #define JSON_HEDLEY_IBM_VERSION JSON_HEDLEY_VERSION_ENCODE(__xlC__ >> 8, __xlC__ & 0xff, 0)
  561#endif
  562
  563#if defined(JSON_HEDLEY_IBM_VERSION_CHECK)
  564    #undef JSON_HEDLEY_IBM_VERSION_CHECK
  565#endif
  566#if defined(JSON_HEDLEY_IBM_VERSION)
  567    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IBM_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  568#else
  569    #define JSON_HEDLEY_IBM_VERSION_CHECK(major,minor,patch) (0)
  570#endif
  571
  572#if defined(JSON_HEDLEY_TI_VERSION)
  573    #undef JSON_HEDLEY_TI_VERSION
  574#endif
  575#if \
  576    defined(__TI_COMPILER_VERSION__) && \
  577    ( \
  578      defined(__TMS470__) || defined(__TI_ARM__) || \
  579      defined(__MSP430__) || \
  580      defined(__TMS320C2000__) \
  581    )
  582#if (__TI_COMPILER_VERSION__ >= 16000000)
  583    #define JSON_HEDLEY_TI_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  584#endif
  585#endif
  586
  587#if defined(JSON_HEDLEY_TI_VERSION_CHECK)
  588    #undef JSON_HEDLEY_TI_VERSION_CHECK
  589#endif
  590#if defined(JSON_HEDLEY_TI_VERSION)
  591    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  592#else
  593    #define JSON_HEDLEY_TI_VERSION_CHECK(major,minor,patch) (0)
  594#endif
  595
  596#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
  597    #undef JSON_HEDLEY_TI_CL2000_VERSION
  598#endif
  599#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C2000__)
  600    #define JSON_HEDLEY_TI_CL2000_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  601#endif
  602
  603#if defined(JSON_HEDLEY_TI_CL2000_VERSION_CHECK)
  604    #undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
  605#endif
  606#if defined(JSON_HEDLEY_TI_CL2000_VERSION)
  607    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL2000_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  608#else
  609    #define JSON_HEDLEY_TI_CL2000_VERSION_CHECK(major,minor,patch) (0)
  610#endif
  611
  612#if defined(JSON_HEDLEY_TI_CL430_VERSION)
  613    #undef JSON_HEDLEY_TI_CL430_VERSION
  614#endif
  615#if defined(__TI_COMPILER_VERSION__) && defined(__MSP430__)
  616    #define JSON_HEDLEY_TI_CL430_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  617#endif
  618
  619#if defined(JSON_HEDLEY_TI_CL430_VERSION_CHECK)
  620    #undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
  621#endif
  622#if defined(JSON_HEDLEY_TI_CL430_VERSION)
  623    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL430_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  624#else
  625    #define JSON_HEDLEY_TI_CL430_VERSION_CHECK(major,minor,patch) (0)
  626#endif
  627
  628#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
  629    #undef JSON_HEDLEY_TI_ARMCL_VERSION
  630#endif
  631#if defined(__TI_COMPILER_VERSION__) && (defined(__TMS470__) || defined(__TI_ARM__))
  632    #define JSON_HEDLEY_TI_ARMCL_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  633#endif
  634
  635#if defined(JSON_HEDLEY_TI_ARMCL_VERSION_CHECK)
  636    #undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
  637#endif
  638#if defined(JSON_HEDLEY_TI_ARMCL_VERSION)
  639    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_ARMCL_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  640#else
  641    #define JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(major,minor,patch) (0)
  642#endif
  643
  644#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
  645    #undef JSON_HEDLEY_TI_CL6X_VERSION
  646#endif
  647#if defined(__TI_COMPILER_VERSION__) && defined(__TMS320C6X__)
  648    #define JSON_HEDLEY_TI_CL6X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  649#endif
  650
  651#if defined(JSON_HEDLEY_TI_CL6X_VERSION_CHECK)
  652    #undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
  653#endif
  654#if defined(JSON_HEDLEY_TI_CL6X_VERSION)
  655    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL6X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  656#else
  657    #define JSON_HEDLEY_TI_CL6X_VERSION_CHECK(major,minor,patch) (0)
  658#endif
  659
  660#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
  661    #undef JSON_HEDLEY_TI_CL7X_VERSION
  662#endif
  663#if defined(__TI_COMPILER_VERSION__) && defined(__C7000__)
  664    #define JSON_HEDLEY_TI_CL7X_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  665#endif
  666
  667#if defined(JSON_HEDLEY_TI_CL7X_VERSION_CHECK)
  668    #undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
  669#endif
  670#if defined(JSON_HEDLEY_TI_CL7X_VERSION)
  671    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CL7X_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  672#else
  673    #define JSON_HEDLEY_TI_CL7X_VERSION_CHECK(major,minor,patch) (0)
  674#endif
  675
  676#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
  677    #undef JSON_HEDLEY_TI_CLPRU_VERSION
  678#endif
  679#if defined(__TI_COMPILER_VERSION__) && defined(__PRU__)
  680    #define JSON_HEDLEY_TI_CLPRU_VERSION JSON_HEDLEY_VERSION_ENCODE(__TI_COMPILER_VERSION__ / 1000000, (__TI_COMPILER_VERSION__ % 1000000) / 1000, (__TI_COMPILER_VERSION__ % 1000))
  681#endif
  682
  683#if defined(JSON_HEDLEY_TI_CLPRU_VERSION_CHECK)
  684    #undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
  685#endif
  686#if defined(JSON_HEDLEY_TI_CLPRU_VERSION)
  687    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TI_CLPRU_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  688#else
  689    #define JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(major,minor,patch) (0)
  690#endif
  691
  692#if defined(JSON_HEDLEY_CRAY_VERSION)
  693    #undef JSON_HEDLEY_CRAY_VERSION
  694#endif
  695#if defined(_CRAYC)
  696    #if defined(_RELEASE_PATCHLEVEL)
  697        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, _RELEASE_PATCHLEVEL)
  698    #else
  699        #define JSON_HEDLEY_CRAY_VERSION JSON_HEDLEY_VERSION_ENCODE(_RELEASE_MAJOR, _RELEASE_MINOR, 0)
  700    #endif
  701#endif
  702
  703#if defined(JSON_HEDLEY_CRAY_VERSION_CHECK)
  704    #undef JSON_HEDLEY_CRAY_VERSION_CHECK
  705#endif
  706#if defined(JSON_HEDLEY_CRAY_VERSION)
  707    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_CRAY_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  708#else
  709    #define JSON_HEDLEY_CRAY_VERSION_CHECK(major,minor,patch) (0)
  710#endif
  711
  712#if defined(JSON_HEDLEY_IAR_VERSION)
  713    #undef JSON_HEDLEY_IAR_VERSION
  714#endif
  715#if defined(__IAR_SYSTEMS_ICC__)
  716    #if __VER__ > 1000
  717        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE((__VER__ / 1000000), ((__VER__ / 1000) % 1000), (__VER__ % 1000))
  718    #else
  719        #define JSON_HEDLEY_IAR_VERSION JSON_HEDLEY_VERSION_ENCODE(__VER__ / 100, __VER__ % 100, 0)
  720    #endif
  721#endif
  722
  723#if defined(JSON_HEDLEY_IAR_VERSION_CHECK)
  724    #undef JSON_HEDLEY_IAR_VERSION_CHECK
  725#endif
  726#if defined(JSON_HEDLEY_IAR_VERSION)
  727    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_IAR_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  728#else
  729    #define JSON_HEDLEY_IAR_VERSION_CHECK(major,minor,patch) (0)
  730#endif
  731
  732#if defined(JSON_HEDLEY_TINYC_VERSION)
  733    #undef JSON_HEDLEY_TINYC_VERSION
  734#endif
  735#if defined(__TINYC__)
  736    #define JSON_HEDLEY_TINYC_VERSION JSON_HEDLEY_VERSION_ENCODE(__TINYC__ / 1000, (__TINYC__ / 100) % 10, __TINYC__ % 100)
  737#endif
  738
  739#if defined(JSON_HEDLEY_TINYC_VERSION_CHECK)
  740    #undef JSON_HEDLEY_TINYC_VERSION_CHECK
  741#endif
  742#if defined(JSON_HEDLEY_TINYC_VERSION)
  743    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_TINYC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  744#else
  745    #define JSON_HEDLEY_TINYC_VERSION_CHECK(major,minor,patch) (0)
  746#endif
  747
  748#if defined(JSON_HEDLEY_DMC_VERSION)
  749    #undef JSON_HEDLEY_DMC_VERSION
  750#endif
  751#if defined(__DMC__)
  752    #define JSON_HEDLEY_DMC_VERSION JSON_HEDLEY_VERSION_ENCODE(__DMC__ >> 8, (__DMC__ >> 4) & 0xf, __DMC__ & 0xf)
  753#endif
  754
  755#if defined(JSON_HEDLEY_DMC_VERSION_CHECK)
  756    #undef JSON_HEDLEY_DMC_VERSION_CHECK
  757#endif
  758#if defined(JSON_HEDLEY_DMC_VERSION)
  759    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_DMC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  760#else
  761    #define JSON_HEDLEY_DMC_VERSION_CHECK(major,minor,patch) (0)
  762#endif
  763
  764#if defined(JSON_HEDLEY_COMPCERT_VERSION)
  765    #undef JSON_HEDLEY_COMPCERT_VERSION
  766#endif
  767#if defined(__COMPCERT_VERSION__)
  768    #define JSON_HEDLEY_COMPCERT_VERSION JSON_HEDLEY_VERSION_ENCODE(__COMPCERT_VERSION__ / 10000, (__COMPCERT_VERSION__ / 100) % 100, __COMPCERT_VERSION__ % 100)
  769#endif
  770
  771#if defined(JSON_HEDLEY_COMPCERT_VERSION_CHECK)
  772    #undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
  773#endif
  774#if defined(JSON_HEDLEY_COMPCERT_VERSION)
  775    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_COMPCERT_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  776#else
  777    #define JSON_HEDLEY_COMPCERT_VERSION_CHECK(major,minor,patch) (0)
  778#endif
  779
  780#if defined(JSON_HEDLEY_PELLES_VERSION)
  781    #undef JSON_HEDLEY_PELLES_VERSION
  782#endif
  783#if defined(__POCC__)
  784    #define JSON_HEDLEY_PELLES_VERSION JSON_HEDLEY_VERSION_ENCODE(__POCC__ / 100, __POCC__ % 100, 0)
  785#endif
  786
  787#if defined(JSON_HEDLEY_PELLES_VERSION_CHECK)
  788    #undef JSON_HEDLEY_PELLES_VERSION_CHECK
  789#endif
  790#if defined(JSON_HEDLEY_PELLES_VERSION)
  791    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_PELLES_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  792#else
  793    #define JSON_HEDLEY_PELLES_VERSION_CHECK(major,minor,patch) (0)
  794#endif
  795
  796#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
  797    #undef JSON_HEDLEY_MCST_LCC_VERSION
  798#endif
  799#if defined(__LCC__) && defined(__LCC_MINOR__)
  800    #define JSON_HEDLEY_MCST_LCC_VERSION JSON_HEDLEY_VERSION_ENCODE(__LCC__ / 100, __LCC__ % 100, __LCC_MINOR__)
  801#endif
  802
  803#if defined(JSON_HEDLEY_MCST_LCC_VERSION_CHECK)
  804    #undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
  805#endif
  806#if defined(JSON_HEDLEY_MCST_LCC_VERSION)
  807    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_MCST_LCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  808#else
  809    #define JSON_HEDLEY_MCST_LCC_VERSION_CHECK(major,minor,patch) (0)
  810#endif
  811
  812#if defined(JSON_HEDLEY_GCC_VERSION)
  813    #undef JSON_HEDLEY_GCC_VERSION
  814#endif
  815#if \
  816    defined(JSON_HEDLEY_GNUC_VERSION) && \
  817    !defined(__clang__) && \
  818    !defined(JSON_HEDLEY_INTEL_VERSION) && \
  819    !defined(JSON_HEDLEY_PGI_VERSION) && \
  820    !defined(JSON_HEDLEY_ARM_VERSION) && \
  821    !defined(JSON_HEDLEY_CRAY_VERSION) && \
  822    !defined(JSON_HEDLEY_TI_VERSION) && \
  823    !defined(JSON_HEDLEY_TI_ARMCL_VERSION) && \
  824    !defined(JSON_HEDLEY_TI_CL430_VERSION) && \
  825    !defined(JSON_HEDLEY_TI_CL2000_VERSION) && \
  826    !defined(JSON_HEDLEY_TI_CL6X_VERSION) && \
  827    !defined(JSON_HEDLEY_TI_CL7X_VERSION) && \
  828    !defined(JSON_HEDLEY_TI_CLPRU_VERSION) && \
  829    !defined(__COMPCERT__) && \
  830    !defined(JSON_HEDLEY_MCST_LCC_VERSION)
  831    #define JSON_HEDLEY_GCC_VERSION JSON_HEDLEY_GNUC_VERSION
  832#endif
  833
  834#if defined(JSON_HEDLEY_GCC_VERSION_CHECK)
  835    #undef JSON_HEDLEY_GCC_VERSION_CHECK
  836#endif
  837#if defined(JSON_HEDLEY_GCC_VERSION)
  838    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (JSON_HEDLEY_GCC_VERSION >= JSON_HEDLEY_VERSION_ENCODE(major, minor, patch))
  839#else
  840    #define JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch) (0)
  841#endif
  842
  843#if defined(JSON_HEDLEY_HAS_ATTRIBUTE)
  844    #undef JSON_HEDLEY_HAS_ATTRIBUTE
  845#endif
  846#if \
  847  defined(__has_attribute) && \
  848  ( \
  849    (!defined(JSON_HEDLEY_IAR_VERSION) || JSON_HEDLEY_IAR_VERSION_CHECK(8,5,9)) \
  850  )
  851#  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) __has_attribute(attribute)
  852#else
  853#  define JSON_HEDLEY_HAS_ATTRIBUTE(attribute) (0)
  854#endif
  855
  856#if defined(JSON_HEDLEY_GNUC_HAS_ATTRIBUTE)
  857    #undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
  858#endif
  859#if defined(__has_attribute)
  860    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
  861#else
  862    #define JSON_HEDLEY_GNUC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
  863#endif
  864
  865#if defined(JSON_HEDLEY_GCC_HAS_ATTRIBUTE)
  866    #undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
  867#endif
  868#if defined(__has_attribute)
  869    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
  870#else
  871    #define JSON_HEDLEY_GCC_HAS_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
  872#endif
  873
  874#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE)
  875    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
  876#endif
  877#if \
  878    defined(__has_cpp_attribute) && \
  879    defined(__cplusplus) && \
  880    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0))
  881    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) __has_cpp_attribute(attribute)
  882#else
  883    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute) (0)
  884#endif
  885
  886#if defined(JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS)
  887    #undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
  888#endif
  889#if !defined(__cplusplus) || !defined(__has_cpp_attribute)
  890    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
  891#elif \
  892    !defined(JSON_HEDLEY_PGI_VERSION) && \
  893    !defined(JSON_HEDLEY_IAR_VERSION) && \
  894    (!defined(JSON_HEDLEY_SUNPRO_VERSION) || JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0)) && \
  895    (!defined(JSON_HEDLEY_MSVC_VERSION) || JSON_HEDLEY_MSVC_VERSION_CHECK(19,20,0))
  896    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(ns::attribute)
  897#else
  898    #define JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(ns,attribute) (0)
  899#endif
  900
  901#if defined(JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE)
  902    #undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
  903#endif
  904#if defined(__has_cpp_attribute) && defined(__cplusplus)
  905    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
  906#else
  907    #define JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
  908#endif
  909
  910#if defined(JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE)
  911    #undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
  912#endif
  913#if defined(__has_cpp_attribute) && defined(__cplusplus)
  914    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) __has_cpp_attribute(attribute)
  915#else
  916    #define JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
  917#endif
  918
  919#if defined(JSON_HEDLEY_HAS_BUILTIN)
  920    #undef JSON_HEDLEY_HAS_BUILTIN
  921#endif
  922#if defined(__has_builtin)
  923    #define JSON_HEDLEY_HAS_BUILTIN(builtin) __has_builtin(builtin)
  924#else
  925    #define JSON_HEDLEY_HAS_BUILTIN(builtin) (0)
  926#endif
  927
  928#if defined(JSON_HEDLEY_GNUC_HAS_BUILTIN)
  929    #undef JSON_HEDLEY_GNUC_HAS_BUILTIN
  930#endif
  931#if defined(__has_builtin)
  932    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
  933#else
  934    #define JSON_HEDLEY_GNUC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
  935#endif
  936
  937#if defined(JSON_HEDLEY_GCC_HAS_BUILTIN)
  938    #undef JSON_HEDLEY_GCC_HAS_BUILTIN
  939#endif
  940#if defined(__has_builtin)
  941    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) __has_builtin(builtin)
  942#else
  943    #define JSON_HEDLEY_GCC_HAS_BUILTIN(builtin,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
  944#endif
  945
  946#if defined(JSON_HEDLEY_HAS_FEATURE)
  947    #undef JSON_HEDLEY_HAS_FEATURE
  948#endif
  949#if defined(__has_feature)
  950    #define JSON_HEDLEY_HAS_FEATURE(feature) __has_feature(feature)
  951#else
  952    #define JSON_HEDLEY_HAS_FEATURE(feature) (0)
  953#endif
  954
  955#if defined(JSON_HEDLEY_GNUC_HAS_FEATURE)
  956    #undef JSON_HEDLEY_GNUC_HAS_FEATURE
  957#endif
  958#if defined(__has_feature)
  959    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
  960#else
  961    #define JSON_HEDLEY_GNUC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
  962#endif
  963
  964#if defined(JSON_HEDLEY_GCC_HAS_FEATURE)
  965    #undef JSON_HEDLEY_GCC_HAS_FEATURE
  966#endif
  967#if defined(__has_feature)
  968    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) __has_feature(feature)
  969#else
  970    #define JSON_HEDLEY_GCC_HAS_FEATURE(feature,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
  971#endif
  972
  973#if defined(JSON_HEDLEY_HAS_EXTENSION)
  974    #undef JSON_HEDLEY_HAS_EXTENSION
  975#endif
  976#if defined(__has_extension)
  977    #define JSON_HEDLEY_HAS_EXTENSION(extension) __has_extension(extension)
  978#else
  979    #define JSON_HEDLEY_HAS_EXTENSION(extension) (0)
  980#endif
  981
  982#if defined(JSON_HEDLEY_GNUC_HAS_EXTENSION)
  983    #undef JSON_HEDLEY_GNUC_HAS_EXTENSION
  984#endif
  985#if defined(__has_extension)
  986    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
  987#else
  988    #define JSON_HEDLEY_GNUC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
  989#endif
  990
  991#if defined(JSON_HEDLEY_GCC_HAS_EXTENSION)
  992    #undef JSON_HEDLEY_GCC_HAS_EXTENSION
  993#endif
  994#if defined(__has_extension)
  995    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) __has_extension(extension)
  996#else
  997    #define JSON_HEDLEY_GCC_HAS_EXTENSION(extension,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
  998#endif
  999
 1000#if defined(JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE)
 1001    #undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
 1002#endif
 1003#if defined(__has_declspec_attribute)
 1004    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) __has_declspec_attribute(attribute)
 1005#else
 1006    #define JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute) (0)
 1007#endif
 1008
 1009#if defined(JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE)
 1010    #undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
 1011#endif
 1012#if defined(__has_declspec_attribute)
 1013    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
 1014#else
 1015    #define JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
 1016#endif
 1017
 1018#if defined(JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE)
 1019    #undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
 1020#endif
 1021#if defined(__has_declspec_attribute)
 1022    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) __has_declspec_attribute(attribute)
 1023#else
 1024    #define JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE(attribute,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
 1025#endif
 1026
 1027#if defined(JSON_HEDLEY_HAS_WARNING)
 1028    #undef JSON_HEDLEY_HAS_WARNING
 1029#endif
 1030#if defined(__has_warning)
 1031    #define JSON_HEDLEY_HAS_WARNING(warning) __has_warning(warning)
 1032#else
 1033    #define JSON_HEDLEY_HAS_WARNING(warning) (0)
 1034#endif
 1035
 1036#if defined(JSON_HEDLEY_GNUC_HAS_WARNING)
 1037    #undef JSON_HEDLEY_GNUC_HAS_WARNING
 1038#endif
 1039#if defined(__has_warning)
 1040    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
 1041#else
 1042    #define JSON_HEDLEY_GNUC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GNUC_VERSION_CHECK(major,minor,patch)
 1043#endif
 1044
 1045#if defined(JSON_HEDLEY_GCC_HAS_WARNING)
 1046    #undef JSON_HEDLEY_GCC_HAS_WARNING
 1047#endif
 1048#if defined(__has_warning)
 1049    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) __has_warning(warning)
 1050#else
 1051    #define JSON_HEDLEY_GCC_HAS_WARNING(warning,major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
 1052#endif
 1053
 1054#if \
 1055    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
 1056    defined(__clang__) || \
 1057    JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
 1058    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1059    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
 1060    JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
 1061    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1062    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1063    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
 1064    JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
 1065    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
 1066    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,0,0) || \
 1067    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1068    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1069    JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0) || \
 1070    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,17) || \
 1071    JSON_HEDLEY_SUNPRO_VERSION_CHECK(8,0,0) || \
 1072    (JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) && defined(__C99_PRAGMA_OPERATOR))
 1073    #define JSON_HEDLEY_PRAGMA(value) _Pragma(#value)
 1074#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
 1075    #define JSON_HEDLEY_PRAGMA(value) __pragma(value)
 1076#else
 1077    #define JSON_HEDLEY_PRAGMA(value)
 1078#endif
 1079
 1080#if defined(JSON_HEDLEY_DIAGNOSTIC_PUSH)
 1081    #undef JSON_HEDLEY_DIAGNOSTIC_PUSH
 1082#endif
 1083#if defined(JSON_HEDLEY_DIAGNOSTIC_POP)
 1084    #undef JSON_HEDLEY_DIAGNOSTIC_POP
 1085#endif
 1086#if defined(__clang__)
 1087    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("clang diagnostic push")
 1088    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("clang diagnostic pop")
 1089#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 1090    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
 1091    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
 1092#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
 1093    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("GCC diagnostic push")
 1094    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("GCC diagnostic pop")
 1095#elif \
 1096    JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
 1097    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1098    #define JSON_HEDLEY_DIAGNOSTIC_PUSH __pragma(warning(push))
 1099    #define JSON_HEDLEY_DIAGNOSTIC_POP __pragma(warning(pop))
 1100#elif JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0)
 1101    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("push")
 1102    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("pop")
 1103#elif \
 1104    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1105    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1106    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,4,0) || \
 1107    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
 1108    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1109    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
 1110    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("diag_push")
 1111    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("diag_pop")
 1112#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
 1113    #define JSON_HEDLEY_DIAGNOSTIC_PUSH _Pragma("warning(push)")
 1114    #define JSON_HEDLEY_DIAGNOSTIC_POP _Pragma("warning(pop)")
 1115#else
 1116    #define JSON_HEDLEY_DIAGNOSTIC_PUSH
 1117    #define JSON_HEDLEY_DIAGNOSTIC_POP
 1118#endif
 1119
 1120/* JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_ is for
 1121   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
 1122#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
 1123    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
 1124#endif
 1125#if defined(__cplusplus)
 1126#  if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat")
 1127#    if JSON_HEDLEY_HAS_WARNING("-Wc++17-extensions")
 1128#      if JSON_HEDLEY_HAS_WARNING("-Wc++1z-extensions")
 1129#        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
 1130    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 1131    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
 1132    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
 1133    _Pragma("clang diagnostic ignored \"-Wc++1z-extensions\"") \
 1134    xpr \
 1135    JSON_HEDLEY_DIAGNOSTIC_POP
 1136#      else
 1137#        define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
 1138    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 1139    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
 1140    _Pragma("clang diagnostic ignored \"-Wc++17-extensions\"") \
 1141    xpr \
 1142    JSON_HEDLEY_DIAGNOSTIC_POP
 1143#      endif
 1144#    else
 1145#      define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(xpr) \
 1146    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 1147    _Pragma("clang diagnostic ignored \"-Wc++98-compat\"") \
 1148    xpr \
 1149    JSON_HEDLEY_DIAGNOSTIC_POP
 1150#    endif
 1151#  endif
 1152#endif
 1153#if !defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_)
 1154    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(x) x
 1155#endif
 1156
 1157#if defined(JSON_HEDLEY_CONST_CAST)
 1158    #undef JSON_HEDLEY_CONST_CAST
 1159#endif
 1160#if defined(__cplusplus)
 1161#  define JSON_HEDLEY_CONST_CAST(T, expr) (const_cast<T>(expr))
 1162#elif \
 1163  JSON_HEDLEY_HAS_WARNING("-Wcast-qual") || \
 1164  JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0) || \
 1165  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 1166#  define JSON_HEDLEY_CONST_CAST(T, expr) (__extension__ ({ \
 1167        JSON_HEDLEY_DIAGNOSTIC_PUSH \
 1168        JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL \
 1169        ((T) (expr)); \
 1170        JSON_HEDLEY_DIAGNOSTIC_POP \
 1171    }))
 1172#else
 1173#  define JSON_HEDLEY_CONST_CAST(T, expr) ((T) (expr))
 1174#endif
 1175
 1176#if defined(JSON_HEDLEY_REINTERPRET_CAST)
 1177    #undef JSON_HEDLEY_REINTERPRET_CAST
 1178#endif
 1179#if defined(__cplusplus)
 1180    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) (reinterpret_cast<T>(expr))
 1181#else
 1182    #define JSON_HEDLEY_REINTERPRET_CAST(T, expr) ((T) (expr))
 1183#endif
 1184
 1185#if defined(JSON_HEDLEY_STATIC_CAST)
 1186    #undef JSON_HEDLEY_STATIC_CAST
 1187#endif
 1188#if defined(__cplusplus)
 1189    #define JSON_HEDLEY_STATIC_CAST(T, expr) (static_cast<T>(expr))
 1190#else
 1191    #define JSON_HEDLEY_STATIC_CAST(T, expr) ((T) (expr))
 1192#endif
 1193
 1194#if defined(JSON_HEDLEY_CPP_CAST)
 1195    #undef JSON_HEDLEY_CPP_CAST
 1196#endif
 1197#if defined(__cplusplus)
 1198#  if JSON_HEDLEY_HAS_WARNING("-Wold-style-cast")
 1199#    define JSON_HEDLEY_CPP_CAST(T, expr) \
 1200    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 1201    _Pragma("clang diagnostic ignored \"-Wold-style-cast\"") \
 1202    ((T) (expr)) \
 1203    JSON_HEDLEY_DIAGNOSTIC_POP
 1204#  elif JSON_HEDLEY_IAR_VERSION_CHECK(8,3,0)
 1205#    define JSON_HEDLEY_CPP_CAST(T, expr) \
 1206    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 1207    _Pragma("diag_suppress=Pe137") \
 1208    JSON_HEDLEY_DIAGNOSTIC_POP
 1209#  else
 1210#    define JSON_HEDLEY_CPP_CAST(T, expr) ((T) (expr))
 1211#  endif
 1212#else
 1213#  define JSON_HEDLEY_CPP_CAST(T, expr) (expr)
 1214#endif
 1215
 1216#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED)
 1217    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
 1218#endif
 1219#if JSON_HEDLEY_HAS_WARNING("-Wdeprecated-declarations")
 1220    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("clang diagnostic ignored \"-Wdeprecated-declarations\"")
 1221#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 1222    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warning(disable:1478 1786)")
 1223#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1224    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:1478 1786))
 1225#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
 1226    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1216,1444,1445")
 1227#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
 1228    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
 1229#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
 1230    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
 1231#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
 1232    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED __pragma(warning(disable:4996))
 1233#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1234    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1215,1444")
 1235#elif \
 1236    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1237    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1238    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1239    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1240    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1241    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1242    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1243    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1244    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1245    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1246    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0)
 1247    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress 1291,1718")
 1248#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && !defined(__cplusplus)
 1249    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,E_DEPRECATED_ATT,E_DEPRECATED_ATT_MESS)")
 1250#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) && defined(__cplusplus)
 1251    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("error_messages(off,symdeprecated,symdeprecated2)")
 1252#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1253    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("diag_suppress=Pe1444,Pe1215")
 1254#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,90,0)
 1255    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED _Pragma("warn(disable:2241)")
 1256#else
 1257    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
 1258#endif
 1259
 1260#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS)
 1261    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
 1262#endif
 1263#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
 1264    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("clang diagnostic ignored \"-Wunknown-pragmas\"")
 1265#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 1266    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("warning(disable:161)")
 1267#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1268    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:161))
 1269#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
 1270    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 1675")
 1271#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0)
 1272    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("GCC diagnostic ignored \"-Wunknown-pragmas\"")
 1273#elif JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0)
 1274    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS __pragma(warning(disable:4068))
 1275#elif \
 1276    JSON_HEDLEY_TI_VERSION_CHECK(16,9,0) || \
 1277    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
 1278    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1279    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0)
 1280    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
 1281#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0)
 1282    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 163")
 1283#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1284    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress=Pe161")
 1285#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1286    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS _Pragma("diag_suppress 161")
 1287#else
 1288    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
 1289#endif
 1290
 1291#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES)
 1292    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
 1293#endif
 1294#if JSON_HEDLEY_HAS_WARNING("-Wunknown-attributes")
 1295    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("clang diagnostic ignored \"-Wunknown-attributes\"")
 1296#elif JSON_HEDLEY_GCC_VERSION_CHECK(4,6,0)
 1297    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("GCC diagnostic ignored \"-Wdeprecated-declarations\"")
 1298#elif JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0)
 1299    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("warning(disable:1292)")
 1300#elif JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1301    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:1292))
 1302#elif JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,0)
 1303    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES __pragma(warning(disable:5030))
 1304#elif JSON_HEDLEY_PGI_VERSION_CHECK(20,7,0)
 1305    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097,1098")
 1306#elif JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0)
 1307    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
 1308#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)
 1309    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("error_messages(off,attrskipunsup)")
 1310#elif \
 1311    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
 1312    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
 1313    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0)
 1314    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1173")
 1315#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1316    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress=Pe1097")
 1317#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1318    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES _Pragma("diag_suppress 1097")
 1319#else
 1320    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
 1321#endif
 1322
 1323#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL)
 1324    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
 1325#endif
 1326#if JSON_HEDLEY_HAS_WARNING("-Wcast-qual")
 1327    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("clang diagnostic ignored \"-Wcast-qual\"")
 1328#elif JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 1329    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("warning(disable:2203 2331)")
 1330#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0)
 1331    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL _Pragma("GCC diagnostic ignored \"-Wcast-qual\"")
 1332#else
 1333    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
 1334#endif
 1335
 1336#if defined(JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION)
 1337    #undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
 1338#endif
 1339#if JSON_HEDLEY_HAS_WARNING("-Wunused-function")
 1340    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("clang diagnostic ignored \"-Wunused-function\"")
 1341#elif JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0)
 1342    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("GCC diagnostic ignored \"-Wunused-function\"")
 1343#elif JSON_HEDLEY_MSVC_VERSION_CHECK(1,0,0)
 1344    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION __pragma(warning(disable:4505))
 1345#elif JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1346    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION _Pragma("diag_suppress 3142")
 1347#else
 1348    #define JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
 1349#endif
 1350
 1351#if defined(JSON_HEDLEY_DEPRECATED)
 1352    #undef JSON_HEDLEY_DEPRECATED
 1353#endif
 1354#if defined(JSON_HEDLEY_DEPRECATED_FOR)
 1355    #undef JSON_HEDLEY_DEPRECATED_FOR
 1356#endif
 1357#if \
 1358    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
 1359    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1360    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated("Since " # since))
 1361    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated("Since " #since "; use " #replacement))
 1362#elif \
 1363    (JSON_HEDLEY_HAS_EXTENSION(attribute_deprecated_with_message) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
 1364    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
 1365    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1366    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
 1367    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,13,0) || \
 1368    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
 1369    JSON_HEDLEY_TI_VERSION_CHECK(18,1,0) || \
 1370    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(18,1,0) || \
 1371    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,3,0) || \
 1372    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1373    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,3,0) || \
 1374    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1375    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__("Since " #since)))
 1376    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__("Since " #since "; use " #replacement)))
 1377#elif defined(__cplusplus) && (__cplusplus >= 201402L)
 1378    #define JSON_HEDLEY_DEPRECATED(since) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since)]])
 1379    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[deprecated("Since " #since "; use " #replacement)]])
 1380#elif \
 1381    JSON_HEDLEY_HAS_ATTRIBUTE(deprecated) || \
 1382    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
 1383    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1384    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1385    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1386    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1387    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1388    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1389    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1390    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1391    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1392    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1393    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1394    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1395    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
 1396    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
 1397    #define JSON_HEDLEY_DEPRECATED(since) __attribute__((__deprecated__))
 1398    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __attribute__((__deprecated__))
 1399#elif \
 1400    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
 1401    JSON_HEDLEY_PELLES_VERSION_CHECK(6,50,0) || \
 1402    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1403    #define JSON_HEDLEY_DEPRECATED(since) __declspec(deprecated)
 1404    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) __declspec(deprecated)
 1405#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1406    #define JSON_HEDLEY_DEPRECATED(since) _Pragma("deprecated")
 1407    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement) _Pragma("deprecated")
 1408#else
 1409    #define JSON_HEDLEY_DEPRECATED(since)
 1410    #define JSON_HEDLEY_DEPRECATED_FOR(since, replacement)
 1411#endif
 1412
 1413#if defined(JSON_HEDLEY_UNAVAILABLE)
 1414    #undef JSON_HEDLEY_UNAVAILABLE
 1415#endif
 1416#if \
 1417    JSON_HEDLEY_HAS_ATTRIBUTE(warning) || \
 1418    JSON_HEDLEY_GCC_VERSION_CHECK(4,3,0) || \
 1419    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1420    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1421    #define JSON_HEDLEY_UNAVAILABLE(available_since) __attribute__((__warning__("Not available until " #available_since)))
 1422#else
 1423    #define JSON_HEDLEY_UNAVAILABLE(available_since)
 1424#endif
 1425
 1426#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT)
 1427    #undef JSON_HEDLEY_WARN_UNUSED_RESULT
 1428#endif
 1429#if defined(JSON_HEDLEY_WARN_UNUSED_RESULT_MSG)
 1430    #undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
 1431#endif
 1432#if \
 1433    JSON_HEDLEY_HAS_ATTRIBUTE(warn_unused_result) || \
 1434    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
 1435    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1436    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1437    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1438    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1439    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1440    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1441    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1442    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1443    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1444    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1445    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1446    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1447    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
 1448    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
 1449    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1450    #define JSON_HEDLEY_WARN_UNUSED_RESULT __attribute__((__warn_unused_result__))
 1451    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) __attribute__((__warn_unused_result__))
 1452#elif (JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard) >= 201907L)
 1453    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
 1454    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard(msg)]])
 1455#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(nodiscard)
 1456    #define JSON_HEDLEY_WARN_UNUSED_RESULT JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
 1457    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[nodiscard]])
 1458#elif defined(_Check_return_) /* SAL */
 1459    #define JSON_HEDLEY_WARN_UNUSED_RESULT _Check_return_
 1460    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg) _Check_return_
 1461#else
 1462    #define JSON_HEDLEY_WARN_UNUSED_RESULT
 1463    #define JSON_HEDLEY_WARN_UNUSED_RESULT_MSG(msg)
 1464#endif
 1465
 1466#if defined(JSON_HEDLEY_SENTINEL)
 1467    #undef JSON_HEDLEY_SENTINEL
 1468#endif
 1469#if \
 1470    JSON_HEDLEY_HAS_ATTRIBUTE(sentinel) || \
 1471    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
 1472    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1473    JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
 1474    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1475    #define JSON_HEDLEY_SENTINEL(position) __attribute__((__sentinel__(position)))
 1476#else
 1477    #define JSON_HEDLEY_SENTINEL(position)
 1478#endif
 1479
 1480#if defined(JSON_HEDLEY_NO_RETURN)
 1481    #undef JSON_HEDLEY_NO_RETURN
 1482#endif
 1483#if JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1484    #define JSON_HEDLEY_NO_RETURN __noreturn
 1485#elif \
 1486    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1487    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1488    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
 1489#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
 1490    #define JSON_HEDLEY_NO_RETURN _Noreturn
 1491#elif defined(__cplusplus) && (__cplusplus >= 201103L)
 1492    #define JSON_HEDLEY_NO_RETURN JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[noreturn]])
 1493#elif \
 1494    JSON_HEDLEY_HAS_ATTRIBUTE(noreturn) || \
 1495    JSON_HEDLEY_GCC_VERSION_CHECK(3,2,0) || \
 1496    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1497    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1498    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1499    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1500    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1501    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1502    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1503    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1504    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1505    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1506    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1507    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1508    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1509    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1510    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
 1511    #define JSON_HEDLEY_NO_RETURN __attribute__((__noreturn__))
 1512#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
 1513    #define JSON_HEDLEY_NO_RETURN _Pragma("does_not_return")
 1514#elif \
 1515    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
 1516    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1517    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
 1518#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
 1519    #define JSON_HEDLEY_NO_RETURN _Pragma("FUNC_NEVER_RETURNS;")
 1520#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
 1521    #define JSON_HEDLEY_NO_RETURN __attribute((noreturn))
 1522#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
 1523    #define JSON_HEDLEY_NO_RETURN __declspec(noreturn)
 1524#else
 1525    #define JSON_HEDLEY_NO_RETURN
 1526#endif
 1527
 1528#if defined(JSON_HEDLEY_NO_ESCAPE)
 1529    #undef JSON_HEDLEY_NO_ESCAPE
 1530#endif
 1531#if JSON_HEDLEY_HAS_ATTRIBUTE(noescape)
 1532    #define JSON_HEDLEY_NO_ESCAPE __attribute__((__noescape__))
 1533#else
 1534    #define JSON_HEDLEY_NO_ESCAPE
 1535#endif
 1536
 1537#if defined(JSON_HEDLEY_UNREACHABLE)
 1538    #undef JSON_HEDLEY_UNREACHABLE
 1539#endif
 1540#if defined(JSON_HEDLEY_UNREACHABLE_RETURN)
 1541    #undef JSON_HEDLEY_UNREACHABLE_RETURN
 1542#endif
 1543#if defined(JSON_HEDLEY_ASSUME)
 1544    #undef JSON_HEDLEY_ASSUME
 1545#endif
 1546#if \
 1547    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
 1548    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1549    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1550    #define JSON_HEDLEY_ASSUME(expr) __assume(expr)
 1551#elif JSON_HEDLEY_HAS_BUILTIN(__builtin_assume)
 1552    #define JSON_HEDLEY_ASSUME(expr) __builtin_assume(expr)
 1553#elif \
 1554    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
 1555    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
 1556    #if defined(__cplusplus)
 1557        #define JSON_HEDLEY_ASSUME(expr) std::_nassert(expr)
 1558    #else
 1559        #define JSON_HEDLEY_ASSUME(expr) _nassert(expr)
 1560    #endif
 1561#endif
 1562#if \
 1563    (JSON_HEDLEY_HAS_BUILTIN(__builtin_unreachable) && (!defined(JSON_HEDLEY_ARM_VERSION))) || \
 1564    JSON_HEDLEY_GCC_VERSION_CHECK(4,5,0) || \
 1565    JSON_HEDLEY_PGI_VERSION_CHECK(18,10,0) || \
 1566    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1567    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,5) || \
 1568    JSON_HEDLEY_CRAY_VERSION_CHECK(10,0,0) || \
 1569    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1570    #define JSON_HEDLEY_UNREACHABLE() __builtin_unreachable()
 1571#elif defined(JSON_HEDLEY_ASSUME)
 1572    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
 1573#endif
 1574#if !defined(JSON_HEDLEY_ASSUME)
 1575    #if defined(JSON_HEDLEY_UNREACHABLE)
 1576        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, ((expr) ? 1 : (JSON_HEDLEY_UNREACHABLE(), 1)))
 1577    #else
 1578        #define JSON_HEDLEY_ASSUME(expr) JSON_HEDLEY_STATIC_CAST(void, expr)
 1579    #endif
 1580#endif
 1581#if defined(JSON_HEDLEY_UNREACHABLE)
 1582    #if  \
 1583        JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
 1584        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0)
 1585        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (JSON_HEDLEY_STATIC_CAST(void, JSON_HEDLEY_ASSUME(0)), (value))
 1586    #else
 1587        #define JSON_HEDLEY_UNREACHABLE_RETURN(value) JSON_HEDLEY_UNREACHABLE()
 1588    #endif
 1589#else
 1590    #define JSON_HEDLEY_UNREACHABLE_RETURN(value) return (value)
 1591#endif
 1592#if !defined(JSON_HEDLEY_UNREACHABLE)
 1593    #define JSON_HEDLEY_UNREACHABLE() JSON_HEDLEY_ASSUME(0)
 1594#endif
 1595
 1596JSON_HEDLEY_DIAGNOSTIC_PUSH
 1597#if JSON_HEDLEY_HAS_WARNING("-Wpedantic")
 1598    #pragma clang diagnostic ignored "-Wpedantic"
 1599#endif
 1600#if JSON_HEDLEY_HAS_WARNING("-Wc++98-compat-pedantic") && defined(__cplusplus)
 1601    #pragma clang diagnostic ignored "-Wc++98-compat-pedantic"
 1602#endif
 1603#if JSON_HEDLEY_GCC_HAS_WARNING("-Wvariadic-macros",4,0,0)
 1604    #if defined(__clang__)
 1605        #pragma clang diagnostic ignored "-Wvariadic-macros"
 1606    #elif defined(JSON_HEDLEY_GCC_VERSION)
 1607        #pragma GCC diagnostic ignored "-Wvariadic-macros"
 1608    #endif
 1609#endif
 1610#if defined(JSON_HEDLEY_NON_NULL)
 1611    #undef JSON_HEDLEY_NON_NULL
 1612#endif
 1613#if \
 1614    JSON_HEDLEY_HAS_ATTRIBUTE(nonnull) || \
 1615    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
 1616    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1617    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
 1618    #define JSON_HEDLEY_NON_NULL(...) __attribute__((__nonnull__(__VA_ARGS__)))
 1619#else
 1620    #define JSON_HEDLEY_NON_NULL(...)
 1621#endif
 1622JSON_HEDLEY_DIAGNOSTIC_POP
 1623
 1624#if defined(JSON_HEDLEY_PRINTF_FORMAT)
 1625    #undef JSON_HEDLEY_PRINTF_FORMAT
 1626#endif
 1627#if defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && !defined(__USE_MINGW_ANSI_STDIO)
 1628    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(ms_printf, string_idx, first_to_check)))
 1629#elif defined(__MINGW32__) && JSON_HEDLEY_GCC_HAS_ATTRIBUTE(format,4,4,0) && defined(__USE_MINGW_ANSI_STDIO)
 1630    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(gnu_printf, string_idx, first_to_check)))
 1631#elif \
 1632    JSON_HEDLEY_HAS_ATTRIBUTE(format) || \
 1633    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
 1634    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1635    JSON_HEDLEY_ARM_VERSION_CHECK(5,6,0) || \
 1636    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1637    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1638    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1639    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1640    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1641    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1642    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1643    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1644    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1645    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1646    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1647    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1648    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1649    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __attribute__((__format__(__printf__, string_idx, first_to_check)))
 1650#elif JSON_HEDLEY_PELLES_VERSION_CHECK(6,0,0)
 1651    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check) __declspec(vaformat(printf,string_idx,first_to_check))
 1652#else
 1653    #define JSON_HEDLEY_PRINTF_FORMAT(string_idx,first_to_check)
 1654#endif
 1655
 1656#if defined(JSON_HEDLEY_CONSTEXPR)
 1657    #undef JSON_HEDLEY_CONSTEXPR
 1658#endif
 1659#if defined(__cplusplus)
 1660    #if __cplusplus >= 201103L
 1661        #define JSON_HEDLEY_CONSTEXPR JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(constexpr)
 1662    #endif
 1663#endif
 1664#if !defined(JSON_HEDLEY_CONSTEXPR)
 1665    #define JSON_HEDLEY_CONSTEXPR
 1666#endif
 1667
 1668#if defined(JSON_HEDLEY_PREDICT)
 1669    #undef JSON_HEDLEY_PREDICT
 1670#endif
 1671#if defined(JSON_HEDLEY_LIKELY)
 1672    #undef JSON_HEDLEY_LIKELY
 1673#endif
 1674#if defined(JSON_HEDLEY_UNLIKELY)
 1675    #undef JSON_HEDLEY_UNLIKELY
 1676#endif
 1677#if defined(JSON_HEDLEY_UNPREDICTABLE)
 1678    #undef JSON_HEDLEY_UNPREDICTABLE
 1679#endif
 1680#if JSON_HEDLEY_HAS_BUILTIN(__builtin_unpredictable)
 1681    #define JSON_HEDLEY_UNPREDICTABLE(expr) __builtin_unpredictable((expr))
 1682#endif
 1683#if \
 1684  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect_with_probability) && !defined(JSON_HEDLEY_PGI_VERSION)) || \
 1685  JSON_HEDLEY_GCC_VERSION_CHECK(9,0,0) || \
 1686  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1687#  define JSON_HEDLEY_PREDICT(expr, value, probability) __builtin_expect_with_probability(  (expr), (value), (probability))
 1688#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability)   __builtin_expect_with_probability(!!(expr),    1   , (probability))
 1689#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability)  __builtin_expect_with_probability(!!(expr),    0   , (probability))
 1690#  define JSON_HEDLEY_LIKELY(expr)                      __builtin_expect                 (!!(expr),    1                  )
 1691#  define JSON_HEDLEY_UNLIKELY(expr)                    __builtin_expect                 (!!(expr),    0                  )
 1692#elif \
 1693  (JSON_HEDLEY_HAS_BUILTIN(__builtin_expect) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
 1694  JSON_HEDLEY_GCC_VERSION_CHECK(3,0,0) || \
 1695  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1696  (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,15,0) && defined(__cplusplus)) || \
 1697  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1698  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1699  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1700  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,7,0) || \
 1701  JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
 1702  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,1,0) || \
 1703  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
 1704  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1705  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1706  JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,27) || \
 1707  JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
 1708  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1709#  define JSON_HEDLEY_PREDICT(expr, expected, probability) \
 1710    (((probability) >= 0.9) ? __builtin_expect((expr), (expected)) : (JSON_HEDLEY_STATIC_CAST(void, expected), (expr)))
 1711#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) \
 1712    (__extension__ ({ \
 1713        double hedley_probability_ = (probability); \
 1714        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 1) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 0) : !!(expr))); \
 1715    }))
 1716#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) \
 1717    (__extension__ ({ \
 1718        double hedley_probability_ = (probability); \
 1719        ((hedley_probability_ >= 0.9) ? __builtin_expect(!!(expr), 0) : ((hedley_probability_ <= 0.1) ? __builtin_expect(!!(expr), 1) : !!(expr))); \
 1720    }))
 1721#  define JSON_HEDLEY_LIKELY(expr)   __builtin_expect(!!(expr), 1)
 1722#  define JSON_HEDLEY_UNLIKELY(expr) __builtin_expect(!!(expr), 0)
 1723#else
 1724#  define JSON_HEDLEY_PREDICT(expr, expected, probability) (JSON_HEDLEY_STATIC_CAST(void, expected), (expr))
 1725#  define JSON_HEDLEY_PREDICT_TRUE(expr, probability) (!!(expr))
 1726#  define JSON_HEDLEY_PREDICT_FALSE(expr, probability) (!!(expr))
 1727#  define JSON_HEDLEY_LIKELY(expr) (!!(expr))
 1728#  define JSON_HEDLEY_UNLIKELY(expr) (!!(expr))
 1729#endif
 1730#if !defined(JSON_HEDLEY_UNPREDICTABLE)
 1731    #define JSON_HEDLEY_UNPREDICTABLE(expr) JSON_HEDLEY_PREDICT(expr, 1, 0.5)
 1732#endif
 1733
 1734#if defined(JSON_HEDLEY_MALLOC)
 1735    #undef JSON_HEDLEY_MALLOC
 1736#endif
 1737#if \
 1738    JSON_HEDLEY_HAS_ATTRIBUTE(malloc) || \
 1739    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
 1740    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1741    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1742    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1743    JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
 1744    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1745    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1746    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1747    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1748    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1749    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1750    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1751    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1752    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1753    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1754    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1755    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1756    #define JSON_HEDLEY_MALLOC __attribute__((__malloc__))
 1757#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
 1758    #define JSON_HEDLEY_MALLOC _Pragma("returns_new_memory")
 1759#elif \
 1760    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
 1761    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1762    #define JSON_HEDLEY_MALLOC __declspec(restrict)
 1763#else
 1764    #define JSON_HEDLEY_MALLOC
 1765#endif
 1766
 1767#if defined(JSON_HEDLEY_PURE)
 1768    #undef JSON_HEDLEY_PURE
 1769#endif
 1770#if \
 1771  JSON_HEDLEY_HAS_ATTRIBUTE(pure) || \
 1772  JSON_HEDLEY_GCC_VERSION_CHECK(2,96,0) || \
 1773  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1774  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1775  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1776  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1777  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1778  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1779  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1780  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1781  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1782  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1783  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1784  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1785  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1786  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1787  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1788  JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
 1789  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1790#  define JSON_HEDLEY_PURE __attribute__((__pure__))
 1791#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
 1792#  define JSON_HEDLEY_PURE _Pragma("does_not_write_global_data")
 1793#elif defined(__cplusplus) && \
 1794    ( \
 1795      JSON_HEDLEY_TI_CL430_VERSION_CHECK(2,0,1) || \
 1796      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(4,0,0) || \
 1797      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) \
 1798    )
 1799#  define JSON_HEDLEY_PURE _Pragma("FUNC_IS_PURE;")
 1800#else
 1801#  define JSON_HEDLEY_PURE
 1802#endif
 1803
 1804#if defined(JSON_HEDLEY_CONST)
 1805    #undef JSON_HEDLEY_CONST
 1806#endif
 1807#if \
 1808    JSON_HEDLEY_HAS_ATTRIBUTE(const) || \
 1809    JSON_HEDLEY_GCC_VERSION_CHECK(2,5,0) || \
 1810    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1811    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1812    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1813    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1814    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1815    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1816    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1817    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1818    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1819    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1820    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1821    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1822    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1823    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1824    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1825    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
 1826    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1827    #define JSON_HEDLEY_CONST __attribute__((__const__))
 1828#elif \
 1829    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0)
 1830    #define JSON_HEDLEY_CONST _Pragma("no_side_effect")
 1831#else
 1832    #define JSON_HEDLEY_CONST JSON_HEDLEY_PURE
 1833#endif
 1834
 1835#if defined(JSON_HEDLEY_RESTRICT)
 1836    #undef JSON_HEDLEY_RESTRICT
 1837#endif
 1838#if defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && !defined(__cplusplus)
 1839    #define JSON_HEDLEY_RESTRICT restrict
 1840#elif \
 1841    JSON_HEDLEY_GCC_VERSION_CHECK(3,1,0) || \
 1842    JSON_HEDLEY_MSVC_VERSION_CHECK(14,0,0) || \
 1843    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1844    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
 1845    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1846    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1847    JSON_HEDLEY_PGI_VERSION_CHECK(17,10,0) || \
 1848    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1849    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,4) || \
 1850    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,1,0) || \
 1851    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1852    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,14,0) && defined(__cplusplus)) || \
 1853    JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0) || \
 1854    defined(__clang__) || \
 1855    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1856    #define JSON_HEDLEY_RESTRICT __restrict
 1857#elif JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,3,0) && !defined(__cplusplus)
 1858    #define JSON_HEDLEY_RESTRICT _Restrict
 1859#else
 1860    #define JSON_HEDLEY_RESTRICT
 1861#endif
 1862
 1863#if defined(JSON_HEDLEY_INLINE)
 1864    #undef JSON_HEDLEY_INLINE
 1865#endif
 1866#if \
 1867    (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L)) || \
 1868    (defined(__cplusplus) && (__cplusplus >= 199711L))
 1869    #define JSON_HEDLEY_INLINE inline
 1870#elif \
 1871    defined(JSON_HEDLEY_GCC_VERSION) || \
 1872    JSON_HEDLEY_ARM_VERSION_CHECK(6,2,0)
 1873    #define JSON_HEDLEY_INLINE __inline__
 1874#elif \
 1875    JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
 1876    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
 1877    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1878    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,1,0) || \
 1879    JSON_HEDLEY_TI_CL430_VERSION_CHECK(3,1,0) || \
 1880    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,2,0) || \
 1881    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(8,0,0) || \
 1882    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1883    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1884    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 1885    #define JSON_HEDLEY_INLINE __inline
 1886#else
 1887    #define JSON_HEDLEY_INLINE
 1888#endif
 1889
 1890#if defined(JSON_HEDLEY_ALWAYS_INLINE)
 1891    #undef JSON_HEDLEY_ALWAYS_INLINE
 1892#endif
 1893#if \
 1894  JSON_HEDLEY_HAS_ATTRIBUTE(always_inline) || \
 1895  JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
 1896  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1897  JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1898  JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1899  JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1900  JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1901  (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1902  JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1903  (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1904  JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1905  (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1906  JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1907  (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1908  JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1909  JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1910  JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1911  JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
 1912  JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
 1913#  define JSON_HEDLEY_ALWAYS_INLINE __attribute__((__always_inline__)) JSON_HEDLEY_INLINE
 1914#elif \
 1915  JSON_HEDLEY_MSVC_VERSION_CHECK(12,0,0) || \
 1916  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1917#  define JSON_HEDLEY_ALWAYS_INLINE __forceinline
 1918#elif defined(__cplusplus) && \
 1919    ( \
 1920      JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1921      JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1922      JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1923      JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
 1924      JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1925      JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) \
 1926    )
 1927#  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("FUNC_ALWAYS_INLINE;")
 1928#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1929#  define JSON_HEDLEY_ALWAYS_INLINE _Pragma("inline=forced")
 1930#else
 1931#  define JSON_HEDLEY_ALWAYS_INLINE JSON_HEDLEY_INLINE
 1932#endif
 1933
 1934#if defined(JSON_HEDLEY_NEVER_INLINE)
 1935    #undef JSON_HEDLEY_NEVER_INLINE
 1936#endif
 1937#if \
 1938    JSON_HEDLEY_HAS_ATTRIBUTE(noinline) || \
 1939    JSON_HEDLEY_GCC_VERSION_CHECK(4,0,0) || \
 1940    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1941    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1942    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1943    JSON_HEDLEY_IBM_VERSION_CHECK(10,1,0) || \
 1944    JSON_HEDLEY_TI_VERSION_CHECK(15,12,0) || \
 1945    (JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(4,8,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1946    JSON_HEDLEY_TI_ARMCL_VERSION_CHECK(5,2,0) || \
 1947    (JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1948    JSON_HEDLEY_TI_CL2000_VERSION_CHECK(6,4,0) || \
 1949    (JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,0,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1950    JSON_HEDLEY_TI_CL430_VERSION_CHECK(4,3,0) || \
 1951    (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 1952    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) || \
 1953    JSON_HEDLEY_TI_CL7X_VERSION_CHECK(1,2,0) || \
 1954    JSON_HEDLEY_TI_CLPRU_VERSION_CHECK(2,1,0) || \
 1955    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10) || \
 1956    JSON_HEDLEY_IAR_VERSION_CHECK(8,10,0)
 1957    #define JSON_HEDLEY_NEVER_INLINE __attribute__((__noinline__))
 1958#elif \
 1959    JSON_HEDLEY_MSVC_VERSION_CHECK(13,10,0) || \
 1960    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 1961    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
 1962#elif JSON_HEDLEY_PGI_VERSION_CHECK(10,2,0)
 1963    #define JSON_HEDLEY_NEVER_INLINE _Pragma("noinline")
 1964#elif JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,0,0) && defined(__cplusplus)
 1965    #define JSON_HEDLEY_NEVER_INLINE _Pragma("FUNC_CANNOT_INLINE;")
 1966#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 1967    #define JSON_HEDLEY_NEVER_INLINE _Pragma("inline=never")
 1968#elif JSON_HEDLEY_COMPCERT_VERSION_CHECK(3,2,0)
 1969    #define JSON_HEDLEY_NEVER_INLINE __attribute((noinline))
 1970#elif JSON_HEDLEY_PELLES_VERSION_CHECK(9,0,0)
 1971    #define JSON_HEDLEY_NEVER_INLINE __declspec(noinline)
 1972#else
 1973    #define JSON_HEDLEY_NEVER_INLINE
 1974#endif
 1975
 1976#if defined(JSON_HEDLEY_PRIVATE)
 1977    #undef JSON_HEDLEY_PRIVATE
 1978#endif
 1979#if defined(JSON_HEDLEY_PUBLIC)
 1980    #undef JSON_HEDLEY_PUBLIC
 1981#endif
 1982#if defined(JSON_HEDLEY_IMPORT)
 1983    #undef JSON_HEDLEY_IMPORT
 1984#endif
 1985#if defined(_WIN32) || defined(__CYGWIN__)
 1986#  define JSON_HEDLEY_PRIVATE
 1987#  define JSON_HEDLEY_PUBLIC   __declspec(dllexport)
 1988#  define JSON_HEDLEY_IMPORT   __declspec(dllimport)
 1989#else
 1990#  if \
 1991    JSON_HEDLEY_HAS_ATTRIBUTE(visibility) || \
 1992    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
 1993    JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,11,0) || \
 1994    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 1995    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 1996    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
 1997    ( \
 1998      defined(__TI_EABI__) && \
 1999      ( \
 2000        (JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,2,0) && defined(__TI_GNU_ATTRIBUTE_SUPPORT__)) || \
 2001        JSON_HEDLEY_TI_CL6X_VERSION_CHECK(7,5,0) \
 2002      ) \
 2003    ) || \
 2004    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 2005#    define JSON_HEDLEY_PRIVATE __attribute__((__visibility__("hidden")))
 2006#    define JSON_HEDLEY_PUBLIC  __attribute__((__visibility__("default")))
 2007#  else
 2008#    define JSON_HEDLEY_PRIVATE
 2009#    define JSON_HEDLEY_PUBLIC
 2010#  endif
 2011#  define JSON_HEDLEY_IMPORT    extern
 2012#endif
 2013
 2014#if defined(JSON_HEDLEY_NO_THROW)
 2015    #undef JSON_HEDLEY_NO_THROW
 2016#endif
 2017#if \
 2018    JSON_HEDLEY_HAS_ATTRIBUTE(nothrow) || \
 2019    JSON_HEDLEY_GCC_VERSION_CHECK(3,3,0) || \
 2020    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 2021    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 2022    #define JSON_HEDLEY_NO_THROW __attribute__((__nothrow__))
 2023#elif \
 2024    JSON_HEDLEY_MSVC_VERSION_CHECK(13,1,0) || \
 2025    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0) || \
 2026    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0)
 2027    #define JSON_HEDLEY_NO_THROW __declspec(nothrow)
 2028#else
 2029    #define JSON_HEDLEY_NO_THROW
 2030#endif
 2031
 2032#if defined(JSON_HEDLEY_FALL_THROUGH)
 2033    #undef JSON_HEDLEY_FALL_THROUGH
 2034#endif
 2035#if \
 2036    JSON_HEDLEY_HAS_ATTRIBUTE(fallthrough) || \
 2037    JSON_HEDLEY_GCC_VERSION_CHECK(7,0,0) || \
 2038    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 2039    #define JSON_HEDLEY_FALL_THROUGH __attribute__((__fallthrough__))
 2040#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS(clang,fallthrough)
 2041    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[clang::fallthrough]])
 2042#elif JSON_HEDLEY_HAS_CPP_ATTRIBUTE(fallthrough)
 2043    #define JSON_HEDLEY_FALL_THROUGH JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_([[fallthrough]])
 2044#elif defined(__fallthrough) /* SAL */
 2045    #define JSON_HEDLEY_FALL_THROUGH __fallthrough
 2046#else
 2047    #define JSON_HEDLEY_FALL_THROUGH
 2048#endif
 2049
 2050#if defined(JSON_HEDLEY_RETURNS_NON_NULL)
 2051    #undef JSON_HEDLEY_RETURNS_NON_NULL
 2052#endif
 2053#if \
 2054    JSON_HEDLEY_HAS_ATTRIBUTE(returns_nonnull) || \
 2055    JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
 2056    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 2057    #define JSON_HEDLEY_RETURNS_NON_NULL __attribute__((__returns_nonnull__))
 2058#elif defined(_Ret_notnull_) /* SAL */
 2059    #define JSON_HEDLEY_RETURNS_NON_NULL _Ret_notnull_
 2060#else
 2061    #define JSON_HEDLEY_RETURNS_NON_NULL
 2062#endif
 2063
 2064#if defined(JSON_HEDLEY_ARRAY_PARAM)
 2065    #undef JSON_HEDLEY_ARRAY_PARAM
 2066#endif
 2067#if \
 2068    defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 199901L) && \
 2069    !defined(__STDC_NO_VLA__) && \
 2070    !defined(__cplusplus) && \
 2071    !defined(JSON_HEDLEY_PGI_VERSION) && \
 2072    !defined(JSON_HEDLEY_TINYC_VERSION)
 2073    #define JSON_HEDLEY_ARRAY_PARAM(name) (name)
 2074#else
 2075    #define JSON_HEDLEY_ARRAY_PARAM(name)
 2076#endif
 2077
 2078#if defined(JSON_HEDLEY_IS_CONSTANT)
 2079    #undef JSON_HEDLEY_IS_CONSTANT
 2080#endif
 2081#if defined(JSON_HEDLEY_REQUIRE_CONSTEXPR)
 2082    #undef JSON_HEDLEY_REQUIRE_CONSTEXPR
 2083#endif
 2084/* JSON_HEDLEY_IS_CONSTEXPR_ is for
 2085   HEDLEY INTERNAL USE ONLY.  API subject to change without notice. */
 2086#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
 2087    #undef JSON_HEDLEY_IS_CONSTEXPR_
 2088#endif
 2089#if \
 2090    JSON_HEDLEY_HAS_BUILTIN(__builtin_constant_p) || \
 2091    JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
 2092    JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 2093    JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,19) || \
 2094    JSON_HEDLEY_ARM_VERSION_CHECK(4,1,0) || \
 2095    JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
 2096    JSON_HEDLEY_TI_CL6X_VERSION_CHECK(6,1,0) || \
 2097    (JSON_HEDLEY_SUNPRO_VERSION_CHECK(5,10,0) && !defined(__cplusplus)) || \
 2098    JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
 2099    JSON_HEDLEY_MCST_LCC_VERSION_CHECK(1,25,10)
 2100    #define JSON_HEDLEY_IS_CONSTANT(expr) __builtin_constant_p(expr)
 2101#endif
 2102#if !defined(__cplusplus)
 2103#  if \
 2104       JSON_HEDLEY_HAS_BUILTIN(__builtin_types_compatible_p) || \
 2105       JSON_HEDLEY_GCC_VERSION_CHECK(3,4,0) || \
 2106       JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 2107       JSON_HEDLEY_IBM_VERSION_CHECK(13,1,0) || \
 2108       JSON_HEDLEY_CRAY_VERSION_CHECK(8,1,0) || \
 2109       JSON_HEDLEY_ARM_VERSION_CHECK(5,4,0) || \
 2110       JSON_HEDLEY_TINYC_VERSION_CHECK(0,9,24)
 2111#if defined(__INTPTR_TYPE__)
 2112    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0)), int*)
 2113#else
 2114    #include <stdint.h>
 2115    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) __builtin_types_compatible_p(__typeof__((1 ? (void*) ((intptr_t) ((expr) * 0)) : (int*) 0)), int*)
 2116#endif
 2117#  elif \
 2118       ( \
 2119          defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L) && \
 2120          !defined(JSON_HEDLEY_SUNPRO_VERSION) && \
 2121          !defined(JSON_HEDLEY_PGI_VERSION) && \
 2122          !defined(JSON_HEDLEY_IAR_VERSION)) || \
 2123       (JSON_HEDLEY_HAS_EXTENSION(c_generic_selections) && !defined(JSON_HEDLEY_IAR_VERSION)) || \
 2124       JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0) || \
 2125       JSON_HEDLEY_INTEL_VERSION_CHECK(17,0,0) || \
 2126       JSON_HEDLEY_IBM_VERSION_CHECK(12,1,0) || \
 2127       JSON_HEDLEY_ARM_VERSION_CHECK(5,3,0)
 2128#if defined(__INTPTR_TYPE__)
 2129    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((__INTPTR_TYPE__) ((expr) * 0)) : (int*) 0), int*: 1, void*: 0)
 2130#else
 2131    #include <stdint.h>
 2132    #define JSON_HEDLEY_IS_CONSTEXPR_(expr) _Generic((1 ? (void*) ((intptr_t) * 0) : (int*) 0), int*: 1, void*: 0)
 2133#endif
 2134#  elif \
 2135       defined(JSON_HEDLEY_GCC_VERSION) || \
 2136       defined(JSON_HEDLEY_INTEL_VERSION) || \
 2137       defined(JSON_HEDLEY_TINYC_VERSION) || \
 2138       defined(JSON_HEDLEY_TI_ARMCL_VERSION) || \
 2139       JSON_HEDLEY_TI_CL430_VERSION_CHECK(18,12,0) || \
 2140       defined(JSON_HEDLEY_TI_CL2000_VERSION) || \
 2141       defined(JSON_HEDLEY_TI_CL6X_VERSION) || \
 2142       defined(JSON_HEDLEY_TI_CL7X_VERSION) || \
 2143       defined(JSON_HEDLEY_TI_CLPRU_VERSION) || \
 2144       defined(__clang__)
 2145#    define JSON_HEDLEY_IS_CONSTEXPR_(expr) ( \
 2146        sizeof(void) != \
 2147        sizeof(*( \
 2148                  1 ? \
 2149                  ((void*) ((expr) * 0L) ) : \
 2150((struct { char v[sizeof(void) * 2]; } *) 1) \
 2151                ) \
 2152              ) \
 2153                                            )
 2154#  endif
 2155#endif
 2156#if defined(JSON_HEDLEY_IS_CONSTEXPR_)
 2157    #if !defined(JSON_HEDLEY_IS_CONSTANT)
 2158        #define JSON_HEDLEY_IS_CONSTANT(expr) JSON_HEDLEY_IS_CONSTEXPR_(expr)
 2159    #endif
 2160    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (JSON_HEDLEY_IS_CONSTEXPR_(expr) ? (expr) : (-1))
 2161#else
 2162    #if !defined(JSON_HEDLEY_IS_CONSTANT)
 2163        #define JSON_HEDLEY_IS_CONSTANT(expr) (0)
 2164    #endif
 2165    #define JSON_HEDLEY_REQUIRE_CONSTEXPR(expr) (expr)
 2166#endif
 2167
 2168#if defined(JSON_HEDLEY_BEGIN_C_DECLS)
 2169    #undef JSON_HEDLEY_BEGIN_C_DECLS
 2170#endif
 2171#if defined(JSON_HEDLEY_END_C_DECLS)
 2172    #undef JSON_HEDLEY_END_C_DECLS
 2173#endif
 2174#if defined(JSON_HEDLEY_C_DECL)
 2175    #undef JSON_HEDLEY_C_DECL
 2176#endif
 2177#if defined(__cplusplus)
 2178    #define JSON_HEDLEY_BEGIN_C_DECLS extern "C" {
 2179    #define JSON_HEDLEY_END_C_DECLS }
 2180    #define JSON_HEDLEY_C_DECL extern "C"
 2181#else
 2182    #define JSON_HEDLEY_BEGIN_C_DECLS
 2183    #define JSON_HEDLEY_END_C_DECLS
 2184    #define JSON_HEDLEY_C_DECL
 2185#endif
 2186
 2187#if defined(JSON_HEDLEY_STATIC_ASSERT)
 2188    #undef JSON_HEDLEY_STATIC_ASSERT
 2189#endif
 2190#if \
 2191  !defined(__cplusplus) && ( \
 2192      (defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)) || \
 2193      (JSON_HEDLEY_HAS_FEATURE(c_static_assert) && !defined(JSON_HEDLEY_INTEL_CL_VERSION)) || \
 2194      JSON_HEDLEY_GCC_VERSION_CHECK(6,0,0) || \
 2195      JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0) || \
 2196      defined(_Static_assert) \
 2197    )
 2198#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) _Static_assert(expr, message)
 2199#elif \
 2200  (defined(__cplusplus) && (__cplusplus >= 201103L)) || \
 2201  JSON_HEDLEY_MSVC_VERSION_CHECK(16,0,0) || \
 2202  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 2203#  define JSON_HEDLEY_STATIC_ASSERT(expr, message) JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(static_assert(expr, message))
 2204#else
 2205#  define JSON_HEDLEY_STATIC_ASSERT(expr, message)
 2206#endif
 2207
 2208#if defined(JSON_HEDLEY_NULL)
 2209    #undef JSON_HEDLEY_NULL
 2210#endif
 2211#if defined(__cplusplus)
 2212    #if __cplusplus >= 201103L
 2213        #define JSON_HEDLEY_NULL JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_(nullptr)
 2214    #elif defined(NULL)
 2215        #define JSON_HEDLEY_NULL NULL
 2216    #else
 2217        #define JSON_HEDLEY_NULL JSON_HEDLEY_STATIC_CAST(void*, 0)
 2218    #endif
 2219#elif defined(NULL)
 2220    #define JSON_HEDLEY_NULL NULL
 2221#else
 2222    #define JSON_HEDLEY_NULL ((void*) 0)
 2223#endif
 2224
 2225#if defined(JSON_HEDLEY_MESSAGE)
 2226    #undef JSON_HEDLEY_MESSAGE
 2227#endif
 2228#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
 2229#  define JSON_HEDLEY_MESSAGE(msg) \
 2230    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 2231    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
 2232    JSON_HEDLEY_PRAGMA(message msg) \
 2233    JSON_HEDLEY_DIAGNOSTIC_POP
 2234#elif \
 2235  JSON_HEDLEY_GCC_VERSION_CHECK(4,4,0) || \
 2236  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 2237#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message msg)
 2238#elif JSON_HEDLEY_CRAY_VERSION_CHECK(5,0,0)
 2239#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(_CRI message msg)
 2240#elif JSON_HEDLEY_IAR_VERSION_CHECK(8,0,0)
 2241#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
 2242#elif JSON_HEDLEY_PELLES_VERSION_CHECK(2,0,0)
 2243#  define JSON_HEDLEY_MESSAGE(msg) JSON_HEDLEY_PRAGMA(message(msg))
 2244#else
 2245#  define JSON_HEDLEY_MESSAGE(msg)
 2246#endif
 2247
 2248#if defined(JSON_HEDLEY_WARNING)
 2249    #undef JSON_HEDLEY_WARNING
 2250#endif
 2251#if JSON_HEDLEY_HAS_WARNING("-Wunknown-pragmas")
 2252#  define JSON_HEDLEY_WARNING(msg) \
 2253    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 2254    JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS \
 2255    JSON_HEDLEY_PRAGMA(clang warning msg) \
 2256    JSON_HEDLEY_DIAGNOSTIC_POP
 2257#elif \
 2258  JSON_HEDLEY_GCC_VERSION_CHECK(4,8,0) || \
 2259  JSON_HEDLEY_PGI_VERSION_CHECK(18,4,0) || \
 2260  JSON_HEDLEY_INTEL_VERSION_CHECK(13,0,0)
 2261#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(GCC warning msg)
 2262#elif \
 2263  JSON_HEDLEY_MSVC_VERSION_CHECK(15,0,0) || \
 2264  JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 2265#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_PRAGMA(message(msg))
 2266#else
 2267#  define JSON_HEDLEY_WARNING(msg) JSON_HEDLEY_MESSAGE(msg)
 2268#endif
 2269
 2270#if defined(JSON_HEDLEY_REQUIRE)
 2271    #undef JSON_HEDLEY_REQUIRE
 2272#endif
 2273#if defined(JSON_HEDLEY_REQUIRE_MSG)
 2274    #undef JSON_HEDLEY_REQUIRE_MSG
 2275#endif
 2276#if JSON_HEDLEY_HAS_ATTRIBUTE(diagnose_if)
 2277#  if JSON_HEDLEY_HAS_WARNING("-Wgcc-compat")
 2278#    define JSON_HEDLEY_REQUIRE(expr) \
 2279    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 2280    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
 2281    __attribute__((diagnose_if(!(expr), #expr, "error"))) \
 2282    JSON_HEDLEY_DIAGNOSTIC_POP
 2283#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) \
 2284    JSON_HEDLEY_DIAGNOSTIC_PUSH \
 2285    _Pragma("clang diagnostic ignored \"-Wgcc-compat\"") \
 2286    __attribute__((diagnose_if(!(expr), msg, "error"))) \
 2287    JSON_HEDLEY_DIAGNOSTIC_POP
 2288#  else
 2289#    define JSON_HEDLEY_REQUIRE(expr) __attribute__((diagnose_if(!(expr), #expr, "error")))
 2290#    define JSON_HEDLEY_REQUIRE_MSG(expr,msg) __attribute__((diagnose_if(!(expr), msg, "error")))
 2291#  endif
 2292#else
 2293#  define JSON_HEDLEY_REQUIRE(expr)
 2294#  define JSON_HEDLEY_REQUIRE_MSG(expr,msg)
 2295#endif
 2296
 2297#if defined(JSON_HEDLEY_FLAGS)
 2298    #undef JSON_HEDLEY_FLAGS
 2299#endif
 2300#if JSON_HEDLEY_HAS_ATTRIBUTE(flag_enum) && (!defined(__cplusplus) || JSON_HEDLEY_HAS_WARNING("-Wbitfield-enum-conversion"))
 2301    #define JSON_HEDLEY_FLAGS __attribute__((__flag_enum__))
 2302#else
 2303    #define JSON_HEDLEY_FLAGS
 2304#endif
 2305
 2306#if defined(JSON_HEDLEY_FLAGS_CAST)
 2307    #undef JSON_HEDLEY_FLAGS_CAST
 2308#endif
 2309#if JSON_HEDLEY_INTEL_VERSION_CHECK(19,0,0)
 2310#  define JSON_HEDLEY_FLAGS_CAST(T, expr) (__extension__ ({ \
 2311        JSON_HEDLEY_DIAGNOSTIC_PUSH \
 2312        _Pragma("warning(disable:188)") \
 2313        ((T) (expr)); \
 2314        JSON_HEDLEY_DIAGNOSTIC_POP \
 2315    }))
 2316#else
 2317#  define JSON_HEDLEY_FLAGS_CAST(T, expr) JSON_HEDLEY_STATIC_CAST(T, expr)
 2318#endif
 2319
 2320#if defined(JSON_HEDLEY_EMPTY_BASES)
 2321    #undef JSON_HEDLEY_EMPTY_BASES
 2322#endif
 2323#if \
 2324    (JSON_HEDLEY_MSVC_VERSION_CHECK(19,0,23918) && !JSON_HEDLEY_MSVC_VERSION_CHECK(20,0,0)) || \
 2325    JSON_HEDLEY_INTEL_CL_VERSION_CHECK(2021,1,0)
 2326    #define JSON_HEDLEY_EMPTY_BASES __declspec(empty_bases)
 2327#else
 2328    #define JSON_HEDLEY_EMPTY_BASES
 2329#endif
 2330
 2331/* Remaining macros are deprecated. */
 2332
 2333#if defined(JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK)
 2334    #undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
 2335#endif
 2336#if defined(__clang__)
 2337    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) (0)
 2338#else
 2339    #define JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK(major,minor,patch) JSON_HEDLEY_GCC_VERSION_CHECK(major,minor,patch)
 2340#endif
 2341
 2342#if defined(JSON_HEDLEY_CLANG_HAS_ATTRIBUTE)
 2343    #undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
 2344#endif
 2345#define JSON_HEDLEY_CLANG_HAS_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_ATTRIBUTE(attribute)
 2346
 2347#if defined(JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE)
 2348    #undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
 2349#endif
 2350#define JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_CPP_ATTRIBUTE(attribute)
 2351
 2352#if defined(JSON_HEDLEY_CLANG_HAS_BUILTIN)
 2353    #undef JSON_HEDLEY_CLANG_HAS_BUILTIN
 2354#endif
 2355#define JSON_HEDLEY_CLANG_HAS_BUILTIN(builtin) JSON_HEDLEY_HAS_BUILTIN(builtin)
 2356
 2357#if defined(JSON_HEDLEY_CLANG_HAS_FEATURE)
 2358    #undef JSON_HEDLEY_CLANG_HAS_FEATURE
 2359#endif
 2360#define JSON_HEDLEY_CLANG_HAS_FEATURE(feature) JSON_HEDLEY_HAS_FEATURE(feature)
 2361
 2362#if defined(JSON_HEDLEY_CLANG_HAS_EXTENSION)
 2363    #undef JSON_HEDLEY_CLANG_HAS_EXTENSION
 2364#endif
 2365#define JSON_HEDLEY_CLANG_HAS_EXTENSION(extension) JSON_HEDLEY_HAS_EXTENSION(extension)
 2366
 2367#if defined(JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE)
 2368    #undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
 2369#endif
 2370#define JSON_HEDLEY_CLANG_HAS_DECLSPEC_ATTRIBUTE(attribute) JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE(attribute)
 2371
 2372#if defined(JSON_HEDLEY_CLANG_HAS_WARNING)
 2373    #undef JSON_HEDLEY_CLANG_HAS_WARNING
 2374#endif
 2375#define JSON_HEDLEY_CLANG_HAS_WARNING(warning) JSON_HEDLEY_HAS_WARNING(warning)
 2376
 2377#endif /* !defined(JSON_HEDLEY_VERSION) || (JSON_HEDLEY_VERSION < X) */
 2378
 2379
 2380// This file contains all internal macro definitions (except those affecting ABI)
 2381// You MUST include macro_unscope.hpp at the end of json.hpp to undef all of them
 2382
 2383// #include <nlohmann/detail/abi_macros.hpp>
 2384
 2385
 2386// exclude unsupported compilers
 2387#if !defined(JSON_SKIP_UNSUPPORTED_COMPILER_CHECK)
 2388    #if defined(__clang__)
 2389        #if (__clang_major__ * 10000 + __clang_minor__ * 100 + __clang_patchlevel__) < 30400
 2390            #error "unsupported Clang version - see https://github.com/nlohmann/json#supported-compilers"
 2391        #endif
 2392    #elif defined(__GNUC__) && !(defined(__ICC) || defined(__INTEL_COMPILER))
 2393        #if (__GNUC__ * 10000 + __GNUC_MINOR__ * 100 + __GNUC_PATCHLEVEL__) < 40800
 2394            #error "unsupported GCC version - see https://github.com/nlohmann/json#supported-compilers"
 2395        #endif
 2396    #endif
 2397#endif
 2398
 2399// C++ language standard detection
 2400// if the user manually specified the used c++ version this is skipped
 2401#if !defined(JSON_HAS_CPP_23) && !defined(JSON_HAS_CPP_20) && !defined(JSON_HAS_CPP_17) && !defined(JSON_HAS_CPP_14) && !defined(JSON_HAS_CPP_11)
 2402    #if (defined(__cplusplus) && __cplusplus > 202002L) || (defined(_MSVC_LANG) && _MSVC_LANG > 202002L)
 2403        #define JSON_HAS_CPP_23
 2404        #define JSON_HAS_CPP_20
 2405        #define JSON_HAS_CPP_17
 2406        #define JSON_HAS_CPP_14
 2407    #elif (defined(__cplusplus) && __cplusplus > 201703L) || (defined(_MSVC_LANG) && _MSVC_LANG > 201703L)
 2408        #define JSON_HAS_CPP_20
 2409        #define JSON_HAS_CPP_17
 2410        #define JSON_HAS_CPP_14
 2411    #elif (defined(__cplusplus) && __cplusplus > 201402L) || (defined(_HAS_CXX17) && _HAS_CXX17 == 1) // fix for issue #464
 2412        #define JSON_HAS_CPP_17
 2413        #define JSON_HAS_CPP_14
 2414    #elif (defined(__cplusplus) && __cplusplus > 201103L) || (defined(_HAS_CXX14) && _HAS_CXX14 == 1)
 2415        #define JSON_HAS_CPP_14
 2416    #endif
 2417    // the cpp 11 flag is always specified because it is the minimal required version
 2418    #define JSON_HAS_CPP_11
 2419#endif
 2420
 2421#ifdef __has_include
 2422    #if __has_include(<version>)
 2423        #include <version>
 2424    #endif
 2425#endif
 2426
 2427#if !defined(JSON_HAS_FILESYSTEM) && !defined(JSON_HAS_EXPERIMENTAL_FILESYSTEM)
 2428    #ifdef JSON_HAS_CPP_17
 2429        #if defined(__cpp_lib_filesystem)
 2430            #define JSON_HAS_FILESYSTEM 1
 2431        #elif defined(__cpp_lib_experimental_filesystem)
 2432            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
 2433        #elif !defined(__has_include)
 2434            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
 2435        #elif __has_include(<filesystem>)
 2436            #define JSON_HAS_FILESYSTEM 1
 2437        #elif __has_include(<experimental/filesystem>)
 2438            #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 1
 2439        #endif
 2440
 2441        // std::filesystem does not work on MinGW GCC 8: https://sourceforge.net/p/mingw-w64/bugs/737/
 2442        #if defined(__MINGW32__) && defined(__GNUC__) && __GNUC__ == 8
 2443            #undef JSON_HAS_FILESYSTEM
 2444            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2445        #endif
 2446
 2447        // no filesystem support before GCC 8: https://en.cppreference.com/w/cpp/compiler_support
 2448        #if defined(__GNUC__) && !defined(__clang__) && __GNUC__ < 8
 2449            #undef JSON_HAS_FILESYSTEM
 2450            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2451        #endif
 2452
 2453        // no filesystem support before Clang 7: https://en.cppreference.com/w/cpp/compiler_support
 2454        #if defined(__clang_major__) && __clang_major__ < 7
 2455            #undef JSON_HAS_FILESYSTEM
 2456            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2457        #endif
 2458
 2459        // no filesystem support before MSVC 19.14: https://en.cppreference.com/w/cpp/compiler_support
 2460        #if defined(_MSC_VER) && _MSC_VER < 1914
 2461            #undef JSON_HAS_FILESYSTEM
 2462            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2463        #endif
 2464
 2465        // no filesystem support before iOS 13
 2466        #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 130000
 2467            #undef JSON_HAS_FILESYSTEM
 2468            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2469        #endif
 2470
 2471        // no filesystem support before macOS Catalina
 2472        #if defined(__MAC_OS_X_VERSION_MIN_REQUIRED) && __MAC_OS_X_VERSION_MIN_REQUIRED < 101500
 2473            #undef JSON_HAS_FILESYSTEM
 2474            #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2475        #endif
 2476    #endif
 2477#endif
 2478
 2479#ifndef JSON_HAS_EXPERIMENTAL_FILESYSTEM
 2480    #define JSON_HAS_EXPERIMENTAL_FILESYSTEM 0
 2481#endif
 2482
 2483#ifndef JSON_HAS_FILESYSTEM
 2484    #define JSON_HAS_FILESYSTEM 0
 2485#endif
 2486
 2487#ifndef JSON_HAS_THREE_WAY_COMPARISON
 2488    #if defined(__cpp_impl_three_way_comparison) && __cpp_impl_three_way_comparison >= 201907L \
 2489        && defined(__cpp_lib_three_way_comparison) && __cpp_lib_three_way_comparison >= 201907L
 2490        #define JSON_HAS_THREE_WAY_COMPARISON 1
 2491    #else
 2492        #define JSON_HAS_THREE_WAY_COMPARISON 0
 2493    #endif
 2494#endif
 2495
 2496#ifndef JSON_HAS_RANGES
 2497    // ranges header shipping in GCC 11.1.0 (released 2021-04-27) has syntax error
 2498    #if defined(__GLIBCXX__) && __GLIBCXX__ == 20210427
 2499        #define JSON_HAS_RANGES 0
 2500    #elif defined(__cpp_lib_ranges)
 2501        #define JSON_HAS_RANGES 1
 2502    #else
 2503        #define JSON_HAS_RANGES 0
 2504    #endif
 2505#endif
 2506
 2507#ifndef JSON_HAS_STATIC_RTTI
 2508    #if !defined(_HAS_STATIC_RTTI) || _HAS_STATIC_RTTI != 0
 2509        #define JSON_HAS_STATIC_RTTI 1
 2510    #else
 2511        #define JSON_HAS_STATIC_RTTI 0
 2512    #endif
 2513#endif
 2514
 2515#ifdef JSON_HAS_CPP_17
 2516    #define JSON_INLINE_VARIABLE inline
 2517#else
 2518    #define JSON_INLINE_VARIABLE
 2519#endif
 2520
 2521#if JSON_HEDLEY_HAS_ATTRIBUTE(no_unique_address)
 2522    #define JSON_NO_UNIQUE_ADDRESS [[no_unique_address]]
 2523#else
 2524    #define JSON_NO_UNIQUE_ADDRESS
 2525#endif
 2526
 2527// disable documentation warnings on clang
 2528#if defined(__clang__)
 2529    #pragma clang diagnostic push
 2530    #pragma clang diagnostic ignored "-Wdocumentation"
 2531    #pragma clang diagnostic ignored "-Wdocumentation-unknown-command"
 2532#endif
 2533
 2534// allow disabling exceptions
 2535#if (defined(__cpp_exceptions) || defined(__EXCEPTIONS) || defined(_CPPUNWIND)) && !defined(JSON_NOEXCEPTION)
 2536    #define JSON_THROW(exception) throw exception
 2537    #define JSON_TRY try
 2538    #define JSON_CATCH(exception) catch(exception)
 2539    #define JSON_INTERNAL_CATCH(exception) catch(exception)
 2540#else
 2541    #include <cstdlib>
 2542    #define JSON_THROW(exception) std::abort()
 2543    #define JSON_TRY if(true)
 2544    #define JSON_CATCH(exception) if(false)
 2545    #define JSON_INTERNAL_CATCH(exception) if(false)
 2546#endif
 2547
 2548// override exception macros
 2549#if defined(JSON_THROW_USER)
 2550    #undef JSON_THROW
 2551    #define JSON_THROW JSON_THROW_USER
 2552#endif
 2553#if defined(JSON_TRY_USER)
 2554    #undef JSON_TRY
 2555    #define JSON_TRY JSON_TRY_USER
 2556#endif
 2557#if defined(JSON_CATCH_USER)
 2558    #undef JSON_CATCH
 2559    #define JSON_CATCH JSON_CATCH_USER
 2560    #undef JSON_INTERNAL_CATCH
 2561    #define JSON_INTERNAL_CATCH JSON_CATCH_USER
 2562#endif
 2563#if defined(JSON_INTERNAL_CATCH_USER)
 2564    #undef JSON_INTERNAL_CATCH
 2565    #define JSON_INTERNAL_CATCH JSON_INTERNAL_CATCH_USER
 2566#endif
 2567
 2568// allow overriding assert
 2569#if !defined(JSON_ASSERT)
 2570    #include <cassert> // assert
 2571    #define JSON_ASSERT(x) assert(x)
 2572#endif
 2573
 2574// allow to access some private functions (needed by the test suite)
 2575#if defined(JSON_TESTS_PRIVATE)
 2576    #define JSON_PRIVATE_UNLESS_TESTED public
 2577#else
 2578    #define JSON_PRIVATE_UNLESS_TESTED private
 2579#endif
 2580
 2581/*!
 2582@brief macro to briefly define a mapping between an enum and JSON
 2583@def NLOHMANN_JSON_SERIALIZE_ENUM
 2584@since version 3.4.0
 2585*/
 2586#define NLOHMANN_JSON_SERIALIZE_ENUM(ENUM_TYPE, ...)                                            \
 2587    template<typename BasicJsonType>                                                            \
 2588    inline void to_json(BasicJsonType& j, const ENUM_TYPE& e)                                   \
 2589    {                                                                                           \
 2590        /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */                                \
 2591        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
 2592        /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */       \
 2593        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
 2594        auto it = std::find_if(std::begin(m), std::end(m),                                      \
 2595                               [e](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool  \
 2596        {                                                                                       \
 2597            return ej_pair.first == e;                                                          \
 2598        });                                                                                     \
 2599        j = ((it != std::end(m)) ? it : std::begin(m))->second;                                 \
 2600    }                                                                                           \
 2601    template<typename BasicJsonType>                                                            \
 2602    inline void from_json(const BasicJsonType& j, ENUM_TYPE& e)                                 \
 2603    {                                                                                           \
 2604        /* NOLINTNEXTLINE(modernize-type-traits) we use C++11 */                                \
 2605        static_assert(std::is_enum<ENUM_TYPE>::value, #ENUM_TYPE " must be an enum!");          \
 2606        /* NOLINTNEXTLINE(modernize-avoid-c-arrays) we don't want to depend on <array> */       \
 2607        static const std::pair<ENUM_TYPE, BasicJsonType> m[] = __VA_ARGS__;                     \
 2608        auto it = std::find_if(std::begin(m), std::end(m),                                      \
 2609                               [&j](const std::pair<ENUM_TYPE, BasicJsonType>& ej_pair) -> bool \
 2610        {                                                                                       \
 2611            return ej_pair.second == j;                                                         \
 2612        });                                                                                     \
 2613        e = ((it != std::end(m)) ? it : std::begin(m))->first;                                  \
 2614    }
 2615
 2616// Ugly macros to avoid uglier copy-paste when specializing basic_json. They
 2617// may be removed in the future once the class is split.
 2618
 2619#define NLOHMANN_BASIC_JSON_TPL_DECLARATION                                \
 2620    template<template<typename, typename, typename...> class ObjectType,   \
 2621             template<typename, typename...> class ArrayType,              \
 2622             class StringType, class BooleanType, class NumberIntegerType, \
 2623             class NumberUnsignedType, class NumberFloatType,              \
 2624             template<typename> class AllocatorType,                       \
 2625             template<typename, typename = void> class JSONSerializer,     \
 2626             class BinaryType,                                             \
 2627             class CustomBaseClass>
 2628
 2629#define NLOHMANN_BASIC_JSON_TPL                                            \
 2630    basic_json<ObjectType, ArrayType, StringType, BooleanType,             \
 2631    NumberIntegerType, NumberUnsignedType, NumberFloatType,                \
 2632    AllocatorType, JSONSerializer, BinaryType, CustomBaseClass>
 2633
 2634// Macros to simplify conversion from/to types
 2635
 2636#define NLOHMANN_JSON_EXPAND( x ) x
 2637#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
 2638#define NLOHMANN_JSON_PASTE(...) NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_GET_MACRO(__VA_ARGS__, \
 2639        NLOHMANN_JSON_PASTE64, \
 2640        NLOHMANN_JSON_PASTE63, \
 2641        NLOHMANN_JSON_PASTE62, \
 2642        NLOHMANN_JSON_PASTE61, \
 2643        NLOHMANN_JSON_PASTE60, \
 2644        NLOHMANN_JSON_PASTE59, \
 2645        NLOHMANN_JSON_PASTE58, \
 2646        NLOHMANN_JSON_PASTE57, \
 2647        NLOHMANN_JSON_PASTE56, \
 2648        NLOHMANN_JSON_PASTE55, \
 2649        NLOHMANN_JSON_PASTE54, \
 2650        NLOHMANN_JSON_PASTE53, \
 2651        NLOHMANN_JSON_PASTE52, \
 2652        NLOHMANN_JSON_PASTE51, \
 2653        NLOHMANN_JSON_PASTE50, \
 2654        NLOHMANN_JSON_PASTE49, \
 2655        NLOHMANN_JSON_PASTE48, \
 2656        NLOHMANN_JSON_PASTE47, \
 2657        NLOHMANN_JSON_PASTE46, \
 2658        NLOHMANN_JSON_PASTE45, \
 2659        NLOHMANN_JSON_PASTE44, \
 2660        NLOHMANN_JSON_PASTE43, \
 2661        NLOHMANN_JSON_PASTE42, \
 2662        NLOHMANN_JSON_PASTE41, \
 2663        NLOHMANN_JSON_PASTE40, \
 2664        NLOHMANN_JSON_PASTE39, \
 2665        NLOHMANN_JSON_PASTE38, \
 2666        NLOHMANN_JSON_PASTE37, \
 2667        NLOHMANN_JSON_PASTE36, \
 2668        NLOHMANN_JSON_PASTE35, \
 2669        NLOHMANN_JSON_PASTE34, \
 2670        NLOHMANN_JSON_PASTE33, \
 2671        NLOHMANN_JSON_PASTE32, \
 2672        NLOHMANN_JSON_PASTE31, \
 2673        NLOHMANN_JSON_PASTE30, \
 2674        NLOHMANN_JSON_PASTE29, \
 2675        NLOHMANN_JSON_PASTE28, \
 2676        NLOHMANN_JSON_PASTE27, \
 2677        NLOHMANN_JSON_PASTE26, \
 2678        NLOHMANN_JSON_PASTE25, \
 2679        NLOHMANN_JSON_PASTE24, \
 2680        NLOHMANN_JSON_PASTE23, \
 2681        NLOHMANN_JSON_PASTE22, \
 2682        NLOHMANN_JSON_PASTE21, \
 2683        NLOHMANN_JSON_PASTE20, \
 2684        NLOHMANN_JSON_PASTE19, \
 2685        NLOHMANN_JSON_PASTE18, \
 2686        NLOHMANN_JSON_PASTE17, \
 2687        NLOHMANN_JSON_PASTE16, \
 2688        NLOHMANN_JSON_PASTE15, \
 2689        NLOHMANN_JSON_PASTE14, \
 2690        NLOHMANN_JSON_PASTE13, \
 2691        NLOHMANN_JSON_PASTE12, \
 2692        NLOHMANN_JSON_PASTE11, \
 2693        NLOHMANN_JSON_PASTE10, \
 2694        NLOHMANN_JSON_PASTE9, \
 2695        NLOHMANN_JSON_PASTE8, \
 2696        NLOHMANN_JSON_PASTE7, \
 2697        NLOHMANN_JSON_PASTE6, \
 2698        NLOHMANN_JSON_PASTE5, \
 2699        NLOHMANN_JSON_PASTE4, \
 2700        NLOHMANN_JSON_PASTE3, \
 2701        NLOHMANN_JSON_PASTE2, \
 2702        NLOHMANN_JSON_PASTE1)(__VA_ARGS__))
 2703#define NLOHMANN_JSON_PASTE2(func, v1) func(v1)
 2704#define NLOHMANN_JSON_PASTE3(func, v1, v2) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE2(func, v2)
 2705#define NLOHMANN_JSON_PASTE4(func, v1, v2, v3) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE3(func, v2, v3)
 2706#define NLOHMANN_JSON_PASTE5(func, v1, v2, v3, v4) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE4(func, v2, v3, v4)
 2707#define NLOHMANN_JSON_PASTE6(func, v1, v2, v3, v4, v5) NLOHMANN_JSON_PASTE2(func, v1) NLOHMANN_JSON_PASTE5(func, v2, v3, v4, v5)
 2708#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)
 2709#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)
 2710#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)
 2711#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)
 2712#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)
 2713#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)
 2714#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)
 2715#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)
 2716#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)
 2717#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)
 2718#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)
 2719#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)
 2720#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)
 2721#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)
 2722#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)
 2723#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)
 2724#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)
 2725#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)
 2726#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)
 2727#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)
 2728#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)
 2729#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)
 2730#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)
 2731#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)
 2732#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)
 2733#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)
 2734#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)
 2735#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)
 2736#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)
 2737#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)
 2738#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)
 2739#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)
 2740#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)
 2741#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)
 2742#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)
 2743#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)
 2744#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)
 2745#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)
 2746#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)
 2747#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)
 2748#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)
 2749#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)
 2750#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)
 2751#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)
 2752#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)
 2753#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)
 2754#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)
 2755#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)
 2756#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)
 2757#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)
 2758#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)
 2759#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)
 2760#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)
 2761#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)
 2762#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)
 2763#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)
 2764#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)
 2765#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)
 2766
 2767#define NLOHMANN_JSON_TO(v1) nlohmann_json_j[#v1] = nlohmann_json_t.v1;
 2768#define NLOHMANN_JSON_FROM(v1) nlohmann_json_j.at(#v1).get_to(nlohmann_json_t.v1);
 2769#define NLOHMANN_JSON_FROM_WITH_DEFAULT(v1) nlohmann_json_t.v1 = !nlohmann_json_j.is_null() ? nlohmann_json_j.value(#v1, nlohmann_json_default_obj.v1) : nlohmann_json_default_obj.v1;
 2770
 2771/*!
 2772@brief macro
 2773@def NLOHMANN_DEFINE_TYPE_INTRUSIVE
 2774@since version 3.9.0
 2775@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
 2776*/
 2777#define NLOHMANN_DEFINE_TYPE_INTRUSIVE(Type, ...)  \
 2778    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2779    friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2780    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2781    friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
 2782
 2783/*!
 2784@brief macro
 2785@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT
 2786@since version 3.11.0
 2787@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
 2788*/
 2789#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
 2790    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2791    friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2792    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2793    friend void from_json(const BasicJsonType& 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__)) }
 2794
 2795/*!
 2796@brief macro
 2797@def NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE
 2798@since version 3.11.3
 2799@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_intrusive/
 2800*/
 2801#define NLOHMANN_DEFINE_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \
 2802    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2803    friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
 2804
 2805/*!
 2806@brief macro
 2807@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE
 2808@since version 3.9.0
 2809@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
 2810*/
 2811#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE(Type, ...)  \
 2812    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2813    void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2814    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2815    void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
 2816
 2817/*!
 2818@brief macro
 2819@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT
 2820@since version 3.11.0
 2821@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
 2822*/
 2823#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, ...)  \
 2824    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2825    void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2826    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2827    void from_json(const BasicJsonType& 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__)) }
 2828
 2829/*!
 2830@brief macro
 2831@def NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
 2832@since version 3.11.3
 2833@sa https://json.nlohmann.me/api/macros/nlohmann_define_type_non_intrusive/
 2834*/
 2835#define NLOHMANN_DEFINE_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, ...)  \
 2836    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2837    void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
 2838
 2839/*!
 2840@brief macro
 2841@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE
 2842@since version 3.12.0
 2843@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
 2844*/
 2845#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE(Type, BaseType, ...)  \
 2846    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2847    friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2848    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2849    friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
 2850
 2851/*!
 2852@brief macro
 2853@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT
 2854@since version 3.12.0
 2855@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
 2856*/
 2857#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...)  \
 2858    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2859    friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2860    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2861    friend void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
 2862
 2863/*!
 2864@brief macro
 2865@def NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE
 2866@since version 3.12.0
 2867@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
 2868*/
 2869#define NLOHMANN_DEFINE_DERIVED_TYPE_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...)  \
 2870    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2871    friend void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
 2872
 2873/*!
 2874@brief macro
 2875@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE
 2876@since version 3.12.0
 2877@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
 2878*/
 2879#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE(Type, BaseType, ...)  \
 2880    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2881    void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2882    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2883    void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM, __VA_ARGS__)) }
 2884
 2885/*!
 2886@brief macro
 2887@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT
 2888@since version 3.12.0
 2889@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
 2890*/
 2891#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_WITH_DEFAULT(Type, BaseType, ...)  \
 2892    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2893    void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) } \
 2894    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2895    void from_json(const BasicJsonType& nlohmann_json_j, Type& nlohmann_json_t) { nlohmann::from_json(nlohmann_json_j, static_cast<BaseType&>(nlohmann_json_t)); const Type nlohmann_json_default_obj{}; NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_FROM_WITH_DEFAULT, __VA_ARGS__)) }
 2896
 2897/*!
 2898@brief macro
 2899@def NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE
 2900@since version 3.12.0
 2901@sa https://json.nlohmann.me/api/macros/nlohmann_define_derived_type/
 2902*/
 2903#define NLOHMANN_DEFINE_DERIVED_TYPE_NON_INTRUSIVE_ONLY_SERIALIZE(Type, BaseType, ...)  \
 2904    template<typename BasicJsonType, nlohmann::detail::enable_if_t<nlohmann::detail::is_basic_json<BasicJsonType>::value, int> = 0> \
 2905    void to_json(BasicJsonType& nlohmann_json_j, const Type& nlohmann_json_t) { nlohmann::to_json(nlohmann_json_j, static_cast<const BaseType &>(nlohmann_json_t)); NLOHMANN_JSON_EXPAND(NLOHMANN_JSON_PASTE(NLOHMANN_JSON_TO, __VA_ARGS__)) }
 2906
 2907// inspired from https://stackoverflow.com/a/26745591
 2908// allows calling any std function as if (e.g., with begin):
 2909// using std::begin; begin(x);
 2910//
 2911// it allows using the detected idiom to retrieve the return type
 2912// of such an expression
 2913#define NLOHMANN_CAN_CALL_STD_FUNC_IMPL(std_name)                                 \
 2914    namespace detail {                                                            \
 2915    using std::std_name;                                                          \
 2916    \
 2917    template<typename... T>                                                       \
 2918    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
 2919    }                                                                             \
 2920    \
 2921    namespace detail2 {                                                           \
 2922    struct std_name##_tag                                                         \
 2923    {                                                                             \
 2924    };                                                                            \
 2925    \
 2926    template<typename... T>                                                       \
 2927    std_name##_tag std_name(T&&...);                                              \
 2928    \
 2929    template<typename... T>                                                       \
 2930    using result_of_##std_name = decltype(std_name(std::declval<T>()...));        \
 2931    \
 2932    template<typename... T>                                                       \
 2933    struct would_call_std_##std_name                                              \
 2934    {                                                                             \
 2935        static constexpr auto const value = ::nlohmann::detail::                  \
 2936                                            is_detected_exact<std_name##_tag, result_of_##std_name, T...>::value; \
 2937    };                                                                            \
 2938    } /* namespace detail2 */ \
 2939    \
 2940    template<typename... T>                                                       \
 2941    struct would_call_std_##std_name : detail2::would_call_std_##std_name<T...>   \
 2942    {                                                                             \
 2943    }
 2944
 2945#ifndef JSON_USE_IMPLICIT_CONVERSIONS
 2946    #define JSON_USE_IMPLICIT_CONVERSIONS 1
 2947#endif
 2948
 2949#if JSON_USE_IMPLICIT_CONVERSIONS
 2950    #define JSON_EXPLICIT
 2951#else
 2952    #define JSON_EXPLICIT explicit
 2953#endif
 2954
 2955#ifndef JSON_DISABLE_ENUM_SERIALIZATION
 2956    #define JSON_DISABLE_ENUM_SERIALIZATION 0
 2957#endif
 2958
 2959#ifndef JSON_USE_GLOBAL_UDLS
 2960    #define JSON_USE_GLOBAL_UDLS 1
 2961#endif
 2962
 2963#if JSON_HAS_THREE_WAY_COMPARISON
 2964    #include <compare> // partial_ordering
 2965#endif
 2966
 2967NLOHMANN_JSON_NAMESPACE_BEGIN
 2968namespace detail
 2969{
 2970
 2971///////////////////////////
 2972// JSON type enumeration //
 2973///////////////////////////
 2974
 2975/*!
 2976@brief the JSON type enumeration
 2977
 2978This enumeration collects the different JSON types. It is internally used to
 2979distinguish the stored values, and the functions @ref basic_json::is_null(),
 2980@ref basic_json::is_object(), @ref basic_json::is_array(),
 2981@ref basic_json::is_string(), @ref basic_json::is_boolean(),
 2982@ref basic_json::is_number() (with @ref basic_json::is_number_integer(),
 2983@ref basic_json::is_number_unsigned(), and @ref basic_json::is_number_float()),
 2984@ref basic_json::is_discarded(), @ref basic_json::is_primitive(), and
 2985@ref basic_json::is_structured() rely on it.
 2986
 2987@note There are three enumeration entries (number_integer, number_unsigned, and
 2988number_float), because the library distinguishes these three types for numbers:
 2989@ref basic_json::number_unsigned_t is used for unsigned integers,
 2990@ref basic_json::number_integer_t is used for signed integers, and
 2991@ref basic_json::number_float_t is used for floating-point numbers or to
 2992approximate integers which do not fit in the limits of their respective type.
 2993
 2994@sa see @ref basic_json::basic_json(const value_t value_type) -- create a JSON
 2995value with the default value for a given type
 2996
 2997@since version 1.0.0
 2998*/
 2999enum class value_t : std::uint8_t
 3000{
 3001    null,             ///< null value
 3002    object,           ///< object (unordered set of name/value pairs)
 3003    array,            ///< array (ordered collection of values)
 3004    string,           ///< string value
 3005    boolean,          ///< boolean value
 3006    number_integer,   ///< number value (signed integer)
 3007    number_unsigned,  ///< number value (unsigned integer)
 3008    number_float,     ///< number value (floating-point)
 3009    binary,           ///< binary array (ordered collection of bytes)
 3010    discarded         ///< discarded by the parser callback function
 3011};
 3012
 3013/*!
 3014@brief comparison operator for JSON types
 3015
 3016Returns an ordering that is similar to Python:
 3017- order: null < boolean < number < object < array < string < binary
 3018- furthermore, each type is not smaller than itself
 3019- discarded values are not comparable
 3020- binary is represented as a b"" string in python and directly comparable to a
 3021  string; however, making a binary array directly comparable with a string would
 3022  be surprising behavior in a JSON file.
 3023
 3024@since version 1.0.0
 3025*/
 3026#if JSON_HAS_THREE_WAY_COMPARISON
 3027    inline std::partial_ordering operator<=>(const value_t lhs, const value_t rhs) noexcept // *NOPAD*
 3028#else
 3029    inline bool operator<(const value_t lhs, const value_t rhs) noexcept
 3030#endif
 3031{
 3032    static constexpr std::array<std::uint8_t, 9> order = {{
 3033            0 /* null */, 3 /* object */, 4 /* array */, 5 /* string */,
 3034            1 /* boolean */, 2 /* integer */, 2 /* unsigned */, 2 /* float */,
 3035            6 /* binary */
 3036        }
 3037    };
 3038
 3039    const auto l_index = static_cast<std::size_t>(lhs);
 3040    const auto r_index = static_cast<std::size_t>(rhs);
 3041#if JSON_HAS_THREE_WAY_COMPARISON
 3042    if (l_index < order.size() && r_index < order.size())
 3043    {
 3044        return order[l_index] <=> order[r_index]; // *NOPAD*
 3045    }
 3046    return std::partial_ordering::unordered;
 3047#else
 3048    return l_index < order.size() && r_index < order.size() && order[l_index] < order[r_index];
 3049#endif
 3050}
 3051
 3052// GCC selects the built-in operator< over an operator rewritten from
 3053// a user-defined spaceship operator
 3054// Clang, MSVC, and ICC select the rewritten candidate
 3055// (see GCC bug https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105200)
 3056#if JSON_HAS_THREE_WAY_COMPARISON && defined(__GNUC__)
 3057inline bool operator<(const value_t lhs, const value_t rhs) noexcept
 3058{
 3059    return std::is_lt(lhs <=> rhs); // *NOPAD*
 3060}
 3061#endif
 3062
 3063}  // namespace detail
 3064NLOHMANN_JSON_NAMESPACE_END
 3065
 3066// #include <nlohmann/detail/string_escape.hpp>
 3067//     __ _____ _____ _____
 3068//  __|  |   __|     |   | |  JSON for Modern C++
 3069// |  |  |__   |  |  | | | |  version 3.12.0
 3070// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3071//
 3072// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3073// SPDX-License-Identifier: MIT
 3074
 3075
 3076
 3077// #include <nlohmann/detail/abi_macros.hpp>
 3078
 3079
 3080NLOHMANN_JSON_NAMESPACE_BEGIN
 3081namespace detail
 3082{
 3083
 3084/*!
 3085@brief replace all occurrences of a substring by another string
 3086
 3087@param[in,out] s  the string to manipulate; changed so that all
 3088               occurrences of @a f are replaced with @a t
 3089@param[in]     f  the substring to replace with @a t
 3090@param[in]     t  the string to replace @a f
 3091
 3092@pre The search string @a f must not be empty. **This precondition is
 3093enforced with an assertion.**
 3094
 3095@since version 2.0.0
 3096*/
 3097template<typename StringType>
 3098inline void replace_substring(StringType& s, const StringType& f,
 3099                              const StringType& t)
 3100{
 3101    JSON_ASSERT(!f.empty());
 3102    for (auto pos = s.find(f);                // find first occurrence of f
 3103            pos != StringType::npos;          // make sure f was found
 3104            s.replace(pos, f.size(), t),      // replace with t, and
 3105            pos = s.find(f, pos + t.size()))  // find next occurrence of f
 3106    {}
 3107}
 3108
 3109/*!
 3110 * @brief string escaping as described in RFC 6901 (Sect. 4)
 3111 * @param[in] s string to escape
 3112 * @return    escaped string
 3113 *
 3114 * Note the order of escaping "~" to "~0" and "/" to "~1" is important.
 3115 */
 3116template<typename StringType>
 3117inline StringType escape(StringType s)
 3118{
 3119    replace_substring(s, StringType{"~"}, StringType{"~0"});
 3120    replace_substring(s, StringType{"/"}, StringType{"~1"});
 3121    return s;
 3122}
 3123
 3124/*!
 3125 * @brief string unescaping as described in RFC 6901 (Sect. 4)
 3126 * @param[in] s string to unescape
 3127 * @return    unescaped string
 3128 *
 3129 * Note the order of escaping "~1" to "/" and "~0" to "~" is important.
 3130 */
 3131template<typename StringType>
 3132static void unescape(StringType& s)
 3133{
 3134    replace_substring(s, StringType{"~1"}, StringType{"/"});
 3135    replace_substring(s, StringType{"~0"}, StringType{"~"});
 3136}
 3137
 3138}  // namespace detail
 3139NLOHMANN_JSON_NAMESPACE_END
 3140
 3141// #include <nlohmann/detail/input/position_t.hpp>
 3142//     __ _____ _____ _____
 3143//  __|  |   __|     |   | |  JSON for Modern C++
 3144// |  |  |__   |  |  | | | |  version 3.12.0
 3145// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3146//
 3147// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3148// SPDX-License-Identifier: MIT
 3149
 3150
 3151
 3152#include <cstddef> // size_t
 3153
 3154// #include <nlohmann/detail/abi_macros.hpp>
 3155
 3156
 3157NLOHMANN_JSON_NAMESPACE_BEGIN
 3158namespace detail
 3159{
 3160
 3161/// struct to capture the start position of the current token
 3162struct position_t
 3163{
 3164    /// the total number of characters read
 3165    std::size_t chars_read_total = 0;
 3166    /// the number of characters read in the current line
 3167    std::size_t chars_read_current_line = 0;
 3168    /// the number of lines read
 3169    std::size_t lines_read = 0;
 3170
 3171    /// conversion to size_t to preserve SAX interface
 3172    constexpr operator size_t() const
 3173    {
 3174        return chars_read_total;
 3175    }
 3176};
 3177
 3178}  // namespace detail
 3179NLOHMANN_JSON_NAMESPACE_END
 3180
 3181// #include <nlohmann/detail/macro_scope.hpp>
 3182
 3183// #include <nlohmann/detail/meta/cpp_future.hpp>
 3184//     __ _____ _____ _____
 3185//  __|  |   __|     |   | |  JSON for Modern C++
 3186// |  |  |__   |  |  | | | |  version 3.12.0
 3187// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3188//
 3189// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3190// SPDX-FileCopyrightText: 2018 The Abseil Authors
 3191// SPDX-License-Identifier: MIT
 3192
 3193
 3194
 3195#include <array> // array
 3196#include <cstddef> // size_t
 3197#include <type_traits> // conditional, enable_if, false_type, integral_constant, is_constructible, is_integral, is_same, remove_cv, remove_reference, true_type
 3198#include <utility> // index_sequence, make_index_sequence, index_sequence_for
 3199
 3200// #include <nlohmann/detail/macro_scope.hpp>
 3201
 3202
 3203NLOHMANN_JSON_NAMESPACE_BEGIN
 3204namespace detail
 3205{
 3206
 3207template<typename T>
 3208using uncvref_t = typename std::remove_cv<typename std::remove_reference<T>::type>::type;
 3209
 3210#ifdef JSON_HAS_CPP_14
 3211
 3212// the following utilities are natively available in C++14
 3213using std::enable_if_t;
 3214using std::index_sequence;
 3215using std::make_index_sequence;
 3216using std::index_sequence_for;
 3217
 3218#else
 3219
 3220// alias templates to reduce boilerplate
 3221template<bool B, typename T = void>
 3222using enable_if_t = typename std::enable_if<B, T>::type;
 3223
 3224// The following code is taken from https://github.com/abseil/abseil-cpp/blob/10cb35e459f5ecca5b2ff107635da0bfa41011b4/absl/utility/utility.h
 3225// which is part of Google Abseil (https://github.com/abseil/abseil-cpp), licensed under the Apache License 2.0.
 3226
 3227//// START OF CODE FROM GOOGLE ABSEIL
 3228
 3229// integer_sequence
 3230//
 3231// Class template representing a compile-time integer sequence. An instantiation
 3232// of `integer_sequence<T, Ints...>` has a sequence of integers encoded in its
 3233// type through its template arguments (which is a common need when
 3234// working with C++11 variadic templates). `absl::integer_sequence` is designed
 3235// to be a drop-in replacement for C++14's `std::integer_sequence`.
 3236//
 3237// Example:
 3238//
 3239//   template< class T, T... Ints >
 3240//   void user_function(integer_sequence<T, Ints...>);
 3241//
 3242//   int main()
 3243//   {
 3244//     // user_function's `T` will be deduced to `int` and `Ints...`
 3245//     // will be deduced to `0, 1, 2, 3, 4`.
 3246//     user_function(make_integer_sequence<int, 5>());
 3247//   }
 3248template <typename T, T... Ints>
 3249struct integer_sequence
 3250{
 3251    using value_type = T;
 3252    static constexpr std::size_t size() noexcept
 3253    {
 3254        return sizeof...(Ints);
 3255    }
 3256};
 3257
 3258// index_sequence
 3259//
 3260// A helper template for an `integer_sequence` of `size_t`,
 3261// `absl::index_sequence` is designed to be a drop-in replacement for C++14's
 3262// `std::index_sequence`.
 3263template <size_t... Ints>
 3264using index_sequence = integer_sequence<size_t, Ints...>;
 3265
 3266namespace utility_internal
 3267{
 3268
 3269template <typename Seq, size_t SeqSize, size_t Rem>
 3270struct Extend;
 3271
 3272// Note that SeqSize == sizeof...(Ints). It's passed explicitly for efficiency.
 3273template <typename T, T... Ints, size_t SeqSize>
 3274struct Extend<integer_sequence<T, Ints...>, SeqSize, 0>
 3275{
 3276    using type = integer_sequence < T, Ints..., (Ints + SeqSize)... >;
 3277};
 3278
 3279template <typename T, T... Ints, size_t SeqSize>
 3280struct Extend<integer_sequence<T, Ints...>, SeqSize, 1>
 3281{
 3282    using type = integer_sequence < T, Ints..., (Ints + SeqSize)..., 2 * SeqSize >;
 3283};
 3284
 3285// Recursion helper for 'make_integer_sequence<T, N>'.
 3286// 'Gen<T, N>::type' is an alias for 'integer_sequence<T, 0, 1, ... N-1>'.
 3287template <typename T, size_t N>
 3288struct Gen
 3289{
 3290    using type =
 3291        typename Extend < typename Gen < T, N / 2 >::type, N / 2, N % 2 >::type;
 3292};
 3293
 3294template <typename T>
 3295struct Gen<T, 0>
 3296{
 3297    using type = integer_sequence<T>;
 3298};
 3299
 3300}  // namespace utility_internal
 3301
 3302// Compile-time sequences of integers
 3303
 3304// make_integer_sequence
 3305//
 3306// This template alias is equivalent to
 3307// `integer_sequence<int, 0, 1, ..., N-1>`, and is designed to be a drop-in
 3308// replacement for C++14's `std::make_integer_sequence`.
 3309template <typename T, T N>
 3310using make_integer_sequence = typename utility_internal::Gen<T, N>::type;
 3311
 3312// make_index_sequence
 3313//
 3314// This template alias is equivalent to `index_sequence<0, 1, ..., N-1>`,
 3315// and is designed to be a drop-in replacement for C++14's
 3316// `std::make_index_sequence`.
 3317template <size_t N>
 3318using make_index_sequence = make_integer_sequence<size_t, N>;
 3319
 3320// index_sequence_for
 3321//
 3322// Converts a typename pack into an index sequence of the same length, and
 3323// is designed to be a drop-in replacement for C++14's
 3324// `std::index_sequence_for()`
 3325template <typename... Ts>
 3326using index_sequence_for = make_index_sequence<sizeof...(Ts)>;
 3327
 3328//// END OF CODE FROM GOOGLE ABSEIL
 3329
 3330#endif
 3331
 3332// dispatch utility (taken from ranges-v3)
 3333template<unsigned N> struct priority_tag : priority_tag < N - 1 > {};
 3334template<> struct priority_tag<0> {};
 3335
 3336// taken from ranges-v3
 3337template<typename T>
 3338struct static_const
 3339{
 3340    static JSON_INLINE_VARIABLE constexpr T value{};
 3341};
 3342
 3343#ifndef JSON_HAS_CPP_17
 3344    template<typename T>
 3345    constexpr T static_const<T>::value;
 3346#endif
 3347
 3348template<typename T, typename... Args>
 3349constexpr std::array<T, sizeof...(Args)> make_array(Args&& ... args)
 3350{
 3351    return std::array<T, sizeof...(Args)> {{static_cast<T>(std::forward<Args>(args))...}};
 3352}
 3353
 3354}  // namespace detail
 3355NLOHMANN_JSON_NAMESPACE_END
 3356
 3357// #include <nlohmann/detail/meta/type_traits.hpp>
 3358//     __ _____ _____ _____
 3359//  __|  |   __|     |   | |  JSON for Modern C++
 3360// |  |  |__   |  |  | | | |  version 3.12.0
 3361// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3362//
 3363// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3364// SPDX-License-Identifier: MIT
 3365
 3366
 3367
 3368#include <limits> // numeric_limits
 3369#include <string> // char_traits
 3370#include <tuple> // tuple
 3371#include <type_traits> // false_type, is_constructible, is_integral, is_same, true_type
 3372#include <utility> // declval
 3373
 3374// #include <nlohmann/detail/iterators/iterator_traits.hpp>
 3375//     __ _____ _____ _____
 3376//  __|  |   __|     |   | |  JSON for Modern C++
 3377// |  |  |__   |  |  | | | |  version 3.12.0
 3378// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3379//
 3380// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3381// SPDX-License-Identifier: MIT
 3382
 3383
 3384
 3385#include <iterator> // random_access_iterator_tag
 3386
 3387// #include <nlohmann/detail/abi_macros.hpp>
 3388
 3389// #include <nlohmann/detail/meta/void_t.hpp>
 3390
 3391// #include <nlohmann/detail/meta/cpp_future.hpp>
 3392
 3393
 3394NLOHMANN_JSON_NAMESPACE_BEGIN
 3395namespace detail
 3396{
 3397
 3398template<typename It, typename = void>
 3399struct iterator_types {};
 3400
 3401template<typename It>
 3402struct iterator_types <
 3403    It,
 3404    void_t<typename It::difference_type, typename It::value_type, typename It::pointer,
 3405    typename It::reference, typename It::iterator_category >>
 3406{
 3407    using difference_type = typename It::difference_type;
 3408    using value_type = typename It::value_type;
 3409    using pointer = typename It::pointer;
 3410    using reference = typename It::reference;
 3411    using iterator_category = typename It::iterator_category;
 3412};
 3413
 3414// This is required as some compilers implement std::iterator_traits in a way that
 3415// doesn't work with SFINAE. See https://github.com/nlohmann/json/issues/1341.
 3416template<typename T, typename = void>
 3417struct iterator_traits
 3418{
 3419};
 3420
 3421template<typename T>
 3422struct iterator_traits < T, enable_if_t < !std::is_pointer<T>::value >>
 3423    : iterator_types<T>
 3424{
 3425};
 3426
 3427template<typename T>
 3428struct iterator_traits<T*, enable_if_t<std::is_object<T>::value>>
 3429{
 3430    using iterator_category = std::random_access_iterator_tag;
 3431    using value_type = T;
 3432    using difference_type = ptrdiff_t;
 3433    using pointer = T*;
 3434    using reference = T&;
 3435};
 3436
 3437}  // namespace detail
 3438NLOHMANN_JSON_NAMESPACE_END
 3439
 3440// #include <nlohmann/detail/macro_scope.hpp>
 3441
 3442// #include <nlohmann/detail/meta/call_std/begin.hpp>
 3443//     __ _____ _____ _____
 3444//  __|  |   __|     |   | |  JSON for Modern C++
 3445// |  |  |__   |  |  | | | |  version 3.12.0
 3446// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3447//
 3448// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3449// SPDX-License-Identifier: MIT
 3450
 3451
 3452
 3453// #include <nlohmann/detail/macro_scope.hpp>
 3454
 3455
 3456NLOHMANN_JSON_NAMESPACE_BEGIN
 3457
 3458NLOHMANN_CAN_CALL_STD_FUNC_IMPL(begin);
 3459
 3460NLOHMANN_JSON_NAMESPACE_END
 3461
 3462// #include <nlohmann/detail/meta/call_std/end.hpp>
 3463//     __ _____ _____ _____
 3464//  __|  |   __|     |   | |  JSON for Modern C++
 3465// |  |  |__   |  |  | | | |  version 3.12.0
 3466// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3467//
 3468// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3469// SPDX-License-Identifier: MIT
 3470
 3471
 3472
 3473// #include <nlohmann/detail/macro_scope.hpp>
 3474
 3475
 3476NLOHMANN_JSON_NAMESPACE_BEGIN
 3477
 3478NLOHMANN_CAN_CALL_STD_FUNC_IMPL(end);
 3479
 3480NLOHMANN_JSON_NAMESPACE_END
 3481
 3482// #include <nlohmann/detail/meta/cpp_future.hpp>
 3483
 3484// #include <nlohmann/detail/meta/detected.hpp>
 3485
 3486// #include <nlohmann/json_fwd.hpp>
 3487//     __ _____ _____ _____
 3488//  __|  |   __|     |   | |  JSON for Modern C++
 3489// |  |  |__   |  |  | | | |  version 3.12.0
 3490// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 3491//
 3492// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 3493// SPDX-License-Identifier: MIT
 3494
 3495#ifndef INCLUDE_NLOHMANN_JSON_FWD_HPP_
 3496    #define INCLUDE_NLOHMANN_JSON_FWD_HPP_
 3497
 3498    #include <cstdint> // int64_t, uint64_t
 3499    #include <map> // map
 3500    #include <memory> // allocator
 3501    #include <string> // string
 3502    #include <vector> // vector
 3503
 3504    // #include <nlohmann/detail/abi_macros.hpp>
 3505
 3506
 3507    /*!
 3508    @brief namespace for Niels Lohmann
 3509    @see https://github.com/nlohmann
 3510    @since version 1.0.0
 3511    */
 3512    NLOHMANN_JSON_NAMESPACE_BEGIN
 3513
 3514    /*!
 3515    @brief default JSONSerializer template argument
 3516
 3517    This serializer ignores the template arguments and uses ADL
 3518    ([argument-dependent lookup](https://en.cppreference.com/w/cpp/language/adl))
 3519    for serialization.
 3520    */
 3521    template<typename T = void, typename SFINAE = void>
 3522    struct adl_serializer;
 3523
 3524    /// a class to store JSON values
 3525    /// @sa https://json.nlohmann.me/api/basic_json/
 3526    template<template<typename U, typename V, typename... Args> class ObjectType =
 3527    std::map,
 3528    template<typename U, typename... Args> class ArrayType = std::vector,
 3529    class StringType = std::string, class BooleanType = bool,
 3530    class NumberIntegerType = std::int64_t,
 3531    class NumberUnsignedType = std::uint64_t,
 3532    class NumberFloatType = double,
 3533    template<typename U> class AllocatorType = std::allocator,
 3534    template<typename T, typename SFINAE = void> class JSONSerializer =
 3535    adl_serializer,
 3536    class BinaryType = std::vector<std::uint8_t>, // cppcheck-suppress syntaxError
 3537    class CustomBaseClass = void>
 3538    class basic_json;
 3539
 3540    /// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
 3541    /// @sa https://json.nlohmann.me/api/json_pointer/
 3542    template<typename RefStringType>
 3543    class json_pointer;
 3544
 3545    /*!
 3546    @brief default specialization
 3547    @sa https://json.nlohmann.me/api/json/
 3548    */
 3549    using json = basic_json<>;
 3550
 3551    /// @brief a minimal map-like container that preserves insertion order
 3552    /// @sa https://json.nlohmann.me/api/ordered_map/
 3553    template<class Key, class T, class IgnoredLess, class Allocator>
 3554    struct ordered_map;
 3555
 3556    /// @brief specialization that maintains the insertion order of object keys
 3557    /// @sa https://json.nlohmann.me/api/ordered_json/
 3558    using ordered_json = basic_json<nlohmann::ordered_map>;
 3559
 3560    NLOHMANN_JSON_NAMESPACE_END
 3561
 3562#endif  // INCLUDE_NLOHMANN_JSON_FWD_HPP_
 3563
 3564
 3565NLOHMANN_JSON_NAMESPACE_BEGIN
 3566/*!
 3567@brief detail namespace with internal helper functions
 3568
 3569This namespace collects functions that should not be exposed,
 3570implementations of some @ref basic_json methods, and meta-programming helpers.
 3571
 3572@since version 2.1.0
 3573*/
 3574namespace detail
 3575{
 3576
 3577/////////////
 3578// helpers //
 3579/////////////
 3580
 3581// Note to maintainers:
 3582//
 3583// Every trait in this file expects a non CV-qualified type.
 3584// The only exceptions are in the 'aliases for detected' section
 3585// (i.e. those of the form: decltype(T::member_function(std::declval<T>())))
 3586//
 3587// In this case, T has to be properly CV-qualified to constraint the function arguments
 3588// (e.g. to_json(BasicJsonType&, const T&))
 3589
 3590template<typename> struct is_basic_json : std::false_type {};
 3591
 3592NLOHMANN_BASIC_JSON_TPL_DECLARATION
 3593struct is_basic_json<NLOHMANN_BASIC_JSON_TPL> : std::true_type {};
 3594
 3595// used by exceptions create() member functions
 3596// true_type for pointer to possibly cv-qualified basic_json or std::nullptr_t
 3597// false_type otherwise
 3598template<typename BasicJsonContext>
 3599struct is_basic_json_context :
 3600    std::integral_constant < bool,
 3601    is_basic_json<typename std::remove_cv<typename std::remove_pointer<BasicJsonContext>::type>::type>::value
 3602    || std::is_same<BasicJsonContext, std::nullptr_t>::value >
 3603{};
 3604
 3605//////////////////////
 3606// json_ref helpers //
 3607//////////////////////
 3608
 3609template<typename>
 3610class json_ref;
 3611
 3612template<typename>
 3613struct is_json_ref : std::false_type {};
 3614
 3615template<typename T>
 3616struct is_json_ref<json_ref<T>> : std::true_type {};
 3617
 3618//////////////////////////
 3619// aliases for detected //
 3620//////////////////////////
 3621
 3622template<typename T>
 3623using mapped_type_t = typename T::mapped_type;
 3624
 3625template<typename T>
 3626using key_type_t = typename T::key_type;
 3627
 3628template<typename T>
 3629using value_type_t = typename T::value_type;
 3630
 3631template<typename T>
 3632using difference_type_t = typename T::difference_type;
 3633
 3634template<typename T>
 3635using pointer_t = typename T::pointer;
 3636
 3637template<typename T>
 3638using reference_t = typename T::reference;
 3639
 3640template<typename T>
 3641using iterator_category_t = typename T::iterator_category;
 3642
 3643template<typename T, typename... Args>
 3644using to_json_function = decltype(T::to_json(std::declval<Args>()...));
 3645
 3646template<typename T, typename... Args>
 3647using from_json_function = decltype(T::from_json(std::declval<Args>()...));
 3648
 3649template<typename T, typename U>
 3650using get_template_function = decltype(std::declval<T>().template get<U>());
 3651
 3652// trait checking if JSONSerializer<T>::from_json(json const&, udt&) exists
 3653template<typename BasicJsonType, typename T, typename = void>
 3654struct has_from_json : std::false_type {};
 3655
 3656// trait checking if j.get<T> is valid
 3657// use this trait instead of std::is_constructible or std::is_convertible,
 3658// both rely on, or make use of implicit conversions, and thus fail when T
 3659// has several constructors/operator= (see https://github.com/nlohmann/json/issues/958)
 3660template <typename BasicJsonType, typename T>
 3661struct is_getable
 3662{
 3663    static constexpr bool value = is_detected<get_template_function, const BasicJsonType&, T>::value;
 3664};
 3665
 3666template<typename BasicJsonType, typename T>
 3667struct has_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
 3668{
 3669    using serializer = typename BasicJsonType::template json_serializer<T, void>;
 3670
 3671    static constexpr bool value =
 3672        is_detected_exact<void, from_json_function, serializer,
 3673        const BasicJsonType&, T&>::value;
 3674};
 3675
 3676// This trait checks if JSONSerializer<T>::from_json(json const&) exists
 3677// this overload is used for non-default-constructible user-defined-types
 3678template<typename BasicJsonType, typename T, typename = void>
 3679struct has_non_default_from_json : std::false_type {};
 3680
 3681template<typename BasicJsonType, typename T>
 3682struct has_non_default_from_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
 3683{
 3684    using serializer = typename BasicJsonType::template json_serializer<T, void>;
 3685
 3686    static constexpr bool value =
 3687        is_detected_exact<T, from_json_function, serializer,
 3688        const BasicJsonType&>::value;
 3689};
 3690
 3691// This trait checks if BasicJsonType::json_serializer<T>::to_json exists
 3692// Do not evaluate the trait when T is a basic_json type, to avoid template instantiation infinite recursion.
 3693template<typename BasicJsonType, typename T, typename = void>
 3694struct has_to_json : std::false_type {};
 3695
 3696template<typename BasicJsonType, typename T>
 3697struct has_to_json < BasicJsonType, T, enable_if_t < !is_basic_json<T>::value >>
 3698{
 3699    using serializer = typename BasicJsonType::template json_serializer<T, void>;
 3700
 3701    static constexpr bool value =
 3702        is_detected_exact<void, to_json_function, serializer, BasicJsonType&,
 3703        T>::value;
 3704};
 3705
 3706template<typename T>
 3707using detect_key_compare = typename T::key_compare;
 3708
 3709template<typename T>
 3710struct has_key_compare : std::integral_constant<bool, is_detected<detect_key_compare, T>::value> {};
 3711
 3712// obtains the actual object key comparator
 3713template<typename BasicJsonType>
 3714struct actual_object_comparator
 3715{
 3716    using object_t = typename BasicJsonType::object_t;
 3717    using object_comparator_t = typename BasicJsonType::default_object_comparator_t;
 3718    using type = typename std::conditional < has_key_compare<object_t>::value,
 3719          typename object_t::key_compare, object_comparator_t>::type;
 3720};
 3721
 3722template<typename BasicJsonType>
 3723using actual_object_comparator_t = typename actual_object_comparator<BasicJsonType>::type;
 3724
 3725/////////////////
 3726// char_traits //
 3727/////////////////
 3728
 3729// Primary template of char_traits calls std char_traits
 3730template<typename T>
 3731struct char_traits : std::char_traits<T>
 3732{};
 3733
 3734// Explicitly define char traits for unsigned char since it is not standard
 3735template<>
 3736struct char_traits<unsigned char> : std::char_traits<char>
 3737{
 3738    using char_type = unsigned char;
 3739    using int_type = uint64_t;
 3740
 3741    // Redefine to_int_type function
 3742    static int_type to_int_type(char_type c) noexcept
 3743    {
 3744        return static_cast<int_type>(c);
 3745    }
 3746
 3747    static char_type to_char_type(int_type i) noexcept
 3748    {
 3749        return static_cast<char_type>(i);
 3750    }
 3751
 3752    static constexpr int_type eof() noexcept
 3753    {
 3754        return static_cast<int_type>(std::char_traits<char>::eof());
 3755    }
 3756};
 3757
 3758// Explicitly define char traits for signed char since it is not standard
 3759template<>
 3760struct char_traits<signed char> : std::char_traits<char>
 3761{
 3762    using char_type = signed char;
 3763    using int_type = uint64_t;
 3764
 3765    // Redefine to_int_type function
 3766    static int_type to_int_type(char_type c) noexcept
 3767    {
 3768        return static_cast<int_type>(c);
 3769    }
 3770
 3771    static char_type to_char_type(int_type i) noexcept
 3772    {
 3773        return static_cast<char_type>(i);
 3774    }
 3775
 3776    static constexpr int_type eof() noexcept
 3777    {
 3778        return static_cast<int_type>(std::char_traits<char>::eof());
 3779    }
 3780};
 3781
 3782///////////////////
 3783// is_ functions //
 3784///////////////////
 3785
 3786// https://en.cppreference.com/w/cpp/types/conjunction
 3787template<class...> struct conjunction : std::true_type { };
 3788template<class B> struct conjunction<B> : B { };
 3789template<class B, class... Bn>
 3790struct conjunction<B, Bn...>
 3791: std::conditional<static_cast<bool>(B::value), conjunction<Bn...>, B>::type {};
 3792
 3793// https://en.cppreference.com/w/cpp/types/negation
 3794template<class B> struct negation : std::integral_constant < bool, !B::value > { };
 3795
 3796// Reimplementation of is_constructible and is_default_constructible, due to them being broken for
 3797// std::pair and std::tuple until LWG 2367 fix (see https://cplusplus.github.io/LWG/lwg-defects.html#2367).
 3798// This causes compile errors in e.g. clang 3.5 or gcc 4.9.
 3799template <typename T>
 3800struct is_default_constructible : std::is_default_constructible<T> {};
 3801
 3802template <typename T1, typename T2>
 3803struct is_default_constructible<std::pair<T1, T2>>
 3804    : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
 3805
 3806template <typename T1, typename T2>
 3807struct is_default_constructible<const std::pair<T1, T2>>
 3808    : conjunction<is_default_constructible<T1>, is_default_constructible<T2>> {};
 3809
 3810template <typename... Ts>
 3811struct is_default_constructible<std::tuple<Ts...>>
 3812    : conjunction<is_default_constructible<Ts>...> {};
 3813
 3814template <typename... Ts>
 3815struct is_default_constructible<const std::tuple<Ts...>>
 3816    : conjunction<is_default_constructible<Ts>...> {};
 3817
 3818template <typename T, typename... Args>
 3819struct is_constructible : std::is_constructible<T, Args...> {};
 3820
 3821template <typename T1, typename T2>
 3822struct is_constructible<std::pair<T1, T2>> : is_default_constructible<std::pair<T1, T2>> {};
 3823
 3824template <typename T1, typename T2>
 3825struct is_constructible<const std::pair<T1, T2>> : is_default_constructible<const std::pair<T1, T2>> {};
 3826
 3827template <typename... Ts>
 3828struct is_constructible<std::tuple<Ts...>> : is_default_constructible<std::tuple<Ts...>> {};
 3829
 3830template <typename... Ts>
 3831struct is_constructible<const std::tuple<Ts...>> : is_default_constructible<const std::tuple<Ts...>> {};
 3832
 3833template<typename T, typename = void>
 3834struct is_iterator_traits : std::false_type {};
 3835
 3836template<typename T>
 3837struct is_iterator_traits<iterator_traits<T>>
 3838{
 3839  private:
 3840    using traits = iterator_traits<T>;
 3841
 3842  public:
 3843    static constexpr auto value =
 3844        is_detected<value_type_t, traits>::value &&
 3845        is_detected<difference_type_t, traits>::value &&
 3846        is_detected<pointer_t, traits>::value &&
 3847        is_detected<iterator_category_t, traits>::value &&
 3848        is_detected<reference_t, traits>::value;
 3849};
 3850
 3851template<typename T>
 3852struct is_range
 3853{
 3854  private:
 3855    using t_ref = typename std::add_lvalue_reference<T>::type;
 3856
 3857    using iterator = detected_t<result_of_begin, t_ref>;
 3858    using sentinel = detected_t<result_of_end, t_ref>;
 3859
 3860    // to be 100% correct, it should use https://en.cppreference.com/w/cpp/iterator/input_or_output_iterator
 3861    // and https://en.cppreference.com/w/cpp/iterator/sentinel_for
 3862    // but reimplementing these would be too much work, as a lot of other concepts are used underneath
 3863    static constexpr auto is_iterator_begin =
 3864        is_iterator_traits<iterator_traits<iterator>>::value;
 3865
 3866  public:
 3867    static constexpr bool value = !std::is_same<iterator, nonesuch>::value && !std::is_same<sentinel, nonesuch>::value && is_iterator_begin;
 3868};
 3869
 3870template<typename R>
 3871using iterator_t = enable_if_t<is_range<R>::value, result_of_begin<decltype(std::declval<R&>())>>;
 3872
 3873template<typename T>
 3874using range_value_t = value_type_t<iterator_traits<iterator_t<T>>>;
 3875
 3876// The following implementation of is_complete_type is taken from
 3877// https://blogs.msdn.microsoft.com/vcblog/2015/12/02/partial-support-for-expression-sfinae-in-vs-2015-update-1/
 3878// and is written by Xiang Fan who agreed to using it in this library.
 3879
 3880template<typename T, typename = void>
 3881struct is_complete_type : std::false_type {};
 3882
 3883template<typename T>
 3884struct is_complete_type<T, decltype(void(sizeof(T)))> : std::true_type {};
 3885
 3886template<typename BasicJsonType, typename CompatibleObjectType,
 3887         typename = void>
 3888struct is_compatible_object_type_impl : std::false_type {};
 3889
 3890template<typename BasicJsonType, typename CompatibleObjectType>
 3891struct is_compatible_object_type_impl <
 3892    BasicJsonType, CompatibleObjectType,
 3893    enable_if_t < is_detected<mapped_type_t, CompatibleObjectType>::value&&
 3894    is_detected<key_type_t, CompatibleObjectType>::value >>
 3895{
 3896    using object_t = typename BasicJsonType::object_t;
 3897
 3898    // macOS's is_constructible does not play well with nonesuch...
 3899    static constexpr bool value =
 3900        is_constructible<typename object_t::key_type,
 3901        typename CompatibleObjectType::key_type>::value &&
 3902        is_constructible<typename object_t::mapped_type,
 3903        typename CompatibleObjectType::mapped_type>::value;
 3904};
 3905
 3906template<typename BasicJsonType, typename CompatibleObjectType>
 3907struct is_compatible_object_type
 3908    : is_compatible_object_type_impl<BasicJsonType, CompatibleObjectType> {};
 3909
 3910template<typename BasicJsonType, typename ConstructibleObjectType,
 3911         typename = void>
 3912struct is_constructible_object_type_impl : std::false_type {};
 3913
 3914template<typename BasicJsonType, typename ConstructibleObjectType>
 3915struct is_constructible_object_type_impl <
 3916    BasicJsonType, ConstructibleObjectType,
 3917    enable_if_t < is_detected<mapped_type_t, ConstructibleObjectType>::value&&
 3918    is_detected<key_type_t, ConstructibleObjectType>::value >>
 3919{
 3920    using object_t = typename BasicJsonType::object_t;
 3921
 3922    static constexpr bool value =
 3923        (is_default_constructible<ConstructibleObjectType>::value &&
 3924         (std::is_move_assignable<ConstructibleObjectType>::value ||
 3925          std::is_copy_assignable<ConstructibleObjectType>::value) &&
 3926         (is_constructible<typename ConstructibleObjectType::key_type,
 3927          typename object_t::key_type>::value &&
 3928          std::is_same <
 3929          typename object_t::mapped_type,
 3930          typename ConstructibleObjectType::mapped_type >::value)) ||
 3931        (has_from_json<BasicJsonType,
 3932         typename ConstructibleObjectType::mapped_type>::value ||
 3933         has_non_default_from_json <
 3934         BasicJsonType,
 3935         typename ConstructibleObjectType::mapped_type >::value);
 3936};
 3937
 3938template<typename BasicJsonType, typename ConstructibleObjectType>
 3939struct is_constructible_object_type
 3940    : is_constructible_object_type_impl<BasicJsonType,
 3941      ConstructibleObjectType> {};
 3942
 3943template<typename BasicJsonType, typename CompatibleStringType>
 3944struct is_compatible_string_type
 3945{
 3946    static constexpr auto value =
 3947        is_constructible<typename BasicJsonType::string_t, CompatibleStringType>::value;
 3948};
 3949
 3950template<typename BasicJsonType, typename ConstructibleStringType>
 3951struct is_constructible_string_type
 3952{
 3953    // launder type through decltype() to fix compilation failure on ICPC
 3954#ifdef __INTEL_COMPILER
 3955    using laundered_type = decltype(std::declval<ConstructibleStringType>());
 3956#else
 3957    using laundered_type = ConstructibleStringType;
 3958#endif
 3959
 3960    static constexpr auto value =
 3961        conjunction <
 3962        is_constructible<laundered_type, typename BasicJsonType::string_t>,
 3963        is_detected_exact<typename BasicJsonType::string_t::value_type,
 3964        value_type_t, laundered_type >>::value;
 3965};
 3966
 3967template<typename BasicJsonType, typename CompatibleArrayType, typename = void>
 3968struct is_compatible_array_type_impl : std::false_type {};
 3969
 3970template<typename BasicJsonType, typename CompatibleArrayType>
 3971struct is_compatible_array_type_impl <
 3972    BasicJsonType, CompatibleArrayType,
 3973    enable_if_t <
 3974    is_detected<iterator_t, CompatibleArrayType>::value&&
 3975    is_iterator_traits<iterator_traits<detected_t<iterator_t, CompatibleArrayType>>>::value&&
 3976// special case for types like std::filesystem::path whose iterator's value_type are themselves
 3977// c.f. https://github.com/nlohmann/json/pull/3073
 3978    !std::is_same<CompatibleArrayType, detected_t<range_value_t, CompatibleArrayType>>::value >>
 3979{
 3980    static constexpr bool value =
 3981        is_constructible<BasicJsonType,
 3982        range_value_t<CompatibleArrayType>>::value;
 3983};
 3984
 3985template<typename BasicJsonType, typename CompatibleArrayType>
 3986struct is_compatible_array_type
 3987    : is_compatible_array_type_impl<BasicJsonType, CompatibleArrayType> {};
 3988
 3989template<typename BasicJsonType, typename ConstructibleArrayType, typename = void>
 3990struct is_constructible_array_type_impl : std::false_type {};
 3991
 3992template<typename BasicJsonType, typename ConstructibleArrayType>
 3993struct is_constructible_array_type_impl <
 3994    BasicJsonType, ConstructibleArrayType,
 3995    enable_if_t<std::is_same<ConstructibleArrayType,
 3996    typename BasicJsonType::value_type>::value >>
 3997            : std::true_type {};
 3998
 3999template<typename BasicJsonType, typename ConstructibleArrayType>
 4000struct is_constructible_array_type_impl <
 4001    BasicJsonType, ConstructibleArrayType,
 4002    enable_if_t < !std::is_same<ConstructibleArrayType,
 4003    typename BasicJsonType::value_type>::value&&
 4004    !is_compatible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
 4005    is_default_constructible<ConstructibleArrayType>::value&&
 4006(std::is_move_assignable<ConstructibleArrayType>::value ||
 4007 std::is_copy_assignable<ConstructibleArrayType>::value)&&
 4008is_detected<iterator_t, ConstructibleArrayType>::value&&
 4009is_iterator_traits<iterator_traits<detected_t<iterator_t, ConstructibleArrayType>>>::value&&
 4010is_detected<range_value_t, ConstructibleArrayType>::value&&
 4011// special case for types like std::filesystem::path whose iterator's value_type are themselves
 4012// c.f. https://github.com/nlohmann/json/pull/3073
 4013!std::is_same<ConstructibleArrayType, detected_t<range_value_t, ConstructibleArrayType>>::value&&
 4014is_complete_type <
 4015detected_t<range_value_t, ConstructibleArrayType >>::value >>
 4016{
 4017    using value_type = range_value_t<ConstructibleArrayType>;
 4018
 4019    static constexpr bool value =
 4020        std::is_same<value_type,
 4021        typename BasicJsonType::array_t::value_type>::value ||
 4022        has_from_json<BasicJsonType,
 4023        value_type>::value ||
 4024        has_non_default_from_json <
 4025        BasicJsonType,
 4026        value_type >::value;
 4027};
 4028
 4029template<typename BasicJsonType, typename ConstructibleArrayType>
 4030struct is_constructible_array_type
 4031    : is_constructible_array_type_impl<BasicJsonType, ConstructibleArrayType> {};
 4032
 4033template<typename RealIntegerType, typename CompatibleNumberIntegerType,
 4034         typename = void>
 4035struct is_compatible_integer_type_impl : std::false_type {};
 4036
 4037template<typename RealIntegerType, typename CompatibleNumberIntegerType>
 4038struct is_compatible_integer_type_impl <
 4039    RealIntegerType, CompatibleNumberIntegerType,
 4040    enable_if_t < std::is_integral<RealIntegerType>::value&&
 4041    std::is_integral<CompatibleNumberIntegerType>::value&&
 4042    !std::is_same<bool, CompatibleNumberIntegerType>::value >>
 4043{
 4044    // is there an assert somewhere on overflows?
 4045    using RealLimits = std::numeric_limits<RealIntegerType>;
 4046    using CompatibleLimits = std::numeric_limits<CompatibleNumberIntegerType>;
 4047
 4048    static constexpr auto value =
 4049        is_constructible<RealIntegerType,
 4050        CompatibleNumberIntegerType>::value &&
 4051        CompatibleLimits::is_integer &&
 4052        RealLimits::is_signed == CompatibleLimits::is_signed;
 4053};
 4054
 4055template<typename RealIntegerType, typename CompatibleNumberIntegerType>
 4056struct is_compatible_integer_type
 4057    : is_compatible_integer_type_impl<RealIntegerType,
 4058      CompatibleNumberIntegerType> {};
 4059
 4060template<typename BasicJsonType, typename CompatibleType, typename = void>
 4061struct is_compatible_type_impl: std::false_type {};
 4062
 4063template<typename BasicJsonType, typename CompatibleType>
 4064struct is_compatible_type_impl <
 4065    BasicJsonType, CompatibleType,
 4066    enable_if_t<is_complete_type<CompatibleType>::value >>
 4067{
 4068    static constexpr bool value =
 4069        has_to_json<BasicJsonType, CompatibleType>::value;
 4070};
 4071
 4072template<typename BasicJsonType, typename CompatibleType>
 4073struct is_compatible_type
 4074    : is_compatible_type_impl<BasicJsonType, CompatibleType> {};
 4075
 4076template<typename T1, typename T2>
 4077struct is_constructible_tuple : std::false_type {};
 4078
 4079template<typename T1, typename... Args>
 4080struct is_constructible_tuple<T1, std::tuple<Args...>> : conjunction<is_constructible<T1, Args>...> {};
 4081
 4082template<typename BasicJsonType, typename T>
 4083struct is_json_iterator_of : std::false_type {};
 4084
 4085template<typename BasicJsonType>
 4086struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::iterator> : std::true_type {};
 4087
 4088template<typename BasicJsonType>
 4089struct is_json_iterator_of<BasicJsonType, typename BasicJsonType::const_iterator> : std::true_type
 4090{};
 4091
 4092// checks if a given type T is a template specialization of Primary
 4093template<template <typename...> class Primary, typename T>
 4094struct is_specialization_of : std::false_type {};
 4095
 4096template<template <typename...> class Primary, typename... Args>
 4097struct is_specialization_of<Primary, Primary<Args...>> : std::true_type {};
 4098
 4099template<typename T>
 4100using is_json_pointer = is_specialization_of<::nlohmann::json_pointer, uncvref_t<T>>;
 4101
 4102// checks if A and B are comparable using Compare functor
 4103template<typename Compare, typename A, typename B, typename = void>
 4104struct is_comparable : std::false_type {};
 4105
 4106template<typename Compare, typename A, typename B>
 4107struct is_comparable<Compare, A, B, void_t<
 4108decltype(std::declval<Compare>()(std::declval<A>(), std::declval<B>())),
 4109decltype(std::declval<Compare>()(std::declval<B>(), std::declval<A>()))
 4110>> : std::true_type {};
 4111
 4112template<typename T>
 4113using detect_is_transparent = typename T::is_transparent;
 4114
 4115// type trait to check if KeyType can be used as object key (without a BasicJsonType)
 4116// see is_usable_as_basic_json_key_type below
 4117template<typename Comparator, typename ObjectKeyType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
 4118         bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
 4119using is_usable_as_key_type = typename std::conditional <
 4120                              is_comparable<Comparator, ObjectKeyType, KeyTypeCVRef>::value
 4121                              && !(ExcludeObjectKeyType && std::is_same<KeyType,
 4122                                   ObjectKeyType>::value)
 4123                              && (!RequireTransparentComparator
 4124                                  || is_detected <detect_is_transparent, Comparator>::value)
 4125                              && !is_json_pointer<KeyType>::value,
 4126                              std::true_type,
 4127                              std::false_type >::type;
 4128
 4129// type trait to check if KeyType can be used as object key
 4130// true if:
 4131//   - KeyType is comparable with BasicJsonType::object_t::key_type
 4132//   - if ExcludeObjectKeyType is true, KeyType is not BasicJsonType::object_t::key_type
 4133//   - the comparator is transparent or RequireTransparentComparator is false
 4134//   - KeyType is not a JSON iterator or json_pointer
 4135template<typename BasicJsonType, typename KeyTypeCVRef, bool RequireTransparentComparator = true,
 4136         bool ExcludeObjectKeyType = RequireTransparentComparator, typename KeyType = uncvref_t<KeyTypeCVRef>>
 4137using is_usable_as_basic_json_key_type = typename std::conditional <
 4138    is_usable_as_key_type<typename BasicJsonType::object_comparator_t,
 4139    typename BasicJsonType::object_t::key_type, KeyTypeCVRef,
 4140    RequireTransparentComparator, ExcludeObjectKeyType>::value
 4141    && !is_json_iterator_of<BasicJsonType, KeyType>::value,
 4142    std::true_type,
 4143    std::false_type >::type;
 4144
 4145template<typename ObjectType, typename KeyType>
 4146using detect_erase_with_key_type = decltype(std::declval<ObjectType&>().erase(std::declval<KeyType>()));
 4147
 4148// type trait to check if object_t has an erase() member functions accepting KeyType
 4149template<typename BasicJsonType, typename KeyType>
 4150using has_erase_with_key_type = typename std::conditional <
 4151                                is_detected <
 4152                                detect_erase_with_key_type,
 4153                                typename BasicJsonType::object_t, KeyType >::value,
 4154                                std::true_type,
 4155                                std::false_type >::type;
 4156
 4157// a naive helper to check if a type is an ordered_map (exploits the fact that
 4158// ordered_map inherits capacity() from std::vector)
 4159template <typename T>
 4160struct is_ordered_map
 4161{
 4162    using one = char;
 4163
 4164    struct two
 4165    {
 4166        char x[2]; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 4167    };
 4168
 4169    template <typename C> static one test( decltype(&C::capacity) ) ;
 4170    template <typename C> static two test(...);
 4171
 4172    enum { value = sizeof(test<T>(nullptr)) == sizeof(char) }; // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
 4173};
 4174
 4175// to avoid useless casts (see https://github.com/nlohmann/json/issues/2893#issuecomment-889152324)
 4176template < typename T, typename U, enable_if_t < !std::is_same<T, U>::value, int > = 0 >
 4177T conditional_static_cast(U value)
 4178{
 4179    return static_cast<T>(value);
 4180}
 4181
 4182template<typename T, typename U, enable_if_t<std::is_same<T, U>::value, int> = 0>
 4183T conditional_static_cast(U value)
 4184{
 4185    return value;
 4186}
 4187
 4188template<typename... Types>
 4189using all_integral = conjunction<std::is_integral<Types>...>;
 4190
 4191template<typename... Types>
 4192using all_signed = conjunction<std::is_signed<Types>...>;
 4193
 4194template<typename... Types>
 4195using all_unsigned = conjunction<std::is_unsigned<Types>...>;
 4196
 4197// there's a disjunction trait in another PR; replace when merged
 4198template<typename... Types>
 4199using same_sign = std::integral_constant < bool,
 4200      all_signed<Types...>::value || all_unsigned<Types...>::value >;
 4201
 4202template<typename OfType, typename T>
 4203using never_out_of_range = std::integral_constant < bool,
 4204      (std::is_signed<OfType>::value && (sizeof(T) < sizeof(OfType)))
 4205      || (same_sign<OfType, T>::value && sizeof(OfType) == sizeof(T)) >;
 4206
 4207template<typename OfType, typename T,
 4208         bool OfTypeSigned = std::is_signed<OfType>::value,
 4209         bool TSigned = std::is_signed<T>::value>
 4210struct value_in_range_of_impl2;
 4211
 4212template<typename OfType, typename T>
 4213struct value_in_range_of_impl2<OfType, T, false, false>
 4214{
 4215    static constexpr bool test(T val)
 4216    {
 4217        using CommonType = typename std::common_type<OfType, T>::type;
 4218        return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
 4219    }
 4220};
 4221
 4222template<typename OfType, typename T>
 4223struct value_in_range_of_impl2<OfType, T, true, false>
 4224{
 4225    static constexpr bool test(T val)
 4226    {
 4227        using CommonType = typename std::common_type<OfType, T>::type;
 4228        return static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
 4229    }
 4230};
 4231
 4232template<typename OfType, typename T>
 4233struct value_in_range_of_impl2<OfType, T, false, true>
 4234{
 4235    static constexpr bool test(T val)
 4236    {
 4237        using CommonType = typename std::common_type<OfType, T>::type;
 4238        return val >= 0 && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
 4239    }
 4240};
 4241
 4242template<typename OfType, typename T>
 4243struct value_in_range_of_impl2<OfType, T, true, true>
 4244{
 4245    static constexpr bool test(T val)
 4246    {
 4247        using CommonType = typename std::common_type<OfType, T>::type;
 4248        return static_cast<CommonType>(val) >= static_cast<CommonType>((std::numeric_limits<OfType>::min)())
 4249               && static_cast<CommonType>(val) <= static_cast<CommonType>((std::numeric_limits<OfType>::max)());
 4250    }
 4251};
 4252
 4253template<typename OfType, typename T,
 4254         bool NeverOutOfRange = never_out_of_range<OfType, T>::value,
 4255         typename = detail::enable_if_t<all_integral<OfType, T>::value>>
 4256struct value_in_range_of_impl1;
 4257
 4258template<typename OfType, typename T>
 4259struct value_in_range_of_impl1<OfType, T, false>
 4260{
 4261    static constexpr bool test(T val)
 4262    {
 4263        return value_in_range_of_impl2<OfType, T>::test(val);
 4264    }
 4265};
 4266
 4267template<typename OfType, typename T>
 4268struct value_in_range_of_impl1<OfType, T, true>
 4269{
 4270    static constexpr bool test(T /*val*/)
 4271    {
 4272        return true;
 4273    }
 4274};
 4275
 4276template<typename OfType, typename T>
 4277constexpr bool value_in_range_of(T val)
 4278{
 4279    return value_in_range_of_impl1<OfType, T>::test(val);
 4280}
 4281
 4282template<bool Value>
 4283using bool_constant = std::integral_constant<bool, Value>;
 4284
 4285///////////////////////////////////////////////////////////////////////////////
 4286// is_c_string
 4287///////////////////////////////////////////////////////////////////////////////
 4288
 4289namespace impl
 4290{
 4291
 4292template<typename T>
 4293constexpr bool is_c_string()
 4294{
 4295    using TUnExt = typename std::remove_extent<T>::type;
 4296    using TUnCVExt = typename std::remove_cv<TUnExt>::type;
 4297    using TUnPtr = typename std::remove_pointer<T>::type;
 4298    using TUnCVPtr = typename std::remove_cv<TUnPtr>::type;
 4299    return
 4300        (std::is_array<T>::value && std::is_same<TUnCVExt, char>::value)
 4301        || (std::is_pointer<T>::value && std::is_same<TUnCVPtr, char>::value);
 4302}
 4303
 4304}  // namespace impl
 4305
 4306// checks whether T is a [cv] char */[cv] char[] C string
 4307template<typename T>
 4308struct is_c_string : bool_constant<impl::is_c_string<T>()> {};
 4309
 4310template<typename T>
 4311using is_c_string_uncvref = is_c_string<uncvref_t<T>>;
 4312
 4313///////////////////////////////////////////////////////////////////////////////
 4314// is_transparent
 4315///////////////////////////////////////////////////////////////////////////////
 4316
 4317namespace impl
 4318{
 4319
 4320template<typename T>
 4321constexpr bool is_transparent()
 4322{
 4323    return is_detected<detect_is_transparent, T>::value;
 4324}
 4325
 4326}  // namespace impl
 4327
 4328// checks whether T has a member named is_transparent
 4329template<typename T>
 4330struct is_transparent : bool_constant<impl::is_transparent<T>()> {};
 4331
 4332///////////////////////////////////////////////////////////////////////////////
 4333
 4334}  // namespace detail
 4335NLOHMANN_JSON_NAMESPACE_END
 4336
 4337// #include <nlohmann/detail/string_concat.hpp>
 4338//     __ _____ _____ _____
 4339//  __|  |   __|     |   | |  JSON for Modern C++
 4340// |  |  |__   |  |  | | | |  version 3.12.0
 4341// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 4342//
 4343// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 4344// SPDX-License-Identifier: MIT
 4345
 4346
 4347
 4348#include <cstring> // strlen
 4349#include <string> // string
 4350#include <utility> // forward
 4351
 4352// #include <nlohmann/detail/meta/cpp_future.hpp>
 4353
 4354// #include <nlohmann/detail/meta/detected.hpp>
 4355
 4356
 4357NLOHMANN_JSON_NAMESPACE_BEGIN
 4358namespace detail
 4359{
 4360
 4361inline std::size_t concat_length()
 4362{
 4363    return 0;
 4364}
 4365
 4366template<typename... Args>
 4367inline std::size_t concat_length(const char* cstr, const Args& ... rest);
 4368
 4369template<typename StringType, typename... Args>
 4370inline std::size_t concat_length(const StringType& str, const Args& ... rest);
 4371
 4372template<typename... Args>
 4373inline std::size_t concat_length(const char /*c*/, const Args& ... rest)
 4374{
 4375    return 1 + concat_length(rest...);
 4376}
 4377
 4378template<typename... Args>
 4379inline std::size_t concat_length(const char* cstr, const Args& ... rest)
 4380{
 4381    // cppcheck-suppress ignoredReturnValue
 4382    return ::strlen(cstr) + concat_length(rest...);
 4383}
 4384
 4385template<typename StringType, typename... Args>
 4386inline std::size_t concat_length(const StringType& str, const Args& ... rest)
 4387{
 4388    return str.size() + concat_length(rest...);
 4389}
 4390
 4391template<typename OutStringType>
 4392inline void concat_into(OutStringType& /*out*/)
 4393{}
 4394
 4395template<typename StringType, typename Arg>
 4396using string_can_append = decltype(std::declval<StringType&>().append(std::declval < Arg && > ()));
 4397
 4398template<typename StringType, typename Arg>
 4399using detect_string_can_append = is_detected<string_can_append, StringType, Arg>;
 4400
 4401template<typename StringType, typename Arg>
 4402using string_can_append_op = decltype(std::declval<StringType&>() += std::declval < Arg && > ());
 4403
 4404template<typename StringType, typename Arg>
 4405using detect_string_can_append_op = is_detected<string_can_append_op, StringType, Arg>;
 4406
 4407template<typename StringType, typename Arg>
 4408using string_can_append_iter = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().begin(), std::declval<const Arg&>().end()));
 4409
 4410template<typename StringType, typename Arg>
 4411using detect_string_can_append_iter = is_detected<string_can_append_iter, StringType, Arg>;
 4412
 4413template<typename StringType, typename Arg>
 4414using string_can_append_data = decltype(std::declval<StringType&>().append(std::declval<const Arg&>().data(), std::declval<const Arg&>().size()));
 4415
 4416template<typename StringType, typename Arg>
 4417using detect_string_can_append_data = is_detected<string_can_append_data, StringType, Arg>;
 4418
 4419template < typename OutStringType, typename Arg, typename... Args,
 4420           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
 4421                         && detect_string_can_append_op<OutStringType, Arg>::value, int > = 0 >
 4422inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest);
 4423
 4424template < typename OutStringType, typename Arg, typename... Args,
 4425           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
 4426                         && !detect_string_can_append_op<OutStringType, Arg>::value
 4427                         && detect_string_can_append_iter<OutStringType, Arg>::value, int > = 0 >
 4428inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
 4429
 4430template < typename OutStringType, typename Arg, typename... Args,
 4431           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
 4432                         && !detect_string_can_append_op<OutStringType, Arg>::value
 4433                         && !detect_string_can_append_iter<OutStringType, Arg>::value
 4434                         && detect_string_can_append_data<OutStringType, Arg>::value, int > = 0 >
 4435inline void concat_into(OutStringType& out, const Arg& arg, Args && ... rest);
 4436
 4437template<typename OutStringType, typename Arg, typename... Args,
 4438         enable_if_t<detect_string_can_append<OutStringType, Arg>::value, int> = 0>
 4439inline void concat_into(OutStringType& out, Arg && arg, Args && ... rest)
 4440{
 4441    out.append(std::forward<Arg>(arg));
 4442    concat_into(out, std::forward<Args>(rest)...);
 4443}
 4444
 4445template < typename OutStringType, typename Arg, typename... Args,
 4446           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
 4447                         && detect_string_can_append_op<OutStringType, Arg>::value, int > >
 4448inline void concat_into(OutStringType& out, Arg&& arg, Args&& ... rest)
 4449{
 4450    out += std::forward<Arg>(arg);
 4451    concat_into(out, std::forward<Args>(rest)...);
 4452}
 4453
 4454template < typename OutStringType, typename Arg, typename... Args,
 4455           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
 4456                         && !detect_string_can_append_op<OutStringType, Arg>::value
 4457                         && detect_string_can_append_iter<OutStringType, Arg>::value, int > >
 4458inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
 4459{
 4460    out.append(arg.begin(), arg.end());
 4461    concat_into(out, std::forward<Args>(rest)...);
 4462}
 4463
 4464template < typename OutStringType, typename Arg, typename... Args,
 4465           enable_if_t < !detect_string_can_append<OutStringType, Arg>::value
 4466                         && !detect_string_can_append_op<OutStringType, Arg>::value
 4467                         && !detect_string_can_append_iter<OutStringType, Arg>::value
 4468                         && detect_string_can_append_data<OutStringType, Arg>::value, int > >
 4469inline void concat_into(OutStringType& out, const Arg& arg, Args&& ... rest)
 4470{
 4471    out.append(arg.data(), arg.size());
 4472    concat_into(out, std::forward<Args>(rest)...);
 4473}
 4474
 4475template<typename OutStringType = std::string, typename... Args>
 4476inline OutStringType concat(Args && ... args)
 4477{
 4478    OutStringType str;
 4479    str.reserve(concat_length(args...));
 4480    concat_into(str, std::forward<Args>(args)...);
 4481    return str;
 4482}
 4483
 4484}  // namespace detail
 4485NLOHMANN_JSON_NAMESPACE_END
 4486
 4487
 4488// With -Wweak-vtables, Clang will complain about the exception classes as they
 4489// have no out-of-line virtual method definitions and their vtable will be
 4490// emitted in every translation unit. This issue cannot be fixed with a
 4491// header-only library as there is no implementation file to move these
 4492// functions to. As a result, we suppress this warning here to avoid client
 4493// code to stumble over this. See https://github.com/nlohmann/json/issues/4087
 4494// for a discussion.
 4495#if defined(__clang__)
 4496    #pragma clang diagnostic push
 4497    #pragma clang diagnostic ignored "-Wweak-vtables"
 4498#endif
 4499
 4500NLOHMANN_JSON_NAMESPACE_BEGIN
 4501namespace detail
 4502{
 4503
 4504////////////////
 4505// exceptions //
 4506////////////////
 4507
 4508/// @brief general exception of the @ref basic_json class
 4509/// @sa https://json.nlohmann.me/api/basic_json/exception/
 4510class exception : public std::exception
 4511{
 4512  public:
 4513    /// returns the explanatory string
 4514    const char* what() const noexcept override
 4515    {
 4516        return m.what();
 4517    }
 4518
 4519    /// the id of the exception
 4520    const int id; // NOLINT(cppcoreguidelines-non-private-member-variables-in-classes)
 4521
 4522  protected:
 4523    JSON_HEDLEY_NON_NULL(3)
 4524    exception(int id_, const char* what_arg) : id(id_), m(what_arg) {} // NOLINT(bugprone-throw-keyword-missing)
 4525
 4526    static std::string name(const std::string& ename, int id_)
 4527    {
 4528        return concat("[json.exception.", ename, '.', std::to_string(id_), "] ");
 4529    }
 4530
 4531    static std::string diagnostics(std::nullptr_t /*leaf_element*/)
 4532    {
 4533        return "";
 4534    }
 4535
 4536    template<typename BasicJsonType>
 4537    static std::string diagnostics(const BasicJsonType* leaf_element)
 4538    {
 4539#if JSON_DIAGNOSTICS
 4540        std::vector<std::string> tokens;
 4541        for (const auto* current = leaf_element; current != nullptr && current->m_parent != nullptr; current = current->m_parent)
 4542        {
 4543            switch (current->m_parent->type())
 4544            {
 4545                case value_t::array:
 4546                {
 4547                    for (std::size_t i = 0; i < current->m_parent->m_data.m_value.array->size(); ++i)
 4548                    {
 4549                        if (&current->m_parent->m_data.m_value.array->operator[](i) == current)
 4550                        {
 4551                            tokens.emplace_back(std::to_string(i));
 4552                            break;
 4553                        }
 4554                    }
 4555                    break;
 4556                }
 4557
 4558                case value_t::object:
 4559                {
 4560                    for (const auto& element : *current->m_parent->m_data.m_value.object)
 4561                    {
 4562                        if (&element.second == current)
 4563                        {
 4564                            tokens.emplace_back(element.first.c_str());
 4565                            break;
 4566                        }
 4567                    }
 4568                    break;
 4569                }
 4570
 4571                case value_t::null: // LCOV_EXCL_LINE
 4572                case value_t::string: // LCOV_EXCL_LINE
 4573                case value_t::boolean: // LCOV_EXCL_LINE
 4574                case value_t::number_integer: // LCOV_EXCL_LINE
 4575                case value_t::number_unsigned: // LCOV_EXCL_LINE
 4576                case value_t::number_float: // LCOV_EXCL_LINE
 4577                case value_t::binary: // LCOV_EXCL_LINE
 4578                case value_t::discarded: // LCOV_EXCL_LINE
 4579                default:   // LCOV_EXCL_LINE
 4580                    break; // LCOV_EXCL_LINE
 4581            }
 4582        }
 4583
 4584        if (tokens.empty())
 4585        {
 4586            return "";
 4587        }
 4588
 4589        auto str = std::accumulate(tokens.rbegin(), tokens.rend(), std::string{},
 4590                                   [](const std::string & a, const std::string & b)
 4591        {
 4592            return concat(a, '/', detail::escape(b));
 4593        });
 4594
 4595        return concat('(', str, ") ", get_byte_positions(leaf_element));
 4596#else
 4597        return get_byte_positions(leaf_element);
 4598#endif
 4599    }
 4600
 4601  private:
 4602    /// an exception object as storage for error messages
 4603    std::runtime_error m;
 4604#if JSON_DIAGNOSTIC_POSITIONS
 4605    template<typename BasicJsonType>
 4606    static std::string get_byte_positions(const BasicJsonType* leaf_element)
 4607    {
 4608        if ((leaf_element->start_pos() != std::string::npos) && (leaf_element->end_pos() != std::string::npos))
 4609        {
 4610            return concat("(bytes ", std::to_string(leaf_element->start_pos()), "-", std::to_string(leaf_element->end_pos()), ") ");
 4611        }
 4612        return "";
 4613    }
 4614#else
 4615    template<typename BasicJsonType>
 4616    static std::string get_byte_positions(const BasicJsonType* leaf_element)
 4617    {
 4618        static_cast<void>(leaf_element);
 4619        return "";
 4620    }
 4621#endif
 4622};
 4623
 4624/// @brief exception indicating a parse error
 4625/// @sa https://json.nlohmann.me/api/basic_json/parse_error/
 4626class parse_error : public exception
 4627{
 4628  public:
 4629    /*!
 4630    @brief create a parse error exception
 4631    @param[in] id_       the id of the exception
 4632    @param[in] pos       the position where the error occurred (or with
 4633                         chars_read_total=0 if the position cannot be
 4634                         determined)
 4635    @param[in] what_arg  the explanatory string
 4636    @return parse_error object
 4637    */
 4638    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
 4639    static parse_error create(int id_, const position_t& pos, const std::string& what_arg, BasicJsonContext context)
 4640    {
 4641        const std::string w = concat(exception::name("parse_error", id_), "parse error",
 4642                                     position_string(pos), ": ", exception::diagnostics(context), what_arg);
 4643        return {id_, pos.chars_read_total, w.c_str()};
 4644    }
 4645
 4646    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
 4647    static parse_error create(int id_, std::size_t byte_, const std::string& what_arg, BasicJsonContext context)
 4648    {
 4649        const std::string w = concat(exception::name("parse_error", id_), "parse error",
 4650                                     (byte_ != 0 ? (concat(" at byte ", std::to_string(byte_))) : ""),
 4651                                     ": ", exception::diagnostics(context), what_arg);
 4652        return {id_, byte_, w.c_str()};
 4653    }
 4654
 4655    /*!
 4656    @brief byte index of the parse error
 4657
 4658    The byte index of the last read character in the input file.
 4659
 4660    @note For an input with n bytes, 1 is the index of the first character and
 4661          n+1 is the index of the terminating null byte or the end of file.
 4662          This also holds true when reading a byte vector (CBOR or MessagePack).
 4663    */
 4664    const std::size_t byte;
 4665
 4666  private:
 4667    parse_error(int id_, std::size_t byte_, const char* what_arg)
 4668        : exception(id_, what_arg), byte(byte_) {}
 4669
 4670    static std::string position_string(const position_t& pos)
 4671    {
 4672        return concat(" at line ", std::to_string(pos.lines_read + 1),
 4673                      ", column ", std::to_string(pos.chars_read_current_line));
 4674    }
 4675};
 4676
 4677/// @brief exception indicating errors with iterators
 4678/// @sa https://json.nlohmann.me/api/basic_json/invalid_iterator/
 4679class invalid_iterator : public exception
 4680{
 4681  public:
 4682    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
 4683    static invalid_iterator create(int id_, const std::string& what_arg, BasicJsonContext context)
 4684    {
 4685        const std::string w = concat(exception::name("invalid_iterator", id_), exception::diagnostics(context), what_arg);
 4686        return {id_, w.c_str()};
 4687    }
 4688
 4689  private:
 4690    JSON_HEDLEY_NON_NULL(3)
 4691    invalid_iterator(int id_, const char* what_arg)
 4692        : exception(id_, what_arg) {}
 4693};
 4694
 4695/// @brief exception indicating executing a member function with a wrong type
 4696/// @sa https://json.nlohmann.me/api/basic_json/type_error/
 4697class type_error : public exception
 4698{
 4699  public:
 4700    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
 4701    static type_error create(int id_, const std::string& what_arg, BasicJsonContext context)
 4702    {
 4703        const std::string w = concat(exception::name("type_error", id_), exception::diagnostics(context), what_arg);
 4704        return {id_, w.c_str()};
 4705    }
 4706
 4707  private:
 4708    JSON_HEDLEY_NON_NULL(3)
 4709    type_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
 4710};
 4711
 4712/// @brief exception indicating access out of the defined range
 4713/// @sa https://json.nlohmann.me/api/basic_json/out_of_range/
 4714class out_of_range : public exception
 4715{
 4716  public:
 4717    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
 4718    static out_of_range create(int id_, const std::string& what_arg, BasicJsonContext context)
 4719    {
 4720        const std::string w = concat(exception::name("out_of_range", id_), exception::diagnostics(context), what_arg);
 4721        return {id_, w.c_str()};
 4722    }
 4723
 4724  private:
 4725    JSON_HEDLEY_NON_NULL(3)
 4726    out_of_range(int id_, const char* what_arg) : exception(id_, what_arg) {}
 4727};
 4728
 4729/// @brief exception indicating other library errors
 4730/// @sa https://json.nlohmann.me/api/basic_json/other_error/
 4731class other_error : public exception
 4732{
 4733  public:
 4734    template<typename BasicJsonContext, enable_if_t<is_basic_json_context<BasicJsonContext>::value, int> = 0>
 4735    static other_error create(int id_, const std::string& what_arg, BasicJsonContext context)
 4736    {
 4737        const std::string w = concat(exception::name("other_error", id_), exception::diagnostics(context), what_arg);
 4738        return {id_, w.c_str()};
 4739    }
 4740
 4741  private:
 4742    JSON_HEDLEY_NON_NULL(3)
 4743    other_error(int id_, const char* what_arg) : exception(id_, what_arg) {}
 4744};
 4745
 4746}  // namespace detail
 4747NLOHMANN_JSON_NAMESPACE_END
 4748
 4749#if defined(__clang__)
 4750    #pragma clang diagnostic pop
 4751#endif
 4752
 4753// #include <nlohmann/detail/macro_scope.hpp>
 4754
 4755// #include <nlohmann/detail/meta/cpp_future.hpp>
 4756
 4757// #include <nlohmann/detail/meta/identity_tag.hpp>
 4758//     __ _____ _____ _____
 4759//  __|  |   __|     |   | |  JSON for Modern C++
 4760// |  |  |__   |  |  | | | |  version 3.12.0
 4761// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 4762//
 4763// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 4764// SPDX-License-Identifier: MIT
 4765
 4766
 4767
 4768// #include <nlohmann/detail/abi_macros.hpp>
 4769
 4770
 4771NLOHMANN_JSON_NAMESPACE_BEGIN
 4772namespace detail
 4773{
 4774
 4775// dispatching helper struct
 4776template <class T> struct identity_tag {};
 4777
 4778}  // namespace detail
 4779NLOHMANN_JSON_NAMESPACE_END
 4780
 4781// #include <nlohmann/detail/meta/std_fs.hpp>
 4782//     __ _____ _____ _____
 4783//  __|  |   __|     |   | |  JSON for Modern C++
 4784// |  |  |__   |  |  | | | |  version 3.12.0
 4785// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 4786//
 4787// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 4788// SPDX-License-Identifier: MIT
 4789
 4790
 4791
 4792// #include <nlohmann/detail/macro_scope.hpp>
 4793
 4794
 4795#if JSON_HAS_EXPERIMENTAL_FILESYSTEM
 4796#include <experimental/filesystem>
 4797NLOHMANN_JSON_NAMESPACE_BEGIN
 4798namespace detail
 4799{
 4800namespace std_fs = std::experimental::filesystem;
 4801}  // namespace detail
 4802NLOHMANN_JSON_NAMESPACE_END
 4803#elif JSON_HAS_FILESYSTEM
 4804#include <filesystem> // NOLINT(build/c++17)
 4805NLOHMANN_JSON_NAMESPACE_BEGIN
 4806namespace detail
 4807{
 4808namespace std_fs = std::filesystem;
 4809}  // namespace detail
 4810NLOHMANN_JSON_NAMESPACE_END
 4811#endif
 4812
 4813// #include <nlohmann/detail/meta/type_traits.hpp>
 4814
 4815// #include <nlohmann/detail/string_concat.hpp>
 4816
 4817// #include <nlohmann/detail/value_t.hpp>
 4818
 4819
 4820NLOHMANN_JSON_NAMESPACE_BEGIN
 4821namespace detail
 4822{
 4823
 4824template<typename BasicJsonType>
 4825inline void from_json(const BasicJsonType& j, typename std::nullptr_t& n)
 4826{
 4827    if (JSON_HEDLEY_UNLIKELY(!j.is_null()))
 4828    {
 4829        JSON_THROW(type_error::create(302, concat("type must be null, but is ", j.type_name()), &j));
 4830    }
 4831    n = nullptr;
 4832}
 4833
 4834#ifdef JSON_HAS_CPP_17
 4835#ifndef JSON_USE_IMPLICIT_CONVERSIONS
 4836template<typename BasicJsonType, typename T>
 4837void from_json(const BasicJsonType& j, std::optional<T>& opt)
 4838{
 4839    if (j.is_null())
 4840    {
 4841        opt = std::nullopt;
 4842    }
 4843    else
 4844    {
 4845        opt.emplace(j.template get<T>());
 4846    }
 4847}
 4848
 4849#endif // JSON_USE_IMPLICIT_CONVERSIONS
 4850#endif // JSON_HAS_CPP_17
 4851
 4852// overloads for basic_json template parameters
 4853template < typename BasicJsonType, typename ArithmeticType,
 4854           enable_if_t < std::is_arithmetic<ArithmeticType>::value&&
 4855                         !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
 4856                         int > = 0 >
 4857void get_arithmetic_value(const BasicJsonType& j, ArithmeticType& val)
 4858{
 4859    switch (static_cast<value_t>(j))
 4860    {
 4861        case value_t::number_unsigned:
 4862        {
 4863            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
 4864            break;
 4865        }
 4866        case value_t::number_integer:
 4867        {
 4868            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
 4869            break;
 4870        }
 4871        case value_t::number_float:
 4872        {
 4873            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
 4874            break;
 4875        }
 4876
 4877        case value_t::null:
 4878        case value_t::object:
 4879        case value_t::array:
 4880        case value_t::string:
 4881        case value_t::boolean:
 4882        case value_t::binary:
 4883        case value_t::discarded:
 4884        default:
 4885            JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
 4886    }
 4887}
 4888
 4889template<typename BasicJsonType>
 4890inline void from_json(const BasicJsonType& j, typename BasicJsonType::boolean_t& b)
 4891{
 4892    if (JSON_HEDLEY_UNLIKELY(!j.is_boolean()))
 4893    {
 4894        JSON_THROW(type_error::create(302, concat("type must be boolean, but is ", j.type_name()), &j));
 4895    }
 4896    b = *j.template get_ptr<const typename BasicJsonType::boolean_t*>();
 4897}
 4898
 4899template<typename BasicJsonType>
 4900inline void from_json(const BasicJsonType& j, typename BasicJsonType::string_t& s)
 4901{
 4902    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
 4903    {
 4904        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
 4905    }
 4906    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
 4907}
 4908
 4909template <
 4910    typename BasicJsonType, typename StringType,
 4911    enable_if_t <
 4912        std::is_assignable<StringType&, const typename BasicJsonType::string_t>::value
 4913        && is_detected_exact<typename BasicJsonType::string_t::value_type, value_type_t, StringType>::value
 4914        && !std::is_same<typename BasicJsonType::string_t, StringType>::value
 4915        && !is_json_ref<StringType>::value, int > = 0 >
 4916inline void from_json(const BasicJsonType& j, StringType& s)
 4917{
 4918    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
 4919    {
 4920        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
 4921    }
 4922
 4923    s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
 4924}
 4925
 4926template<typename BasicJsonType>
 4927inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_float_t& val)
 4928{
 4929    get_arithmetic_value(j, val);
 4930}
 4931
 4932template<typename BasicJsonType>
 4933inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_unsigned_t& val)
 4934{
 4935    get_arithmetic_value(j, val);
 4936}
 4937
 4938template<typename BasicJsonType>
 4939inline void from_json(const BasicJsonType& j, typename BasicJsonType::number_integer_t& val)
 4940{
 4941    get_arithmetic_value(j, val);
 4942}
 4943
 4944#if !JSON_DISABLE_ENUM_SERIALIZATION
 4945template<typename BasicJsonType, typename EnumType,
 4946         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
 4947inline void from_json(const BasicJsonType& j, EnumType& e)
 4948{
 4949    typename std::underlying_type<EnumType>::type val;
 4950    get_arithmetic_value(j, val);
 4951    e = static_cast<EnumType>(val);
 4952}
 4953#endif  // JSON_DISABLE_ENUM_SERIALIZATION
 4954
 4955// forward_list doesn't have an insert method
 4956template<typename BasicJsonType, typename T, typename Allocator,
 4957         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
 4958inline void from_json(const BasicJsonType& j, std::forward_list<T, Allocator>& l)
 4959{
 4960    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 4961    {
 4962        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 4963    }
 4964    l.clear();
 4965    std::transform(j.rbegin(), j.rend(),
 4966                   std::front_inserter(l), [](const BasicJsonType & i)
 4967    {
 4968        return i.template get<T>();
 4969    });
 4970}
 4971
 4972// valarray doesn't have an insert method
 4973template<typename BasicJsonType, typename T,
 4974         enable_if_t<is_getable<BasicJsonType, T>::value, int> = 0>
 4975inline void from_json(const BasicJsonType& j, std::valarray<T>& l)
 4976{
 4977    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 4978    {
 4979        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 4980    }
 4981    l.resize(j.size());
 4982    std::transform(j.begin(), j.end(), std::begin(l),
 4983                   [](const BasicJsonType & elem)
 4984    {
 4985        return elem.template get<T>();
 4986    });
 4987}
 4988
 4989template<typename BasicJsonType, typename T, std::size_t N>
 4990auto from_json(const BasicJsonType& j, T (&arr)[N])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 4991-> decltype(j.template get<T>(), void())
 4992{
 4993    for (std::size_t i = 0; i < N; ++i)
 4994    {
 4995        arr[i] = j.at(i).template get<T>();
 4996    }
 4997}
 4998
 4999template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2>
 5000auto from_json(const BasicJsonType& j, T (&arr)[N1][N2])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 5001-> decltype(j.template get<T>(), void())
 5002{
 5003    for (std::size_t i1 = 0; i1 < N1; ++i1)
 5004    {
 5005        for (std::size_t i2 = 0; i2 < N2; ++i2)
 5006        {
 5007            arr[i1][i2] = j.at(i1).at(i2).template get<T>();
 5008        }
 5009    }
 5010}
 5011
 5012template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3>
 5013auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 5014-> decltype(j.template get<T>(), void())
 5015{
 5016    for (std::size_t i1 = 0; i1 < N1; ++i1)
 5017    {
 5018        for (std::size_t i2 = 0; i2 < N2; ++i2)
 5019        {
 5020            for (std::size_t i3 = 0; i3 < N3; ++i3)
 5021            {
 5022                arr[i1][i2][i3] = j.at(i1).at(i2).at(i3).template get<T>();
 5023            }
 5024        }
 5025    }
 5026}
 5027
 5028template<typename BasicJsonType, typename T, std::size_t N1, std::size_t N2, std::size_t N3, std::size_t N4>
 5029auto from_json(const BasicJsonType& j, T (&arr)[N1][N2][N3][N4])  // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 5030-> decltype(j.template get<T>(), void())
 5031{
 5032    for (std::size_t i1 = 0; i1 < N1; ++i1)
 5033    {
 5034        for (std::size_t i2 = 0; i2 < N2; ++i2)
 5035        {
 5036            for (std::size_t i3 = 0; i3 < N3; ++i3)
 5037            {
 5038                for (std::size_t i4 = 0; i4 < N4; ++i4)
 5039                {
 5040                    arr[i1][i2][i3][i4] = j.at(i1).at(i2).at(i3).at(i4).template get<T>();
 5041                }
 5042            }
 5043        }
 5044    }
 5045}
 5046
 5047template<typename BasicJsonType>
 5048inline void from_json_array_impl(const BasicJsonType& j, typename BasicJsonType::array_t& arr, priority_tag<3> /*unused*/)
 5049{
 5050    arr = *j.template get_ptr<const typename BasicJsonType::array_t*>();
 5051}
 5052
 5053template<typename BasicJsonType, typename T, std::size_t N>
 5054auto from_json_array_impl(const BasicJsonType& j, std::array<T, N>& arr,
 5055                          priority_tag<2> /*unused*/)
 5056-> decltype(j.template get<T>(), void())
 5057{
 5058    for (std::size_t i = 0; i < N; ++i)
 5059    {
 5060        arr[i] = j.at(i).template get<T>();
 5061    }
 5062}
 5063
 5064template<typename BasicJsonType, typename ConstructibleArrayType,
 5065         enable_if_t<
 5066             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
 5067             int> = 0>
 5068auto from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr, priority_tag<1> /*unused*/)
 5069-> decltype(
 5070    arr.reserve(std::declval<typename ConstructibleArrayType::size_type>()),
 5071    j.template get<typename ConstructibleArrayType::value_type>(),
 5072    void())
 5073{
 5074    using std::end;
 5075
 5076    ConstructibleArrayType ret;
 5077    ret.reserve(j.size());
 5078    std::transform(j.begin(), j.end(),
 5079                   std::inserter(ret, end(ret)), [](const BasicJsonType & i)
 5080    {
 5081        // get<BasicJsonType>() returns *this, this won't call a from_json
 5082        // method when value_type is BasicJsonType
 5083        return i.template get<typename ConstructibleArrayType::value_type>();
 5084    });
 5085    arr = std::move(ret);
 5086}
 5087
 5088template<typename BasicJsonType, typename ConstructibleArrayType,
 5089         enable_if_t<
 5090             std::is_assignable<ConstructibleArrayType&, ConstructibleArrayType>::value,
 5091             int> = 0>
 5092inline void from_json_array_impl(const BasicJsonType& j, ConstructibleArrayType& arr,
 5093                                 priority_tag<0> /*unused*/)
 5094{
 5095    using std::end;
 5096
 5097    ConstructibleArrayType ret;
 5098    std::transform(
 5099        j.begin(), j.end(), std::inserter(ret, end(ret)),
 5100        [](const BasicJsonType & i)
 5101    {
 5102        // get<BasicJsonType>() returns *this, this won't call a from_json
 5103        // method when value_type is BasicJsonType
 5104        return i.template get<typename ConstructibleArrayType::value_type>();
 5105    });
 5106    arr = std::move(ret);
 5107}
 5108
 5109template < typename BasicJsonType, typename ConstructibleArrayType,
 5110           enable_if_t <
 5111               is_constructible_array_type<BasicJsonType, ConstructibleArrayType>::value&&
 5112               !is_constructible_object_type<BasicJsonType, ConstructibleArrayType>::value&&
 5113               !is_constructible_string_type<BasicJsonType, ConstructibleArrayType>::value&&
 5114               !std::is_same<ConstructibleArrayType, typename BasicJsonType::binary_t>::value&&
 5115               !is_basic_json<ConstructibleArrayType>::value,
 5116               int > = 0 >
 5117auto from_json(const BasicJsonType& j, ConstructibleArrayType& arr)
 5118-> decltype(from_json_array_impl(j, arr, priority_tag<3> {}),
 5119j.template get<typename ConstructibleArrayType::value_type>(),
 5120void())
 5121{
 5122    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 5123    {
 5124        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 5125    }
 5126
 5127    from_json_array_impl(j, arr, priority_tag<3> {});
 5128}
 5129
 5130template < typename BasicJsonType, typename T, std::size_t... Idx >
 5131std::array<T, sizeof...(Idx)> from_json_inplace_array_impl(BasicJsonType&& j,
 5132                     identity_tag<std::array<T, sizeof...(Idx)>> /*unused*/, index_sequence<Idx...> /*unused*/)
 5133{
 5134    return { { std::forward<BasicJsonType>(j).at(Idx).template get<T>()... } };
 5135}
 5136
 5137template < typename BasicJsonType, typename T, std::size_t N >
 5138auto from_json(BasicJsonType&& j, identity_tag<std::array<T, N>> tag)
 5139-> decltype(from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {}))
 5140{
 5141    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 5142    {
 5143        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 5144    }
 5145
 5146    return from_json_inplace_array_impl(std::forward<BasicJsonType>(j), tag, make_index_sequence<N> {});
 5147}
 5148
 5149template<typename BasicJsonType>
 5150inline void from_json(const BasicJsonType& j, typename BasicJsonType::binary_t& bin)
 5151{
 5152    if (JSON_HEDLEY_UNLIKELY(!j.is_binary()))
 5153    {
 5154        JSON_THROW(type_error::create(302, concat("type must be binary, but is ", j.type_name()), &j));
 5155    }
 5156
 5157    bin = *j.template get_ptr<const typename BasicJsonType::binary_t*>();
 5158}
 5159
 5160template<typename BasicJsonType, typename ConstructibleObjectType,
 5161         enable_if_t<is_constructible_object_type<BasicJsonType, ConstructibleObjectType>::value, int> = 0>
 5162inline void from_json(const BasicJsonType& j, ConstructibleObjectType& obj)
 5163{
 5164    if (JSON_HEDLEY_UNLIKELY(!j.is_object()))
 5165    {
 5166        JSON_THROW(type_error::create(302, concat("type must be object, but is ", j.type_name()), &j));
 5167    }
 5168
 5169    ConstructibleObjectType ret;
 5170    const auto* inner_object = j.template get_ptr<const typename BasicJsonType::object_t*>();
 5171    using value_type = typename ConstructibleObjectType::value_type;
 5172    std::transform(
 5173        inner_object->begin(), inner_object->end(),
 5174        std::inserter(ret, ret.begin()),
 5175        [](typename BasicJsonType::object_t::value_type const & p)
 5176    {
 5177        return value_type(p.first, p.second.template get<typename ConstructibleObjectType::mapped_type>());
 5178    });
 5179    obj = std::move(ret);
 5180}
 5181
 5182// overload for arithmetic types, not chosen for basic_json template arguments
 5183// (BooleanType, etc..); note: Is it really necessary to provide explicit
 5184// overloads for boolean_t etc. in case of a custom BooleanType which is not
 5185// an arithmetic type?
 5186template < typename BasicJsonType, typename ArithmeticType,
 5187           enable_if_t <
 5188               std::is_arithmetic<ArithmeticType>::value&&
 5189               !std::is_same<ArithmeticType, typename BasicJsonType::number_unsigned_t>::value&&
 5190               !std::is_same<ArithmeticType, typename BasicJsonType::number_integer_t>::value&&
 5191               !std::is_same<ArithmeticType, typename BasicJsonType::number_float_t>::value&&
 5192               !std::is_same<ArithmeticType, typename BasicJsonType::boolean_t>::value,
 5193               int > = 0 >
 5194inline void from_json(const BasicJsonType& j, ArithmeticType& val)
 5195{
 5196    switch (static_cast<value_t>(j))
 5197    {
 5198        case value_t::number_unsigned:
 5199        {
 5200            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_unsigned_t*>());
 5201            break;
 5202        }
 5203        case value_t::number_integer:
 5204        {
 5205            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_integer_t*>());
 5206            break;
 5207        }
 5208        case value_t::number_float:
 5209        {
 5210            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::number_float_t*>());
 5211            break;
 5212        }
 5213        case value_t::boolean:
 5214        {
 5215            val = static_cast<ArithmeticType>(*j.template get_ptr<const typename BasicJsonType::boolean_t*>());
 5216            break;
 5217        }
 5218
 5219        case value_t::null:
 5220        case value_t::object:
 5221        case value_t::array:
 5222        case value_t::string:
 5223        case value_t::binary:
 5224        case value_t::discarded:
 5225        default:
 5226            JSON_THROW(type_error::create(302, concat("type must be number, but is ", j.type_name()), &j));
 5227    }
 5228}
 5229
 5230template<typename BasicJsonType, typename... Args, std::size_t... Idx>
 5231std::tuple<Args...> from_json_tuple_impl_base(BasicJsonType&& j, index_sequence<Idx...> /*unused*/)
 5232{
 5233    return std::make_tuple(std::forward<BasicJsonType>(j).at(Idx).template get<Args>()...);
 5234}
 5235
 5236template<typename BasicJsonType>
 5237std::tuple<> from_json_tuple_impl_base(BasicJsonType& /*unused*/, index_sequence<> /*unused*/)
 5238{
 5239    return {};
 5240}
 5241
 5242template < typename BasicJsonType, class A1, class A2 >
 5243std::pair<A1, A2> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::pair<A1, A2>> /*unused*/, priority_tag<0> /*unused*/)
 5244{
 5245    return {std::forward<BasicJsonType>(j).at(0).template get<A1>(),
 5246            std::forward<BasicJsonType>(j).at(1).template get<A2>()};
 5247}
 5248
 5249template<typename BasicJsonType, typename A1, typename A2>
 5250inline void from_json_tuple_impl(BasicJsonType&& j, std::pair<A1, A2>& p, priority_tag<1> /*unused*/)
 5251{
 5252    p = from_json_tuple_impl(std::forward<BasicJsonType>(j), identity_tag<std::pair<A1, A2>> {}, priority_tag<0> {});
 5253}
 5254
 5255template<typename BasicJsonType, typename... Args>
 5256std::tuple<Args...> from_json_tuple_impl(BasicJsonType&& j, identity_tag<std::tuple<Args...>> /*unused*/, priority_tag<2> /*unused*/)
 5257{
 5258    return from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
 5259}
 5260
 5261template<typename BasicJsonType, typename... Args>
 5262inline void from_json_tuple_impl(BasicJsonType&& j, std::tuple<Args...>& t, priority_tag<3> /*unused*/)
 5263{
 5264    t = from_json_tuple_impl_base<BasicJsonType, Args...>(std::forward<BasicJsonType>(j), index_sequence_for<Args...> {});
 5265}
 5266
 5267template<typename BasicJsonType, typename TupleRelated>
 5268auto from_json(BasicJsonType&& j, TupleRelated&& t)
 5269-> decltype(from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {}))
 5270{
 5271    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 5272    {
 5273        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 5274    }
 5275
 5276    return from_json_tuple_impl(std::forward<BasicJsonType>(j), std::forward<TupleRelated>(t), priority_tag<3> {});
 5277}
 5278
 5279template < typename BasicJsonType, typename Key, typename Value, typename Compare, typename Allocator,
 5280           typename = enable_if_t < !std::is_constructible <
 5281                                        typename BasicJsonType::string_t, Key >::value >>
 5282inline void from_json(const BasicJsonType& j, std::map<Key, Value, Compare, Allocator>& m)
 5283{
 5284    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 5285    {
 5286        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 5287    }
 5288    m.clear();
 5289    for (const auto& p : j)
 5290    {
 5291        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
 5292        {
 5293            JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
 5294        }
 5295        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
 5296    }
 5297}
 5298
 5299template < typename BasicJsonType, typename Key, typename Value, typename Hash, typename KeyEqual, typename Allocator,
 5300           typename = enable_if_t < !std::is_constructible <
 5301                                        typename BasicJsonType::string_t, Key >::value >>
 5302inline void from_json(const BasicJsonType& j, std::unordered_map<Key, Value, Hash, KeyEqual, Allocator>& m)
 5303{
 5304    if (JSON_HEDLEY_UNLIKELY(!j.is_array()))
 5305    {
 5306        JSON_THROW(type_error::create(302, concat("type must be array, but is ", j.type_name()), &j));
 5307    }
 5308    m.clear();
 5309    for (const auto& p : j)
 5310    {
 5311        if (JSON_HEDLEY_UNLIKELY(!p.is_array()))
 5312        {
 5313            JSON_THROW(type_error::create(302, concat("type must be array, but is ", p.type_name()), &j));
 5314        }
 5315        m.emplace(p.at(0).template get<Key>(), p.at(1).template get<Value>());
 5316    }
 5317}
 5318
 5319#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
 5320template<typename BasicJsonType>
 5321inline void from_json(const BasicJsonType& j, std_fs::path& p)
 5322{
 5323    if (JSON_HEDLEY_UNLIKELY(!j.is_string()))
 5324    {
 5325        JSON_THROW(type_error::create(302, concat("type must be string, but is ", j.type_name()), &j));
 5326    }
 5327    const auto& s = *j.template get_ptr<const typename BasicJsonType::string_t*>();
 5328#ifdef JSON_HAS_CPP_20
 5329    p = std_fs::path(std::u8string_view(reinterpret_cast<const char8_t*>(s.data()), s.size()));
 5330#else
 5331    p = std_fs::u8path(s); // accepts UTF-8 encoded std::string in C++17, deprecated in C++20
 5332#endif
 5333}
 5334#endif
 5335
 5336struct from_json_fn
 5337{
 5338    template<typename BasicJsonType, typename T>
 5339    auto operator()(const BasicJsonType& j, T&& val) const
 5340    noexcept(noexcept(from_json(j, std::forward<T>(val))))
 5341    -> decltype(from_json(j, std::forward<T>(val)))
 5342    {
 5343        return from_json(j, std::forward<T>(val));
 5344    }
 5345};
 5346
 5347}  // namespace detail
 5348
 5349#ifndef JSON_HAS_CPP_17
 5350/// namespace to hold default `from_json` function
 5351/// to see why this is required:
 5352/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
 5353namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
 5354{
 5355#endif
 5356JSON_INLINE_VARIABLE constexpr const auto& from_json = // NOLINT(misc-definitions-in-headers)
 5357    detail::static_const<detail::from_json_fn>::value;
 5358#ifndef JSON_HAS_CPP_17
 5359}  // namespace
 5360#endif
 5361
 5362NLOHMANN_JSON_NAMESPACE_END
 5363
 5364// #include <nlohmann/detail/conversions/to_json.hpp>
 5365//     __ _____ _____ _____
 5366//  __|  |   __|     |   | |  JSON for Modern C++
 5367// |  |  |__   |  |  | | | |  version 3.12.0
 5368// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 5369//
 5370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 5371// SPDX-License-Identifier: MIT
 5372
 5373
 5374
 5375// #include <nlohmann/detail/macro_scope.hpp>
 5376// JSON_HAS_CPP_17
 5377#ifdef JSON_HAS_CPP_17
 5378    #include <optional> // optional
 5379#endif
 5380
 5381#include <algorithm> // copy
 5382#include <iterator> // begin, end
 5383#include <string> // string
 5384#include <tuple> // tuple, get
 5385#include <type_traits> // is_same, is_constructible, is_floating_point, is_enum, underlying_type
 5386#include <utility> // move, forward, declval, pair
 5387#include <valarray> // valarray
 5388#include <vector> // vector
 5389
 5390// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
 5391//     __ _____ _____ _____
 5392//  __|  |   __|     |   | |  JSON for Modern C++
 5393// |  |  |__   |  |  | | | |  version 3.12.0
 5394// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 5395//
 5396// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 5397// SPDX-License-Identifier: MIT
 5398
 5399
 5400
 5401#include <cstddef> // size_t
 5402#include <iterator> // forward_iterator_tag
 5403#include <tuple> // tuple_size, get, tuple_element
 5404#include <utility> // move
 5405
 5406#if JSON_HAS_RANGES
 5407    #include <ranges> // enable_borrowed_range
 5408#endif
 5409
 5410// #include <nlohmann/detail/abi_macros.hpp>
 5411
 5412// #include <nlohmann/detail/meta/type_traits.hpp>
 5413
 5414// #include <nlohmann/detail/string_utils.hpp>
 5415//     __ _____ _____ _____
 5416//  __|  |   __|     |   | |  JSON for Modern C++
 5417// |  |  |__   |  |  | | | |  version 3.12.0
 5418// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 5419//
 5420// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 5421// SPDX-License-Identifier: MIT
 5422
 5423
 5424
 5425#include <cstddef> // size_t
 5426#include <string> // string, to_string
 5427
 5428// #include <nlohmann/detail/abi_macros.hpp>
 5429
 5430
 5431NLOHMANN_JSON_NAMESPACE_BEGIN
 5432namespace detail
 5433{
 5434
 5435template<typename StringType>
 5436void int_to_string(StringType& target, std::size_t value)
 5437{
 5438    // For ADL
 5439    using std::to_string;
 5440    target = to_string(value);
 5441}
 5442
 5443template<typename StringType>
 5444StringType to_string(std::size_t value)
 5445{
 5446    StringType result;
 5447    int_to_string(result, value);
 5448    return result;
 5449}
 5450
 5451}  // namespace detail
 5452NLOHMANN_JSON_NAMESPACE_END
 5453
 5454// #include <nlohmann/detail/value_t.hpp>
 5455
 5456
 5457NLOHMANN_JSON_NAMESPACE_BEGIN
 5458namespace detail
 5459{
 5460
 5461template<typename IteratorType> class iteration_proxy_value
 5462{
 5463  public:
 5464    using difference_type = std::ptrdiff_t;
 5465    using value_type = iteration_proxy_value;
 5466    using pointer = value_type *;
 5467    using reference = value_type &;
 5468    using iterator_category = std::forward_iterator_tag;
 5469    using string_type = typename std::remove_cv< typename std::remove_reference<decltype( std::declval<IteratorType>().key() ) >::type >::type;
 5470
 5471  private:
 5472    /// the iterator
 5473    IteratorType anchor{};
 5474    /// an index for arrays (used to create key names)
 5475    std::size_t array_index = 0;
 5476    /// last stringified array index
 5477    mutable std::size_t array_index_last = 0;
 5478    /// a string representation of the array index
 5479    mutable string_type array_index_str = "0";
 5480    /// an empty string (to return a reference for primitive values)
 5481    string_type empty_str{};
 5482
 5483  public:
 5484    explicit iteration_proxy_value() = default;
 5485    explicit iteration_proxy_value(IteratorType it, std::size_t array_index_ = 0)
 5486    noexcept(std::is_nothrow_move_constructible<IteratorType>::value
 5487             && std::is_nothrow_default_constructible<string_type>::value)
 5488        : anchor(std::move(it))
 5489        , array_index(array_index_)
 5490    {}
 5491
 5492    iteration_proxy_value(iteration_proxy_value const&) = default;
 5493    iteration_proxy_value& operator=(iteration_proxy_value const&) = default;
 5494    // older GCCs are a bit fussy and require explicit noexcept specifiers on defaulted functions
 5495    iteration_proxy_value(iteration_proxy_value&&)
 5496    noexcept(std::is_nothrow_move_constructible<IteratorType>::value
 5497             && std::is_nothrow_move_constructible<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
 5498    iteration_proxy_value& operator=(iteration_proxy_value&&)
 5499    noexcept(std::is_nothrow_move_assignable<IteratorType>::value
 5500             && std::is_nothrow_move_assignable<string_type>::value) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor,cppcoreguidelines-noexcept-move-operations)
 5501    ~iteration_proxy_value() = default;
 5502
 5503    /// dereference operator (needed for range-based for)
 5504    const iteration_proxy_value& operator*() const
 5505    {
 5506        return *this;
 5507    }
 5508
 5509    /// increment operator (needed for range-based for)
 5510    iteration_proxy_value& operator++()
 5511    {
 5512        ++anchor;
 5513        ++array_index;
 5514
 5515        return *this;
 5516    }
 5517
 5518    iteration_proxy_value operator++(int)& // NOLINT(cert-dcl21-cpp)
 5519    {
 5520        auto tmp = iteration_proxy_value(anchor, array_index);
 5521        ++anchor;
 5522        ++array_index;
 5523        return tmp;
 5524    }
 5525
 5526    /// equality operator (needed for InputIterator)
 5527    bool operator==(const iteration_proxy_value& o) const
 5528    {
 5529        return anchor == o.anchor;
 5530    }
 5531
 5532    /// inequality operator (needed for range-based for)
 5533    bool operator!=(const iteration_proxy_value& o) const
 5534    {
 5535        return anchor != o.anchor;
 5536    }
 5537
 5538    /// return key of the iterator
 5539    const string_type& key() const
 5540    {
 5541        JSON_ASSERT(anchor.m_object != nullptr);
 5542
 5543        switch (anchor.m_object->type())
 5544        {
 5545            // use integer array index as key
 5546            case value_t::array:
 5547            {
 5548                if (array_index != array_index_last)
 5549                {
 5550                    int_to_string( array_index_str, array_index );
 5551                    array_index_last = array_index;
 5552                }
 5553                return array_index_str;
 5554            }
 5555
 5556            // use key from the object
 5557            case value_t::object:
 5558                return anchor.key();
 5559
 5560            // use an empty key for all primitive types
 5561            case value_t::null:
 5562            case value_t::string:
 5563            case value_t::boolean:
 5564            case value_t::number_integer:
 5565            case value_t::number_unsigned:
 5566            case value_t::number_float:
 5567            case value_t::binary:
 5568            case value_t::discarded:
 5569            default:
 5570                return empty_str;
 5571        }
 5572    }
 5573
 5574    /// return value of the iterator
 5575    typename IteratorType::reference value() const
 5576    {
 5577        return anchor.value();
 5578    }
 5579};
 5580
 5581/// proxy class for the items() function
 5582template<typename IteratorType> class iteration_proxy
 5583{
 5584  private:
 5585    /// the container to iterate
 5586    typename IteratorType::pointer container = nullptr;
 5587
 5588  public:
 5589    explicit iteration_proxy() = default;
 5590
 5591    /// construct iteration proxy from a container
 5592    explicit iteration_proxy(typename IteratorType::reference cont) noexcept
 5593        : container(&cont) {}
 5594
 5595    iteration_proxy(iteration_proxy const&) = default;
 5596    iteration_proxy& operator=(iteration_proxy const&) = default;
 5597    iteration_proxy(iteration_proxy&&) noexcept = default;
 5598    iteration_proxy& operator=(iteration_proxy&&) noexcept = default;
 5599    ~iteration_proxy() = default;
 5600
 5601    /// return iterator begin (needed for range-based for)
 5602    iteration_proxy_value<IteratorType> begin() const noexcept
 5603    {
 5604        return iteration_proxy_value<IteratorType>(container->begin());
 5605    }
 5606
 5607    /// return iterator end (needed for range-based for)
 5608    iteration_proxy_value<IteratorType> end() const noexcept
 5609    {
 5610        return iteration_proxy_value<IteratorType>(container->end());
 5611    }
 5612};
 5613
 5614// Structured Bindings Support
 5615// For further reference see https://blog.tartanllama.xyz/structured-bindings/
 5616// And see https://github.com/nlohmann/json/pull/1391
 5617template<std::size_t N, typename IteratorType, enable_if_t<N == 0, int> = 0>
 5618auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.key())
 5619{
 5620    return i.key();
 5621}
 5622// Structured Bindings Support
 5623// For further reference see https://blog.tartanllama.xyz/structured-bindings/
 5624// And see https://github.com/nlohmann/json/pull/1391
 5625template<std::size_t N, typename IteratorType, enable_if_t<N == 1, int> = 0>
 5626auto get(const nlohmann::detail::iteration_proxy_value<IteratorType>& i) -> decltype(i.value())
 5627{
 5628    return i.value();
 5629}
 5630
 5631}  // namespace detail
 5632NLOHMANN_JSON_NAMESPACE_END
 5633
 5634// The Addition to the STD Namespace is required to add
 5635// Structured Bindings Support to the iteration_proxy_value class
 5636// For further reference see https://blog.tartanllama.xyz/structured-bindings/
 5637// And see https://github.com/nlohmann/json/pull/1391
 5638namespace std
 5639{
 5640
 5641#if defined(__clang__)
 5642    // Fix: https://github.com/nlohmann/json/issues/1401
 5643    #pragma clang diagnostic push
 5644    #pragma clang diagnostic ignored "-Wmismatched-tags"
 5645#endif
 5646template<typename IteratorType>
 5647class tuple_size<::nlohmann::detail::iteration_proxy_value<IteratorType>> // NOLINT(cert-dcl58-cpp)
 5648    : public std::integral_constant<std::size_t, 2> {};
 5649
 5650template<std::size_t N, typename IteratorType>
 5651class tuple_element<N, ::nlohmann::detail::iteration_proxy_value<IteratorType >> // NOLINT(cert-dcl58-cpp)
 5652{
 5653  public:
 5654    using type = decltype(
 5655                     get<N>(std::declval <
 5656                            ::nlohmann::detail::iteration_proxy_value<IteratorType >> ()));
 5657};
 5658#if defined(__clang__)
 5659    #pragma clang diagnostic pop
 5660#endif
 5661
 5662}  // namespace std
 5663
 5664#if JSON_HAS_RANGES
 5665    template <typename IteratorType>
 5666    inline constexpr bool ::std::ranges::enable_borrowed_range<::nlohmann::detail::iteration_proxy<IteratorType>> = true;
 5667#endif
 5668
 5669// #include <nlohmann/detail/meta/cpp_future.hpp>
 5670
 5671// #include <nlohmann/detail/meta/std_fs.hpp>
 5672
 5673// #include <nlohmann/detail/meta/type_traits.hpp>
 5674
 5675// #include <nlohmann/detail/value_t.hpp>
 5676
 5677
 5678NLOHMANN_JSON_NAMESPACE_BEGIN
 5679namespace detail
 5680{
 5681
 5682//////////////////
 5683// constructors //
 5684//////////////////
 5685
 5686/*
 5687 * Note all external_constructor<>::construct functions need to call
 5688 * j.m_data.m_value.destroy(j.m_data.m_type) to avoid a memory leak in case j contains an
 5689 * allocated value (e.g., a string). See bug issue
 5690 * https://github.com/nlohmann/json/issues/2865 for more information.
 5691 */
 5692
 5693template<value_t> struct external_constructor;
 5694
 5695template<>
 5696struct external_constructor<value_t::boolean>
 5697{
 5698    template<typename BasicJsonType>
 5699    static void construct(BasicJsonType& j, typename BasicJsonType::boolean_t b) noexcept
 5700    {
 5701        j.m_data.m_value.destroy(j.m_data.m_type);
 5702        j.m_data.m_type = value_t::boolean;
 5703        j.m_data.m_value = b;
 5704        j.assert_invariant();
 5705    }
 5706};
 5707
 5708template<>
 5709struct external_constructor<value_t::string>
 5710{
 5711    template<typename BasicJsonType>
 5712    static void construct(BasicJsonType& j, const typename BasicJsonType::string_t& s)
 5713    {
 5714        j.m_data.m_value.destroy(j.m_data.m_type);
 5715        j.m_data.m_type = value_t::string;
 5716        j.m_data.m_value = s;
 5717        j.assert_invariant();
 5718    }
 5719
 5720    template<typename BasicJsonType>
 5721    static void construct(BasicJsonType& j, typename BasicJsonType::string_t&& s)
 5722    {
 5723        j.m_data.m_value.destroy(j.m_data.m_type);
 5724        j.m_data.m_type = value_t::string;
 5725        j.m_data.m_value = std::move(s);
 5726        j.assert_invariant();
 5727    }
 5728
 5729    template < typename BasicJsonType, typename CompatibleStringType,
 5730               enable_if_t < !std::is_same<CompatibleStringType, typename BasicJsonType::string_t>::value,
 5731                             int > = 0 >
 5732    static void construct(BasicJsonType& j, const CompatibleStringType& str)
 5733    {
 5734        j.m_data.m_value.destroy(j.m_data.m_type);
 5735        j.m_data.m_type = value_t::string;
 5736        j.m_data.m_value.string = j.template create<typename BasicJsonType::string_t>(str);
 5737        j.assert_invariant();
 5738    }
 5739};
 5740
 5741template<>
 5742struct external_constructor<value_t::binary>
 5743{
 5744    template<typename BasicJsonType>
 5745    static void construct(BasicJsonType& j, const typename BasicJsonType::binary_t& b)
 5746    {
 5747        j.m_data.m_value.destroy(j.m_data.m_type);
 5748        j.m_data.m_type = value_t::binary;
 5749        j.m_data.m_value = typename BasicJsonType::binary_t(b);
 5750        j.assert_invariant();
 5751    }
 5752
 5753    template<typename BasicJsonType>
 5754    static void construct(BasicJsonType& j, typename BasicJsonType::binary_t&& b)
 5755    {
 5756        j.m_data.m_value.destroy(j.m_data.m_type);
 5757        j.m_data.m_type = value_t::binary;
 5758        j.m_data.m_value = typename BasicJsonType::binary_t(std::move(b));
 5759        j.assert_invariant();
 5760    }
 5761};
 5762
 5763template<>
 5764struct external_constructor<value_t::number_float>
 5765{
 5766    template<typename BasicJsonType>
 5767    static void construct(BasicJsonType& j, typename BasicJsonType::number_float_t val) noexcept
 5768    {
 5769        j.m_data.m_value.destroy(j.m_data.m_type);
 5770        j.m_data.m_type = value_t::number_float;
 5771        j.m_data.m_value = val;
 5772        j.assert_invariant();
 5773    }
 5774};
 5775
 5776template<>
 5777struct external_constructor<value_t::number_unsigned>
 5778{
 5779    template<typename BasicJsonType>
 5780    static void construct(BasicJsonType& j, typename BasicJsonType::number_unsigned_t val) noexcept
 5781    {
 5782        j.m_data.m_value.destroy(j.m_data.m_type);
 5783        j.m_data.m_type = value_t::number_unsigned;
 5784        j.m_data.m_value = val;
 5785        j.assert_invariant();
 5786    }
 5787};
 5788
 5789template<>
 5790struct external_constructor<value_t::number_integer>
 5791{
 5792    template<typename BasicJsonType>
 5793    static void construct(BasicJsonType& j, typename BasicJsonType::number_integer_t val) noexcept
 5794    {
 5795        j.m_data.m_value.destroy(j.m_data.m_type);
 5796        j.m_data.m_type = value_t::number_integer;
 5797        j.m_data.m_value = val;
 5798        j.assert_invariant();
 5799    }
 5800};
 5801
 5802template<>
 5803struct external_constructor<value_t::array>
 5804{
 5805    template<typename BasicJsonType>
 5806    static void construct(BasicJsonType& j, const typename BasicJsonType::array_t& arr)
 5807    {
 5808        j.m_data.m_value.destroy(j.m_data.m_type);
 5809        j.m_data.m_type = value_t::array;
 5810        j.m_data.m_value = arr;
 5811        j.set_parents();
 5812        j.assert_invariant();
 5813    }
 5814
 5815    template<typename BasicJsonType>
 5816    static void construct(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
 5817    {
 5818        j.m_data.m_value.destroy(j.m_data.m_type);
 5819        j.m_data.m_type = value_t::array;
 5820        j.m_data.m_value = std::move(arr);
 5821        j.set_parents();
 5822        j.assert_invariant();
 5823    }
 5824
 5825    template < typename BasicJsonType, typename CompatibleArrayType,
 5826               enable_if_t < !std::is_same<CompatibleArrayType, typename BasicJsonType::array_t>::value,
 5827                             int > = 0 >
 5828    static void construct(BasicJsonType& j, const CompatibleArrayType& arr)
 5829    {
 5830        using std::begin;
 5831        using std::end;
 5832
 5833        j.m_data.m_value.destroy(j.m_data.m_type);
 5834        j.m_data.m_type = value_t::array;
 5835        j.m_data.m_value.array = j.template create<typename BasicJsonType::array_t>(begin(arr), end(arr));
 5836        j.set_parents();
 5837        j.assert_invariant();
 5838    }
 5839
 5840    template<typename BasicJsonType>
 5841    static void construct(BasicJsonType& j, const std::vector<bool>& arr)
 5842    {
 5843        j.m_data.m_value.destroy(j.m_data.m_type);
 5844        j.m_data.m_type = value_t::array;
 5845        j.m_data.m_value = value_t::array;
 5846        j.m_data.m_value.array->reserve(arr.size());
 5847        for (const bool x : arr)
 5848        {
 5849            j.m_data.m_value.array->push_back(x);
 5850            j.set_parent(j.m_data.m_value.array->back());
 5851        }
 5852        j.assert_invariant();
 5853    }
 5854
 5855    template<typename BasicJsonType, typename T,
 5856             enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
 5857    static void construct(BasicJsonType& j, const std::valarray<T>& arr)
 5858    {
 5859        j.m_data.m_value.destroy(j.m_data.m_type);
 5860        j.m_data.m_type = value_t::array;
 5861        j.m_data.m_value = value_t::array;
 5862        j.m_data.m_value.array->resize(arr.size());
 5863        if (arr.size() > 0)
 5864        {
 5865            std::copy(std::begin(arr), std::end(arr), j.m_data.m_value.array->begin());
 5866        }
 5867        j.set_parents();
 5868        j.assert_invariant();
 5869    }
 5870};
 5871
 5872template<>
 5873struct external_constructor<value_t::object>
 5874{
 5875    template<typename BasicJsonType>
 5876    static void construct(BasicJsonType& j, const typename BasicJsonType::object_t& obj)
 5877    {
 5878        j.m_data.m_value.destroy(j.m_data.m_type);
 5879        j.m_data.m_type = value_t::object;
 5880        j.m_data.m_value = obj;
 5881        j.set_parents();
 5882        j.assert_invariant();
 5883    }
 5884
 5885    template<typename BasicJsonType>
 5886    static void construct(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
 5887    {
 5888        j.m_data.m_value.destroy(j.m_data.m_type);
 5889        j.m_data.m_type = value_t::object;
 5890        j.m_data.m_value = std::move(obj);
 5891        j.set_parents();
 5892        j.assert_invariant();
 5893    }
 5894
 5895    template < typename BasicJsonType, typename CompatibleObjectType,
 5896               enable_if_t < !std::is_same<CompatibleObjectType, typename BasicJsonType::object_t>::value, int > = 0 >
 5897    static void construct(BasicJsonType& j, const CompatibleObjectType& obj)
 5898    {
 5899        using std::begin;
 5900        using std::end;
 5901
 5902        j.m_data.m_value.destroy(j.m_data.m_type);
 5903        j.m_data.m_type = value_t::object;
 5904        j.m_data.m_value.object = j.template create<typename BasicJsonType::object_t>(begin(obj), end(obj));
 5905        j.set_parents();
 5906        j.assert_invariant();
 5907    }
 5908};
 5909
 5910/////////////
 5911// to_json //
 5912/////////////
 5913
 5914#ifdef JSON_HAS_CPP_17
 5915template<typename BasicJsonType, typename T,
 5916         enable_if_t<std::is_constructible<BasicJsonType, T>::value, int> = 0>
 5917void to_json(BasicJsonType& j, const std::optional<T>& opt)
 5918{
 5919    if (opt.has_value())
 5920    {
 5921        j = *opt;
 5922    }
 5923    else
 5924    {
 5925        j = nullptr;
 5926    }
 5927}
 5928#endif
 5929
 5930template<typename BasicJsonType, typename T,
 5931         enable_if_t<std::is_same<T, typename BasicJsonType::boolean_t>::value, int> = 0>
 5932inline void to_json(BasicJsonType& j, T b) noexcept
 5933{
 5934    external_constructor<value_t::boolean>::construct(j, b);
 5935}
 5936
 5937template < typename BasicJsonType, typename BoolRef,
 5938           enable_if_t <
 5939               ((std::is_same<std::vector<bool>::reference, BoolRef>::value
 5940                 && !std::is_same <std::vector<bool>::reference, typename BasicJsonType::boolean_t&>::value)
 5941                || (std::is_same<std::vector<bool>::const_reference, BoolRef>::value
 5942                    && !std::is_same <detail::uncvref_t<std::vector<bool>::const_reference>,
 5943                                      typename BasicJsonType::boolean_t >::value))
 5944               && std::is_convertible<const BoolRef&, typename BasicJsonType::boolean_t>::value, int > = 0 >
 5945inline void to_json(BasicJsonType& j, const BoolRef& b) noexcept
 5946{
 5947    external_constructor<value_t::boolean>::construct(j, static_cast<typename BasicJsonType::boolean_t>(b));
 5948}
 5949
 5950template<typename BasicJsonType, typename CompatibleString,
 5951         enable_if_t<std::is_constructible<typename BasicJsonType::string_t, CompatibleString>::value, int> = 0>
 5952inline void to_json(BasicJsonType& j, const CompatibleString& s)
 5953{
 5954    external_constructor<value_t::string>::construct(j, s);
 5955}
 5956
 5957template<typename BasicJsonType>
 5958inline void to_json(BasicJsonType& j, typename BasicJsonType::string_t&& s)
 5959{
 5960    external_constructor<value_t::string>::construct(j, std::move(s));
 5961}
 5962
 5963template<typename BasicJsonType, typename FloatType,
 5964         enable_if_t<std::is_floating_point<FloatType>::value, int> = 0>
 5965inline void to_json(BasicJsonType& j, FloatType val) noexcept
 5966{
 5967    external_constructor<value_t::number_float>::construct(j, static_cast<typename BasicJsonType::number_float_t>(val));
 5968}
 5969
 5970template<typename BasicJsonType, typename CompatibleNumberUnsignedType,
 5971         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_unsigned_t, CompatibleNumberUnsignedType>::value, int> = 0>
 5972inline void to_json(BasicJsonType& j, CompatibleNumberUnsignedType val) noexcept
 5973{
 5974    external_constructor<value_t::number_unsigned>::construct(j, static_cast<typename BasicJsonType::number_unsigned_t>(val));
 5975}
 5976
 5977template<typename BasicJsonType, typename CompatibleNumberIntegerType,
 5978         enable_if_t<is_compatible_integer_type<typename BasicJsonType::number_integer_t, CompatibleNumberIntegerType>::value, int> = 0>
 5979inline void to_json(BasicJsonType& j, CompatibleNumberIntegerType val) noexcept
 5980{
 5981    external_constructor<value_t::number_integer>::construct(j, static_cast<typename BasicJsonType::number_integer_t>(val));
 5982}
 5983
 5984#if !JSON_DISABLE_ENUM_SERIALIZATION
 5985template<typename BasicJsonType, typename EnumType,
 5986         enable_if_t<std::is_enum<EnumType>::value, int> = 0>
 5987inline void to_json(BasicJsonType& j, EnumType e) noexcept
 5988{
 5989    using underlying_type = typename std::underlying_type<EnumType>::type;
 5990    static constexpr value_t integral_value_t = std::is_unsigned<underlying_type>::value ? value_t::number_unsigned : value_t::number_integer;
 5991    external_constructor<integral_value_t>::construct(j, static_cast<underlying_type>(e));
 5992}
 5993#endif  // JSON_DISABLE_ENUM_SERIALIZATION
 5994
 5995template<typename BasicJsonType>
 5996inline void to_json(BasicJsonType& j, const std::vector<bool>& e)
 5997{
 5998    external_constructor<value_t::array>::construct(j, e);
 5999}
 6000
 6001template < typename BasicJsonType, typename CompatibleArrayType,
 6002           enable_if_t < is_compatible_array_type<BasicJsonType,
 6003                         CompatibleArrayType>::value&&
 6004                         !is_compatible_object_type<BasicJsonType, CompatibleArrayType>::value&&
 6005                         !is_compatible_string_type<BasicJsonType, CompatibleArrayType>::value&&
 6006                         !std::is_same<typename BasicJsonType::binary_t, CompatibleArrayType>::value&&
 6007                         !is_basic_json<CompatibleArrayType>::value,
 6008                         int > = 0 >
 6009inline void to_json(BasicJsonType& j, const CompatibleArrayType& arr)
 6010{
 6011    external_constructor<value_t::array>::construct(j, arr);
 6012}
 6013
 6014template<typename BasicJsonType>
 6015inline void to_json(BasicJsonType& j, const typename BasicJsonType::binary_t& bin)
 6016{
 6017    external_constructor<value_t::binary>::construct(j, bin);
 6018}
 6019
 6020template<typename BasicJsonType, typename T,
 6021         enable_if_t<std::is_convertible<T, BasicJsonType>::value, int> = 0>
 6022inline void to_json(BasicJsonType& j, const std::valarray<T>& arr)
 6023{
 6024    external_constructor<value_t::array>::construct(j, std::move(arr));
 6025}
 6026
 6027template<typename BasicJsonType>
 6028inline void to_json(BasicJsonType& j, typename BasicJsonType::array_t&& arr)
 6029{
 6030    external_constructor<value_t::array>::construct(j, std::move(arr));
 6031}
 6032
 6033template < typename BasicJsonType, typename CompatibleObjectType,
 6034           enable_if_t < is_compatible_object_type<BasicJsonType, CompatibleObjectType>::value&& !is_basic_json<CompatibleObjectType>::value, int > = 0 >
 6035inline void to_json(BasicJsonType& j, const CompatibleObjectType& obj)
 6036{
 6037    external_constructor<value_t::object>::construct(j, obj);
 6038}
 6039
 6040template<typename BasicJsonType>
 6041inline void to_json(BasicJsonType& j, typename BasicJsonType::object_t&& obj)
 6042{
 6043    external_constructor<value_t::object>::construct(j, std::move(obj));
 6044}
 6045
 6046template <
 6047    typename BasicJsonType, typename T, std::size_t N,
 6048    enable_if_t < !std::is_constructible<typename BasicJsonType::string_t,
 6049                  const T(&)[N]>::value, // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 6050                  int > = 0 >
 6051inline void to_json(BasicJsonType& j, const T(&arr)[N]) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 6052{
 6053    external_constructor<value_t::array>::construct(j, arr);
 6054}
 6055
 6056template < typename BasicJsonType, typename T1, typename T2, enable_if_t < std::is_constructible<BasicJsonType, T1>::value&& std::is_constructible<BasicJsonType, T2>::value, int > = 0 >
 6057inline void to_json(BasicJsonType& j, const std::pair<T1, T2>& p)
 6058{
 6059    j = { p.first, p.second };
 6060}
 6061
 6062// for https://github.com/nlohmann/json/pull/1134
 6063template<typename BasicJsonType, typename T,
 6064         enable_if_t<std::is_same<T, iteration_proxy_value<typename BasicJsonType::iterator>>::value, int> = 0>
 6065inline void to_json(BasicJsonType& j, const T& b)
 6066{
 6067    j = { {b.key(), b.value()} };
 6068}
 6069
 6070template<typename BasicJsonType, typename Tuple, std::size_t... Idx>
 6071inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& t, index_sequence<Idx...> /*unused*/)
 6072{
 6073    j = { std::get<Idx>(t)... };
 6074}
 6075
 6076template<typename BasicJsonType, typename Tuple>
 6077inline void to_json_tuple_impl(BasicJsonType& j, const Tuple& /*unused*/, index_sequence<> /*unused*/)
 6078{
 6079    using array_t = typename BasicJsonType::array_t;
 6080    j = array_t();
 6081}
 6082
 6083template<typename BasicJsonType, typename T, enable_if_t<is_constructible_tuple<BasicJsonType, T>::value, int > = 0>
 6084inline void to_json(BasicJsonType& j, const T& t)
 6085{
 6086    to_json_tuple_impl(j, t, make_index_sequence<std::tuple_size<T>::value> {});
 6087}
 6088
 6089#if JSON_HAS_FILESYSTEM || JSON_HAS_EXPERIMENTAL_FILESYSTEM
 6090template<typename BasicJsonType>
 6091inline void to_json(BasicJsonType& j, const std_fs::path& p)
 6092{
 6093#ifdef JSON_HAS_CPP_20
 6094    const std::u8string s = p.u8string();
 6095    j = std::string(s.begin(), s.end());
 6096#else
 6097    j = p.u8string(); // returns std::string in C++17
 6098#endif
 6099}
 6100#endif
 6101
 6102struct to_json_fn
 6103{
 6104    template<typename BasicJsonType, typename T>
 6105    auto operator()(BasicJsonType& j, T&& val) const noexcept(noexcept(to_json(j, std::forward<T>(val))))
 6106    -> decltype(to_json(j, std::forward<T>(val)), void())
 6107    {
 6108        return to_json(j, std::forward<T>(val));
 6109    }
 6110};
 6111}  // namespace detail
 6112
 6113#ifndef JSON_HAS_CPP_17
 6114/// namespace to hold default `to_json` function
 6115/// to see why this is required:
 6116/// http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/n4381.html
 6117namespace // NOLINT(cert-dcl59-cpp,fuchsia-header-anon-namespaces,google-build-namespaces)
 6118{
 6119#endif
 6120JSON_INLINE_VARIABLE constexpr const auto& to_json = // NOLINT(misc-definitions-in-headers)
 6121    detail::static_const<detail::to_json_fn>::value;
 6122#ifndef JSON_HAS_CPP_17
 6123}  // namespace
 6124#endif
 6125
 6126NLOHMANN_JSON_NAMESPACE_END
 6127
 6128// #include <nlohmann/detail/meta/identity_tag.hpp>
 6129
 6130
 6131NLOHMANN_JSON_NAMESPACE_BEGIN
 6132
 6133/// @sa https://json.nlohmann.me/api/adl_serializer/
 6134template<typename ValueType, typename>
 6135struct adl_serializer
 6136{
 6137    /// @brief convert a JSON value to any value type
 6138    /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
 6139    template<typename BasicJsonType, typename TargetType = ValueType>
 6140    static auto from_json(BasicJsonType && j, TargetType& val) noexcept(
 6141        noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), val)))
 6142    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), val), void())
 6143    {
 6144        ::nlohmann::from_json(std::forward<BasicJsonType>(j), val);
 6145    }
 6146
 6147    /// @brief convert a JSON value to any value type
 6148    /// @sa https://json.nlohmann.me/api/adl_serializer/from_json/
 6149    template<typename BasicJsonType, typename TargetType = ValueType>
 6150    static auto from_json(BasicJsonType && j) noexcept(
 6151    noexcept(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {})))
 6152    -> decltype(::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {}))
 6153    {
 6154        return ::nlohmann::from_json(std::forward<BasicJsonType>(j), detail::identity_tag<TargetType> {});
 6155    }
 6156
 6157    /// @brief convert any value type to a JSON value
 6158    /// @sa https://json.nlohmann.me/api/adl_serializer/to_json/
 6159    template<typename BasicJsonType, typename TargetType = ValueType>
 6160    static auto to_json(BasicJsonType& j, TargetType && val) noexcept(
 6161        noexcept(::nlohmann::to_json(j, std::forward<TargetType>(val))))
 6162    -> decltype(::nlohmann::to_json(j, std::forward<TargetType>(val)), void())
 6163    {
 6164        ::nlohmann::to_json(j, std::forward<TargetType>(val));
 6165    }
 6166};
 6167
 6168NLOHMANN_JSON_NAMESPACE_END
 6169
 6170// #include <nlohmann/byte_container_with_subtype.hpp>
 6171//     __ _____ _____ _____
 6172//  __|  |   __|     |   | |  JSON for Modern C++
 6173// |  |  |__   |  |  | | | |  version 3.12.0
 6174// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 6175//
 6176// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 6177// SPDX-License-Identifier: MIT
 6178
 6179
 6180
 6181#include <cstdint> // uint8_t, uint64_t
 6182#include <tuple> // tie
 6183#include <utility> // move
 6184
 6185// #include <nlohmann/detail/abi_macros.hpp>
 6186
 6187
 6188NLOHMANN_JSON_NAMESPACE_BEGIN
 6189
 6190/// @brief an internal type for a backed binary type
 6191/// @sa https://json.nlohmann.me/api/byte_container_with_subtype/
 6192template<typename BinaryType>
 6193class byte_container_with_subtype : public BinaryType
 6194{
 6195  public:
 6196    using container_type = BinaryType;
 6197    using subtype_type = std::uint64_t;
 6198
 6199    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
 6200    byte_container_with_subtype() noexcept(noexcept(container_type()))
 6201        : container_type()
 6202    {}
 6203
 6204    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
 6205    byte_container_with_subtype(const container_type& b) noexcept(noexcept(container_type(b)))
 6206        : container_type(b)
 6207    {}
 6208
 6209    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
 6210    byte_container_with_subtype(container_type&& b) noexcept(noexcept(container_type(std::move(b))))
 6211        : container_type(std::move(b))
 6212    {}
 6213
 6214    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
 6215    byte_container_with_subtype(const container_type& b, subtype_type subtype_) noexcept(noexcept(container_type(b)))
 6216        : container_type(b)
 6217        , m_subtype(subtype_)
 6218        , m_has_subtype(true)
 6219    {}
 6220
 6221    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/byte_container_with_subtype/
 6222    byte_container_with_subtype(container_type&& b, subtype_type subtype_) noexcept(noexcept(container_type(std::move(b))))
 6223        : container_type(std::move(b))
 6224        , m_subtype(subtype_)
 6225        , m_has_subtype(true)
 6226    {}
 6227
 6228    bool operator==(const byte_container_with_subtype& rhs) const
 6229    {
 6230        return std::tie(static_cast<const BinaryType&>(*this), m_subtype, m_has_subtype) ==
 6231               std::tie(static_cast<const BinaryType&>(rhs), rhs.m_subtype, rhs.m_has_subtype);
 6232    }
 6233
 6234    bool operator!=(const byte_container_with_subtype& rhs) const
 6235    {
 6236        return !(rhs == *this);
 6237    }
 6238
 6239    /// @brief sets the binary subtype
 6240    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/set_subtype/
 6241    void set_subtype(subtype_type subtype_) noexcept
 6242    {
 6243        m_subtype = subtype_;
 6244        m_has_subtype = true;
 6245    }
 6246
 6247    /// @brief return the binary subtype
 6248    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/subtype/
 6249    constexpr subtype_type subtype() const noexcept
 6250    {
 6251        return m_has_subtype ? m_subtype : static_cast<subtype_type>(-1);
 6252    }
 6253
 6254    /// @brief return whether the value has a subtype
 6255    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/has_subtype/
 6256    constexpr bool has_subtype() const noexcept
 6257    {
 6258        return m_has_subtype;
 6259    }
 6260
 6261    /// @brief clears the binary subtype
 6262    /// @sa https://json.nlohmann.me/api/byte_container_with_subtype/clear_subtype/
 6263    void clear_subtype() noexcept
 6264    {
 6265        m_subtype = 0;
 6266        m_has_subtype = false;
 6267    }
 6268
 6269  private:
 6270    subtype_type m_subtype = 0;
 6271    bool m_has_subtype = false;
 6272};
 6273
 6274NLOHMANN_JSON_NAMESPACE_END
 6275
 6276// #include <nlohmann/detail/conversions/from_json.hpp>
 6277
 6278// #include <nlohmann/detail/conversions/to_json.hpp>
 6279
 6280// #include <nlohmann/detail/exceptions.hpp>
 6281
 6282// #include <nlohmann/detail/hash.hpp>
 6283//     __ _____ _____ _____
 6284//  __|  |   __|     |   | |  JSON for Modern C++
 6285// |  |  |__   |  |  | | | |  version 3.12.0
 6286// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 6287//
 6288// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 6289// SPDX-License-Identifier: MIT
 6290
 6291
 6292
 6293#include <cstdint> // uint8_t
 6294#include <cstddef> // size_t
 6295#include <functional> // hash
 6296
 6297// #include <nlohmann/detail/abi_macros.hpp>
 6298
 6299// #include <nlohmann/detail/value_t.hpp>
 6300
 6301
 6302NLOHMANN_JSON_NAMESPACE_BEGIN
 6303namespace detail
 6304{
 6305
 6306// boost::hash_combine
 6307inline std::size_t combine(std::size_t seed, std::size_t h) noexcept
 6308{
 6309    seed ^= h + 0x9e3779b9 + (seed << 6U) + (seed >> 2U);
 6310    return seed;
 6311}
 6312
 6313/*!
 6314@brief hash a JSON value
 6315
 6316The hash function tries to rely on std::hash where possible. Furthermore, the
 6317type of the JSON value is taken into account to have different hash values for
 6318null, 0, 0U, and false, etc.
 6319
 6320@tparam BasicJsonType basic_json specialization
 6321@param j JSON value to hash
 6322@return hash value of j
 6323*/
 6324template<typename BasicJsonType>
 6325std::size_t hash(const BasicJsonType& j)
 6326{
 6327    using string_t = typename BasicJsonType::string_t;
 6328    using number_integer_t = typename BasicJsonType::number_integer_t;
 6329    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 6330    using number_float_t = typename BasicJsonType::number_float_t;
 6331
 6332    const auto type = static_cast<std::size_t>(j.type());
 6333    switch (j.type())
 6334    {
 6335        case BasicJsonType::value_t::null:
 6336        case BasicJsonType::value_t::discarded:
 6337        {
 6338            return combine(type, 0);
 6339        }
 6340
 6341        case BasicJsonType::value_t::object:
 6342        {
 6343            auto seed = combine(type, j.size());
 6344            for (const auto& element : j.items())
 6345            {
 6346                const auto h = std::hash<string_t> {}(element.key());
 6347                seed = combine(seed, h);
 6348                seed = combine(seed, hash(element.value()));
 6349            }
 6350            return seed;
 6351        }
 6352
 6353        case BasicJsonType::value_t::array:
 6354        {
 6355            auto seed = combine(type, j.size());
 6356            for (const auto& element : j)
 6357            {
 6358                seed = combine(seed, hash(element));
 6359            }
 6360            return seed;
 6361        }
 6362
 6363        case BasicJsonType::value_t::string:
 6364        {
 6365            const auto h = std::hash<string_t> {}(j.template get_ref<const string_t&>());
 6366            return combine(type, h);
 6367        }
 6368
 6369        case BasicJsonType::value_t::boolean:
 6370        {
 6371            const auto h = std::hash<bool> {}(j.template get<bool>());
 6372            return combine(type, h);
 6373        }
 6374
 6375        case BasicJsonType::value_t::number_integer:
 6376        {
 6377            const auto h = std::hash<number_integer_t> {}(j.template get<number_integer_t>());
 6378            return combine(type, h);
 6379        }
 6380
 6381        case BasicJsonType::value_t::number_unsigned:
 6382        {
 6383            const auto h = std::hash<number_unsigned_t> {}(j.template get<number_unsigned_t>());
 6384            return combine(type, h);
 6385        }
 6386
 6387        case BasicJsonType::value_t::number_float:
 6388        {
 6389            const auto h = std::hash<number_float_t> {}(j.template get<number_float_t>());
 6390            return combine(type, h);
 6391        }
 6392
 6393        case BasicJsonType::value_t::binary:
 6394        {
 6395            auto seed = combine(type, j.get_binary().size());
 6396            const auto h = std::hash<bool> {}(j.get_binary().has_subtype());
 6397            seed = combine(seed, h);
 6398            seed = combine(seed, static_cast<std::size_t>(j.get_binary().subtype()));
 6399            for (const auto byte : j.get_binary())
 6400            {
 6401                seed = combine(seed, std::hash<std::uint8_t> {}(byte));
 6402            }
 6403            return seed;
 6404        }
 6405
 6406        default:                   // LCOV_EXCL_LINE
 6407            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 6408            return 0;              // LCOV_EXCL_LINE
 6409    }
 6410}
 6411
 6412}  // namespace detail
 6413NLOHMANN_JSON_NAMESPACE_END
 6414
 6415// #include <nlohmann/detail/input/binary_reader.hpp>
 6416//     __ _____ _____ _____
 6417//  __|  |   __|     |   | |  JSON for Modern C++
 6418// |  |  |__   |  |  | | | |  version 3.12.0
 6419// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 6420//
 6421// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 6422// SPDX-License-Identifier: MIT
 6423
 6424
 6425
 6426#include <algorithm> // generate_n
 6427#include <array> // array
 6428#include <cmath> // ldexp
 6429#include <cstddef> // size_t
 6430#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
 6431#include <cstdio> // snprintf
 6432#include <cstring> // memcpy
 6433#include <iterator> // back_inserter
 6434#include <limits> // numeric_limits
 6435#include <string> // char_traits, string
 6436#include <utility> // make_pair, move
 6437#include <vector> // vector
 6438#ifdef __cpp_lib_byteswap
 6439    #include <bit>  //byteswap
 6440#endif
 6441
 6442// #include <nlohmann/detail/exceptions.hpp>
 6443
 6444// #include <nlohmann/detail/input/input_adapters.hpp>
 6445//     __ _____ _____ _____
 6446//  __|  |   __|     |   | |  JSON for Modern C++
 6447// |  |  |__   |  |  | | | |  version 3.12.0
 6448// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 6449//
 6450// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 6451// SPDX-License-Identifier: MIT
 6452
 6453
 6454
 6455#include <array> // array
 6456#include <cstddef> // size_t
 6457#include <cstring> // strlen
 6458#include <iterator> // begin, end, iterator_traits, random_access_iterator_tag, distance, next
 6459#include <memory> // shared_ptr, make_shared, addressof
 6460#include <numeric> // accumulate
 6461#include <string> // string, char_traits
 6462#include <type_traits> // enable_if, is_base_of, is_pointer, is_integral, remove_pointer
 6463#include <utility> // pair, declval
 6464
 6465#ifndef JSON_NO_IO
 6466    #include <cstdio>   // FILE *
 6467    #include <istream>  // istream
 6468#endif                  // JSON_NO_IO
 6469
 6470// #include <nlohmann/detail/exceptions.hpp>
 6471
 6472// #include <nlohmann/detail/iterators/iterator_traits.hpp>
 6473
 6474// #include <nlohmann/detail/macro_scope.hpp>
 6475
 6476// #include <nlohmann/detail/meta/type_traits.hpp>
 6477
 6478
 6479NLOHMANN_JSON_NAMESPACE_BEGIN
 6480namespace detail
 6481{
 6482
 6483/// the supported input formats
 6484enum class input_format_t { json, cbor, msgpack, ubjson, bson, bjdata };
 6485
 6486////////////////////
 6487// input adapters //
 6488////////////////////
 6489
 6490#ifndef JSON_NO_IO
 6491/*!
 6492Input adapter for stdio file access. This adapter read only 1 byte and do not use any
 6493 buffer. This adapter is a very low level adapter.
 6494*/
 6495class file_input_adapter
 6496{
 6497  public:
 6498    using char_type = char;
 6499
 6500    JSON_HEDLEY_NON_NULL(2)
 6501    explicit file_input_adapter(std::FILE* f) noexcept
 6502        : m_file(f)
 6503    {
 6504        JSON_ASSERT(m_file != nullptr);
 6505    }
 6506
 6507    // make class move-only
 6508    file_input_adapter(const file_input_adapter&) = delete;
 6509    file_input_adapter(file_input_adapter&&) noexcept = default;
 6510    file_input_adapter& operator=(const file_input_adapter&) = delete;
 6511    file_input_adapter& operator=(file_input_adapter&&) = delete;
 6512    ~file_input_adapter() = default;
 6513
 6514    std::char_traits<char>::int_type get_character() noexcept
 6515    {
 6516        return std::fgetc(m_file);
 6517    }
 6518
 6519    // returns the number of characters successfully read
 6520    template<class T>
 6521    std::size_t get_elements(T* dest, std::size_t count = 1)
 6522    {
 6523        return fread(dest, 1, sizeof(T) * count, m_file);
 6524    }
 6525
 6526  private:
 6527    /// the file pointer to read from
 6528    std::FILE* m_file;
 6529};
 6530
 6531/*!
 6532Input adapter for a (caching) istream. Ignores a UFT Byte Order Mark at
 6533beginning of input. Does not support changing the underlying std::streambuf
 6534in mid-input. Maintains underlying std::istream and std::streambuf to support
 6535subsequent use of standard std::istream operations to process any input
 6536characters following those used in parsing the JSON input.  Clears the
 6537std::istream flags; any input errors (e.g., EOF) will be detected by the first
 6538subsequent call for input from the std::istream.
 6539*/
 6540class input_stream_adapter
 6541{
 6542  public:
 6543    using char_type = char;
 6544
 6545    ~input_stream_adapter()
 6546    {
 6547        // clear stream flags; we use underlying streambuf I/O, do not
 6548        // maintain ifstream flags, except eof
 6549        if (is != nullptr)
 6550        {
 6551            is->clear(is->rdstate() & std::ios::eofbit);
 6552        }
 6553    }
 6554
 6555    explicit input_stream_adapter(std::istream& i)
 6556        : is(&i), sb(i.rdbuf())
 6557    {}
 6558
 6559    // delete because of pointer members
 6560    input_stream_adapter(const input_stream_adapter&) = delete;
 6561    input_stream_adapter& operator=(input_stream_adapter&) = delete;
 6562    input_stream_adapter& operator=(input_stream_adapter&&) = delete;
 6563
 6564    input_stream_adapter(input_stream_adapter&& rhs) noexcept
 6565        : is(rhs.is), sb(rhs.sb)
 6566    {
 6567        rhs.is = nullptr;
 6568        rhs.sb = nullptr;
 6569    }
 6570
 6571    // std::istream/std::streambuf use std::char_traits<char>::to_int_type, to
 6572    // ensure that std::char_traits<char>::eof() and the character 0xFF do not
 6573    // end up as the same value, e.g. 0xFFFFFFFF.
 6574    std::char_traits<char>::int_type get_character()
 6575    {
 6576        auto res = sb->sbumpc();
 6577        // set eof manually, as we don't use the istream interface.
 6578        if (JSON_HEDLEY_UNLIKELY(res == std::char_traits<char>::eof()))
 6579        {
 6580            is->clear(is->rdstate() | std::ios::eofbit);
 6581        }
 6582        return res;
 6583    }
 6584
 6585    template<class T>
 6586    std::size_t get_elements(T* dest, std::size_t count = 1)
 6587    {
 6588        auto res = static_cast<std::size_t>(sb->sgetn(reinterpret_cast<char*>(dest), static_cast<std::streamsize>(count * sizeof(T))));
 6589        if (JSON_HEDLEY_UNLIKELY(res < count * sizeof(T)))
 6590        {
 6591            is->clear(is->rdstate() | std::ios::eofbit);
 6592        }
 6593        return res;
 6594    }
 6595
 6596  private:
 6597    /// the associated input stream
 6598    std::istream* is = nullptr;
 6599    std::streambuf* sb = nullptr;
 6600};
 6601#endif  // JSON_NO_IO
 6602
 6603// General-purpose iterator-based adapter. It might not be as fast as
 6604// theoretically possible for some containers, but it is extremely versatile.
 6605template<typename IteratorType>
 6606class iterator_input_adapter
 6607{
 6608  public:
 6609    using char_type = typename std::iterator_traits<IteratorType>::value_type;
 6610
 6611    iterator_input_adapter(IteratorType first, IteratorType last)
 6612        : current(std::move(first)), end(std::move(last))
 6613    {}
 6614
 6615    typename char_traits<char_type>::int_type get_character()
 6616    {
 6617        if (JSON_HEDLEY_LIKELY(current != end))
 6618        {
 6619            auto result = char_traits<char_type>::to_int_type(*current);
 6620            std::advance(current, 1);
 6621            return result;
 6622        }
 6623
 6624        return char_traits<char_type>::eof();
 6625    }
 6626
 6627    // for general iterators, we cannot really do something better than falling back to processing the range one-by-one
 6628    template<class T>
 6629    std::size_t get_elements(T* dest, std::size_t count = 1)
 6630    {
 6631        auto* ptr = reinterpret_cast<char*>(dest);
 6632        for (std::size_t read_index = 0; read_index < count * sizeof(T); ++read_index)
 6633        {
 6634            if (JSON_HEDLEY_LIKELY(current != end))
 6635            {
 6636                ptr[read_index] = static_cast<char>(*current);
 6637                std::advance(current, 1);
 6638            }
 6639            else
 6640            {
 6641                return read_index;
 6642            }
 6643        }
 6644        return count * sizeof(T);
 6645    }
 6646
 6647  private:
 6648    IteratorType current;
 6649    IteratorType end;
 6650
 6651    template<typename BaseInputAdapter, size_t T>
 6652    friend struct wide_string_input_helper;
 6653
 6654    bool empty() const
 6655    {
 6656        return current == end;
 6657    }
 6658};
 6659
 6660template<typename BaseInputAdapter, size_t T>
 6661struct wide_string_input_helper;
 6662
 6663template<typename BaseInputAdapter>
 6664struct wide_string_input_helper<BaseInputAdapter, 4>
 6665{
 6666    // UTF-32
 6667    static void fill_buffer(BaseInputAdapter& input,
 6668                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
 6669                            size_t& utf8_bytes_index,
 6670                            size_t& utf8_bytes_filled)
 6671    {
 6672        utf8_bytes_index = 0;
 6673
 6674        if (JSON_HEDLEY_UNLIKELY(input.empty()))
 6675        {
 6676            utf8_bytes[0] = std::char_traits<char>::eof();
 6677            utf8_bytes_filled = 1;
 6678        }
 6679        else
 6680        {
 6681            // get the current character
 6682            const auto wc = input.get_character();
 6683
 6684            // UTF-32 to UTF-8 encoding
 6685            if (wc < 0x80)
 6686            {
 6687                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
 6688                utf8_bytes_filled = 1;
 6689            }
 6690            else if (wc <= 0x7FF)
 6691            {
 6692                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u) & 0x1Fu));
 6693                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 6694                utf8_bytes_filled = 2;
 6695            }
 6696            else if (wc <= 0xFFFF)
 6697            {
 6698                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u) & 0x0Fu));
 6699                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
 6700                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 6701                utf8_bytes_filled = 3;
 6702            }
 6703            else if (wc <= 0x10FFFF)
 6704            {
 6705                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | ((static_cast<unsigned int>(wc) >> 18u) & 0x07u));
 6706                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 12u) & 0x3Fu));
 6707                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
 6708                utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 6709                utf8_bytes_filled = 4;
 6710            }
 6711            else
 6712            {
 6713                // unknown character
 6714                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
 6715                utf8_bytes_filled = 1;
 6716            }
 6717        }
 6718    }
 6719};
 6720
 6721template<typename BaseInputAdapter>
 6722struct wide_string_input_helper<BaseInputAdapter, 2>
 6723{
 6724    // UTF-16
 6725    static void fill_buffer(BaseInputAdapter& input,
 6726                            std::array<std::char_traits<char>::int_type, 4>& utf8_bytes,
 6727                            size_t& utf8_bytes_index,
 6728                            size_t& utf8_bytes_filled)
 6729    {
 6730        utf8_bytes_index = 0;
 6731
 6732        if (JSON_HEDLEY_UNLIKELY(input.empty()))
 6733        {
 6734            utf8_bytes[0] = std::char_traits<char>::eof();
 6735            utf8_bytes_filled = 1;
 6736        }
 6737        else
 6738        {
 6739            // get the current character
 6740            const auto wc = input.get_character();
 6741
 6742            // UTF-16 to UTF-8 encoding
 6743            if (wc < 0x80)
 6744            {
 6745                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
 6746                utf8_bytes_filled = 1;
 6747            }
 6748            else if (wc <= 0x7FF)
 6749            {
 6750                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xC0u | ((static_cast<unsigned int>(wc) >> 6u)));
 6751                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 6752                utf8_bytes_filled = 2;
 6753            }
 6754            else if (0xD800 > wc || wc >= 0xE000)
 6755            {
 6756                utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xE0u | ((static_cast<unsigned int>(wc) >> 12u)));
 6757                utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((static_cast<unsigned int>(wc) >> 6u) & 0x3Fu));
 6758                utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | (static_cast<unsigned int>(wc) & 0x3Fu));
 6759                utf8_bytes_filled = 3;
 6760            }
 6761            else
 6762            {
 6763                if (JSON_HEDLEY_UNLIKELY(!input.empty()))
 6764                {
 6765                    const auto wc2 = static_cast<unsigned int>(input.get_character());
 6766                    const auto charcode = 0x10000u + (((static_cast<unsigned int>(wc) & 0x3FFu) << 10u) | (wc2 & 0x3FFu));
 6767                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(0xF0u | (charcode >> 18u));
 6768                    utf8_bytes[1] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 12u) & 0x3Fu));
 6769                    utf8_bytes[2] = static_cast<std::char_traits<char>::int_type>(0x80u | ((charcode >> 6u) & 0x3Fu));
 6770                    utf8_bytes[3] = static_cast<std::char_traits<char>::int_type>(0x80u | (charcode & 0x3Fu));
 6771                    utf8_bytes_filled = 4;
 6772                }
 6773                else
 6774                {
 6775                    utf8_bytes[0] = static_cast<std::char_traits<char>::int_type>(wc);
 6776                    utf8_bytes_filled = 1;
 6777                }
 6778            }
 6779        }
 6780    }
 6781};
 6782
 6783// Wraps another input adapter to convert wide character types into individual bytes.
 6784template<typename BaseInputAdapter, typename WideCharType>
 6785class wide_string_input_adapter
 6786{
 6787  public:
 6788    using char_type = char;
 6789
 6790    wide_string_input_adapter(BaseInputAdapter base)
 6791        : base_adapter(base) {}
 6792
 6793    typename std::char_traits<char>::int_type get_character() noexcept
 6794    {
 6795        // check if buffer needs to be filled
 6796        if (utf8_bytes_index == utf8_bytes_filled)
 6797        {
 6798            fill_buffer<sizeof(WideCharType)>();
 6799
 6800            JSON_ASSERT(utf8_bytes_filled > 0);
 6801            JSON_ASSERT(utf8_bytes_index == 0);
 6802        }
 6803
 6804        // use buffer
 6805        JSON_ASSERT(utf8_bytes_filled > 0);
 6806        JSON_ASSERT(utf8_bytes_index < utf8_bytes_filled);
 6807        return utf8_bytes[utf8_bytes_index++];
 6808    }
 6809
 6810    // parsing binary with wchar doesn't make sense, but since the parsing mode can be runtime, we need something here
 6811    template<class T>
 6812    std::size_t get_elements(T* /*dest*/, std::size_t /*count*/ = 1)
 6813    {
 6814        JSON_THROW(parse_error::create(112, 1, "wide string type cannot be interpreted as binary data", nullptr));
 6815    }
 6816
 6817  private:
 6818    BaseInputAdapter base_adapter;
 6819
 6820    template<size_t T>
 6821    void fill_buffer()
 6822    {
 6823        wide_string_input_helper<BaseInputAdapter, T>::fill_buffer(base_adapter, utf8_bytes, utf8_bytes_index, utf8_bytes_filled);
 6824    }
 6825
 6826    /// a buffer for UTF-8 bytes
 6827    std::array<std::char_traits<char>::int_type, 4> utf8_bytes = {{0, 0, 0, 0}};
 6828
 6829    /// index to the utf8_codes array for the next valid byte
 6830    std::size_t utf8_bytes_index = 0;
 6831    /// number of valid bytes in the utf8_codes array
 6832    std::size_t utf8_bytes_filled = 0;
 6833};
 6834
 6835template<typename IteratorType, typename Enable = void>
 6836struct iterator_input_adapter_factory
 6837{
 6838    using iterator_type = IteratorType;
 6839    using char_type = typename std::iterator_traits<iterator_type>::value_type;
 6840    using adapter_type = iterator_input_adapter<iterator_type>;
 6841
 6842    static adapter_type create(IteratorType first, IteratorType last)
 6843    {
 6844        return adapter_type(std::move(first), std::move(last));
 6845    }
 6846};
 6847
 6848template<typename T>
 6849struct is_iterator_of_multibyte
 6850{
 6851    using value_type = typename std::iterator_traits<T>::value_type;
 6852    enum
 6853    {
 6854        value = sizeof(value_type) > 1
 6855    };
 6856};
 6857
 6858template<typename IteratorType>
 6859struct iterator_input_adapter_factory<IteratorType, enable_if_t<is_iterator_of_multibyte<IteratorType>::value>>
 6860{
 6861    using iterator_type = IteratorType;
 6862    using char_type = typename std::iterator_traits<iterator_type>::value_type;
 6863    using base_adapter_type = iterator_input_adapter<iterator_type>;
 6864    using adapter_type = wide_string_input_adapter<base_adapter_type, char_type>;
 6865
 6866    static adapter_type create(IteratorType first, IteratorType last)
 6867    {
 6868        return adapter_type(base_adapter_type(std::move(first), std::move(last)));
 6869    }
 6870};
 6871
 6872// General purpose iterator-based input
 6873template<typename IteratorType>
 6874typename iterator_input_adapter_factory<IteratorType>::adapter_type input_adapter(IteratorType first, IteratorType last)
 6875{
 6876    using factory_type = iterator_input_adapter_factory<IteratorType>;
 6877    return factory_type::create(first, last);
 6878}
 6879
 6880// Convenience shorthand from container to iterator
 6881// Enables ADL on begin(container) and end(container)
 6882// Encloses the using declarations in namespace for not to leak them to outside scope
 6883
 6884namespace container_input_adapter_factory_impl
 6885{
 6886
 6887using std::begin;
 6888using std::end;
 6889
 6890template<typename ContainerType, typename Enable = void>
 6891struct container_input_adapter_factory {};
 6892
 6893template<typename ContainerType>
 6894struct container_input_adapter_factory< ContainerType,
 6895       void_t<decltype(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>()))>>
 6896       {
 6897           using adapter_type = decltype(input_adapter(begin(std::declval<ContainerType>()), end(std::declval<ContainerType>())));
 6898
 6899           static adapter_type create(const ContainerType& container)
 6900{
 6901    return input_adapter(begin(container), end(container));
 6902}
 6903       };
 6904
 6905}  // namespace container_input_adapter_factory_impl
 6906
 6907template<typename ContainerType>
 6908typename container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::adapter_type input_adapter(const ContainerType& container)
 6909{
 6910    return container_input_adapter_factory_impl::container_input_adapter_factory<ContainerType>::create(container);
 6911}
 6912
 6913// specialization for std::string
 6914using string_input_adapter_type = decltype(input_adapter(std::declval<std::string>()));
 6915
 6916#ifndef JSON_NO_IO
 6917// Special cases with fast paths
 6918inline file_input_adapter input_adapter(std::FILE* file)
 6919{
 6920    if (file == nullptr)
 6921    {
 6922        JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
 6923    }
 6924    return file_input_adapter(file);
 6925}
 6926
 6927inline input_stream_adapter input_adapter(std::istream& stream)
 6928{
 6929    return input_stream_adapter(stream);
 6930}
 6931
 6932inline input_stream_adapter input_adapter(std::istream&& stream)
 6933{
 6934    return input_stream_adapter(stream);
 6935}
 6936#endif  // JSON_NO_IO
 6937
 6938using contiguous_bytes_input_adapter = decltype(input_adapter(std::declval<const char*>(), std::declval<const char*>()));
 6939
 6940// Null-delimited strings, and the like.
 6941template < typename CharT,
 6942           typename std::enable_if <
 6943               std::is_pointer<CharT>::value&&
 6944               !std::is_array<CharT>::value&&
 6945               std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
 6946               sizeof(typename std::remove_pointer<CharT>::type) == 1,
 6947               int >::type = 0 >
 6948contiguous_bytes_input_adapter input_adapter(CharT b)
 6949{
 6950    if (b == nullptr)
 6951    {
 6952        JSON_THROW(parse_error::create(101, 0, "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
 6953    }
 6954    auto length = std::strlen(reinterpret_cast<const char*>(b));
 6955    const auto* ptr = reinterpret_cast<const char*>(b);
 6956    return input_adapter(ptr, ptr + length); // cppcheck-suppress[nullPointerArithmeticRedundantCheck]
 6957}
 6958
 6959template<typename T, std::size_t N>
 6960auto input_adapter(T (&array)[N]) -> decltype(input_adapter(array, array + N)) // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
 6961{
 6962    return input_adapter(array, array + N);
 6963}
 6964
 6965// This class only handles inputs of input_buffer_adapter type.
 6966// It's required so that expressions like {ptr, len} can be implicitly cast
 6967// to the correct adapter.
 6968class span_input_adapter
 6969{
 6970  public:
 6971    template < typename CharT,
 6972               typename std::enable_if <
 6973                   std::is_pointer<CharT>::value&&
 6974                   std::is_integral<typename std::remove_pointer<CharT>::type>::value&&
 6975                   sizeof(typename std::remove_pointer<CharT>::type) == 1,
 6976                   int >::type = 0 >
 6977    span_input_adapter(CharT b, std::size_t l)
 6978        : ia(reinterpret_cast<const char*>(b), reinterpret_cast<const char*>(b) + l) {}
 6979
 6980    template<class IteratorType,
 6981             typename std::enable_if<
 6982                 std::is_same<typename iterator_traits<IteratorType>::iterator_category, std::random_access_iterator_tag>::value,
 6983                 int>::type = 0>
 6984    span_input_adapter(IteratorType first, IteratorType last)
 6985        : ia(input_adapter(first, last)) {}
 6986
 6987    contiguous_bytes_input_adapter&& get()
 6988    {
 6989        return std::move(ia); // NOLINT(hicpp-move-const-arg,performance-move-const-arg)
 6990    }
 6991
 6992  private:
 6993    contiguous_bytes_input_adapter ia;
 6994};
 6995
 6996}  // namespace detail
 6997NLOHMANN_JSON_NAMESPACE_END
 6998
 6999// #include <nlohmann/detail/input/json_sax.hpp>
 7000//     __ _____ _____ _____
 7001//  __|  |   __|     |   | |  JSON for Modern C++
 7002// |  |  |__   |  |  | | | |  version 3.12.0
 7003// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 7004//
 7005// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 7006// SPDX-License-Identifier: MIT
 7007
 7008
 7009
 7010#include <cstddef>
 7011#include <string> // string
 7012#include <type_traits> // enable_if_t
 7013#include <utility> // move
 7014#include <vector> // vector
 7015
 7016// #include <nlohmann/detail/exceptions.hpp>
 7017
 7018// #include <nlohmann/detail/input/lexer.hpp>
 7019//     __ _____ _____ _____
 7020//  __|  |   __|     |   | |  JSON for Modern C++
 7021// |  |  |__   |  |  | | | |  version 3.12.0
 7022// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 7023//
 7024// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 7025// SPDX-License-Identifier: MIT
 7026
 7027
 7028
 7029#include <array> // array
 7030#include <clocale> // localeconv
 7031#include <cstddef> // size_t
 7032#include <cstdio> // snprintf
 7033#include <cstdlib> // strtof, strtod, strtold, strtoll, strtoull
 7034#include <initializer_list> // initializer_list
 7035#include <string> // char_traits, string
 7036#include <utility> // move
 7037#include <vector> // vector
 7038
 7039// #include <nlohmann/detail/input/input_adapters.hpp>
 7040
 7041// #include <nlohmann/detail/input/position_t.hpp>
 7042
 7043// #include <nlohmann/detail/macro_scope.hpp>
 7044
 7045// #include <nlohmann/detail/meta/type_traits.hpp>
 7046
 7047
 7048NLOHMANN_JSON_NAMESPACE_BEGIN
 7049namespace detail
 7050{
 7051
 7052///////////
 7053// lexer //
 7054///////////
 7055
 7056template<typename BasicJsonType>
 7057class lexer_base
 7058{
 7059  public:
 7060    /// token types for the parser
 7061    enum class token_type
 7062    {
 7063        uninitialized,    ///< indicating the scanner is uninitialized
 7064        literal_true,     ///< the `true` literal
 7065        literal_false,    ///< the `false` literal
 7066        literal_null,     ///< the `null` literal
 7067        value_string,     ///< a string -- use get_string() for actual value
 7068        value_unsigned,   ///< an unsigned integer -- use get_number_unsigned() for actual value
 7069        value_integer,    ///< a signed integer -- use get_number_integer() for actual value
 7070        value_float,      ///< an floating point number -- use get_number_float() for actual value
 7071        begin_array,      ///< the character for array begin `[`
 7072        begin_object,     ///< the character for object begin `{`
 7073        end_array,        ///< the character for array end `]`
 7074        end_object,       ///< the character for object end `}`
 7075        name_separator,   ///< the name separator `:`
 7076        value_separator,  ///< the value separator `,`
 7077        parse_error,      ///< indicating a parse error
 7078        end_of_input,     ///< indicating the end of the input buffer
 7079        literal_or_value  ///< a literal or the begin of a value (only for diagnostics)
 7080    };
 7081
 7082    /// return name of values of type token_type (only used for errors)
 7083    JSON_HEDLEY_RETURNS_NON_NULL
 7084    JSON_HEDLEY_CONST
 7085    static const char* token_type_name(const token_type t) noexcept
 7086    {
 7087        switch (t)
 7088        {
 7089            case token_type::uninitialized:
 7090                return "<uninitialized>";
 7091            case token_type::literal_true:
 7092                return "true literal";
 7093            case token_type::literal_false:
 7094                return "false literal";
 7095            case token_type::literal_null:
 7096                return "null literal";
 7097            case token_type::value_string:
 7098                return "string literal";
 7099            case token_type::value_unsigned:
 7100            case token_type::value_integer:
 7101            case token_type::value_float:
 7102                return "number literal";
 7103            case token_type::begin_array:
 7104                return "'['";
 7105            case token_type::begin_object:
 7106                return "'{'";
 7107            case token_type::end_array:
 7108                return "']'";
 7109            case token_type::end_object:
 7110                return "'}'";
 7111            case token_type::name_separator:
 7112                return "':'";
 7113            case token_type::value_separator:
 7114                return "','";
 7115            case token_type::parse_error:
 7116                return "<parse error>";
 7117            case token_type::end_of_input:
 7118                return "end of input";
 7119            case token_type::literal_or_value:
 7120                return "'[', '{', or a literal";
 7121            // LCOV_EXCL_START
 7122            default: // catch non-enum values
 7123                return "unknown token";
 7124                // LCOV_EXCL_STOP
 7125        }
 7126    }
 7127};
 7128/*!
 7129@brief lexical analysis
 7130
 7131This class organizes the lexical analysis during JSON deserialization.
 7132*/
 7133template<typename BasicJsonType, typename InputAdapterType>
 7134class lexer : public lexer_base<BasicJsonType>
 7135{
 7136    using number_integer_t = typename BasicJsonType::number_integer_t;
 7137    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 7138    using number_float_t = typename BasicJsonType::number_float_t;
 7139    using string_t = typename BasicJsonType::string_t;
 7140    using char_type = typename InputAdapterType::char_type;
 7141    using char_int_type = typename char_traits<char_type>::int_type;
 7142
 7143  public:
 7144    using token_type = typename lexer_base<BasicJsonType>::token_type;
 7145
 7146    explicit lexer(InputAdapterType&& adapter, bool ignore_comments_ = false) noexcept
 7147        : ia(std::move(adapter))
 7148        , ignore_comments(ignore_comments_)
 7149        , decimal_point_char(static_cast<char_int_type>(get_decimal_point()))
 7150    {}
 7151
 7152    // delete because of pointer members
 7153    lexer(const lexer&) = delete;
 7154    lexer(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 7155    lexer& operator=(lexer&) = delete;
 7156    lexer& operator=(lexer&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 7157    ~lexer() = default;
 7158
 7159  private:
 7160    /////////////////////
 7161    // locales
 7162    /////////////////////
 7163
 7164    /// return the locale-dependent decimal point
 7165    JSON_HEDLEY_PURE
 7166    static char get_decimal_point() noexcept
 7167    {
 7168        const auto* loc = localeconv();
 7169        JSON_ASSERT(loc != nullptr);
 7170        return (loc->decimal_point == nullptr) ? '.' : *(loc->decimal_point);
 7171    }
 7172
 7173    /////////////////////
 7174    // scan functions
 7175    /////////////////////
 7176
 7177    /*!
 7178    @brief get codepoint from 4 hex characters following `\u`
 7179
 7180    For input "\u c1 c2 c3 c4" the codepoint is:
 7181      (c1 * 0x1000) + (c2 * 0x0100) + (c3 * 0x0010) + c4
 7182    = (c1 << 12) + (c2 << 8) + (c3 << 4) + (c4 << 0)
 7183
 7184    Furthermore, the possible characters '0'..'9', 'A'..'F', and 'a'..'f'
 7185    must be converted to the integers 0x0..0x9, 0xA..0xF, 0xA..0xF, resp. The
 7186    conversion is done by subtracting the offset (0x30, 0x37, and 0x57)
 7187    between the ASCII value of the character and the desired integer value.
 7188
 7189    @return codepoint (0x0000..0xFFFF) or -1 in case of an error (e.g. EOF or
 7190            non-hex character)
 7191    */
 7192    int get_codepoint()
 7193    {
 7194        // this function only makes sense after reading `\u`
 7195        JSON_ASSERT(current == 'u');
 7196        int codepoint = 0;
 7197
 7198        const auto factors = { 12u, 8u, 4u, 0u };
 7199        for (const auto factor : factors)
 7200        {
 7201            get();
 7202
 7203            if (current >= '0' && current <= '9')
 7204            {
 7205                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x30u) << factor);
 7206            }
 7207            else if (current >= 'A' && current <= 'F')
 7208            {
 7209                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x37u) << factor);
 7210            }
 7211            else if (current >= 'a' && current <= 'f')
 7212            {
 7213                codepoint += static_cast<int>((static_cast<unsigned int>(current) - 0x57u) << factor);
 7214            }
 7215            else
 7216            {
 7217                return -1;
 7218            }
 7219        }
 7220
 7221        JSON_ASSERT(0x0000 <= codepoint && codepoint <= 0xFFFF);
 7222        return codepoint;
 7223    }
 7224
 7225    /*!
 7226    @brief check if the next byte(s) are inside a given range
 7227
 7228    Adds the current byte and, for each passed range, reads a new byte and
 7229    checks if it is inside the range. If a violation was detected, set up an
 7230    error message and return false. Otherwise, return true.
 7231
 7232    @param[in] ranges  list of integers; interpreted as list of pairs of
 7233                       inclusive lower and upper bound, respectively
 7234
 7235    @pre The passed list @a ranges must have 2, 4, or 6 elements; that is,
 7236         1, 2, or 3 pairs. This precondition is enforced by an assertion.
 7237
 7238    @return true if and only if no range violation was detected
 7239    */
 7240    bool next_byte_in_range(std::initializer_list<char_int_type> ranges)
 7241    {
 7242        JSON_ASSERT(ranges.size() == 2 || ranges.size() == 4 || ranges.size() == 6);
 7243        add(current);
 7244
 7245        for (auto range = ranges.begin(); range != ranges.end(); ++range)
 7246        {
 7247            get();
 7248            if (JSON_HEDLEY_LIKELY(*range <= current && current <= *(++range))) // NOLINT(bugprone-inc-dec-in-conditions)
 7249            {
 7250                add(current);
 7251            }
 7252            else
 7253            {
 7254                error_message = "invalid string: ill-formed UTF-8 byte";
 7255                return false;
 7256            }
 7257        }
 7258
 7259        return true;
 7260    }
 7261
 7262    /*!
 7263    @brief scan a string literal
 7264
 7265    This function scans a string according to Sect. 7 of RFC 8259. While
 7266    scanning, bytes are escaped and copied into buffer token_buffer. Then the
 7267    function returns successfully, token_buffer is *not* null-terminated (as it
 7268    may contain \0 bytes), and token_buffer.size() is the number of bytes in the
 7269    string.
 7270
 7271    @return token_type::value_string if string could be successfully scanned,
 7272            token_type::parse_error otherwise
 7273
 7274    @note In case of errors, variable error_message contains a textual
 7275          description.
 7276    */
 7277    token_type scan_string()
 7278    {
 7279        // reset token_buffer (ignore opening quote)
 7280        reset();
 7281
 7282        // we entered the function by reading an open quote
 7283        JSON_ASSERT(current == '\"');
 7284
 7285        while (true)
 7286        {
 7287            // get next character
 7288            switch (get())
 7289            {
 7290                // end of file while parsing string
 7291                case char_traits<char_type>::eof():
 7292                {
 7293                    error_message = "invalid string: missing closing quote";
 7294                    return token_type::parse_error;
 7295                }
 7296
 7297                // closing quote
 7298                case '\"':
 7299                {
 7300                    return token_type::value_string;
 7301                }
 7302
 7303                // escapes
 7304                case '\\':
 7305                {
 7306                    switch (get())
 7307                    {
 7308                        // quotation mark
 7309                        case '\"':
 7310                            add('\"');
 7311                            break;
 7312                        // reverse solidus
 7313                        case '\\':
 7314                            add('\\');
 7315                            break;
 7316                        // solidus
 7317                        case '/':
 7318                            add('/');
 7319                            break;
 7320                        // backspace
 7321                        case 'b':
 7322                            add('\b');
 7323                            break;
 7324                        // form feed
 7325                        case 'f':
 7326                            add('\f');
 7327                            break;
 7328                        // line feed
 7329                        case 'n':
 7330                            add('\n');
 7331                            break;
 7332                        // carriage return
 7333                        case 'r':
 7334                            add('\r');
 7335                            break;
 7336                        // tab
 7337                        case 't':
 7338                            add('\t');
 7339                            break;
 7340
 7341                        // unicode escapes
 7342                        case 'u':
 7343                        {
 7344                            const int codepoint1 = get_codepoint();
 7345                            int codepoint = codepoint1; // start with codepoint1
 7346
 7347                            if (JSON_HEDLEY_UNLIKELY(codepoint1 == -1))
 7348                            {
 7349                                error_message = "invalid string: '\\u' must be followed by 4 hex digits";
 7350                                return token_type::parse_error;
 7351                            }
 7352
 7353                            // check if code point is a high surrogate
 7354                            if (0xD800 <= codepoint1 && codepoint1 <= 0xDBFF)
 7355                            {
 7356                                // expect next \uxxxx entry
 7357                                if (JSON_HEDLEY_LIKELY(get() == '\\' && get() == 'u'))
 7358                                {
 7359                                    const int codepoint2 = get_codepoint();
 7360
 7361                                    if (JSON_HEDLEY_UNLIKELY(codepoint2 == -1))
 7362                                    {
 7363                                        error_message = "invalid string: '\\u' must be followed by 4 hex digits";
 7364                                        return token_type::parse_error;
 7365                                    }
 7366
 7367                                    // check if codepoint2 is a low surrogate
 7368                                    if (JSON_HEDLEY_LIKELY(0xDC00 <= codepoint2 && codepoint2 <= 0xDFFF))
 7369                                    {
 7370                                        // overwrite codepoint
 7371                                        codepoint = static_cast<int>(
 7372                                                        // high surrogate occupies the most significant 22 bits
 7373                                                        (static_cast<unsigned int>(codepoint1) << 10u)
 7374                                                        // low surrogate occupies the least significant 15 bits
 7375                                                        + static_cast<unsigned int>(codepoint2)
 7376                                                        // there is still the 0xD800, 0xDC00 and 0x10000 noise
 7377                                                        // in the result, so we have to subtract with:
 7378                                                        // (0xD800 << 10) + DC00 - 0x10000 = 0x35FDC00
 7379                                                        - 0x35FDC00u);
 7380                                    }
 7381                                    else
 7382                                    {
 7383                                        error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
 7384                                        return token_type::parse_error;
 7385                                    }
 7386                                }
 7387                                else
 7388                                {
 7389                                    error_message = "invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF";
 7390                                    return token_type::parse_error;
 7391                                }
 7392                            }
 7393                            else
 7394                            {
 7395                                if (JSON_HEDLEY_UNLIKELY(0xDC00 <= codepoint1 && codepoint1 <= 0xDFFF))
 7396                                {
 7397                                    error_message = "invalid string: surrogate U+DC00..U+DFFF must follow U+D800..U+DBFF";
 7398                                    return token_type::parse_error;
 7399                                }
 7400                            }
 7401
 7402                            // result of the above calculation yields a proper codepoint
 7403                            JSON_ASSERT(0x00 <= codepoint && codepoint <= 0x10FFFF);
 7404
 7405                            // translate codepoint into bytes
 7406                            if (codepoint < 0x80)
 7407                            {
 7408                                // 1-byte characters: 0xxxxxxx (ASCII)
 7409                                add(static_cast<char_int_type>(codepoint));
 7410                            }
 7411                            else if (codepoint <= 0x7FF)
 7412                            {
 7413                                // 2-byte characters: 110xxxxx 10xxxxxx
 7414                                add(static_cast<char_int_type>(0xC0u | (static_cast<unsigned int>(codepoint) >> 6u)));
 7415                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 7416                            }
 7417                            else if (codepoint <= 0xFFFF)
 7418                            {
 7419                                // 3-byte characters: 1110xxxx 10xxxxxx 10xxxxxx
 7420                                add(static_cast<char_int_type>(0xE0u | (static_cast<unsigned int>(codepoint) >> 12u)));
 7421                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
 7422                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 7423                            }
 7424                            else
 7425                            {
 7426                                // 4-byte characters: 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx
 7427                                add(static_cast<char_int_type>(0xF0u | (static_cast<unsigned int>(codepoint) >> 18u)));
 7428                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 12u) & 0x3Fu)));
 7429                                add(static_cast<char_int_type>(0x80u | ((static_cast<unsigned int>(codepoint) >> 6u) & 0x3Fu)));
 7430                                add(static_cast<char_int_type>(0x80u | (static_cast<unsigned int>(codepoint) & 0x3Fu)));
 7431                            }
 7432
 7433                            break;
 7434                        }
 7435
 7436                        // other characters after escape
 7437                        default:
 7438                            error_message = "invalid string: forbidden character after backslash";
 7439                            return token_type::parse_error;
 7440                    }
 7441
 7442                    break;
 7443                }
 7444
 7445                // invalid control characters
 7446                case 0x00:
 7447                {
 7448                    error_message = "invalid string: control character U+0000 (NUL) must be escaped to \\u0000";
 7449                    return token_type::parse_error;
 7450                }
 7451
 7452                case 0x01:
 7453                {
 7454                    error_message = "invalid string: control character U+0001 (SOH) must be escaped to \\u0001";
 7455                    return token_type::parse_error;
 7456                }
 7457
 7458                case 0x02:
 7459                {
 7460                    error_message = "invalid string: control character U+0002 (STX) must be escaped to \\u0002";
 7461                    return token_type::parse_error;
 7462                }
 7463
 7464                case 0x03:
 7465                {
 7466                    error_message = "invalid string: control character U+0003 (ETX) must be escaped to \\u0003";
 7467                    return token_type::parse_error;
 7468                }
 7469
 7470                case 0x04:
 7471                {
 7472                    error_message = "invalid string: control character U+0004 (EOT) must be escaped to \\u0004";
 7473                    return token_type::parse_error;
 7474                }
 7475
 7476                case 0x05:
 7477                {
 7478                    error_message = "invalid string: control character U+0005 (ENQ) must be escaped to \\u0005";
 7479                    return token_type::parse_error;
 7480                }
 7481
 7482                case 0x06:
 7483                {
 7484                    error_message = "invalid string: control character U+0006 (ACK) must be escaped to \\u0006";
 7485                    return token_type::parse_error;
 7486                }
 7487
 7488                case 0x07:
 7489                {
 7490                    error_message = "invalid string: control character U+0007 (BEL) must be escaped to \\u0007";
 7491                    return token_type::parse_error;
 7492                }
 7493
 7494                case 0x08:
 7495                {
 7496                    error_message = "invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b";
 7497                    return token_type::parse_error;
 7498                }
 7499
 7500                case 0x09:
 7501                {
 7502                    error_message = "invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t";
 7503                    return token_type::parse_error;
 7504                }
 7505
 7506                case 0x0A:
 7507                {
 7508                    error_message = "invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n";
 7509                    return token_type::parse_error;
 7510                }
 7511
 7512                case 0x0B:
 7513                {
 7514                    error_message = "invalid string: control character U+000B (VT) must be escaped to \\u000B";
 7515                    return token_type::parse_error;
 7516                }
 7517
 7518                case 0x0C:
 7519                {
 7520                    error_message = "invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f";
 7521                    return token_type::parse_error;
 7522                }
 7523
 7524                case 0x0D:
 7525                {
 7526                    error_message = "invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r";
 7527                    return token_type::parse_error;
 7528                }
 7529
 7530                case 0x0E:
 7531                {
 7532                    error_message = "invalid string: control character U+000E (SO) must be escaped to \\u000E";
 7533                    return token_type::parse_error;
 7534                }
 7535
 7536                case 0x0F:
 7537                {
 7538                    error_message = "invalid string: control character U+000F (SI) must be escaped to \\u000F";
 7539                    return token_type::parse_error;
 7540                }
 7541
 7542                case 0x10:
 7543                {
 7544                    error_message = "invalid string: control character U+0010 (DLE) must be escaped to \\u0010";
 7545                    return token_type::parse_error;
 7546                }
 7547
 7548                case 0x11:
 7549                {
 7550                    error_message = "invalid string: control character U+0011 (DC1) must be escaped to \\u0011";
 7551                    return token_type::parse_error;
 7552                }
 7553
 7554                case 0x12:
 7555                {
 7556                    error_message = "invalid string: control character U+0012 (DC2) must be escaped to \\u0012";
 7557                    return token_type::parse_error;
 7558                }
 7559
 7560                case 0x13:
 7561                {
 7562                    error_message = "invalid string: control character U+0013 (DC3) must be escaped to \\u0013";
 7563                    return token_type::parse_error;
 7564                }
 7565
 7566                case 0x14:
 7567                {
 7568                    error_message = "invalid string: control character U+0014 (DC4) must be escaped to \\u0014";
 7569                    return token_type::parse_error;
 7570                }
 7571
 7572                case 0x15:
 7573                {
 7574                    error_message = "invalid string: control character U+0015 (NAK) must be escaped to \\u0015";
 7575                    return token_type::parse_error;
 7576                }
 7577
 7578                case 0x16:
 7579                {
 7580                    error_message = "invalid string: control character U+0016 (SYN) must be escaped to \\u0016";
 7581                    return token_type::parse_error;
 7582                }
 7583
 7584                case 0x17:
 7585                {
 7586                    error_message = "invalid string: control character U+0017 (ETB) must be escaped to \\u0017";
 7587                    return token_type::parse_error;
 7588                }
 7589
 7590                case 0x18:
 7591                {
 7592                    error_message = "invalid string: control character U+0018 (CAN) must be escaped to \\u0018";
 7593                    return token_type::parse_error;
 7594                }
 7595
 7596                case 0x19:
 7597                {
 7598                    error_message = "invalid string: control character U+0019 (EM) must be escaped to \\u0019";
 7599                    return token_type::parse_error;
 7600                }
 7601
 7602                case 0x1A:
 7603                {
 7604                    error_message = "invalid string: control character U+001A (SUB) must be escaped to \\u001A";
 7605                    return token_type::parse_error;
 7606                }
 7607
 7608                case 0x1B:
 7609                {
 7610                    error_message = "invalid string: control character U+001B (ESC) must be escaped to \\u001B";
 7611                    return token_type::parse_error;
 7612                }
 7613
 7614                case 0x1C:
 7615                {
 7616                    error_message = "invalid string: control character U+001C (FS) must be escaped to \\u001C";
 7617                    return token_type::parse_error;
 7618                }
 7619
 7620                case 0x1D:
 7621                {
 7622                    error_message = "invalid string: control character U+001D (GS) must be escaped to \\u001D";
 7623                    return token_type::parse_error;
 7624                }
 7625
 7626                case 0x1E:
 7627                {
 7628                    error_message = "invalid string: control character U+001E (RS) must be escaped to \\u001E";
 7629                    return token_type::parse_error;
 7630                }
 7631
 7632                case 0x1F:
 7633                {
 7634                    error_message = "invalid string: control character U+001F (US) must be escaped to \\u001F";
 7635                    return token_type::parse_error;
 7636                }
 7637
 7638                // U+0020..U+007F (except U+0022 (quote) and U+005C (backspace))
 7639                case 0x20:
 7640                case 0x21:
 7641                case 0x23:
 7642                case 0x24:
 7643                case 0x25:
 7644                case 0x26:
 7645                case 0x27:
 7646                case 0x28:
 7647                case 0x29:
 7648                case 0x2A:
 7649                case 0x2B:
 7650                case 0x2C:
 7651                case 0x2D:
 7652                case 0x2E:
 7653                case 0x2F:
 7654                case 0x30:
 7655                case 0x31:
 7656                case 0x32:
 7657                case 0x33:
 7658                case 0x34:
 7659                case 0x35:
 7660                case 0x36:
 7661                case 0x37:
 7662                case 0x38:
 7663                case 0x39:
 7664                case 0x3A:
 7665                case 0x3B:
 7666                case 0x3C:
 7667                case 0x3D:
 7668                case 0x3E:
 7669                case 0x3F:
 7670                case 0x40:
 7671                case 0x41:
 7672                case 0x42:
 7673                case 0x43:
 7674                case 0x44:
 7675                case 0x45:
 7676                case 0x46:
 7677                case 0x47:
 7678                case 0x48:
 7679                case 0x49:
 7680                case 0x4A:
 7681                case 0x4B:
 7682                case 0x4C:
 7683                case 0x4D:
 7684                case 0x4E:
 7685                case 0x4F:
 7686                case 0x50:
 7687                case 0x51:
 7688                case 0x52:
 7689                case 0x53:
 7690                case 0x54:
 7691                case 0x55:
 7692                case 0x56:
 7693                case 0x57:
 7694                case 0x58:
 7695                case 0x59:
 7696                case 0x5A:
 7697                case 0x5B:
 7698                case 0x5D:
 7699                case 0x5E:
 7700                case 0x5F:
 7701                case 0x60:
 7702                case 0x61:
 7703                case 0x62:
 7704                case 0x63:
 7705                case 0x64:
 7706                case 0x65:
 7707                case 0x66:
 7708                case 0x67:
 7709                case 0x68:
 7710                case 0x69:
 7711                case 0x6A:
 7712                case 0x6B:
 7713                case 0x6C:
 7714                case 0x6D:
 7715                case 0x6E:
 7716                case 0x6F:
 7717                case 0x70:
 7718                case 0x71:
 7719                case 0x72:
 7720                case 0x73:
 7721                case 0x74:
 7722                case 0x75:
 7723                case 0x76:
 7724                case 0x77:
 7725                case 0x78:
 7726                case 0x79:
 7727                case 0x7A:
 7728                case 0x7B:
 7729                case 0x7C:
 7730                case 0x7D:
 7731                case 0x7E:
 7732                case 0x7F:
 7733                {
 7734                    add(current);
 7735                    break;
 7736                }
 7737
 7738                // U+0080..U+07FF: bytes C2..DF 80..BF
 7739                case 0xC2:
 7740                case 0xC3:
 7741                case 0xC4:
 7742                case 0xC5:
 7743                case 0xC6:
 7744                case 0xC7:
 7745                case 0xC8:
 7746                case 0xC9:
 7747                case 0xCA:
 7748                case 0xCB:
 7749                case 0xCC:
 7750                case 0xCD:
 7751                case 0xCE:
 7752                case 0xCF:
 7753                case 0xD0:
 7754                case 0xD1:
 7755                case 0xD2:
 7756                case 0xD3:
 7757                case 0xD4:
 7758                case 0xD5:
 7759                case 0xD6:
 7760                case 0xD7:
 7761                case 0xD8:
 7762                case 0xD9:
 7763                case 0xDA:
 7764                case 0xDB:
 7765                case 0xDC:
 7766                case 0xDD:
 7767                case 0xDE:
 7768                case 0xDF:
 7769                {
 7770                    if (JSON_HEDLEY_UNLIKELY(!next_byte_in_range({0x80, 0xBF})))
 7771                    {
 7772                        return token_type::parse_error;
 7773                    }
 7774                    break;
 7775                }
 7776
 7777                // U+0800..U+0FFF: bytes E0 A0..BF 80..BF
 7778                case 0xE0:
 7779                {
 7780                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0xA0, 0xBF, 0x80, 0xBF}))))
 7781                    {
 7782                        return token_type::parse_error;
 7783                    }
 7784                    break;
 7785                }
 7786
 7787                // U+1000..U+CFFF: bytes E1..EC 80..BF 80..BF
 7788                // U+E000..U+FFFF: bytes EE..EF 80..BF 80..BF
 7789                case 0xE1:
 7790                case 0xE2:
 7791                case 0xE3:
 7792                case 0xE4:
 7793                case 0xE5:
 7794                case 0xE6:
 7795                case 0xE7:
 7796                case 0xE8:
 7797                case 0xE9:
 7798                case 0xEA:
 7799                case 0xEB:
 7800                case 0xEC:
 7801                case 0xEE:
 7802                case 0xEF:
 7803                {
 7804                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF}))))
 7805                    {
 7806                        return token_type::parse_error;
 7807                    }
 7808                    break;
 7809                }
 7810
 7811                // U+D000..U+D7FF: bytes ED 80..9F 80..BF
 7812                case 0xED:
 7813                {
 7814                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x9F, 0x80, 0xBF}))))
 7815                    {
 7816                        return token_type::parse_error;
 7817                    }
 7818                    break;
 7819                }
 7820
 7821                // U+10000..U+3FFFF F0 90..BF 80..BF 80..BF
 7822                case 0xF0:
 7823                {
 7824                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x90, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
 7825                    {
 7826                        return token_type::parse_error;
 7827                    }
 7828                    break;
 7829                }
 7830
 7831                // U+40000..U+FFFFF F1..F3 80..BF 80..BF 80..BF
 7832                case 0xF1:
 7833                case 0xF2:
 7834                case 0xF3:
 7835                {
 7836                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0xBF, 0x80, 0xBF, 0x80, 0xBF}))))
 7837                    {
 7838                        return token_type::parse_error;
 7839                    }
 7840                    break;
 7841                }
 7842
 7843                // U+100000..U+10FFFF F4 80..8F 80..BF 80..BF
 7844                case 0xF4:
 7845                {
 7846                    if (JSON_HEDLEY_UNLIKELY(!(next_byte_in_range({0x80, 0x8F, 0x80, 0xBF, 0x80, 0xBF}))))
 7847                    {
 7848                        return token_type::parse_error;
 7849                    }
 7850                    break;
 7851                }
 7852
 7853                // remaining bytes (80..C1 and F5..FF) are ill-formed
 7854                default:
 7855                {
 7856                    error_message = "invalid string: ill-formed UTF-8 byte";
 7857                    return token_type::parse_error;
 7858                }
 7859            }
 7860        }
 7861    }
 7862
 7863    /*!
 7864     * @brief scan a comment
 7865     * @return whether comment could be scanned successfully
 7866     */
 7867    bool scan_comment()
 7868    {
 7869        switch (get())
 7870        {
 7871            // single-line comments skip input until a newline or EOF is read
 7872            case '/':
 7873            {
 7874                while (true)
 7875                {
 7876                    switch (get())
 7877                    {
 7878                        case '\n':
 7879                        case '\r':
 7880                        case char_traits<char_type>::eof():
 7881                        case '\0':
 7882                            return true;
 7883
 7884                        default:
 7885                            break;
 7886                    }
 7887                }
 7888            }
 7889
 7890            // multi-line comments skip input until */ is read
 7891            case '*':
 7892            {
 7893                while (true)
 7894                {
 7895                    switch (get())
 7896                    {
 7897                        case char_traits<char_type>::eof():
 7898                        case '\0':
 7899                        {
 7900                            error_message = "invalid comment; missing closing '*/'";
 7901                            return false;
 7902                        }
 7903
 7904                        case '*':
 7905                        {
 7906                            switch (get())
 7907                            {
 7908                                case '/':
 7909                                    return true;
 7910
 7911                                default:
 7912                                {
 7913                                    unget();
 7914                                    continue;
 7915                                }
 7916                            }
 7917                        }
 7918
 7919                        default:
 7920                            continue;
 7921                    }
 7922                }
 7923            }
 7924
 7925            // unexpected character after reading '/'
 7926            default:
 7927            {
 7928                error_message = "invalid comment; expecting '/' or '*' after '/'";
 7929                return false;
 7930            }
 7931        }
 7932    }
 7933
 7934    JSON_HEDLEY_NON_NULL(2)
 7935    static void strtof(float& f, const char* str, char** endptr) noexcept
 7936    {
 7937        f = std::strtof(str, endptr);
 7938    }
 7939
 7940    JSON_HEDLEY_NON_NULL(2)
 7941    static void strtof(double& f, const char* str, char** endptr) noexcept
 7942    {
 7943        f = std::strtod(str, endptr);
 7944    }
 7945
 7946    JSON_HEDLEY_NON_NULL(2)
 7947    static void strtof(long double& f, const char* str, char** endptr) noexcept
 7948    {
 7949        f = std::strtold(str, endptr);
 7950    }
 7951
 7952    /*!
 7953    @brief scan a number literal
 7954
 7955    This function scans a string according to Sect. 6 of RFC 8259.
 7956
 7957    The function is realized with a deterministic finite state machine derived
 7958    from the grammar described in RFC 8259. Starting in state "init", the
 7959    input is read and used to determined the next state. Only state "done"
 7960    accepts the number. State "error" is a trap state to model errors. In the
 7961    table below, "anything" means any character but the ones listed before.
 7962
 7963    state    | 0        | 1-9      | e E      | +       | -       | .        | anything
 7964    ---------|----------|----------|----------|---------|---------|----------|-----------
 7965    init     | zero     | any1     | [error]  | [error] | minus   | [error]  | [error]
 7966    minus    | zero     | any1     | [error]  | [error] | [error] | [error]  | [error]
 7967    zero     | done     | done     | exponent | done    | done    | decimal1 | done
 7968    any1     | any1     | any1     | exponent | done    | done    | decimal1 | done
 7969    decimal1 | decimal2 | decimal2 | [error]  | [error] | [error] | [error]  | [error]
 7970    decimal2 | decimal2 | decimal2 | exponent | done    | done    | done     | done
 7971    exponent | any2     | any2     | [error]  | sign    | sign    | [error]  | [error]
 7972    sign     | any2     | any2     | [error]  | [error] | [error] | [error]  | [error]
 7973    any2     | any2     | any2     | done     | done    | done    | done     | done
 7974
 7975    The state machine is realized with one label per state (prefixed with
 7976    "scan_number_") and `goto` statements between them. The state machine
 7977    contains cycles, but any cycle can be left when EOF is read. Therefore,
 7978    the function is guaranteed to terminate.
 7979
 7980    During scanning, the read bytes are stored in token_buffer. This string is
 7981    then converted to a signed integer, an unsigned integer, or a
 7982    floating-point number.
 7983
 7984    @return token_type::value_unsigned, token_type::value_integer, or
 7985            token_type::value_float if number could be successfully scanned,
 7986            token_type::parse_error otherwise
 7987
 7988    @note The scanner is independent of the current locale. Internally, the
 7989          locale's decimal point is used instead of `.` to work with the
 7990          locale-dependent converters.
 7991    */
 7992    token_type scan_number()  // lgtm [cpp/use-of-goto] `goto` is used in this function to implement the number-parsing state machine described above. By design, any finite input will eventually reach the "done" state or return token_type::parse_error. In each intermediate state, 1 byte of the input is appended to the token_buffer vector, and only the already initialized variables token_buffer, number_type, and error_message are manipulated.
 7993    {
 7994        // reset token_buffer to store the number's bytes
 7995        reset();
 7996
 7997        // the type of the parsed number; initially set to unsigned; will be
 7998        // changed if minus sign, decimal point or exponent is read
 7999        token_type number_type = token_type::value_unsigned;
 8000
 8001        // state (init): we just found out we need to scan a number
 8002        switch (current)
 8003        {
 8004            case '-':
 8005            {
 8006                add(current);
 8007                goto scan_number_minus;
 8008            }
 8009
 8010            case '0':
 8011            {
 8012                add(current);
 8013                goto scan_number_zero;
 8014            }
 8015
 8016            case '1':
 8017            case '2':
 8018            case '3':
 8019            case '4':
 8020            case '5':
 8021            case '6':
 8022            case '7':
 8023            case '8':
 8024            case '9':
 8025            {
 8026                add(current);
 8027                goto scan_number_any1;
 8028            }
 8029
 8030            // all other characters are rejected outside scan_number()
 8031            default:            // LCOV_EXCL_LINE
 8032                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 8033        }
 8034
 8035scan_number_minus:
 8036        // state: we just parsed a leading minus sign
 8037        number_type = token_type::value_integer;
 8038        switch (get())
 8039        {
 8040            case '0':
 8041            {
 8042                add(current);
 8043                goto scan_number_zero;
 8044            }
 8045
 8046            case '1':
 8047            case '2':
 8048            case '3':
 8049            case '4':
 8050            case '5':
 8051            case '6':
 8052            case '7':
 8053            case '8':
 8054            case '9':
 8055            {
 8056                add(current);
 8057                goto scan_number_any1;
 8058            }
 8059
 8060            default:
 8061            {
 8062                error_message = "invalid number; expected digit after '-'";
 8063                return token_type::parse_error;
 8064            }
 8065        }
 8066
 8067scan_number_zero:
 8068        // state: we just parse a zero (maybe with a leading minus sign)
 8069        switch (get())
 8070        {
 8071            case '.':
 8072            {
 8073                add(decimal_point_char);
 8074                decimal_point_position = token_buffer.size() - 1;
 8075                goto scan_number_decimal1;
 8076            }
 8077
 8078            case 'e':
 8079            case 'E':
 8080            {
 8081                add(current);
 8082                goto scan_number_exponent;
 8083            }
 8084
 8085            default:
 8086                goto scan_number_done;
 8087        }
 8088
 8089scan_number_any1:
 8090        // state: we just parsed a number 0-9 (maybe with a leading minus sign)
 8091        switch (get())
 8092        {
 8093            case '0':
 8094            case '1':
 8095            case '2':
 8096            case '3':
 8097            case '4':
 8098            case '5':
 8099            case '6':
 8100            case '7':
 8101            case '8':
 8102            case '9':
 8103            {
 8104                add(current);
 8105                goto scan_number_any1;
 8106            }
 8107
 8108            case '.':
 8109            {
 8110                add(decimal_point_char);
 8111                decimal_point_position = token_buffer.size() - 1;
 8112                goto scan_number_decimal1;
 8113            }
 8114
 8115            case 'e':
 8116            case 'E':
 8117            {
 8118                add(current);
 8119                goto scan_number_exponent;
 8120            }
 8121
 8122            default:
 8123                goto scan_number_done;
 8124        }
 8125
 8126scan_number_decimal1:
 8127        // state: we just parsed a decimal point
 8128        number_type = token_type::value_float;
 8129        switch (get())
 8130        {
 8131            case '0':
 8132            case '1':
 8133            case '2':
 8134            case '3':
 8135            case '4':
 8136            case '5':
 8137            case '6':
 8138            case '7':
 8139            case '8':
 8140            case '9':
 8141            {
 8142                add(current);
 8143                goto scan_number_decimal2;
 8144            }
 8145
 8146            default:
 8147            {
 8148                error_message = "invalid number; expected digit after '.'";
 8149                return token_type::parse_error;
 8150            }
 8151        }
 8152
 8153scan_number_decimal2:
 8154        // we just parsed at least one number after a decimal point
 8155        switch (get())
 8156        {
 8157            case '0':
 8158            case '1':
 8159            case '2':
 8160            case '3':
 8161            case '4':
 8162            case '5':
 8163            case '6':
 8164            case '7':
 8165            case '8':
 8166            case '9':
 8167            {
 8168                add(current);
 8169                goto scan_number_decimal2;
 8170            }
 8171
 8172            case 'e':
 8173            case 'E':
 8174            {
 8175                add(current);
 8176                goto scan_number_exponent;
 8177            }
 8178
 8179            default:
 8180                goto scan_number_done;
 8181        }
 8182
 8183scan_number_exponent:
 8184        // we just parsed an exponent
 8185        number_type = token_type::value_float;
 8186        switch (get())
 8187        {
 8188            case '+':
 8189            case '-':
 8190            {
 8191                add(current);
 8192                goto scan_number_sign;
 8193            }
 8194
 8195            case '0':
 8196            case '1':
 8197            case '2':
 8198            case '3':
 8199            case '4':
 8200            case '5':
 8201            case '6':
 8202            case '7':
 8203            case '8':
 8204            case '9':
 8205            {
 8206                add(current);
 8207                goto scan_number_any2;
 8208            }
 8209
 8210            default:
 8211            {
 8212                error_message =
 8213                    "invalid number; expected '+', '-', or digit after exponent";
 8214                return token_type::parse_error;
 8215            }
 8216        }
 8217
 8218scan_number_sign:
 8219        // we just parsed an exponent sign
 8220        switch (get())
 8221        {
 8222            case '0':
 8223            case '1':
 8224            case '2':
 8225            case '3':
 8226            case '4':
 8227            case '5':
 8228            case '6':
 8229            case '7':
 8230            case '8':
 8231            case '9':
 8232            {
 8233                add(current);
 8234                goto scan_number_any2;
 8235            }
 8236
 8237            default:
 8238            {
 8239                error_message = "invalid number; expected digit after exponent sign";
 8240                return token_type::parse_error;
 8241            }
 8242        }
 8243
 8244scan_number_any2:
 8245        // we just parsed a number after the exponent or exponent sign
 8246        switch (get())
 8247        {
 8248            case '0':
 8249            case '1':
 8250            case '2':
 8251            case '3':
 8252            case '4':
 8253            case '5':
 8254            case '6':
 8255            case '7':
 8256            case '8':
 8257            case '9':
 8258            {
 8259                add(current);
 8260                goto scan_number_any2;
 8261            }
 8262
 8263            default:
 8264                goto scan_number_done;
 8265        }
 8266
 8267scan_number_done:
 8268        // unget the character after the number (we only read it to know that
 8269        // we are done scanning a number)
 8270        unget();
 8271
 8272        char* endptr = nullptr; // NOLINT(misc-const-correctness,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
 8273        errno = 0;
 8274
 8275        // try to parse integers first and fall back to floats
 8276        if (number_type == token_type::value_unsigned)
 8277        {
 8278            const auto x = std::strtoull(token_buffer.data(), &endptr, 10);
 8279
 8280            // we checked the number format before
 8281            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
 8282
 8283            if (errno != ERANGE)
 8284            {
 8285                value_unsigned = static_cast<number_unsigned_t>(x);
 8286                if (value_unsigned == x)
 8287                {
 8288                    return token_type::value_unsigned;
 8289                }
 8290            }
 8291        }
 8292        else if (number_type == token_type::value_integer)
 8293        {
 8294            const auto x = std::strtoll(token_buffer.data(), &endptr, 10);
 8295
 8296            // we checked the number format before
 8297            JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
 8298
 8299            if (errno != ERANGE)
 8300            {
 8301                value_integer = static_cast<number_integer_t>(x);
 8302                if (value_integer == x)
 8303                {
 8304                    return token_type::value_integer;
 8305                }
 8306            }
 8307        }
 8308
 8309        // this code is reached if we parse a floating-point number or if an
 8310        // integer conversion above failed
 8311        strtof(value_float, token_buffer.data(), &endptr);
 8312
 8313        // we checked the number format before
 8314        JSON_ASSERT(endptr == token_buffer.data() + token_buffer.size());
 8315
 8316        return token_type::value_float;
 8317    }
 8318
 8319    /*!
 8320    @param[in] literal_text  the literal text to expect
 8321    @param[in] length        the length of the passed literal text
 8322    @param[in] return_type   the token type to return on success
 8323    */
 8324    JSON_HEDLEY_NON_NULL(2)
 8325    token_type scan_literal(const char_type* literal_text, const std::size_t length,
 8326                            token_type return_type)
 8327    {
 8328        JSON_ASSERT(char_traits<char_type>::to_char_type(current) == literal_text[0]);
 8329        for (std::size_t i = 1; i < length; ++i)
 8330        {
 8331            if (JSON_HEDLEY_UNLIKELY(char_traits<char_type>::to_char_type(get()) != literal_text[i]))
 8332            {
 8333                error_message = "invalid literal";
 8334                return token_type::parse_error;
 8335            }
 8336        }
 8337        return return_type;
 8338    }
 8339
 8340    /////////////////////
 8341    // input management
 8342    /////////////////////
 8343
 8344    /// reset token_buffer; current character is beginning of token
 8345    void reset() noexcept
 8346    {
 8347        token_buffer.clear();
 8348        token_string.clear();
 8349        decimal_point_position = std::string::npos;
 8350        token_string.push_back(char_traits<char_type>::to_char_type(current));
 8351    }
 8352
 8353    /*
 8354    @brief get next character from the input
 8355
 8356    This function provides the interface to the used input adapter. It does
 8357    not throw in case the input reached EOF, but returns a
 8358    `char_traits<char>::eof()` in that case.  Stores the scanned characters
 8359    for use in error messages.
 8360
 8361    @return character read from the input
 8362    */
 8363    char_int_type get()
 8364    {
 8365        ++position.chars_read_total;
 8366        ++position.chars_read_current_line;
 8367
 8368        if (next_unget)
 8369        {
 8370            // just reset the next_unget variable and work with current
 8371            next_unget = false;
 8372        }
 8373        else
 8374        {
 8375            current = ia.get_character();
 8376        }
 8377
 8378        if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
 8379        {
 8380            token_string.push_back(char_traits<char_type>::to_char_type(current));
 8381        }
 8382
 8383        if (current == '\n')
 8384        {
 8385            ++position.lines_read;
 8386            position.chars_read_current_line = 0;
 8387        }
 8388
 8389        return current;
 8390    }
 8391
 8392    /*!
 8393    @brief unget current character (read it again on next get)
 8394
 8395    We implement unget by setting variable next_unget to true. The input is not
 8396    changed - we just simulate ungetting by modifying chars_read_total,
 8397    chars_read_current_line, and token_string. The next call to get() will
 8398    behave as if the unget character is read again.
 8399    */
 8400    void unget()
 8401    {
 8402        next_unget = true;
 8403
 8404        --position.chars_read_total;
 8405
 8406        // in case we "unget" a newline, we have to also decrement the lines_read
 8407        if (position.chars_read_current_line == 0)
 8408        {
 8409            if (position.lines_read > 0)
 8410            {
 8411                --position.lines_read;
 8412            }
 8413        }
 8414        else
 8415        {
 8416            --position.chars_read_current_line;
 8417        }
 8418
 8419        if (JSON_HEDLEY_LIKELY(current != char_traits<char_type>::eof()))
 8420        {
 8421            JSON_ASSERT(!token_string.empty());
 8422            token_string.pop_back();
 8423        }
 8424    }
 8425
 8426    /// add a character to token_buffer
 8427    void add(char_int_type c)
 8428    {
 8429        token_buffer.push_back(static_cast<typename string_t::value_type>(c));
 8430    }
 8431
 8432  public:
 8433    /////////////////////
 8434    // value getters
 8435    /////////////////////
 8436
 8437    /// return integer value
 8438    constexpr number_integer_t get_number_integer() const noexcept
 8439    {
 8440        return value_integer;
 8441    }
 8442
 8443    /// return unsigned integer value
 8444    constexpr number_unsigned_t get_number_unsigned() const noexcept
 8445    {
 8446        return value_unsigned;
 8447    }
 8448
 8449    /// return floating-point value
 8450    constexpr number_float_t get_number_float() const noexcept
 8451    {
 8452        return value_float;
 8453    }
 8454
 8455    /// return current string value (implicitly resets the token; useful only once)
 8456    string_t& get_string()
 8457    {
 8458        // translate decimal points from locale back to '.' (#4084)
 8459        if (decimal_point_char != '.' && decimal_point_position != std::string::npos)
 8460        {
 8461            token_buffer[decimal_point_position] = '.';
 8462        }
 8463        return token_buffer;
 8464    }
 8465
 8466    /////////////////////
 8467    // diagnostics
 8468    /////////////////////
 8469
 8470    /// return position of last read token
 8471    constexpr position_t get_position() const noexcept
 8472    {
 8473        return position;
 8474    }
 8475
 8476    /// return the last read token (for errors only).  Will never contain EOF
 8477    /// (an arbitrary value that is not a valid char value, often -1), because
 8478    /// 255 may legitimately occur.  May contain NUL, which should be escaped.
 8479    std::string get_token_string() const
 8480    {
 8481        // escape control characters
 8482        std::string result;
 8483        for (const auto c : token_string)
 8484        {
 8485            if (static_cast<unsigned char>(c) <= '\x1F')
 8486            {
 8487                // escape control characters
 8488                std::array<char, 9> cs{{}};
 8489                static_cast<void>((std::snprintf)(cs.data(), cs.size(), "<U+%.4X>", static_cast<unsigned char>(c))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
 8490                result += cs.data();
 8491            }
 8492            else
 8493            {
 8494                // add character as is
 8495                result.push_back(static_cast<std::string::value_type>(c));
 8496            }
 8497        }
 8498
 8499        return result;
 8500    }
 8501
 8502    /// return syntax error message
 8503    JSON_HEDLEY_RETURNS_NON_NULL
 8504    constexpr const char* get_error_message() const noexcept
 8505    {
 8506        return error_message;
 8507    }
 8508
 8509    /////////////////////
 8510    // actual scanner
 8511    /////////////////////
 8512
 8513    /*!
 8514    @brief skip the UTF-8 byte order mark
 8515    @return true iff there is no BOM or the correct BOM has been skipped
 8516    */
 8517    bool skip_bom()
 8518    {
 8519        if (get() == 0xEF)
 8520        {
 8521            // check if we completely parse the BOM
 8522            return get() == 0xBB && get() == 0xBF;
 8523        }
 8524
 8525        // the first character is not the beginning of the BOM; unget it to
 8526        // process is later
 8527        unget();
 8528        return true;
 8529    }
 8530
 8531    void skip_whitespace()
 8532    {
 8533        do
 8534        {
 8535            get();
 8536        }
 8537        while (current == ' ' || current == '\t' || current == '\n' || current == '\r');
 8538    }
 8539
 8540    token_type scan()
 8541    {
 8542        // initially, skip the BOM
 8543        if (position.chars_read_total == 0 && !skip_bom())
 8544        {
 8545            error_message = "invalid BOM; must be 0xEF 0xBB 0xBF if given";
 8546            return token_type::parse_error;
 8547        }
 8548
 8549        // read next character and ignore whitespace
 8550        skip_whitespace();
 8551
 8552        // ignore comments
 8553        while (ignore_comments && current == '/')
 8554        {
 8555            if (!scan_comment())
 8556            {
 8557                return token_type::parse_error;
 8558            }
 8559
 8560            // skip following whitespace
 8561            skip_whitespace();
 8562        }
 8563
 8564        switch (current)
 8565        {
 8566            // structural characters
 8567            case '[':
 8568                return token_type::begin_array;
 8569            case ']':
 8570                return token_type::end_array;
 8571            case '{':
 8572                return token_type::begin_object;
 8573            case '}':
 8574                return token_type::end_object;
 8575            case ':':
 8576                return token_type::name_separator;
 8577            case ',':
 8578                return token_type::value_separator;
 8579
 8580            // literals
 8581            case 't':
 8582            {
 8583                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')}};
 8584                return scan_literal(true_literal.data(), true_literal.size(), token_type::literal_true);
 8585            }
 8586            case 'f':
 8587            {
 8588                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')}};
 8589                return scan_literal(false_literal.data(), false_literal.size(), token_type::literal_false);
 8590            }
 8591            case 'n':
 8592            {
 8593                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')}};
 8594                return scan_literal(null_literal.data(), null_literal.size(), token_type::literal_null);
 8595            }
 8596
 8597            // string
 8598            case '\"':
 8599                return scan_string();
 8600
 8601            // number
 8602            case '-':
 8603            case '0':
 8604            case '1':
 8605            case '2':
 8606            case '3':
 8607            case '4':
 8608            case '5':
 8609            case '6':
 8610            case '7':
 8611            case '8':
 8612            case '9':
 8613                return scan_number();
 8614
 8615            // end of input (the null byte is needed when parsing from
 8616            // string literals)
 8617            case '\0':
 8618            case char_traits<char_type>::eof():
 8619                return token_type::end_of_input;
 8620
 8621            // error
 8622            default:
 8623                error_message = "invalid literal";
 8624                return token_type::parse_error;
 8625        }
 8626    }
 8627
 8628  private:
 8629    /// input adapter
 8630    InputAdapterType ia;
 8631
 8632    /// whether comments should be ignored (true) or signaled as errors (false)
 8633    const bool ignore_comments = false;
 8634
 8635    /// the current character
 8636    char_int_type current = char_traits<char_type>::eof();
 8637
 8638    /// whether the next get() call should just return current
 8639    bool next_unget = false;
 8640
 8641    /// the start position of the current token
 8642    position_t position {};
 8643
 8644    /// raw input token string (for error messages)
 8645    std::vector<char_type> token_string {};
 8646
 8647    /// buffer for variable-length tokens (numbers, strings)
 8648    string_t token_buffer {};
 8649
 8650    /// a description of occurred lexer errors
 8651    const char* error_message = "";
 8652
 8653    // number values
 8654    number_integer_t value_integer = 0;
 8655    number_unsigned_t value_unsigned = 0;
 8656    number_float_t value_float = 0;
 8657
 8658    /// the decimal point
 8659    const char_int_type decimal_point_char = '.';
 8660    /// the position of the decimal point in the input
 8661    std::size_t decimal_point_position = std::string::npos;
 8662};
 8663
 8664}  // namespace detail
 8665NLOHMANN_JSON_NAMESPACE_END
 8666
 8667// #include <nlohmann/detail/macro_scope.hpp>
 8668
 8669// #include <nlohmann/detail/string_concat.hpp>
 8670
 8671NLOHMANN_JSON_NAMESPACE_BEGIN
 8672
 8673/*!
 8674@brief SAX interface
 8675
 8676This class describes the SAX interface used by @ref nlohmann::json::sax_parse.
 8677Each function is called in different situations while the input is parsed. The
 8678boolean return value informs the parser whether to continue processing the
 8679input.
 8680*/
 8681template<typename BasicJsonType>
 8682struct json_sax
 8683{
 8684    using number_integer_t = typename BasicJsonType::number_integer_t;
 8685    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 8686    using number_float_t = typename BasicJsonType::number_float_t;
 8687    using string_t = typename BasicJsonType::string_t;
 8688    using binary_t = typename BasicJsonType::binary_t;
 8689
 8690    /*!
 8691    @brief a null value was read
 8692    @return whether parsing should proceed
 8693    */
 8694    virtual bool null() = 0;
 8695
 8696    /*!
 8697    @brief a boolean value was read
 8698    @param[in] val  boolean value
 8699    @return whether parsing should proceed
 8700    */
 8701    virtual bool boolean(bool val) = 0;
 8702
 8703    /*!
 8704    @brief an integer number was read
 8705    @param[in] val  integer value
 8706    @return whether parsing should proceed
 8707    */
 8708    virtual bool number_integer(number_integer_t val) = 0;
 8709
 8710    /*!
 8711    @brief an unsigned integer number was read
 8712    @param[in] val  unsigned integer value
 8713    @return whether parsing should proceed
 8714    */
 8715    virtual bool number_unsigned(number_unsigned_t val) = 0;
 8716
 8717    /*!
 8718    @brief a floating-point number was read
 8719    @param[in] val  floating-point value
 8720    @param[in] s    raw token value
 8721    @return whether parsing should proceed
 8722    */
 8723    virtual bool number_float(number_float_t val, const string_t& s) = 0;
 8724
 8725    /*!
 8726    @brief a string value was read
 8727    @param[in] val  string value
 8728    @return whether parsing should proceed
 8729    @note It is safe to move the passed string value.
 8730    */
 8731    virtual bool string(string_t& val) = 0;
 8732
 8733    /*!
 8734    @brief a binary value was read
 8735    @param[in] val  binary value
 8736    @return whether parsing should proceed
 8737    @note It is safe to move the passed binary value.
 8738    */
 8739    virtual bool binary(binary_t& val) = 0;
 8740
 8741    /*!
 8742    @brief the beginning of an object was read
 8743    @param[in] elements  number of object elements or -1 if unknown
 8744    @return whether parsing should proceed
 8745    @note binary formats may report the number of elements
 8746    */
 8747    virtual bool start_object(std::size_t elements) = 0;
 8748
 8749    /*!
 8750    @brief an object key was read
 8751    @param[in] val  object key
 8752    @return whether parsing should proceed
 8753    @note It is safe to move the passed string.
 8754    */
 8755    virtual bool key(string_t& val) = 0;
 8756
 8757    /*!
 8758    @brief the end of an object was read
 8759    @return whether parsing should proceed
 8760    */
 8761    virtual bool end_object() = 0;
 8762
 8763    /*!
 8764    @brief the beginning of an array was read
 8765    @param[in] elements  number of array elements or -1 if unknown
 8766    @return whether parsing should proceed
 8767    @note binary formats may report the number of elements
 8768    */
 8769    virtual bool start_array(std::size_t elements) = 0;
 8770
 8771    /*!
 8772    @brief the end of an array was read
 8773    @return whether parsing should proceed
 8774    */
 8775    virtual bool end_array() = 0;
 8776
 8777    /*!
 8778    @brief a parse error occurred
 8779    @param[in] position    the position in the input where the error occurs
 8780    @param[in] last_token  the last read token
 8781    @param[in] ex          an exception object describing the error
 8782    @return whether parsing should proceed (must return false)
 8783    */
 8784    virtual bool parse_error(std::size_t position,
 8785                             const std::string& last_token,
 8786                             const detail::exception& ex) = 0;
 8787
 8788    json_sax() = default;
 8789    json_sax(const json_sax&) = default;
 8790    json_sax(json_sax&&) noexcept = default;
 8791    json_sax& operator=(const json_sax&) = default;
 8792    json_sax& operator=(json_sax&&) noexcept = default;
 8793    virtual ~json_sax() = default;
 8794};
 8795
 8796namespace detail
 8797{
 8798constexpr std::size_t unknown_size()
 8799{
 8800    return (std::numeric_limits<std::size_t>::max)();
 8801}
 8802
 8803/*!
 8804@brief SAX implementation to create a JSON value from SAX events
 8805
 8806This class implements the @ref json_sax interface and processes the SAX events
 8807to create a JSON value which makes it basically a DOM parser. The structure or
 8808hierarchy of the JSON value is managed by the stack `ref_stack` which contains
 8809a pointer to the respective array or object for each recursion depth.
 8810
 8811After successful parsing, the value that is passed by reference to the
 8812constructor contains the parsed value.
 8813
 8814@tparam BasicJsonType  the JSON type
 8815*/
 8816template<typename BasicJsonType, typename InputAdapterType>
 8817class json_sax_dom_parser
 8818{
 8819  public:
 8820    using number_integer_t = typename BasicJsonType::number_integer_t;
 8821    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 8822    using number_float_t = typename BasicJsonType::number_float_t;
 8823    using string_t = typename BasicJsonType::string_t;
 8824    using binary_t = typename BasicJsonType::binary_t;
 8825    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
 8826
 8827    /*!
 8828    @param[in,out] r  reference to a JSON value that is manipulated while
 8829                       parsing
 8830    @param[in] allow_exceptions_  whether parse errors yield exceptions
 8831    */
 8832    explicit json_sax_dom_parser(BasicJsonType& r, const bool allow_exceptions_ = true, lexer_t* lexer_ = nullptr)
 8833        : root(r), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
 8834    {}
 8835
 8836    // make class move-only
 8837    json_sax_dom_parser(const json_sax_dom_parser&) = delete;
 8838    json_sax_dom_parser(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 8839    json_sax_dom_parser& operator=(const json_sax_dom_parser&) = delete;
 8840    json_sax_dom_parser& operator=(json_sax_dom_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 8841    ~json_sax_dom_parser() = default;
 8842
 8843    bool null()
 8844    {
 8845        handle_value(nullptr);
 8846        return true;
 8847    }
 8848
 8849    bool boolean(bool val)
 8850    {
 8851        handle_value(val);
 8852        return true;
 8853    }
 8854
 8855    bool number_integer(number_integer_t val)
 8856    {
 8857        handle_value(val);
 8858        return true;
 8859    }
 8860
 8861    bool number_unsigned(number_unsigned_t val)
 8862    {
 8863        handle_value(val);
 8864        return true;
 8865    }
 8866
 8867    bool number_float(number_float_t val, const string_t& /*unused*/)
 8868    {
 8869        handle_value(val);
 8870        return true;
 8871    }
 8872
 8873    bool string(string_t& val)
 8874    {
 8875        handle_value(val);
 8876        return true;
 8877    }
 8878
 8879    bool binary(binary_t& val)
 8880    {
 8881        handle_value(std::move(val));
 8882        return true;
 8883    }
 8884
 8885    bool start_object(std::size_t len)
 8886    {
 8887        ref_stack.push_back(handle_value(BasicJsonType::value_t::object));
 8888
 8889#if JSON_DIAGNOSTIC_POSITIONS
 8890        // Manually set the start position of the object here.
 8891        // Ensure this is after the call to handle_value to ensure correct start position.
 8892        if (m_lexer_ref)
 8893        {
 8894            // Lexer has read the first character of the object, so
 8895            // subtract 1 from the position to get the correct start position.
 8896            ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
 8897        }
 8898#endif
 8899
 8900        if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
 8901        {
 8902            JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
 8903        }
 8904
 8905        return true;
 8906    }
 8907
 8908    bool key(string_t& val)
 8909    {
 8910        JSON_ASSERT(!ref_stack.empty());
 8911        JSON_ASSERT(ref_stack.back()->is_object());
 8912
 8913        // add null at given key and store the reference for later
 8914        object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val));
 8915        return true;
 8916    }
 8917
 8918    bool end_object()
 8919    {
 8920        JSON_ASSERT(!ref_stack.empty());
 8921        JSON_ASSERT(ref_stack.back()->is_object());
 8922
 8923#if JSON_DIAGNOSTIC_POSITIONS
 8924        if (m_lexer_ref)
 8925        {
 8926            // Lexer's position is past the closing brace, so set that as the end position.
 8927            ref_stack.back()->end_position = m_lexer_ref->get_position();
 8928        }
 8929#endif
 8930
 8931        ref_stack.back()->set_parents();
 8932        ref_stack.pop_back();
 8933        return true;
 8934    }
 8935
 8936    bool start_array(std::size_t len)
 8937    {
 8938        ref_stack.push_back(handle_value(BasicJsonType::value_t::array));
 8939
 8940#if JSON_DIAGNOSTIC_POSITIONS
 8941        // Manually set the start position of the array here.
 8942        // Ensure this is after the call to handle_value to ensure correct start position.
 8943        if (m_lexer_ref)
 8944        {
 8945            ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
 8946        }
 8947#endif
 8948
 8949        if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
 8950        {
 8951            JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
 8952        }
 8953
 8954        return true;
 8955    }
 8956
 8957    bool end_array()
 8958    {
 8959        JSON_ASSERT(!ref_stack.empty());
 8960        JSON_ASSERT(ref_stack.back()->is_array());
 8961
 8962#if JSON_DIAGNOSTIC_POSITIONS
 8963        if (m_lexer_ref)
 8964        {
 8965            // Lexer's position is past the closing bracket, so set that as the end position.
 8966            ref_stack.back()->end_position = m_lexer_ref->get_position();
 8967        }
 8968#endif
 8969
 8970        ref_stack.back()->set_parents();
 8971        ref_stack.pop_back();
 8972        return true;
 8973    }
 8974
 8975    template<class Exception>
 8976    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
 8977                     const Exception& ex)
 8978    {
 8979        errored = true;
 8980        static_cast<void>(ex);
 8981        if (allow_exceptions)
 8982        {
 8983            JSON_THROW(ex);
 8984        }
 8985        return false;
 8986    }
 8987
 8988    constexpr bool is_errored() const
 8989    {
 8990        return errored;
 8991    }
 8992
 8993  private:
 8994
 8995#if JSON_DIAGNOSTIC_POSITIONS
 8996    void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
 8997    {
 8998        if (m_lexer_ref)
 8999        {
 9000            // Lexer has read past the current field value, so set the end position to the current position.
 9001            // The start position will be set below based on the length of the string representation
 9002            // of the value.
 9003            v.end_position = m_lexer_ref->get_position();
 9004
 9005            switch (v.type())
 9006            {
 9007                case value_t::boolean:
 9008                {
 9009                    // 4 and 5 are the string length of "true" and "false"
 9010                    v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
 9011                    break;
 9012                }
 9013
 9014                case value_t::null:
 9015                {
 9016                    // 4 is the string length of "null"
 9017                    v.start_position = v.end_position - 4;
 9018                    break;
 9019                }
 9020
 9021                case value_t::string:
 9022                {
 9023                    // include the length of the quotes, which is 2
 9024                    v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
 9025                    break;
 9026                }
 9027
 9028                // As we handle the start and end positions for values created during parsing,
 9029                // we do not expect the following value type to be called. Regardless, set the positions
 9030                // in case this is created manually or through a different constructor. Exclude from lcov
 9031                // since the exact condition of this switch is esoteric.
 9032                // LCOV_EXCL_START
 9033                case value_t::discarded:
 9034                {
 9035                    v.end_position = std::string::npos;
 9036                    v.start_position = v.end_position;
 9037                    break;
 9038                }
 9039                // LCOV_EXCL_STOP
 9040                case value_t::binary:
 9041                case value_t::number_integer:
 9042                case value_t::number_unsigned:
 9043                case value_t::number_float:
 9044                {
 9045                    v.start_position = v.end_position - m_lexer_ref->get_string().size();
 9046                    break;
 9047                }
 9048                case value_t::object:
 9049                case value_t::array:
 9050                {
 9051                    // object and array are handled in start_object() and start_array() handlers
 9052                    // skip setting the values here.
 9053                    break;
 9054                }
 9055                default: // LCOV_EXCL_LINE
 9056                    // Handle all possible types discretely, default handler should never be reached.
 9057                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
 9058            }
 9059        }
 9060    }
 9061#endif
 9062
 9063    /*!
 9064    @invariant If the ref stack is empty, then the passed value will be the new
 9065               root.
 9066    @invariant If the ref stack contains a value, then it is an array or an
 9067               object to which we can add elements
 9068    */
 9069    template<typename Value>
 9070    JSON_HEDLEY_RETURNS_NON_NULL
 9071    BasicJsonType* handle_value(Value&& v)
 9072    {
 9073        if (ref_stack.empty())
 9074        {
 9075            root = BasicJsonType(std::forward<Value>(v));
 9076
 9077#if JSON_DIAGNOSTIC_POSITIONS
 9078            handle_diagnostic_positions_for_json_value(root);
 9079#endif
 9080
 9081            return &root;
 9082        }
 9083
 9084        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
 9085
 9086        if (ref_stack.back()->is_array())
 9087        {
 9088            ref_stack.back()->m_data.m_value.array->emplace_back(std::forward<Value>(v));
 9089
 9090#if JSON_DIAGNOSTIC_POSITIONS
 9091            handle_diagnostic_positions_for_json_value(ref_stack.back()->m_data.m_value.array->back());
 9092#endif
 9093
 9094            return &(ref_stack.back()->m_data.m_value.array->back());
 9095        }
 9096
 9097        JSON_ASSERT(ref_stack.back()->is_object());
 9098        JSON_ASSERT(object_element);
 9099        *object_element = BasicJsonType(std::forward<Value>(v));
 9100
 9101#if JSON_DIAGNOSTIC_POSITIONS
 9102        handle_diagnostic_positions_for_json_value(*object_element);
 9103#endif
 9104
 9105        return object_element;
 9106    }
 9107
 9108    /// the parsed JSON value
 9109    BasicJsonType& root;
 9110    /// stack to model hierarchy of values
 9111    std::vector<BasicJsonType*> ref_stack {};
 9112    /// helper to hold the reference for the next object element
 9113    BasicJsonType* object_element = nullptr;
 9114    /// whether a syntax error occurred
 9115    bool errored = false;
 9116    /// whether to throw exceptions in case of errors
 9117    const bool allow_exceptions = true;
 9118    /// the lexer reference to obtain the current position
 9119    lexer_t* m_lexer_ref = nullptr;
 9120};
 9121
 9122template<typename BasicJsonType, typename InputAdapterType>
 9123class json_sax_dom_callback_parser
 9124{
 9125  public:
 9126    using number_integer_t = typename BasicJsonType::number_integer_t;
 9127    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 9128    using number_float_t = typename BasicJsonType::number_float_t;
 9129    using string_t = typename BasicJsonType::string_t;
 9130    using binary_t = typename BasicJsonType::binary_t;
 9131    using parser_callback_t = typename BasicJsonType::parser_callback_t;
 9132    using parse_event_t = typename BasicJsonType::parse_event_t;
 9133    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
 9134
 9135    json_sax_dom_callback_parser(BasicJsonType& r,
 9136                                 parser_callback_t cb,
 9137                                 const bool allow_exceptions_ = true,
 9138                                 lexer_t* lexer_ = nullptr)
 9139        : root(r), callback(std::move(cb)), allow_exceptions(allow_exceptions_), m_lexer_ref(lexer_)
 9140    {
 9141        keep_stack.push_back(true);
 9142    }
 9143
 9144    // make class move-only
 9145    json_sax_dom_callback_parser(const json_sax_dom_callback_parser&) = delete;
 9146    json_sax_dom_callback_parser(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 9147    json_sax_dom_callback_parser& operator=(const json_sax_dom_callback_parser&) = delete;
 9148    json_sax_dom_callback_parser& operator=(json_sax_dom_callback_parser&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 9149    ~json_sax_dom_callback_parser() = default;
 9150
 9151    bool null()
 9152    {
 9153        handle_value(nullptr);
 9154        return true;
 9155    }
 9156
 9157    bool boolean(bool val)
 9158    {
 9159        handle_value(val);
 9160        return true;
 9161    }
 9162
 9163    bool number_integer(number_integer_t val)
 9164    {
 9165        handle_value(val);
 9166        return true;
 9167    }
 9168
 9169    bool number_unsigned(number_unsigned_t val)
 9170    {
 9171        handle_value(val);
 9172        return true;
 9173    }
 9174
 9175    bool number_float(number_float_t val, const string_t& /*unused*/)
 9176    {
 9177        handle_value(val);
 9178        return true;
 9179    }
 9180
 9181    bool string(string_t& val)
 9182    {
 9183        handle_value(val);
 9184        return true;
 9185    }
 9186
 9187    bool binary(binary_t& val)
 9188    {
 9189        handle_value(std::move(val));
 9190        return true;
 9191    }
 9192
 9193    bool start_object(std::size_t len)
 9194    {
 9195        // check callback for object start
 9196        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::object_start, discarded);
 9197        keep_stack.push_back(keep);
 9198
 9199        auto val = handle_value(BasicJsonType::value_t::object, true);
 9200        ref_stack.push_back(val.second);
 9201
 9202        if (ref_stack.back())
 9203        {
 9204
 9205#if JSON_DIAGNOSTIC_POSITIONS
 9206            // Manually set the start position of the object here.
 9207            // Ensure this is after the call to handle_value to ensure correct start position.
 9208            if (m_lexer_ref)
 9209            {
 9210                // Lexer has read the first character of the object, so
 9211                // subtract 1 from the position to get the correct start position.
 9212                ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
 9213            }
 9214#endif
 9215
 9216            // check object limit
 9217            if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
 9218            {
 9219                JSON_THROW(out_of_range::create(408, concat("excessive object size: ", std::to_string(len)), ref_stack.back()));
 9220            }
 9221        }
 9222        return true;
 9223    }
 9224
 9225    bool key(string_t& val)
 9226    {
 9227        BasicJsonType k = BasicJsonType(val);
 9228
 9229        // check callback for key
 9230        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::key, k);
 9231        key_keep_stack.push_back(keep);
 9232
 9233        // add discarded value at given key and store the reference for later
 9234        if (keep && ref_stack.back())
 9235        {
 9236            object_element = &(ref_stack.back()->m_data.m_value.object->operator[](val) = discarded);
 9237        }
 9238
 9239        return true;
 9240    }
 9241
 9242    bool end_object()
 9243    {
 9244        if (ref_stack.back())
 9245        {
 9246            if (!callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::object_end, *ref_stack.back()))
 9247            {
 9248                // discard object
 9249                *ref_stack.back() = discarded;
 9250
 9251#if JSON_DIAGNOSTIC_POSITIONS
 9252                // Set start/end positions for discarded object.
 9253                handle_diagnostic_positions_for_json_value(*ref_stack.back());
 9254#endif
 9255            }
 9256            else
 9257            {
 9258
 9259#if JSON_DIAGNOSTIC_POSITIONS
 9260                if (m_lexer_ref)
 9261                {
 9262                    // Lexer's position is past the closing brace, so set that as the end position.
 9263                    ref_stack.back()->end_position = m_lexer_ref->get_position();
 9264                }
 9265#endif
 9266
 9267                ref_stack.back()->set_parents();
 9268            }
 9269        }
 9270
 9271        JSON_ASSERT(!ref_stack.empty());
 9272        JSON_ASSERT(!keep_stack.empty());
 9273        ref_stack.pop_back();
 9274        keep_stack.pop_back();
 9275
 9276        if (!ref_stack.empty() && ref_stack.back() && ref_stack.back()->is_structured())
 9277        {
 9278            // remove discarded value
 9279            for (auto it = ref_stack.back()->begin(); it != ref_stack.back()->end(); ++it)
 9280            {
 9281                if (it->is_discarded())
 9282                {
 9283                    ref_stack.back()->erase(it);
 9284                    break;
 9285                }
 9286            }
 9287        }
 9288
 9289        return true;
 9290    }
 9291
 9292    bool start_array(std::size_t len)
 9293    {
 9294        const bool keep = callback(static_cast<int>(ref_stack.size()), parse_event_t::array_start, discarded);
 9295        keep_stack.push_back(keep);
 9296
 9297        auto val = handle_value(BasicJsonType::value_t::array, true);
 9298        ref_stack.push_back(val.second);
 9299
 9300        if (ref_stack.back())
 9301        {
 9302
 9303#if JSON_DIAGNOSTIC_POSITIONS
 9304            // Manually set the start position of the array here.
 9305            // Ensure this is after the call to handle_value to ensure correct start position.
 9306            if (m_lexer_ref)
 9307            {
 9308                // Lexer has read the first character of the array, so
 9309                // subtract 1 from the position to get the correct start position.
 9310                ref_stack.back()->start_position = m_lexer_ref->get_position() - 1;
 9311            }
 9312#endif
 9313
 9314            // check array limit
 9315            if (JSON_HEDLEY_UNLIKELY(len != detail::unknown_size() && len > ref_stack.back()->max_size()))
 9316            {
 9317                JSON_THROW(out_of_range::create(408, concat("excessive array size: ", std::to_string(len)), ref_stack.back()));
 9318            }
 9319        }
 9320
 9321        return true;
 9322    }
 9323
 9324    bool end_array()
 9325    {
 9326        bool keep = true;
 9327
 9328        if (ref_stack.back())
 9329        {
 9330            keep = callback(static_cast<int>(ref_stack.size()) - 1, parse_event_t::array_end, *ref_stack.back());
 9331            if (keep)
 9332            {
 9333
 9334#if JSON_DIAGNOSTIC_POSITIONS
 9335                if (m_lexer_ref)
 9336                {
 9337                    // Lexer's position is past the closing bracket, so set that as the end position.
 9338                    ref_stack.back()->end_position = m_lexer_ref->get_position();
 9339                }
 9340#endif
 9341
 9342                ref_stack.back()->set_parents();
 9343            }
 9344            else
 9345            {
 9346                // discard array
 9347                *ref_stack.back() = discarded;
 9348
 9349#if JSON_DIAGNOSTIC_POSITIONS
 9350                // Set start/end positions for discarded array.
 9351                handle_diagnostic_positions_for_json_value(*ref_stack.back());
 9352#endif
 9353            }
 9354        }
 9355
 9356        JSON_ASSERT(!ref_stack.empty());
 9357        JSON_ASSERT(!keep_stack.empty());
 9358        ref_stack.pop_back();
 9359        keep_stack.pop_back();
 9360
 9361        // remove discarded value
 9362        if (!keep && !ref_stack.empty() && ref_stack.back()->is_array())
 9363        {
 9364            ref_stack.back()->m_data.m_value.array->pop_back();
 9365        }
 9366
 9367        return true;
 9368    }
 9369
 9370    template<class Exception>
 9371    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/,
 9372                     const Exception& ex)
 9373    {
 9374        errored = true;
 9375        static_cast<void>(ex);
 9376        if (allow_exceptions)
 9377        {
 9378            JSON_THROW(ex);
 9379        }
 9380        return false;
 9381    }
 9382
 9383    constexpr bool is_errored() const
 9384    {
 9385        return errored;
 9386    }
 9387
 9388  private:
 9389
 9390#if JSON_DIAGNOSTIC_POSITIONS
 9391    void handle_diagnostic_positions_for_json_value(BasicJsonType& v)
 9392    {
 9393        if (m_lexer_ref)
 9394        {
 9395            // Lexer has read past the current field value, so set the end position to the current position.
 9396            // The start position will be set below based on the length of the string representation
 9397            // of the value.
 9398            v.end_position = m_lexer_ref->get_position();
 9399
 9400            switch (v.type())
 9401            {
 9402                case value_t::boolean:
 9403                {
 9404                    // 4 and 5 are the string length of "true" and "false"
 9405                    v.start_position = v.end_position - (v.m_data.m_value.boolean ? 4 : 5);
 9406                    break;
 9407                }
 9408
 9409                case value_t::null:
 9410                {
 9411                    // 4 is the string length of "null"
 9412                    v.start_position = v.end_position - 4;
 9413                    break;
 9414                }
 9415
 9416                case value_t::string:
 9417                {
 9418                    // include the length of the quotes, which is 2
 9419                    v.start_position = v.end_position - v.m_data.m_value.string->size() - 2;
 9420                    break;
 9421                }
 9422
 9423                case value_t::discarded:
 9424                {
 9425                    v.end_position = std::string::npos;
 9426                    v.start_position = v.end_position;
 9427                    break;
 9428                }
 9429
 9430                case value_t::binary:
 9431                case value_t::number_integer:
 9432                case value_t::number_unsigned:
 9433                case value_t::number_float:
 9434                {
 9435                    v.start_position = v.end_position - m_lexer_ref->get_string().size();
 9436                    break;
 9437                }
 9438
 9439                case value_t::object:
 9440                case value_t::array:
 9441                {
 9442                    // object and array are handled in start_object() and start_array() handlers
 9443                    // skip setting the values here.
 9444                    break;
 9445                }
 9446                default: // LCOV_EXCL_LINE
 9447                    // Handle all possible types discretely, default handler should never be reached.
 9448                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert,-warnings-as-errors) LCOV_EXCL_LINE
 9449            }
 9450        }
 9451    }
 9452#endif
 9453
 9454    /*!
 9455    @param[in] v  value to add to the JSON value we build during parsing
 9456    @param[in] skip_callback  whether we should skip calling the callback
 9457               function; this is required after start_array() and
 9458               start_object() SAX events, because otherwise we would call the
 9459               callback function with an empty array or object, respectively.
 9460
 9461    @invariant If the ref stack is empty, then the passed value will be the new
 9462               root.
 9463    @invariant If the ref stack contains a value, then it is an array or an
 9464               object to which we can add elements
 9465
 9466    @return pair of boolean (whether value should be kept) and pointer (to the
 9467            passed value in the ref_stack hierarchy; nullptr if not kept)
 9468    */
 9469    template<typename Value>
 9470    std::pair<bool, BasicJsonType*> handle_value(Value&& v, const bool skip_callback = false)
 9471    {
 9472        JSON_ASSERT(!keep_stack.empty());
 9473
 9474        // do not handle this value if we know it would be added to a discarded
 9475        // container
 9476        if (!keep_stack.back())
 9477        {
 9478            return {false, nullptr};
 9479        }
 9480
 9481        // create value
 9482        auto value = BasicJsonType(std::forward<Value>(v));
 9483
 9484#if JSON_DIAGNOSTIC_POSITIONS
 9485        handle_diagnostic_positions_for_json_value(value);
 9486#endif
 9487
 9488        // check callback
 9489        const bool keep = skip_callback || callback(static_cast<int>(ref_stack.size()), parse_event_t::value, value);
 9490
 9491        // do not handle this value if we just learnt it shall be discarded
 9492        if (!keep)
 9493        {
 9494            return {false, nullptr};
 9495        }
 9496
 9497        if (ref_stack.empty())
 9498        {
 9499            root = std::move(value);
 9500            return {true, & root};
 9501        }
 9502
 9503        // skip this value if we already decided to skip the parent
 9504        // (https://github.com/nlohmann/json/issues/971#issuecomment-413678360)
 9505        if (!ref_stack.back())
 9506        {
 9507            return {false, nullptr};
 9508        }
 9509
 9510        // we now only expect arrays and objects
 9511        JSON_ASSERT(ref_stack.back()->is_array() || ref_stack.back()->is_object());
 9512
 9513        // array
 9514        if (ref_stack.back()->is_array())
 9515        {
 9516            ref_stack.back()->m_data.m_value.array->emplace_back(std::move(value));
 9517            return {true, & (ref_stack.back()->m_data.m_value.array->back())};
 9518        }
 9519
 9520        // object
 9521        JSON_ASSERT(ref_stack.back()->is_object());
 9522        // check if we should store an element for the current key
 9523        JSON_ASSERT(!key_keep_stack.empty());
 9524        const bool store_element = key_keep_stack.back();
 9525        key_keep_stack.pop_back();
 9526
 9527        if (!store_element)
 9528        {
 9529            return {false, nullptr};
 9530        }
 9531
 9532        JSON_ASSERT(object_element);
 9533        *object_element = std::move(value);
 9534        return {true, object_element};
 9535    }
 9536
 9537    /// the parsed JSON value
 9538    BasicJsonType& root;
 9539    /// stack to model hierarchy of values
 9540    std::vector<BasicJsonType*> ref_stack {};
 9541    /// stack to manage which values to keep
 9542    std::vector<bool> keep_stack {}; // NOLINT(readability-redundant-member-init)
 9543    /// stack to manage which object keys to keep
 9544    std::vector<bool> key_keep_stack {}; // NOLINT(readability-redundant-member-init)
 9545    /// helper to hold the reference for the next object element
 9546    BasicJsonType* object_element = nullptr;
 9547    /// whether a syntax error occurred
 9548    bool errored = false;
 9549    /// callback function
 9550    const parser_callback_t callback = nullptr;
 9551    /// whether to throw exceptions in case of errors
 9552    const bool allow_exceptions = true;
 9553    /// a discarded value for the callback
 9554    BasicJsonType discarded = BasicJsonType::value_t::discarded;
 9555    /// the lexer reference to obtain the current position
 9556    lexer_t* m_lexer_ref = nullptr;
 9557};
 9558
 9559template<typename BasicJsonType>
 9560class json_sax_acceptor
 9561{
 9562  public:
 9563    using number_integer_t = typename BasicJsonType::number_integer_t;
 9564    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 9565    using number_float_t = typename BasicJsonType::number_float_t;
 9566    using string_t = typename BasicJsonType::string_t;
 9567    using binary_t = typename BasicJsonType::binary_t;
 9568
 9569    bool null()
 9570    {
 9571        return true;
 9572    }
 9573
 9574    bool boolean(bool /*unused*/)
 9575    {
 9576        return true;
 9577    }
 9578
 9579    bool number_integer(number_integer_t /*unused*/)
 9580    {
 9581        return true;
 9582    }
 9583
 9584    bool number_unsigned(number_unsigned_t /*unused*/)
 9585    {
 9586        return true;
 9587    }
 9588
 9589    bool number_float(number_float_t /*unused*/, const string_t& /*unused*/)
 9590    {
 9591        return true;
 9592    }
 9593
 9594    bool string(string_t& /*unused*/)
 9595    {
 9596        return true;
 9597    }
 9598
 9599    bool binary(binary_t& /*unused*/)
 9600    {
 9601        return true;
 9602    }
 9603
 9604    bool start_object(std::size_t /*unused*/ = detail::unknown_size())
 9605    {
 9606        return true;
 9607    }
 9608
 9609    bool key(string_t& /*unused*/)
 9610    {
 9611        return true;
 9612    }
 9613
 9614    bool end_object()
 9615    {
 9616        return true;
 9617    }
 9618
 9619    bool start_array(std::size_t /*unused*/ = detail::unknown_size())
 9620    {
 9621        return true;
 9622    }
 9623
 9624    bool end_array()
 9625    {
 9626        return true;
 9627    }
 9628
 9629    bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const detail::exception& /*unused*/)
 9630    {
 9631        return false;
 9632    }
 9633};
 9634
 9635}  // namespace detail
 9636NLOHMANN_JSON_NAMESPACE_END
 9637
 9638// #include <nlohmann/detail/input/lexer.hpp>
 9639
 9640// #include <nlohmann/detail/macro_scope.hpp>
 9641
 9642// #include <nlohmann/detail/meta/is_sax.hpp>
 9643//     __ _____ _____ _____
 9644//  __|  |   __|     |   | |  JSON for Modern C++
 9645// |  |  |__   |  |  | | | |  version 3.12.0
 9646// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
 9647//
 9648// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
 9649// SPDX-License-Identifier: MIT
 9650
 9651
 9652
 9653#include <cstdint> // size_t
 9654#include <utility> // declval
 9655#include <string> // string
 9656
 9657// #include <nlohmann/detail/abi_macros.hpp>
 9658
 9659// #include <nlohmann/detail/meta/detected.hpp>
 9660
 9661// #include <nlohmann/detail/meta/type_traits.hpp>
 9662
 9663
 9664NLOHMANN_JSON_NAMESPACE_BEGIN
 9665namespace detail
 9666{
 9667
 9668template<typename T>
 9669using null_function_t = decltype(std::declval<T&>().null());
 9670
 9671template<typename T>
 9672using boolean_function_t =
 9673    decltype(std::declval<T&>().boolean(std::declval<bool>()));
 9674
 9675template<typename T, typename Integer>
 9676using number_integer_function_t =
 9677    decltype(std::declval<T&>().number_integer(std::declval<Integer>()));
 9678
 9679template<typename T, typename Unsigned>
 9680using number_unsigned_function_t =
 9681    decltype(std::declval<T&>().number_unsigned(std::declval<Unsigned>()));
 9682
 9683template<typename T, typename Float, typename String>
 9684using number_float_function_t = decltype(std::declval<T&>().number_float(
 9685                                    std::declval<Float>(), std::declval<const String&>()));
 9686
 9687template<typename T, typename String>
 9688using string_function_t =
 9689    decltype(std::declval<T&>().string(std::declval<String&>()));
 9690
 9691template<typename T, typename Binary>
 9692using binary_function_t =
 9693    decltype(std::declval<T&>().binary(std::declval<Binary&>()));
 9694
 9695template<typename T>
 9696using start_object_function_t =
 9697    decltype(std::declval<T&>().start_object(std::declval<std::size_t>()));
 9698
 9699template<typename T, typename String>
 9700using key_function_t =
 9701    decltype(std::declval<T&>().key(std::declval<String&>()));
 9702
 9703template<typename T>
 9704using end_object_function_t = decltype(std::declval<T&>().end_object());
 9705
 9706template<typename T>
 9707using start_array_function_t =
 9708    decltype(std::declval<T&>().start_array(std::declval<std::size_t>()));
 9709
 9710template<typename T>
 9711using end_array_function_t = decltype(std::declval<T&>().end_array());
 9712
 9713template<typename T, typename Exception>
 9714using parse_error_function_t = decltype(std::declval<T&>().parse_error(
 9715        std::declval<std::size_t>(), std::declval<const std::string&>(),
 9716        std::declval<const Exception&>()));
 9717
 9718template<typename SAX, typename BasicJsonType>
 9719struct is_sax
 9720{
 9721  private:
 9722    static_assert(is_basic_json<BasicJsonType>::value,
 9723                  "BasicJsonType must be of type basic_json<...>");
 9724
 9725    using number_integer_t = typename BasicJsonType::number_integer_t;
 9726    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 9727    using number_float_t = typename BasicJsonType::number_float_t;
 9728    using string_t = typename BasicJsonType::string_t;
 9729    using binary_t = typename BasicJsonType::binary_t;
 9730    using exception_t = typename BasicJsonType::exception;
 9731
 9732  public:
 9733    static constexpr bool value =
 9734        is_detected_exact<bool, null_function_t, SAX>::value &&
 9735        is_detected_exact<bool, boolean_function_t, SAX>::value &&
 9736        is_detected_exact<bool, number_integer_function_t, SAX, number_integer_t>::value &&
 9737        is_detected_exact<bool, number_unsigned_function_t, SAX, number_unsigned_t>::value &&
 9738        is_detected_exact<bool, number_float_function_t, SAX, number_float_t, string_t>::value &&
 9739        is_detected_exact<bool, string_function_t, SAX, string_t>::value &&
 9740        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value &&
 9741        is_detected_exact<bool, start_object_function_t, SAX>::value &&
 9742        is_detected_exact<bool, key_function_t, SAX, string_t>::value &&
 9743        is_detected_exact<bool, end_object_function_t, SAX>::value &&
 9744        is_detected_exact<bool, start_array_function_t, SAX>::value &&
 9745        is_detected_exact<bool, end_array_function_t, SAX>::value &&
 9746        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value;
 9747};
 9748
 9749template<typename SAX, typename BasicJsonType>
 9750struct is_sax_static_asserts
 9751{
 9752  private:
 9753    static_assert(is_basic_json<BasicJsonType>::value,
 9754                  "BasicJsonType must be of type basic_json<...>");
 9755
 9756    using number_integer_t = typename BasicJsonType::number_integer_t;
 9757    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 9758    using number_float_t = typename BasicJsonType::number_float_t;
 9759    using string_t = typename BasicJsonType::string_t;
 9760    using binary_t = typename BasicJsonType::binary_t;
 9761    using exception_t = typename BasicJsonType::exception;
 9762
 9763  public:
 9764    static_assert(is_detected_exact<bool, null_function_t, SAX>::value,
 9765                  "Missing/invalid function: bool null()");
 9766    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
 9767                  "Missing/invalid function: bool boolean(bool)");
 9768    static_assert(is_detected_exact<bool, boolean_function_t, SAX>::value,
 9769                  "Missing/invalid function: bool boolean(bool)");
 9770    static_assert(
 9771        is_detected_exact<bool, number_integer_function_t, SAX,
 9772        number_integer_t>::value,
 9773        "Missing/invalid function: bool number_integer(number_integer_t)");
 9774    static_assert(
 9775        is_detected_exact<bool, number_unsigned_function_t, SAX,
 9776        number_unsigned_t>::value,
 9777        "Missing/invalid function: bool number_unsigned(number_unsigned_t)");
 9778    static_assert(is_detected_exact<bool, number_float_function_t, SAX,
 9779                  number_float_t, string_t>::value,
 9780                  "Missing/invalid function: bool number_float(number_float_t, const string_t&)");
 9781    static_assert(
 9782        is_detected_exact<bool, string_function_t, SAX, string_t>::value,
 9783        "Missing/invalid function: bool string(string_t&)");
 9784    static_assert(
 9785        is_detected_exact<bool, binary_function_t, SAX, binary_t>::value,
 9786        "Missing/invalid function: bool binary(binary_t&)");
 9787    static_assert(is_detected_exact<bool, start_object_function_t, SAX>::value,
 9788                  "Missing/invalid function: bool start_object(std::size_t)");
 9789    static_assert(is_detected_exact<bool, key_function_t, SAX, string_t>::value,
 9790                  "Missing/invalid function: bool key(string_t&)");
 9791    static_assert(is_detected_exact<bool, end_object_function_t, SAX>::value,
 9792                  "Missing/invalid function: bool end_object()");
 9793    static_assert(is_detected_exact<bool, start_array_function_t, SAX>::value,
 9794                  "Missing/invalid function: bool start_array(std::size_t)");
 9795    static_assert(is_detected_exact<bool, end_array_function_t, SAX>::value,
 9796                  "Missing/invalid function: bool end_array()");
 9797    static_assert(
 9798        is_detected_exact<bool, parse_error_function_t, SAX, exception_t>::value,
 9799        "Missing/invalid function: bool parse_error(std::size_t, const "
 9800        "std::string&, const exception&)");
 9801};
 9802
 9803}  // namespace detail
 9804NLOHMANN_JSON_NAMESPACE_END
 9805
 9806// #include <nlohmann/detail/meta/type_traits.hpp>
 9807
 9808// #include <nlohmann/detail/string_concat.hpp>
 9809
 9810// #include <nlohmann/detail/value_t.hpp>
 9811
 9812
 9813NLOHMANN_JSON_NAMESPACE_BEGIN
 9814namespace detail
 9815{
 9816
 9817/// how to treat CBOR tags
 9818enum class cbor_tag_handler_t
 9819{
 9820    error,   ///< throw a parse_error exception in case of a tag
 9821    ignore,  ///< ignore tags
 9822    store    ///< store tags as binary type
 9823};
 9824
 9825/*!
 9826@brief determine system byte order
 9827
 9828@return true if and only if system's byte order is little endian
 9829
 9830@note from https://stackoverflow.com/a/1001328/266378
 9831*/
 9832static inline bool little_endianness(int num = 1) noexcept
 9833{
 9834    return *reinterpret_cast<char*>(&num) == 1;
 9835}
 9836
 9837///////////////////
 9838// binary reader //
 9839///////////////////
 9840
 9841/*!
 9842@brief deserialization of CBOR, MessagePack, and UBJSON values
 9843*/
 9844template<typename BasicJsonType, typename InputAdapterType, typename SAX = json_sax_dom_parser<BasicJsonType, InputAdapterType>>
 9845class binary_reader
 9846{
 9847    using number_integer_t = typename BasicJsonType::number_integer_t;
 9848    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 9849    using number_float_t = typename BasicJsonType::number_float_t;
 9850    using string_t = typename BasicJsonType::string_t;
 9851    using binary_t = typename BasicJsonType::binary_t;
 9852    using json_sax_t = SAX;
 9853    using char_type = typename InputAdapterType::char_type;
 9854    using char_int_type = typename char_traits<char_type>::int_type;
 9855
 9856  public:
 9857    /*!
 9858    @brief create a binary reader
 9859
 9860    @param[in] adapter  input adapter to read from
 9861    */
 9862    explicit binary_reader(InputAdapterType&& adapter, const input_format_t format = input_format_t::json) noexcept : ia(std::move(adapter)), input_format(format)
 9863    {
 9864        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
 9865    }
 9866
 9867    // make class move-only
 9868    binary_reader(const binary_reader&) = delete;
 9869    binary_reader(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 9870    binary_reader& operator=(const binary_reader&) = delete;
 9871    binary_reader& operator=(binary_reader&&) = default; // NOLINT(hicpp-noexcept-move,performance-noexcept-move-constructor)
 9872    ~binary_reader() = default;
 9873
 9874    /*!
 9875    @param[in] format  the binary format to parse
 9876    @param[in] sax_    a SAX event processor
 9877    @param[in] strict  whether to expect the input to be consumed completed
 9878    @param[in] tag_handler  how to treat CBOR tags
 9879
 9880    @return whether parsing was successful
 9881    */
 9882    JSON_HEDLEY_NON_NULL(3)
 9883    bool sax_parse(const input_format_t format,
 9884                   json_sax_t* sax_,
 9885                   const bool strict = true,
 9886                   const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
 9887    {
 9888        sax = sax_;
 9889        bool result = false;
 9890
 9891        switch (format)
 9892        {
 9893            case input_format_t::bson:
 9894                result = parse_bson_internal();
 9895                break;
 9896
 9897            case input_format_t::cbor:
 9898                result = parse_cbor_internal(true, tag_handler);
 9899                break;
 9900
 9901            case input_format_t::msgpack:
 9902                result = parse_msgpack_internal();
 9903                break;
 9904
 9905            case input_format_t::ubjson:
 9906            case input_format_t::bjdata:
 9907                result = parse_ubjson_internal();
 9908                break;
 9909
 9910            case input_format_t::json: // LCOV_EXCL_LINE
 9911            default:            // LCOV_EXCL_LINE
 9912                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 9913        }
 9914
 9915        // strict mode: next byte must be EOF
 9916        if (result && strict)
 9917        {
 9918            if (input_format == input_format_t::ubjson || input_format == input_format_t::bjdata)
 9919            {
 9920                get_ignore_noop();
 9921            }
 9922            else
 9923            {
 9924                get();
 9925            }
 9926
 9927            if (JSON_HEDLEY_UNLIKELY(current != char_traits<char_type>::eof()))
 9928            {
 9929                return sax->parse_error(chars_read, get_token_string(), parse_error::create(110, chars_read,
 9930                                        exception_message(input_format, concat("expected end of input; last byte: 0x", get_token_string()), "value"), nullptr));
 9931            }
 9932        }
 9933
 9934        return result;
 9935    }
 9936
 9937  private:
 9938    //////////
 9939    // BSON //
 9940    //////////
 9941
 9942    /*!
 9943    @brief Reads in a BSON-object and passes it to the SAX-parser.
 9944    @return whether a valid BSON-value was passed to the SAX parser
 9945    */
 9946    bool parse_bson_internal()
 9947    {
 9948        std::int32_t document_size{};
 9949        get_number<std::int32_t, true>(input_format_t::bson, document_size);
 9950
 9951        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
 9952        {
 9953            return false;
 9954        }
 9955
 9956        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/false)))
 9957        {
 9958            return false;
 9959        }
 9960
 9961        return sax->end_object();
 9962    }
 9963
 9964    /*!
 9965    @brief Parses a C-style string from the BSON input.
 9966    @param[in,out] result  A reference to the string variable where the read
 9967                            string is to be stored.
 9968    @return `true` if the \x00-byte indicating the end of the string was
 9969             encountered before the EOF; false` indicates an unexpected EOF.
 9970    */
 9971    bool get_bson_cstr(string_t& result)
 9972    {
 9973        auto out = std::back_inserter(result);
 9974        while (true)
 9975        {
 9976            get();
 9977            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "cstring")))
 9978            {
 9979                return false;
 9980            }
 9981            if (current == 0x00)
 9982            {
 9983                return true;
 9984            }
 9985            *out++ = static_cast<typename string_t::value_type>(current);
 9986        }
 9987    }
 9988
 9989    /*!
 9990    @brief Parses a zero-terminated string of length @a len from the BSON
 9991           input.
 9992    @param[in] len  The length (including the zero-byte at the end) of the
 9993                    string to be read.
 9994    @param[in,out] result  A reference to the string variable where the read
 9995                            string is to be stored.
 9996    @tparam NumberType The type of the length @a len
 9997    @pre len >= 1
 9998    @return `true` if the string was successfully parsed
 9999    */
10000    template<typename NumberType>
10001    bool get_bson_string(const NumberType len, string_t& result)
10002    {
10003        if (JSON_HEDLEY_UNLIKELY(len < 1))
10004        {
10005            auto last_token = get_token_string();
10006            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10007                                    exception_message(input_format_t::bson, concat("string length must be at least 1, is ", std::to_string(len)), "string"), nullptr));
10008        }
10009
10010        return get_string(input_format_t::bson, len - static_cast<NumberType>(1), result) && get() != char_traits<char_type>::eof();
10011    }
10012
10013    /*!
10014    @brief Parses a byte array input of length @a len from the BSON input.
10015    @param[in] len  The length of the byte array to be read.
10016    @param[in,out] result  A reference to the binary variable where the read
10017                            array is to be stored.
10018    @tparam NumberType The type of the length @a len
10019    @pre len >= 0
10020    @return `true` if the byte array was successfully parsed
10021    */
10022    template<typename NumberType>
10023    bool get_bson_binary(const NumberType len, binary_t& result)
10024    {
10025        if (JSON_HEDLEY_UNLIKELY(len < 0))
10026        {
10027            auto last_token = get_token_string();
10028            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10029                                    exception_message(input_format_t::bson, concat("byte array length cannot be negative, is ", std::to_string(len)), "binary"), nullptr));
10030        }
10031
10032        // All BSON binary values have a subtype
10033        std::uint8_t subtype{};
10034        get_number<std::uint8_t>(input_format_t::bson, subtype);
10035        result.set_subtype(subtype);
10036
10037        return get_binary(input_format_t::bson, len, result);
10038    }
10039
10040    /*!
10041    @brief Read a BSON document element of the given @a element_type.
10042    @param[in] element_type The BSON element type, c.f. http://bsonspec.org/spec.html
10043    @param[in] element_type_parse_position The position in the input stream,
10044               where the `element_type` was read.
10045    @warning Not all BSON element types are supported yet. An unsupported
10046             @a element_type will give rise to a parse_error.114:
10047             Unsupported BSON record type 0x...
10048    @return whether a valid BSON-object/array was passed to the SAX parser
10049    */
10050    bool parse_bson_element_internal(const char_int_type element_type,
10051                                     const std::size_t element_type_parse_position)
10052    {
10053        switch (element_type)
10054        {
10055            case 0x01: // double
10056            {
10057                double number{};
10058                return get_number<double, true>(input_format_t::bson, number) && sax->number_float(static_cast<number_float_t>(number), "");
10059            }
10060
10061            case 0x02: // string
10062            {
10063                std::int32_t len{};
10064                string_t value;
10065                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_string(len, value) && sax->string(value);
10066            }
10067
10068            case 0x03: // object
10069            {
10070                return parse_bson_internal();
10071            }
10072
10073            case 0x04: // array
10074            {
10075                return parse_bson_array();
10076            }
10077
10078            case 0x05: // binary
10079            {
10080                std::int32_t len{};
10081                binary_t value;
10082                return get_number<std::int32_t, true>(input_format_t::bson, len) && get_bson_binary(len, value) && sax->binary(value);
10083            }
10084
10085            case 0x08: // boolean
10086            {
10087                return sax->boolean(get() != 0);
10088            }
10089
10090            case 0x0A: // null
10091            {
10092                return sax->null();
10093            }
10094
10095            case 0x10: // int32
10096            {
10097                std::int32_t value{};
10098                return get_number<std::int32_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10099            }
10100
10101            case 0x12: // int64
10102            {
10103                std::int64_t value{};
10104                return get_number<std::int64_t, true>(input_format_t::bson, value) && sax->number_integer(value);
10105            }
10106
10107            case 0x11: // uint64
10108            {
10109                std::uint64_t value{};
10110                return get_number<std::uint64_t, true>(input_format_t::bson, value) && sax->number_unsigned(value);
10111            }
10112
10113            default: // anything else not supported (yet)
10114            {
10115                std::array<char, 3> cr{{}};
10116                static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(element_type))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
10117                const std::string cr_str{cr.data()};
10118                return sax->parse_error(element_type_parse_position, cr_str,
10119                                        parse_error::create(114, element_type_parse_position, concat("Unsupported BSON record type 0x", cr_str), nullptr));
10120            }
10121        }
10122    }
10123
10124    /*!
10125    @brief Read a BSON element list (as specified in the BSON-spec)
10126
10127    The same binary layout is used for objects and arrays, hence it must be
10128    indicated with the argument @a is_array which one is expected
10129    (true --> array, false --> object).
10130
10131    @param[in] is_array Determines if the element list being read is to be
10132                        treated as an object (@a is_array == false), or as an
10133                        array (@a is_array == true).
10134    @return whether a valid BSON-object/array was passed to the SAX parser
10135    */
10136    bool parse_bson_element_list(const bool is_array)
10137    {
10138        string_t key;
10139
10140        while (auto element_type = get())
10141        {
10142            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::bson, "element list")))
10143            {
10144                return false;
10145            }
10146
10147            const std::size_t element_type_parse_position = chars_read;
10148            if (JSON_HEDLEY_UNLIKELY(!get_bson_cstr(key)))
10149            {
10150                return false;
10151            }
10152
10153            if (!is_array && !sax->key(key))
10154            {
10155                return false;
10156            }
10157
10158            if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_internal(element_type, element_type_parse_position)))
10159            {
10160                return false;
10161            }
10162
10163            // get_bson_cstr only appends
10164            key.clear();
10165        }
10166
10167        return true;
10168    }
10169
10170    /*!
10171    @brief Reads an array from the BSON input and passes it to the SAX-parser.
10172    @return whether a valid BSON-array was passed to the SAX parser
10173    */
10174    bool parse_bson_array()
10175    {
10176        std::int32_t document_size{};
10177        get_number<std::int32_t, true>(input_format_t::bson, document_size);
10178
10179        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
10180        {
10181            return false;
10182        }
10183
10184        if (JSON_HEDLEY_UNLIKELY(!parse_bson_element_list(/*is_array*/true)))
10185        {
10186            return false;
10187        }
10188
10189        return sax->end_array();
10190    }
10191
10192    //////////
10193    // CBOR //
10194    //////////
10195
10196    /*!
10197    @param[in] get_char  whether a new character should be retrieved from the
10198                         input (true) or whether the last read character should
10199                         be considered instead (false)
10200    @param[in] tag_handler how CBOR tags should be treated
10201
10202    @return whether a valid CBOR value was passed to the SAX parser
10203    */
10204    bool parse_cbor_internal(const bool get_char,
10205                             const cbor_tag_handler_t tag_handler)
10206    {
10207        switch (get_char ? get() : current)
10208        {
10209            // EOF
10210            case char_traits<char_type>::eof():
10211                return unexpect_eof(input_format_t::cbor, "value");
10212
10213            // Integer 0x00..0x17 (0..23)
10214            case 0x00:
10215            case 0x01:
10216            case 0x02:
10217            case 0x03:
10218            case 0x04:
10219            case 0x05:
10220            case 0x06:
10221            case 0x07:
10222            case 0x08:
10223            case 0x09:
10224            case 0x0A:
10225            case 0x0B:
10226            case 0x0C:
10227            case 0x0D:
10228            case 0x0E:
10229            case 0x0F:
10230            case 0x10:
10231            case 0x11:
10232            case 0x12:
10233            case 0x13:
10234            case 0x14:
10235            case 0x15:
10236            case 0x16:
10237            case 0x17:
10238                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
10239
10240            case 0x18: // Unsigned integer (one-byte uint8_t follows)
10241            {
10242                std::uint8_t number{};
10243                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10244            }
10245
10246            case 0x19: // Unsigned integer (two-byte uint16_t follows)
10247            {
10248                std::uint16_t number{};
10249                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10250            }
10251
10252            case 0x1A: // Unsigned integer (four-byte uint32_t follows)
10253            {
10254                std::uint32_t number{};
10255                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10256            }
10257
10258            case 0x1B: // Unsigned integer (eight-byte uint64_t follows)
10259            {
10260                std::uint64_t number{};
10261                return get_number(input_format_t::cbor, number) && sax->number_unsigned(number);
10262            }
10263
10264            // Negative integer -1-0x00..-1-0x17 (-1..-24)
10265            case 0x20:
10266            case 0x21:
10267            case 0x22:
10268            case 0x23:
10269            case 0x24:
10270            case 0x25:
10271            case 0x26:
10272            case 0x27:
10273            case 0x28:
10274            case 0x29:
10275            case 0x2A:
10276            case 0x2B:
10277            case 0x2C:
10278            case 0x2D:
10279            case 0x2E:
10280            case 0x2F:
10281            case 0x30:
10282            case 0x31:
10283            case 0x32:
10284            case 0x33:
10285            case 0x34:
10286            case 0x35:
10287            case 0x36:
10288            case 0x37:
10289                return sax->number_integer(static_cast<std::int8_t>(0x20 - 1 - current));
10290
10291            case 0x38: // Negative integer (one-byte uint8_t follows)
10292            {
10293                std::uint8_t number{};
10294                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10295            }
10296
10297            case 0x39: // Negative integer -1-n (two-byte uint16_t follows)
10298            {
10299                std::uint16_t number{};
10300                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10301            }
10302
10303            case 0x3A: // Negative integer -1-n (four-byte uint32_t follows)
10304            {
10305                std::uint32_t number{};
10306                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1) - number);
10307            }
10308
10309            case 0x3B: // Negative integer -1-n (eight-byte uint64_t follows)
10310            {
10311                std::uint64_t number{};
10312                return get_number(input_format_t::cbor, number) && sax->number_integer(static_cast<number_integer_t>(-1)
10313                        - static_cast<number_integer_t>(number));
10314            }
10315
10316            // Binary data (0x00..0x17 bytes follow)
10317            case 0x40:
10318            case 0x41:
10319            case 0x42:
10320            case 0x43:
10321            case 0x44:
10322            case 0x45:
10323            case 0x46:
10324            case 0x47:
10325            case 0x48:
10326            case 0x49:
10327            case 0x4A:
10328            case 0x4B:
10329            case 0x4C:
10330            case 0x4D:
10331            case 0x4E:
10332            case 0x4F:
10333            case 0x50:
10334            case 0x51:
10335            case 0x52:
10336            case 0x53:
10337            case 0x54:
10338            case 0x55:
10339            case 0x56:
10340            case 0x57:
10341            case 0x58: // Binary data (one-byte uint8_t for n follows)
10342            case 0x59: // Binary data (two-byte uint16_t for n follow)
10343            case 0x5A: // Binary data (four-byte uint32_t for n follow)
10344            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10345            case 0x5F: // Binary data (indefinite length)
10346            {
10347                binary_t b;
10348                return get_cbor_binary(b) && sax->binary(b);
10349            }
10350
10351            // UTF-8 string (0x00..0x17 bytes follow)
10352            case 0x60:
10353            case 0x61:
10354            case 0x62:
10355            case 0x63:
10356            case 0x64:
10357            case 0x65:
10358            case 0x66:
10359            case 0x67:
10360            case 0x68:
10361            case 0x69:
10362            case 0x6A:
10363            case 0x6B:
10364            case 0x6C:
10365            case 0x6D:
10366            case 0x6E:
10367            case 0x6F:
10368            case 0x70:
10369            case 0x71:
10370            case 0x72:
10371            case 0x73:
10372            case 0x74:
10373            case 0x75:
10374            case 0x76:
10375            case 0x77:
10376            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10377            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10378            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10379            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10380            case 0x7F: // UTF-8 string (indefinite length)
10381            {
10382                string_t s;
10383                return get_cbor_string(s) && sax->string(s);
10384            }
10385
10386            // array (0x00..0x17 data items follow)
10387            case 0x80:
10388            case 0x81:
10389            case 0x82:
10390            case 0x83:
10391            case 0x84:
10392            case 0x85:
10393            case 0x86:
10394            case 0x87:
10395            case 0x88:
10396            case 0x89:
10397            case 0x8A:
10398            case 0x8B:
10399            case 0x8C:
10400            case 0x8D:
10401            case 0x8E:
10402            case 0x8F:
10403            case 0x90:
10404            case 0x91:
10405            case 0x92:
10406            case 0x93:
10407            case 0x94:
10408            case 0x95:
10409            case 0x96:
10410            case 0x97:
10411                return get_cbor_array(
10412                           conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10413
10414            case 0x98: // array (one-byte uint8_t for n follows)
10415            {
10416                std::uint8_t len{};
10417                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10418            }
10419
10420            case 0x99: // array (two-byte uint16_t for n follow)
10421            {
10422                std::uint16_t len{};
10423                return get_number(input_format_t::cbor, len) && get_cbor_array(static_cast<std::size_t>(len), tag_handler);
10424            }
10425
10426            case 0x9A: // array (four-byte uint32_t for n follow)
10427            {
10428                std::uint32_t len{};
10429                return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10430            }
10431
10432            case 0x9B: // array (eight-byte uint64_t for n follow)
10433            {
10434                std::uint64_t len{};
10435                return get_number(input_format_t::cbor, len) && get_cbor_array(conditional_static_cast<std::size_t>(len), tag_handler);
10436            }
10437
10438            case 0x9F: // array (indefinite length)
10439                return get_cbor_array(detail::unknown_size(), tag_handler);
10440
10441            // map (0x00..0x17 pairs of data items follow)
10442            case 0xA0:
10443            case 0xA1:
10444            case 0xA2:
10445            case 0xA3:
10446            case 0xA4:
10447            case 0xA5:
10448            case 0xA6:
10449            case 0xA7:
10450            case 0xA8:
10451            case 0xA9:
10452            case 0xAA:
10453            case 0xAB:
10454            case 0xAC:
10455            case 0xAD:
10456            case 0xAE:
10457            case 0xAF:
10458            case 0xB0:
10459            case 0xB1:
10460            case 0xB2:
10461            case 0xB3:
10462            case 0xB4:
10463            case 0xB5:
10464            case 0xB6:
10465            case 0xB7:
10466                return get_cbor_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x1Fu), tag_handler);
10467
10468            case 0xB8: // map (one-byte uint8_t for n follows)
10469            {
10470                std::uint8_t len{};
10471                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10472            }
10473
10474            case 0xB9: // map (two-byte uint16_t for n follow)
10475            {
10476                std::uint16_t len{};
10477                return get_number(input_format_t::cbor, len) && get_cbor_object(static_cast<std::size_t>(len), tag_handler);
10478            }
10479
10480            case 0xBA: // map (four-byte uint32_t for n follow)
10481            {
10482                std::uint32_t len{};
10483                return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10484            }
10485
10486            case 0xBB: // map (eight-byte uint64_t for n follow)
10487            {
10488                std::uint64_t len{};
10489                return get_number(input_format_t::cbor, len) && get_cbor_object(conditional_static_cast<std::size_t>(len), tag_handler);
10490            }
10491
10492            case 0xBF: // map (indefinite length)
10493                return get_cbor_object(detail::unknown_size(), tag_handler);
10494
10495            case 0xC6: // tagged item
10496            case 0xC7:
10497            case 0xC8:
10498            case 0xC9:
10499            case 0xCA:
10500            case 0xCB:
10501            case 0xCC:
10502            case 0xCD:
10503            case 0xCE:
10504            case 0xCF:
10505            case 0xD0:
10506            case 0xD1:
10507            case 0xD2:
10508            case 0xD3:
10509            case 0xD4:
10510            case 0xD8: // tagged item (1 bytes follow)
10511            case 0xD9: // tagged item (2 bytes follow)
10512            case 0xDA: // tagged item (4 bytes follow)
10513            case 0xDB: // tagged item (8 bytes follow)
10514            {
10515                switch (tag_handler)
10516                {
10517                    case cbor_tag_handler_t::error:
10518                    {
10519                        auto last_token = get_token_string();
10520                        return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10521                                                exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10522                    }
10523
10524                    case cbor_tag_handler_t::ignore:
10525                    {
10526                        // ignore binary subtype
10527                        switch (current)
10528                        {
10529                            case 0xD8:
10530                            {
10531                                std::uint8_t subtype_to_ignore{};
10532                                get_number(input_format_t::cbor, subtype_to_ignore);
10533                                break;
10534                            }
10535                            case 0xD9:
10536                            {
10537                                std::uint16_t subtype_to_ignore{};
10538                                get_number(input_format_t::cbor, subtype_to_ignore);
10539                                break;
10540                            }
10541                            case 0xDA:
10542                            {
10543                                std::uint32_t subtype_to_ignore{};
10544                                get_number(input_format_t::cbor, subtype_to_ignore);
10545                                break;
10546                            }
10547                            case 0xDB:
10548                            {
10549                                std::uint64_t subtype_to_ignore{};
10550                                get_number(input_format_t::cbor, subtype_to_ignore);
10551                                break;
10552                            }
10553                            default:
10554                                break;
10555                        }
10556                        return parse_cbor_internal(true, tag_handler);
10557                    }
10558
10559                    case cbor_tag_handler_t::store:
10560                    {
10561                        binary_t b;
10562                        // use binary subtype and store in binary container
10563                        switch (current)
10564                        {
10565                            case 0xD8:
10566                            {
10567                                std::uint8_t subtype{};
10568                                get_number(input_format_t::cbor, subtype);
10569                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10570                                break;
10571                            }
10572                            case 0xD9:
10573                            {
10574                                std::uint16_t subtype{};
10575                                get_number(input_format_t::cbor, subtype);
10576                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10577                                break;
10578                            }
10579                            case 0xDA:
10580                            {
10581                                std::uint32_t subtype{};
10582                                get_number(input_format_t::cbor, subtype);
10583                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10584                                break;
10585                            }
10586                            case 0xDB:
10587                            {
10588                                std::uint64_t subtype{};
10589                                get_number(input_format_t::cbor, subtype);
10590                                b.set_subtype(detail::conditional_static_cast<typename binary_t::subtype_type>(subtype));
10591                                break;
10592                            }
10593                            default:
10594                                return parse_cbor_internal(true, tag_handler);
10595                        }
10596                        get();
10597                        return get_cbor_binary(b) && sax->binary(b);
10598                    }
10599
10600                    default:                 // LCOV_EXCL_LINE
10601                        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
10602                        return false;        // LCOV_EXCL_LINE
10603                }
10604            }
10605
10606            case 0xF4: // false
10607                return sax->boolean(false);
10608
10609            case 0xF5: // true
10610                return sax->boolean(true);
10611
10612            case 0xF6: // null
10613                return sax->null();
10614
10615            case 0xF9: // Half-Precision Float (two-byte IEEE 754)
10616            {
10617                const auto byte1_raw = get();
10618                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10619                {
10620                    return false;
10621                }
10622                const auto byte2_raw = get();
10623                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "number")))
10624                {
10625                    return false;
10626                }
10627
10628                const auto byte1 = static_cast<unsigned char>(byte1_raw);
10629                const auto byte2 = static_cast<unsigned char>(byte2_raw);
10630
10631                // code from RFC 7049, Appendix D, Figure 3:
10632                // As half-precision floating-point numbers were only added
10633                // to IEEE 754 in 2008, today's programming platforms often
10634                // still only have limited support for them. It is very
10635                // easy to include at least decoding support for them even
10636                // without such support. An example of a small decoder for
10637                // half-precision floating-point numbers in the C language
10638                // is shown in Fig. 3.
10639                const auto half = static_cast<unsigned int>((byte1 << 8u) + byte2);
10640                const double val = [&half]
10641                {
10642                    const int exp = (half >> 10u) & 0x1Fu;
10643                    const unsigned int mant = half & 0x3FFu;
10644                    JSON_ASSERT(0 <= exp&& exp <= 32);
10645                    JSON_ASSERT(mant <= 1024);
10646                    switch (exp)
10647                    {
10648                        case 0:
10649                            return std::ldexp(mant, -24);
10650                        case 31:
10651                            return (mant == 0)
10652                            ? std::numeric_limits<double>::infinity()
10653                            : std::numeric_limits<double>::quiet_NaN();
10654                        default:
10655                            return std::ldexp(mant + 1024, exp - 25);
10656                    }
10657                }();
10658                return sax->number_float((half & 0x8000u) != 0
10659                                         ? static_cast<number_float_t>(-val)
10660                                         : static_cast<number_float_t>(val), "");
10661            }
10662
10663            case 0xFA: // Single-Precision Float (four-byte IEEE 754)
10664            {
10665                float number{};
10666                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10667            }
10668
10669            case 0xFB: // Double-Precision Float (eight-byte IEEE 754)
10670            {
10671                double number{};
10672                return get_number(input_format_t::cbor, number) && sax->number_float(static_cast<number_float_t>(number), "");
10673            }
10674
10675            default: // anything else (0xFF is handled inside the other types)
10676            {
10677                auto last_token = get_token_string();
10678                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
10679                                        exception_message(input_format_t::cbor, concat("invalid byte: 0x", last_token), "value"), nullptr));
10680            }
10681        }
10682    }
10683
10684    /*!
10685    @brief reads a CBOR string
10686
10687    This function first reads starting bytes to determine the expected
10688    string length and then copies this number of bytes into a string.
10689    Additionally, CBOR's strings with indefinite lengths are supported.
10690
10691    @param[out] result  created string
10692
10693    @return whether string creation completed
10694    */
10695    bool get_cbor_string(string_t& result)
10696    {
10697        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "string")))
10698        {
10699            return false;
10700        }
10701
10702        switch (current)
10703        {
10704            // UTF-8 string (0x00..0x17 bytes follow)
10705            case 0x60:
10706            case 0x61:
10707            case 0x62:
10708            case 0x63:
10709            case 0x64:
10710            case 0x65:
10711            case 0x66:
10712            case 0x67:
10713            case 0x68:
10714            case 0x69:
10715            case 0x6A:
10716            case 0x6B:
10717            case 0x6C:
10718            case 0x6D:
10719            case 0x6E:
10720            case 0x6F:
10721            case 0x70:
10722            case 0x71:
10723            case 0x72:
10724            case 0x73:
10725            case 0x74:
10726            case 0x75:
10727            case 0x76:
10728            case 0x77:
10729            {
10730                return get_string(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10731            }
10732
10733            case 0x78: // UTF-8 string (one-byte uint8_t for n follows)
10734            {
10735                std::uint8_t len{};
10736                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10737            }
10738
10739            case 0x79: // UTF-8 string (two-byte uint16_t for n follow)
10740            {
10741                std::uint16_t len{};
10742                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10743            }
10744
10745            case 0x7A: // UTF-8 string (four-byte uint32_t for n follow)
10746            {
10747                std::uint32_t len{};
10748                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10749            }
10750
10751            case 0x7B: // UTF-8 string (eight-byte uint64_t for n follow)
10752            {
10753                std::uint64_t len{};
10754                return get_number(input_format_t::cbor, len) && get_string(input_format_t::cbor, len, result);
10755            }
10756
10757            case 0x7F: // UTF-8 string (indefinite length)
10758            {
10759                while (get() != 0xFF)
10760                {
10761                    string_t chunk;
10762                    if (!get_cbor_string(chunk))
10763                    {
10764                        return false;
10765                    }
10766                    result.append(chunk);
10767                }
10768                return true;
10769            }
10770
10771            default:
10772            {
10773                auto last_token = get_token_string();
10774                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10775                                        exception_message(input_format_t::cbor, concat("expected length specification (0x60-0x7B) or indefinite string type (0x7F); last byte: 0x", last_token), "string"), nullptr));
10776            }
10777        }
10778    }
10779
10780    /*!
10781    @brief reads a CBOR byte array
10782
10783    This function first reads starting bytes to determine the expected
10784    byte array length and then copies this number of bytes into the byte array.
10785    Additionally, CBOR's byte arrays with indefinite lengths are supported.
10786
10787    @param[out] result  created byte array
10788
10789    @return whether byte array creation completed
10790    */
10791    bool get_cbor_binary(binary_t& result)
10792    {
10793        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::cbor, "binary")))
10794        {
10795            return false;
10796        }
10797
10798        switch (current)
10799        {
10800            // Binary data (0x00..0x17 bytes follow)
10801            case 0x40:
10802            case 0x41:
10803            case 0x42:
10804            case 0x43:
10805            case 0x44:
10806            case 0x45:
10807            case 0x46:
10808            case 0x47:
10809            case 0x48:
10810            case 0x49:
10811            case 0x4A:
10812            case 0x4B:
10813            case 0x4C:
10814            case 0x4D:
10815            case 0x4E:
10816            case 0x4F:
10817            case 0x50:
10818            case 0x51:
10819            case 0x52:
10820            case 0x53:
10821            case 0x54:
10822            case 0x55:
10823            case 0x56:
10824            case 0x57:
10825            {
10826                return get_binary(input_format_t::cbor, static_cast<unsigned int>(current) & 0x1Fu, result);
10827            }
10828
10829            case 0x58: // Binary data (one-byte uint8_t for n follows)
10830            {
10831                std::uint8_t len{};
10832                return get_number(input_format_t::cbor, len) &&
10833                       get_binary(input_format_t::cbor, len, result);
10834            }
10835
10836            case 0x59: // Binary data (two-byte uint16_t for n follow)
10837            {
10838                std::uint16_t len{};
10839                return get_number(input_format_t::cbor, len) &&
10840                       get_binary(input_format_t::cbor, len, result);
10841            }
10842
10843            case 0x5A: // Binary data (four-byte uint32_t for n follow)
10844            {
10845                std::uint32_t len{};
10846                return get_number(input_format_t::cbor, len) &&
10847                       get_binary(input_format_t::cbor, len, result);
10848            }
10849
10850            case 0x5B: // Binary data (eight-byte uint64_t for n follow)
10851            {
10852                std::uint64_t len{};
10853                return get_number(input_format_t::cbor, len) &&
10854                       get_binary(input_format_t::cbor, len, result);
10855            }
10856
10857            case 0x5F: // Binary data (indefinite length)
10858            {
10859                while (get() != 0xFF)
10860                {
10861                    binary_t chunk;
10862                    if (!get_cbor_binary(chunk))
10863                    {
10864                        return false;
10865                    }
10866                    result.insert(result.end(), chunk.begin(), chunk.end());
10867                }
10868                return true;
10869            }
10870
10871            default:
10872            {
10873                auto last_token = get_token_string();
10874                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
10875                                        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));
10876            }
10877        }
10878    }
10879
10880    /*!
10881    @param[in] len  the length of the array or detail::unknown_size() for an
10882                    array of indefinite size
10883    @param[in] tag_handler how CBOR tags should be treated
10884    @return whether array creation completed
10885    */
10886    bool get_cbor_array(const std::size_t len,
10887                        const cbor_tag_handler_t tag_handler)
10888    {
10889        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
10890        {
10891            return false;
10892        }
10893
10894        if (len != detail::unknown_size())
10895        {
10896            for (std::size_t i = 0; i < len; ++i)
10897            {
10898                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10899                {
10900                    return false;
10901                }
10902            }
10903        }
10904        else
10905        {
10906            while (get() != 0xFF)
10907            {
10908                if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(false, tag_handler)))
10909                {
10910                    return false;
10911                }
10912            }
10913        }
10914
10915        return sax->end_array();
10916    }
10917
10918    /*!
10919    @param[in] len  the length of the object or detail::unknown_size() for an
10920                    object of indefinite size
10921    @param[in] tag_handler how CBOR tags should be treated
10922    @return whether object creation completed
10923    */
10924    bool get_cbor_object(const std::size_t len,
10925                         const cbor_tag_handler_t tag_handler)
10926    {
10927        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
10928        {
10929            return false;
10930        }
10931
10932        if (len != 0)
10933        {
10934            string_t key;
10935            if (len != detail::unknown_size())
10936            {
10937                for (std::size_t i = 0; i < len; ++i)
10938                {
10939                    get();
10940                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10941                    {
10942                        return false;
10943                    }
10944
10945                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10946                    {
10947                        return false;
10948                    }
10949                    key.clear();
10950                }
10951            }
10952            else
10953            {
10954                while (get() != 0xFF)
10955                {
10956                    if (JSON_HEDLEY_UNLIKELY(!get_cbor_string(key) || !sax->key(key)))
10957                    {
10958                        return false;
10959                    }
10960
10961                    if (JSON_HEDLEY_UNLIKELY(!parse_cbor_internal(true, tag_handler)))
10962                    {
10963                        return false;
10964                    }
10965                    key.clear();
10966                }
10967            }
10968        }
10969
10970        return sax->end_object();
10971    }
10972
10973    /////////////
10974    // MsgPack //
10975    /////////////
10976
10977    /*!
10978    @return whether a valid MessagePack value was passed to the SAX parser
10979    */
10980    bool parse_msgpack_internal()
10981    {
10982        switch (get())
10983        {
10984            // EOF
10985            case char_traits<char_type>::eof():
10986                return unexpect_eof(input_format_t::msgpack, "value");
10987
10988            // positive fixint
10989            case 0x00:
10990            case 0x01:
10991            case 0x02:
10992            case 0x03:
10993            case 0x04:
10994            case 0x05:
10995            case 0x06:
10996            case 0x07:
10997            case 0x08:
10998            case 0x09:
10999            case 0x0A:
11000            case 0x0B:
11001            case 0x0C:
11002            case 0x0D:
11003            case 0x0E:
11004            case 0x0F:
11005            case 0x10:
11006            case 0x11:
11007            case 0x12:
11008            case 0x13:
11009            case 0x14:
11010            case 0x15:
11011            case 0x16:
11012            case 0x17:
11013            case 0x18:
11014            case 0x19:
11015            case 0x1A:
11016            case 0x1B:
11017            case 0x1C:
11018            case 0x1D:
11019            case 0x1E:
11020            case 0x1F:
11021            case 0x20:
11022            case 0x21:
11023            case 0x22:
11024            case 0x23:
11025            case 0x24:
11026            case 0x25:
11027            case 0x26:
11028            case 0x27:
11029            case 0x28:
11030            case 0x29:
11031            case 0x2A:
11032            case 0x2B:
11033            case 0x2C:
11034            case 0x2D:
11035            case 0x2E:
11036            case 0x2F:
11037            case 0x30:
11038            case 0x31:
11039            case 0x32:
11040            case 0x33:
11041            case 0x34:
11042            case 0x35:
11043            case 0x36:
11044            case 0x37:
11045            case 0x38:
11046            case 0x39:
11047            case 0x3A:
11048            case 0x3B:
11049            case 0x3C:
11050            case 0x3D:
11051            case 0x3E:
11052            case 0x3F:
11053            case 0x40:
11054            case 0x41:
11055            case 0x42:
11056            case 0x43:
11057            case 0x44:
11058            case 0x45:
11059            case 0x46:
11060            case 0x47:
11061            case 0x48:
11062            case 0x49:
11063            case 0x4A:
11064            case 0x4B:
11065            case 0x4C:
11066            case 0x4D:
11067            case 0x4E:
11068            case 0x4F:
11069            case 0x50:
11070            case 0x51:
11071            case 0x52:
11072            case 0x53:
11073            case 0x54:
11074            case 0x55:
11075            case 0x56:
11076            case 0x57:
11077            case 0x58:
11078            case 0x59:
11079            case 0x5A:
11080            case 0x5B:
11081            case 0x5C:
11082            case 0x5D:
11083            case 0x5E:
11084            case 0x5F:
11085            case 0x60:
11086            case 0x61:
11087            case 0x62:
11088            case 0x63:
11089            case 0x64:
11090            case 0x65:
11091            case 0x66:
11092            case 0x67:
11093            case 0x68:
11094            case 0x69:
11095            case 0x6A:
11096            case 0x6B:
11097            case 0x6C:
11098            case 0x6D:
11099            case 0x6E:
11100            case 0x6F:
11101            case 0x70:
11102            case 0x71:
11103            case 0x72:
11104            case 0x73:
11105            case 0x74:
11106            case 0x75:
11107            case 0x76:
11108            case 0x77:
11109            case 0x78:
11110            case 0x79:
11111            case 0x7A:
11112            case 0x7B:
11113            case 0x7C:
11114            case 0x7D:
11115            case 0x7E:
11116            case 0x7F:
11117                return sax->number_unsigned(static_cast<number_unsigned_t>(current));
11118
11119            // fixmap
11120            case 0x80:
11121            case 0x81:
11122            case 0x82:
11123            case 0x83:
11124            case 0x84:
11125            case 0x85:
11126            case 0x86:
11127            case 0x87:
11128            case 0x88:
11129            case 0x89:
11130            case 0x8A:
11131            case 0x8B:
11132            case 0x8C:
11133            case 0x8D:
11134            case 0x8E:
11135            case 0x8F:
11136                return get_msgpack_object(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11137
11138            // fixarray
11139            case 0x90:
11140            case 0x91:
11141            case 0x92:
11142            case 0x93:
11143            case 0x94:
11144            case 0x95:
11145            case 0x96:
11146            case 0x97:
11147            case 0x98:
11148            case 0x99:
11149            case 0x9A:
11150            case 0x9B:
11151            case 0x9C:
11152            case 0x9D:
11153            case 0x9E:
11154            case 0x9F:
11155                return get_msgpack_array(conditional_static_cast<std::size_t>(static_cast<unsigned int>(current) & 0x0Fu));
11156
11157            // fixstr
11158            case 0xA0:
11159            case 0xA1:
11160            case 0xA2:
11161            case 0xA3:
11162            case 0xA4:
11163            case 0xA5:
11164            case 0xA6:
11165            case 0xA7:
11166            case 0xA8:
11167            case 0xA9:
11168            case 0xAA:
11169            case 0xAB:
11170            case 0xAC:
11171            case 0xAD:
11172            case 0xAE:
11173            case 0xAF:
11174            case 0xB0:
11175            case 0xB1:
11176            case 0xB2:
11177            case 0xB3:
11178            case 0xB4:
11179            case 0xB5:
11180            case 0xB6:
11181            case 0xB7:
11182            case 0xB8:
11183            case 0xB9:
11184            case 0xBA:
11185            case 0xBB:
11186            case 0xBC:
11187            case 0xBD:
11188            case 0xBE:
11189            case 0xBF:
11190            case 0xD9: // str 8
11191            case 0xDA: // str 16
11192            case 0xDB: // str 32
11193            {
11194                string_t s;
11195                return get_msgpack_string(s) && sax->string(s);
11196            }
11197
11198            case 0xC0: // nil
11199                return sax->null();
11200
11201            case 0xC2: // false
11202                return sax->boolean(false);
11203
11204            case 0xC3: // true
11205                return sax->boolean(true);
11206
11207            case 0xC4: // bin 8
11208            case 0xC5: // bin 16
11209            case 0xC6: // bin 32
11210            case 0xC7: // ext 8
11211            case 0xC8: // ext 16
11212            case 0xC9: // ext 32
11213            case 0xD4: // fixext 1
11214            case 0xD5: // fixext 2
11215            case 0xD6: // fixext 4
11216            case 0xD7: // fixext 8
11217            case 0xD8: // fixext 16
11218            {
11219                binary_t b;
11220                return get_msgpack_binary(b) && sax->binary(b);
11221            }
11222
11223            case 0xCA: // float 32
11224            {
11225                float number{};
11226                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11227            }
11228
11229            case 0xCB: // float 64
11230            {
11231                double number{};
11232                return get_number(input_format_t::msgpack, number) && sax->number_float(static_cast<number_float_t>(number), "");
11233            }
11234
11235            case 0xCC: // uint 8
11236            {
11237                std::uint8_t number{};
11238                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11239            }
11240
11241            case 0xCD: // uint 16
11242            {
11243                std::uint16_t number{};
11244                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11245            }
11246
11247            case 0xCE: // uint 32
11248            {
11249                std::uint32_t number{};
11250                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11251            }
11252
11253            case 0xCF: // uint 64
11254            {
11255                std::uint64_t number{};
11256                return get_number(input_format_t::msgpack, number) && sax->number_unsigned(number);
11257            }
11258
11259            case 0xD0: // int 8
11260            {
11261                std::int8_t number{};
11262                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11263            }
11264
11265            case 0xD1: // int 16
11266            {
11267                std::int16_t number{};
11268                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11269            }
11270
11271            case 0xD2: // int 32
11272            {
11273                std::int32_t number{};
11274                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11275            }
11276
11277            case 0xD3: // int 64
11278            {
11279                std::int64_t number{};
11280                return get_number(input_format_t::msgpack, number) && sax->number_integer(number);
11281            }
11282
11283            case 0xDC: // array 16
11284            {
11285                std::uint16_t len{};
11286                return get_number(input_format_t::msgpack, len) && get_msgpack_array(static_cast<std::size_t>(len));
11287            }
11288
11289            case 0xDD: // array 32
11290            {
11291                std::uint32_t len{};
11292                return get_number(input_format_t::msgpack, len) && get_msgpack_array(conditional_static_cast<std::size_t>(len));
11293            }
11294
11295            case 0xDE: // map 16
11296            {
11297                std::uint16_t len{};
11298                return get_number(input_format_t::msgpack, len) && get_msgpack_object(static_cast<std::size_t>(len));
11299            }
11300
11301            case 0xDF: // map 32
11302            {
11303                std::uint32_t len{};
11304                return get_number(input_format_t::msgpack, len) && get_msgpack_object(conditional_static_cast<std::size_t>(len));
11305            }
11306
11307            // negative fixint
11308            case 0xE0:
11309            case 0xE1:
11310            case 0xE2:
11311            case 0xE3:
11312            case 0xE4:
11313            case 0xE5:
11314            case 0xE6:
11315            case 0xE7:
11316            case 0xE8:
11317            case 0xE9:
11318            case 0xEA:
11319            case 0xEB:
11320            case 0xEC:
11321            case 0xED:
11322            case 0xEE:
11323            case 0xEF:
11324            case 0xF0:
11325            case 0xF1:
11326            case 0xF2:
11327            case 0xF3:
11328            case 0xF4:
11329            case 0xF5:
11330            case 0xF6:
11331            case 0xF7:
11332            case 0xF8:
11333            case 0xF9:
11334            case 0xFA:
11335            case 0xFB:
11336            case 0xFC:
11337            case 0xFD:
11338            case 0xFE:
11339            case 0xFF:
11340                return sax->number_integer(static_cast<std::int8_t>(current));
11341
11342            default: // anything else
11343            {
11344                auto last_token = get_token_string();
11345                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
11346                                        exception_message(input_format_t::msgpack, concat("invalid byte: 0x", last_token), "value"), nullptr));
11347            }
11348        }
11349    }
11350
11351    /*!
11352    @brief reads a MessagePack string
11353
11354    This function first reads starting bytes to determine the expected
11355    string length and then copies this number of bytes into a string.
11356
11357    @param[out] result  created string
11358
11359    @return whether string creation completed
11360    */
11361    bool get_msgpack_string(string_t& result)
11362    {
11363        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format_t::msgpack, "string")))
11364        {
11365            return false;
11366        }
11367
11368        switch (current)
11369        {
11370            // fixstr
11371            case 0xA0:
11372            case 0xA1:
11373            case 0xA2:
11374            case 0xA3:
11375            case 0xA4:
11376            case 0xA5:
11377            case 0xA6:
11378            case 0xA7:
11379            case 0xA8:
11380            case 0xA9:
11381            case 0xAA:
11382            case 0xAB:
11383            case 0xAC:
11384            case 0xAD:
11385            case 0xAE:
11386            case 0xAF:
11387            case 0xB0:
11388            case 0xB1:
11389            case 0xB2:
11390            case 0xB3:
11391            case 0xB4:
11392            case 0xB5:
11393            case 0xB6:
11394            case 0xB7:
11395            case 0xB8:
11396            case 0xB9:
11397            case 0xBA:
11398            case 0xBB:
11399            case 0xBC:
11400            case 0xBD:
11401            case 0xBE:
11402            case 0xBF:
11403            {
11404                return get_string(input_format_t::msgpack, static_cast<unsigned int>(current) & 0x1Fu, result);
11405            }
11406
11407            case 0xD9: // str 8
11408            {
11409                std::uint8_t len{};
11410                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11411            }
11412
11413            case 0xDA: // str 16
11414            {
11415                std::uint16_t len{};
11416                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11417            }
11418
11419            case 0xDB: // str 32
11420            {
11421                std::uint32_t len{};
11422                return get_number(input_format_t::msgpack, len) && get_string(input_format_t::msgpack, len, result);
11423            }
11424
11425            default:
11426            {
11427                auto last_token = get_token_string();
11428                return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
11429                                        exception_message(input_format_t::msgpack, concat("expected length specification (0xA0-0xBF, 0xD9-0xDB); last byte: 0x", last_token), "string"), nullptr));
11430            }
11431        }
11432    }
11433
11434    /*!
11435    @brief reads a MessagePack byte array
11436
11437    This function first reads starting bytes to determine the expected
11438    byte array length and then copies this number of bytes into a byte array.
11439
11440    @param[out] result  created byte array
11441
11442    @return whether byte array creation completed
11443    */
11444    bool get_msgpack_binary(binary_t& result)
11445    {
11446        // helper function to set the subtype
11447        auto assign_and_return_true = [&result](std::int8_t subtype)
11448        {
11449            result.set_subtype(static_cast<std::uint8_t>(subtype));
11450            return true;
11451        };
11452
11453        switch (current)
11454        {
11455            case 0xC4: // bin 8
11456            {
11457                std::uint8_t len{};
11458                return get_number(input_format_t::msgpack, len) &&
11459                       get_binary(input_format_t::msgpack, len, result);
11460            }
11461
11462            case 0xC5: // bin 16
11463            {
11464                std::uint16_t len{};
11465                return get_number(input_format_t::msgpack, len) &&
11466                       get_binary(input_format_t::msgpack, len, result);
11467            }
11468
11469            case 0xC6: // bin 32
11470            {
11471                std::uint32_t len{};
11472                return get_number(input_format_t::msgpack, len) &&
11473                       get_binary(input_format_t::msgpack, len, result);
11474            }
11475
11476            case 0xC7: // ext 8
11477            {
11478                std::uint8_t len{};
11479                std::int8_t subtype{};
11480                return get_number(input_format_t::msgpack, len) &&
11481                       get_number(input_format_t::msgpack, subtype) &&
11482                       get_binary(input_format_t::msgpack, len, result) &&
11483                       assign_and_return_true(subtype);
11484            }
11485
11486            case 0xC8: // ext 16
11487            {
11488                std::uint16_t len{};
11489                std::int8_t subtype{};
11490                return get_number(input_format_t::msgpack, len) &&
11491                       get_number(input_format_t::msgpack, subtype) &&
11492                       get_binary(input_format_t::msgpack, len, result) &&
11493                       assign_and_return_true(subtype);
11494            }
11495
11496            case 0xC9: // ext 32
11497            {
11498                std::uint32_t len{};
11499                std::int8_t subtype{};
11500                return get_number(input_format_t::msgpack, len) &&
11501                       get_number(input_format_t::msgpack, subtype) &&
11502                       get_binary(input_format_t::msgpack, len, result) &&
11503                       assign_and_return_true(subtype);
11504            }
11505
11506            case 0xD4: // fixext 1
11507            {
11508                std::int8_t subtype{};
11509                return get_number(input_format_t::msgpack, subtype) &&
11510                       get_binary(input_format_t::msgpack, 1, result) &&
11511                       assign_and_return_true(subtype);
11512            }
11513
11514            case 0xD5: // fixext 2
11515            {
11516                std::int8_t subtype{};
11517                return get_number(input_format_t::msgpack, subtype) &&
11518                       get_binary(input_format_t::msgpack, 2, result) &&
11519                       assign_and_return_true(subtype);
11520            }
11521
11522            case 0xD6: // fixext 4
11523            {
11524                std::int8_t subtype{};
11525                return get_number(input_format_t::msgpack, subtype) &&
11526                       get_binary(input_format_t::msgpack, 4, result) &&
11527                       assign_and_return_true(subtype);
11528            }
11529
11530            case 0xD7: // fixext 8
11531            {
11532                std::int8_t subtype{};
11533                return get_number(input_format_t::msgpack, subtype) &&
11534                       get_binary(input_format_t::msgpack, 8, result) &&
11535                       assign_and_return_true(subtype);
11536            }
11537
11538            case 0xD8: // fixext 16
11539            {
11540                std::int8_t subtype{};
11541                return get_number(input_format_t::msgpack, subtype) &&
11542                       get_binary(input_format_t::msgpack, 16, result) &&
11543                       assign_and_return_true(subtype);
11544            }
11545
11546            default:           // LCOV_EXCL_LINE
11547                return false;  // LCOV_EXCL_LINE
11548        }
11549    }
11550
11551    /*!
11552    @param[in] len  the length of the array
11553    @return whether array creation completed
11554    */
11555    bool get_msgpack_array(const std::size_t len)
11556    {
11557        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(len)))
11558        {
11559            return false;
11560        }
11561
11562        for (std::size_t i = 0; i < len; ++i)
11563        {
11564            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11565            {
11566                return false;
11567            }
11568        }
11569
11570        return sax->end_array();
11571    }
11572
11573    /*!
11574    @param[in] len  the length of the object
11575    @return whether object creation completed
11576    */
11577    bool get_msgpack_object(const std::size_t len)
11578    {
11579        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(len)))
11580        {
11581            return false;
11582        }
11583
11584        string_t key;
11585        for (std::size_t i = 0; i < len; ++i)
11586        {
11587            get();
11588            if (JSON_HEDLEY_UNLIKELY(!get_msgpack_string(key) || !sax->key(key)))
11589            {
11590                return false;
11591            }
11592
11593            if (JSON_HEDLEY_UNLIKELY(!parse_msgpack_internal()))
11594            {
11595                return false;
11596            }
11597            key.clear();
11598        }
11599
11600        return sax->end_object();
11601    }
11602
11603    ////////////
11604    // UBJSON //
11605    ////////////
11606
11607    /*!
11608    @param[in] get_char  whether a new character should be retrieved from the
11609                         input (true, default) or whether the last read
11610                         character should be considered instead
11611
11612    @return whether a valid UBJSON value was passed to the SAX parser
11613    */
11614    bool parse_ubjson_internal(const bool get_char = true)
11615    {
11616        return get_ubjson_value(get_char ? get_ignore_noop() : current);
11617    }
11618
11619    /*!
11620    @brief reads a UBJSON string
11621
11622    This function is either called after reading the 'S' byte explicitly
11623    indicating a string, or in case of an object key where the 'S' byte can be
11624    left out.
11625
11626    @param[out] result   created string
11627    @param[in] get_char  whether a new character should be retrieved from the
11628                         input (true, default) or whether the last read
11629                         character should be considered instead
11630
11631    @return whether string creation completed
11632    */
11633    bool get_ubjson_string(string_t& result, const bool get_char = true)
11634    {
11635        if (get_char)
11636        {
11637            get();  // TODO(niels): may we ignore N here?
11638        }
11639
11640        if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
11641        {
11642            return false;
11643        }
11644
11645        switch (current)
11646        {
11647            case 'U':
11648            {
11649                std::uint8_t len{};
11650                return get_number(input_format, len) && get_string(input_format, len, result);
11651            }
11652
11653            case 'i':
11654            {
11655                std::int8_t len{};
11656                return get_number(input_format, len) && get_string(input_format, len, result);
11657            }
11658
11659            case 'I':
11660            {
11661                std::int16_t len{};
11662                return get_number(input_format, len) && get_string(input_format, len, result);
11663            }
11664
11665            case 'l':
11666            {
11667                std::int32_t len{};
11668                return get_number(input_format, len) && get_string(input_format, len, result);
11669            }
11670
11671            case 'L':
11672            {
11673                std::int64_t len{};
11674                return get_number(input_format, len) && get_string(input_format, len, result);
11675            }
11676
11677            case 'u':
11678            {
11679                if (input_format != input_format_t::bjdata)
11680                {
11681                    break;
11682                }
11683                std::uint16_t len{};
11684                return get_number(input_format, len) && get_string(input_format, len, result);
11685            }
11686
11687            case 'm':
11688            {
11689                if (input_format != input_format_t::bjdata)
11690                {
11691                    break;
11692                }
11693                std::uint32_t len{};
11694                return get_number(input_format, len) && get_string(input_format, len, result);
11695            }
11696
11697            case 'M':
11698            {
11699                if (input_format != input_format_t::bjdata)
11700                {
11701                    break;
11702                }
11703                std::uint64_t len{};
11704                return get_number(input_format, len) && get_string(input_format, len, result);
11705            }
11706
11707            default:
11708                break;
11709        }
11710        auto last_token = get_token_string();
11711        std::string message;
11712
11713        if (input_format != input_format_t::bjdata)
11714        {
11715            message = "expected length type specification (U, i, I, l, L); last byte: 0x" + last_token;
11716        }
11717        else
11718        {
11719            message = "expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x" + last_token;
11720        }
11721        return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "string"), nullptr));
11722    }
11723
11724    /*!
11725    @param[out] dim  an integer vector storing the ND array dimensions
11726    @return whether reading ND array size vector is successful
11727    */
11728    bool get_ubjson_ndarray_size(std::vector<size_t>& dim)
11729    {
11730        std::pair<std::size_t, char_int_type> size_and_type;
11731        size_t dimlen = 0;
11732        bool no_ndarray = true;
11733
11734        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type, no_ndarray)))
11735        {
11736            return false;
11737        }
11738
11739        if (size_and_type.first != npos)
11740        {
11741            if (size_and_type.second != 0)
11742            {
11743                if (size_and_type.second != 'N')
11744                {
11745                    for (std::size_t i = 0; i < size_and_type.first; ++i)
11746                    {
11747                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, size_and_type.second)))
11748                        {
11749                            return false;
11750                        }
11751                        dim.push_back(dimlen);
11752                    }
11753                }
11754            }
11755            else
11756            {
11757                for (std::size_t i = 0; i < size_and_type.first; ++i)
11758                {
11759                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray)))
11760                    {
11761                        return false;
11762                    }
11763                    dim.push_back(dimlen);
11764                }
11765            }
11766        }
11767        else
11768        {
11769            while (current != ']')
11770            {
11771                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_value(dimlen, no_ndarray, current)))
11772                {
11773                    return false;
11774                }
11775                dim.push_back(dimlen);
11776                get_ignore_noop();
11777            }
11778        }
11779        return true;
11780    }
11781
11782    /*!
11783    @param[out] result  determined size
11784    @param[in,out] is_ndarray  for input, `true` means already inside an ndarray vector
11785                               or ndarray dimension is not allowed; `false` means ndarray
11786                               is allowed; for output, `true` means an ndarray is found;
11787                               is_ndarray can only return `true` when its initial value
11788                               is `false`
11789    @param[in] prefix  type marker if already read, otherwise set to 0
11790
11791    @return whether size determination completed
11792    */
11793    bool get_ubjson_size_value(std::size_t& result, bool& is_ndarray, char_int_type prefix = 0)
11794    {
11795        if (prefix == 0)
11796        {
11797            prefix = get_ignore_noop();
11798        }
11799
11800        switch (prefix)
11801        {
11802            case 'U':
11803            {
11804                std::uint8_t number{};
11805                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11806                {
11807                    return false;
11808                }
11809                result = static_cast<std::size_t>(number);
11810                return true;
11811            }
11812
11813            case 'i':
11814            {
11815                std::int8_t number{};
11816                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11817                {
11818                    return false;
11819                }
11820                if (number < 0)
11821                {
11822                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11823                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11824                }
11825                result = static_cast<std::size_t>(number); // NOLINT(bugprone-signed-char-misuse,cert-str34-c): number is not a char
11826                return true;
11827            }
11828
11829            case 'I':
11830            {
11831                std::int16_t number{};
11832                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11833                {
11834                    return false;
11835                }
11836                if (number < 0)
11837                {
11838                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11839                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11840                }
11841                result = static_cast<std::size_t>(number);
11842                return true;
11843            }
11844
11845            case 'l':
11846            {
11847                std::int32_t number{};
11848                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11849                {
11850                    return false;
11851                }
11852                if (number < 0)
11853                {
11854                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11855                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11856                }
11857                result = static_cast<std::size_t>(number);
11858                return true;
11859            }
11860
11861            case 'L':
11862            {
11863                std::int64_t number{};
11864                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11865                {
11866                    return false;
11867                }
11868                if (number < 0)
11869                {
11870                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(113, chars_read,
11871                                            exception_message(input_format, "count in an optimized container must be positive", "size"), nullptr));
11872                }
11873                if (!value_in_range_of<std::size_t>(number))
11874                {
11875                    return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11876                                            exception_message(input_format, "integer value overflow", "size"), nullptr));
11877                }
11878                result = static_cast<std::size_t>(number);
11879                return true;
11880            }
11881
11882            case 'u':
11883            {
11884                if (input_format != input_format_t::bjdata)
11885                {
11886                    break;
11887                }
11888                std::uint16_t number{};
11889                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11890                {
11891                    return false;
11892                }
11893                result = static_cast<std::size_t>(number);
11894                return true;
11895            }
11896
11897            case 'm':
11898            {
11899                if (input_format != input_format_t::bjdata)
11900                {
11901                    break;
11902                }
11903                std::uint32_t number{};
11904                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11905                {
11906                    return false;
11907                }
11908                result = conditional_static_cast<std::size_t>(number);
11909                return true;
11910            }
11911
11912            case 'M':
11913            {
11914                if (input_format != input_format_t::bjdata)
11915                {
11916                    break;
11917                }
11918                std::uint64_t number{};
11919                if (JSON_HEDLEY_UNLIKELY(!get_number(input_format, number)))
11920                {
11921                    return false;
11922                }
11923                if (!value_in_range_of<std::size_t>(number))
11924                {
11925                    return sax->parse_error(chars_read, get_token_string(), out_of_range::create(408,
11926                                            exception_message(input_format, "integer value overflow", "size"), nullptr));
11927                }
11928                result = detail::conditional_static_cast<std::size_t>(number);
11929                return true;
11930            }
11931
11932            case '[':
11933            {
11934                if (input_format != input_format_t::bjdata)
11935                {
11936                    break;
11937                }
11938                if (is_ndarray) // ndarray dimensional vector can only contain integers, and can not embed another array
11939                {
11940                    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));
11941                }
11942                std::vector<size_t> dim;
11943                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_ndarray_size(dim)))
11944                {
11945                    return false;
11946                }
11947                if (dim.size() == 1 || (dim.size() == 2 && dim.at(0) == 1)) // return normal array size if 1D row vector
11948                {
11949                    result = dim.at(dim.size() - 1);
11950                    return true;
11951                }
11952                if (!dim.empty())  // if ndarray, convert to an object in JData annotated array format
11953                {
11954                    for (auto i : dim) // test if any dimension in an ndarray is 0, if so, return a 1D empty container
11955                    {
11956                        if ( i == 0 )
11957                        {
11958                            result = 0;
11959                            return true;
11960                        }
11961                    }
11962
11963                    string_t key = "_ArraySize_";
11964                    if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size())))
11965                    {
11966                        return false;
11967                    }
11968                    result = 1;
11969                    for (auto i : dim)
11970                    {
11971                        result *= i;
11972                        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()
11973                        {
11974                            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));
11975                        }
11976                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(static_cast<number_unsigned_t>(i))))
11977                        {
11978                            return false;
11979                        }
11980                    }
11981                    is_ndarray = true;
11982                    return sax->end_array();
11983                }
11984                result = 0;
11985                return true;
11986            }
11987
11988            default:
11989                break;
11990        }
11991        auto last_token = get_token_string();
11992        std::string message;
11993
11994        if (input_format != input_format_t::bjdata)
11995        {
11996            message = "expected length type specification (U, i, I, l, L) after '#'; last byte: 0x" + last_token;
11997        }
11998        else
11999        {
12000            message = "expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x" + last_token;
12001        }
12002        return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read, exception_message(input_format, message, "size"), nullptr));
12003    }
12004
12005    /*!
12006    @brief determine the type and size for a container
12007
12008    In the optimized UBJSON format, a type and a size can be provided to allow
12009    for a more compact representation.
12010
12011    @param[out] result  pair of the size and the type
12012    @param[in] inside_ndarray  whether the parser is parsing an ND array dimensional vector
12013
12014    @return whether pair creation completed
12015    */
12016    bool get_ubjson_size_type(std::pair<std::size_t, char_int_type>& result, bool inside_ndarray = false)
12017    {
12018        result.first = npos; // size
12019        result.second = 0; // type
12020        bool is_ndarray = false;
12021
12022        get_ignore_noop();
12023
12024        if (current == '$')
12025        {
12026            result.second = get();  // must not ignore 'N', because 'N' maybe the type
12027            if (input_format == input_format_t::bjdata
12028                    && JSON_HEDLEY_UNLIKELY(std::binary_search(bjd_optimized_type_markers.begin(), bjd_optimized_type_markers.end(), result.second)))
12029            {
12030                auto last_token = get_token_string();
12031                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12032                                        exception_message(input_format, concat("marker 0x", last_token, " is not a permitted optimized array type"), "type"), nullptr));
12033            }
12034
12035            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "type")))
12036            {
12037                return false;
12038            }
12039
12040            get_ignore_noop();
12041            if (JSON_HEDLEY_UNLIKELY(current != '#'))
12042            {
12043                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "value")))
12044                {
12045                    return false;
12046                }
12047                auto last_token = get_token_string();
12048                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12049                                        exception_message(input_format, concat("expected '#' after type information; last byte: 0x", last_token), "size"), nullptr));
12050            }
12051
12052            const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12053            if (input_format == input_format_t::bjdata && is_ndarray)
12054            {
12055                if (inside_ndarray)
12056                {
12057                    return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12058                                            exception_message(input_format, "ndarray can not be recursive", "size"), nullptr));
12059                }
12060                result.second |= (1 << 8); // use bit 8 to indicate ndarray, all UBJSON and BJData markers should be ASCII letters
12061            }
12062            return is_error;
12063        }
12064
12065        if (current == '#')
12066        {
12067            const bool is_error = get_ubjson_size_value(result.first, is_ndarray);
12068            if (input_format == input_format_t::bjdata && is_ndarray)
12069            {
12070                return sax->parse_error(chars_read, get_token_string(), parse_error::create(112, chars_read,
12071                                        exception_message(input_format, "ndarray requires both type and size", "size"), nullptr));
12072            }
12073            return is_error;
12074        }
12075
12076        return true;
12077    }
12078
12079    /*!
12080    @param prefix  the previously read or set type prefix
12081    @return whether value creation completed
12082    */
12083    bool get_ubjson_value(const char_int_type prefix)
12084    {
12085        switch (prefix)
12086        {
12087            case char_traits<char_type>::eof():  // EOF
12088                return unexpect_eof(input_format, "value");
12089
12090            case 'T':  // true
12091                return sax->boolean(true);
12092            case 'F':  // false
12093                return sax->boolean(false);
12094
12095            case 'Z':  // null
12096                return sax->null();
12097
12098            case 'B':  // byte
12099            {
12100                if (input_format != input_format_t::bjdata)
12101                {
12102                    break;
12103                }
12104                std::uint8_t number{};
12105                return get_number(input_format, number) && sax->number_unsigned(number);
12106            }
12107
12108            case 'U':
12109            {
12110                std::uint8_t number{};
12111                return get_number(input_format, number) && sax->number_unsigned(number);
12112            }
12113
12114            case 'i':
12115            {
12116                std::int8_t number{};
12117                return get_number(input_format, number) && sax->number_integer(number);
12118            }
12119
12120            case 'I':
12121            {
12122                std::int16_t number{};
12123                return get_number(input_format, number) && sax->number_integer(number);
12124            }
12125
12126            case 'l':
12127            {
12128                std::int32_t number{};
12129                return get_number(input_format, number) && sax->number_integer(number);
12130            }
12131
12132            case 'L':
12133            {
12134                std::int64_t number{};
12135                return get_number(input_format, number) && sax->number_integer(number);
12136            }
12137
12138            case 'u':
12139            {
12140                if (input_format != input_format_t::bjdata)
12141                {
12142                    break;
12143                }
12144                std::uint16_t number{};
12145                return get_number(input_format, number) && sax->number_unsigned(number);
12146            }
12147
12148            case 'm':
12149            {
12150                if (input_format != input_format_t::bjdata)
12151                {
12152                    break;
12153                }
12154                std::uint32_t number{};
12155                return get_number(input_format, number) && sax->number_unsigned(number);
12156            }
12157
12158            case 'M':
12159            {
12160                if (input_format != input_format_t::bjdata)
12161                {
12162                    break;
12163                }
12164                std::uint64_t number{};
12165                return get_number(input_format, number) && sax->number_unsigned(number);
12166            }
12167
12168            case 'h':
12169            {
12170                if (input_format != input_format_t::bjdata)
12171                {
12172                    break;
12173                }
12174                const auto byte1_raw = get();
12175                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12176                {
12177                    return false;
12178                }
12179                const auto byte2_raw = get();
12180                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12181                {
12182                    return false;
12183                }
12184
12185                const auto byte1 = static_cast<unsigned char>(byte1_raw);
12186                const auto byte2 = static_cast<unsigned char>(byte2_raw);
12187
12188                // code from RFC 7049, Appendix D, Figure 3:
12189                // As half-precision floating-point numbers were only added
12190                // to IEEE 754 in 2008, today's programming platforms often
12191                // still only have limited support for them. It is very
12192                // easy to include at least decoding support for them even
12193                // without such support. An example of a small decoder for
12194                // half-precision floating-point numbers in the C language
12195                // is shown in Fig. 3.
12196                const auto half = static_cast<unsigned int>((byte2 << 8u) + byte1);
12197                const double val = [&half]
12198                {
12199                    const int exp = (half >> 10u) & 0x1Fu;
12200                    const unsigned int mant = half & 0x3FFu;
12201                    JSON_ASSERT(0 <= exp&& exp <= 32);
12202                    JSON_ASSERT(mant <= 1024);
12203                    switch (exp)
12204                    {
12205                        case 0:
12206                            return std::ldexp(mant, -24);
12207                        case 31:
12208                            return (mant == 0)
12209                            ? std::numeric_limits<double>::infinity()
12210                            : std::numeric_limits<double>::quiet_NaN();
12211                        default:
12212                            return std::ldexp(mant + 1024, exp - 25);
12213                    }
12214                }();
12215                return sax->number_float((half & 0x8000u) != 0
12216                                         ? static_cast<number_float_t>(-val)
12217                                         : static_cast<number_float_t>(val), "");
12218            }
12219
12220            case 'd':
12221            {
12222                float number{};
12223                return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12224            }
12225
12226            case 'D':
12227            {
12228                double number{};
12229                return get_number(input_format, number) && sax->number_float(static_cast<number_float_t>(number), "");
12230            }
12231
12232            case 'H':
12233            {
12234                return get_ubjson_high_precision_number();
12235            }
12236
12237            case 'C':  // char
12238            {
12239                get();
12240                if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "char")))
12241                {
12242                    return false;
12243                }
12244                if (JSON_HEDLEY_UNLIKELY(current > 127))
12245                {
12246                    auto last_token = get_token_string();
12247                    return sax->parse_error(chars_read, last_token, parse_error::create(113, chars_read,
12248                                            exception_message(input_format, concat("byte after 'C' must be in range 0x00..0x7F; last byte: 0x", last_token), "char"), nullptr));
12249                }
12250                string_t s(1, static_cast<typename string_t::value_type>(current));
12251                return sax->string(s);
12252            }
12253
12254            case 'S':  // string
12255            {
12256                string_t s;
12257                return get_ubjson_string(s) && sax->string(s);
12258            }
12259
12260            case '[':  // array
12261                return get_ubjson_array();
12262
12263            case '{':  // object
12264                return get_ubjson_object();
12265
12266            default: // anything else
12267                break;
12268        }
12269        auto last_token = get_token_string();
12270        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));
12271    }
12272
12273    /*!
12274    @return whether array creation completed
12275    */
12276    bool get_ubjson_array()
12277    {
12278        std::pair<std::size_t, char_int_type> size_and_type;
12279        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12280        {
12281            return false;
12282        }
12283
12284        // 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):
12285        // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]}
12286
12287        if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12288        {
12289            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
12290            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)
12291            {
12292                return p.first < t;
12293            });
12294            string_t key = "_ArrayType_";
12295            if (JSON_HEDLEY_UNLIKELY(it == bjd_types_map.end() || it->first != size_and_type.second))
12296            {
12297                auto last_token = get_token_string();
12298                return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12299                                        exception_message(input_format, "invalid byte: 0x" + last_token, "type"), nullptr));
12300            }
12301
12302            string_t type = it->second; // sax->string() takes a reference
12303            if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->string(type)))
12304            {
12305                return false;
12306            }
12307
12308            if (size_and_type.second == 'C' || size_and_type.second == 'B')
12309            {
12310                size_and_type.second = 'U';
12311            }
12312
12313            key = "_ArrayData_";
12314            if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) ))
12315            {
12316                return false;
12317            }
12318
12319            for (std::size_t i = 0; i < size_and_type.first; ++i)
12320            {
12321                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12322                {
12323                    return false;
12324                }
12325            }
12326
12327            return (sax->end_array() && sax->end_object());
12328        }
12329
12330        // If BJData type marker is 'B' decode as binary
12331        if (input_format == input_format_t::bjdata && size_and_type.first != npos && size_and_type.second == 'B')
12332        {
12333            binary_t result;
12334            return get_binary(input_format, size_and_type.first, result) && sax->binary(result);
12335        }
12336
12337        if (size_and_type.first != npos)
12338        {
12339            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(size_and_type.first)))
12340            {
12341                return false;
12342            }
12343
12344            if (size_and_type.second != 0)
12345            {
12346                if (size_and_type.second != 'N')
12347                {
12348                    for (std::size_t i = 0; i < size_and_type.first; ++i)
12349                    {
12350                        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12351                        {
12352                            return false;
12353                        }
12354                    }
12355                }
12356            }
12357            else
12358            {
12359                for (std::size_t i = 0; i < size_and_type.first; ++i)
12360                {
12361                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12362                    {
12363                        return false;
12364                    }
12365                }
12366            }
12367        }
12368        else
12369        {
12370            if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
12371            {
12372                return false;
12373            }
12374
12375            while (current != ']')
12376            {
12377                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal(false)))
12378                {
12379                    return false;
12380                }
12381                get_ignore_noop();
12382            }
12383        }
12384
12385        return sax->end_array();
12386    }
12387
12388    /*!
12389    @return whether object creation completed
12390    */
12391    bool get_ubjson_object()
12392    {
12393        std::pair<std::size_t, char_int_type> size_and_type;
12394        if (JSON_HEDLEY_UNLIKELY(!get_ubjson_size_type(size_and_type)))
12395        {
12396            return false;
12397        }
12398
12399        // do not accept ND-array size in objects in BJData
12400        if (input_format == input_format_t::bjdata && size_and_type.first != npos && (size_and_type.second & (1 << 8)) != 0)
12401        {
12402            auto last_token = get_token_string();
12403            return sax->parse_error(chars_read, last_token, parse_error::create(112, chars_read,
12404                                    exception_message(input_format, "BJData object does not support ND-array size in optimized format", "object"), nullptr));
12405        }
12406
12407        string_t key;
12408        if (size_and_type.first != npos)
12409        {
12410            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(size_and_type.first)))
12411            {
12412                return false;
12413            }
12414
12415            if (size_and_type.second != 0)
12416            {
12417                for (std::size_t i = 0; i < size_and_type.first; ++i)
12418                {
12419                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12420                    {
12421                        return false;
12422                    }
12423                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_value(size_and_type.second)))
12424                    {
12425                        return false;
12426                    }
12427                    key.clear();
12428                }
12429            }
12430            else
12431            {
12432                for (std::size_t i = 0; i < size_and_type.first; ++i)
12433                {
12434                    if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key) || !sax->key(key)))
12435                    {
12436                        return false;
12437                    }
12438                    if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12439                    {
12440                        return false;
12441                    }
12442                    key.clear();
12443                }
12444            }
12445        }
12446        else
12447        {
12448            if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
12449            {
12450                return false;
12451            }
12452
12453            while (current != '}')
12454            {
12455                if (JSON_HEDLEY_UNLIKELY(!get_ubjson_string(key, false) || !sax->key(key)))
12456                {
12457                    return false;
12458                }
12459                if (JSON_HEDLEY_UNLIKELY(!parse_ubjson_internal()))
12460                {
12461                    return false;
12462                }
12463                get_ignore_noop();
12464                key.clear();
12465            }
12466        }
12467
12468        return sax->end_object();
12469    }
12470
12471    // Note, no reader for UBJSON binary types is implemented because they do
12472    // not exist
12473
12474    bool get_ubjson_high_precision_number()
12475    {
12476        // get size of following number string
12477        std::size_t size{};
12478        bool no_ndarray = true;
12479        auto res = get_ubjson_size_value(size, no_ndarray);
12480        if (JSON_HEDLEY_UNLIKELY(!res))
12481        {
12482            return res;
12483        }
12484
12485        // get number string
12486        std::vector<char> number_vector;
12487        for (std::size_t i = 0; i < size; ++i)
12488        {
12489            get();
12490            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(input_format, "number")))
12491            {
12492                return false;
12493            }
12494            number_vector.push_back(static_cast<char>(current));
12495        }
12496
12497        // parse number string
12498        using ia_type = decltype(detail::input_adapter(number_vector));
12499        auto number_lexer = detail::lexer<BasicJsonType, ia_type>(detail::input_adapter(number_vector), false);
12500        const auto result_number = number_lexer.scan();
12501        const auto number_string = number_lexer.get_token_string();
12502        const auto result_remainder = number_lexer.scan();
12503
12504        using token_type = typename detail::lexer_base<BasicJsonType>::token_type;
12505
12506        if (JSON_HEDLEY_UNLIKELY(result_remainder != token_type::end_of_input))
12507        {
12508            return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12509                                    exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12510        }
12511
12512        switch (result_number)
12513        {
12514            case token_type::value_integer:
12515                return sax->number_integer(number_lexer.get_number_integer());
12516            case token_type::value_unsigned:
12517                return sax->number_unsigned(number_lexer.get_number_unsigned());
12518            case token_type::value_float:
12519                return sax->number_float(number_lexer.get_number_float(), std::move(number_string));
12520            case token_type::uninitialized:
12521            case token_type::literal_true:
12522            case token_type::literal_false:
12523            case token_type::literal_null:
12524            case token_type::value_string:
12525            case token_type::begin_array:
12526            case token_type::begin_object:
12527            case token_type::end_array:
12528            case token_type::end_object:
12529            case token_type::name_separator:
12530            case token_type::value_separator:
12531            case token_type::parse_error:
12532            case token_type::end_of_input:
12533            case token_type::literal_or_value:
12534            default:
12535                return sax->parse_error(chars_read, number_string, parse_error::create(115, chars_read,
12536                                        exception_message(input_format, concat("invalid number text: ", number_lexer.get_token_string()), "high-precision number"), nullptr));
12537        }
12538    }
12539
12540    ///////////////////////
12541    // Utility functions //
12542    ///////////////////////
12543
12544    /*!
12545    @brief get next character from the input
12546
12547    This function provides the interface to the used input adapter. It does
12548    not throw in case the input reached EOF, but returns a -'ve valued
12549    `char_traits<char_type>::eof()` in that case.
12550
12551    @return character read from the input
12552    */
12553    char_int_type get()
12554    {
12555        ++chars_read;
12556        return current = ia.get_character();
12557    }
12558
12559    /*!
12560    @brief get_to read into a primitive type
12561
12562    This function provides the interface to the used input adapter. It does
12563    not throw in case the input reached EOF, but returns false instead
12564
12565    @return bool, whether the read was successful
12566    */
12567    template<class T>
12568    bool get_to(T& dest, const input_format_t format, const char* context)
12569    {
12570        auto new_chars_read = ia.get_elements(&dest);
12571        chars_read += new_chars_read;
12572        if (JSON_HEDLEY_UNLIKELY(new_chars_read < sizeof(T)))
12573        {
12574            // in case of failure, advance position by 1 to report failing location
12575            ++chars_read;
12576            sax->parse_error(chars_read, "<end of file>", parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12577            return false;
12578        }
12579        return true;
12580    }
12581
12582    /*!
12583    @return character read from the input after ignoring all 'N' entries
12584    */
12585    char_int_type get_ignore_noop()
12586    {
12587        do
12588        {
12589            get();
12590        }
12591        while (current == 'N');
12592
12593        return current;
12594    }
12595
12596    template<class NumberType>
12597    static void byte_swap(NumberType& number)
12598    {
12599        constexpr std::size_t sz = sizeof(number);
12600#ifdef __cpp_lib_byteswap
12601        if constexpr (sz == 1)
12602        {
12603            return;
12604        }
12605        if constexpr(std::is_integral_v<NumberType>)
12606        {
12607            number = std::byteswap(number);
12608            return;
12609        }
12610#endif
12611        auto* ptr = reinterpret_cast<std::uint8_t*>(&number);
12612        for (std::size_t i = 0; i < sz / 2; ++i)
12613        {
12614            std::swap(ptr[i], ptr[sz - i - 1]);
12615        }
12616    }
12617
12618    /*
12619    @brief read a number from the input
12620
12621    @tparam NumberType the type of the number
12622    @param[in] format   the current format (for diagnostics)
12623    @param[out] result  number of type @a NumberType
12624
12625    @return whether conversion completed
12626
12627    @note This function needs to respect the system's endianness, because
12628          bytes in CBOR, MessagePack, and UBJSON are stored in network order
12629          (big endian) and therefore need reordering on little endian systems.
12630          On the other hand, BSON and BJData use little endian and should reorder
12631          on big endian systems.
12632    */
12633    template<typename NumberType, bool InputIsLittleEndian = false>
12634    bool get_number(const input_format_t format, NumberType& result)
12635    {
12636        // read in the original format
12637
12638        if (JSON_HEDLEY_UNLIKELY(!get_to(result, format, "number")))
12639        {
12640            return false;
12641        }
12642        if (is_little_endian != (InputIsLittleEndian || format == input_format_t::bjdata))
12643        {
12644            byte_swap(result);
12645        }
12646        return true;
12647    }
12648
12649    /*!
12650    @brief create a string by reading characters from the input
12651
12652    @tparam NumberType the type of the number
12653    @param[in] format the current format (for diagnostics)
12654    @param[in] len number of characters to read
12655    @param[out] result string created by reading @a len bytes
12656
12657    @return whether string creation completed
12658
12659    @note We can not reserve @a len bytes for the result, because @a len
12660          may be too large. Usually, @ref unexpect_eof() detects the end of
12661          the input before we run out of string memory.
12662    */
12663    template<typename NumberType>
12664    bool get_string(const input_format_t format,
12665                    const NumberType len,
12666                    string_t& result)
12667    {
12668        bool success = true;
12669        for (NumberType i = 0; i < len; i++)
12670        {
12671            get();
12672            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "string")))
12673            {
12674                success = false;
12675                break;
12676            }
12677            result.push_back(static_cast<typename string_t::value_type>(current));
12678        }
12679        return success;
12680    }
12681
12682    /*!
12683    @brief create a byte array by reading bytes from the input
12684
12685    @tparam NumberType the type of the number
12686    @param[in] format the current format (for diagnostics)
12687    @param[in] len number of bytes to read
12688    @param[out] result byte array created by reading @a len bytes
12689
12690    @return whether byte array creation completed
12691
12692    @note We can not reserve @a len bytes for the result, because @a len
12693          may be too large. Usually, @ref unexpect_eof() detects the end of
12694          the input before we run out of memory.
12695    */
12696    template<typename NumberType>
12697    bool get_binary(const input_format_t format,
12698                    const NumberType len,
12699                    binary_t& result)
12700    {
12701        bool success = true;
12702        for (NumberType i = 0; i < len; i++)
12703        {
12704            get();
12705            if (JSON_HEDLEY_UNLIKELY(!unexpect_eof(format, "binary")))
12706            {
12707                success = false;
12708                break;
12709            }
12710            result.push_back(static_cast<std::uint8_t>(current));
12711        }
12712        return success;
12713    }
12714
12715    /*!
12716    @param[in] format   the current format (for diagnostics)
12717    @param[in] context  further context information (for diagnostics)
12718    @return whether the last read character is not EOF
12719    */
12720    JSON_HEDLEY_NON_NULL(3)
12721    bool unexpect_eof(const input_format_t format, const char* context) const
12722    {
12723        if (JSON_HEDLEY_UNLIKELY(current == char_traits<char_type>::eof()))
12724        {
12725            return sax->parse_error(chars_read, "<end of file>",
12726                                    parse_error::create(110, chars_read, exception_message(format, "unexpected end of input", context), nullptr));
12727        }
12728        return true;
12729    }
12730
12731    /*!
12732    @return a string representation of the last read byte
12733    */
12734    std::string get_token_string() const
12735    {
12736        std::array<char, 3> cr{{}};
12737        static_cast<void>((std::snprintf)(cr.data(), cr.size(), "%.2hhX", static_cast<unsigned char>(current))); // NOLINT(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
12738        return std::string{cr.data()};
12739    }
12740
12741    /*!
12742    @param[in] format   the current format
12743    @param[in] detail   a detailed error message
12744    @param[in] context  further context information
12745    @return a message string to use in the parse_error exceptions
12746    */
12747    std::string exception_message(const input_format_t format,
12748                                  const std::string& detail,
12749                                  const std::string& context) const
12750    {
12751        std::string error_msg = "syntax error while parsing ";
12752
12753        switch (format)
12754        {
12755            case input_format_t::cbor:
12756                error_msg += "CBOR";
12757                break;
12758
12759            case input_format_t::msgpack:
12760                error_msg += "MessagePack";
12761                break;
12762
12763            case input_format_t::ubjson:
12764                error_msg += "UBJSON";
12765                break;
12766
12767            case input_format_t::bson:
12768                error_msg += "BSON";
12769                break;
12770
12771            case input_format_t::bjdata:
12772                error_msg += "BJData";
12773                break;
12774
12775            case input_format_t::json: // LCOV_EXCL_LINE
12776            default:            // LCOV_EXCL_LINE
12777                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
12778        }
12779
12780        return concat(error_msg, ' ', context, ": ", detail);
12781    }
12782
12783  private:
12784    static JSON_INLINE_VARIABLE constexpr std::size_t npos = detail::unknown_size();
12785
12786    /// input adapter
12787    InputAdapterType ia;
12788
12789    /// the current character
12790    char_int_type current = char_traits<char_type>::eof();
12791
12792    /// the number of characters read
12793    std::size_t chars_read = 0;
12794
12795    /// whether we can assume little endianness
12796    const bool is_little_endian = little_endianness();
12797
12798    /// input format
12799    const input_format_t input_format = input_format_t::json;
12800
12801    /// the SAX parser
12802    json_sax_t* sax = nullptr;
12803
12804    // excluded markers in bjdata optimized type
12805#define JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_ \
12806    make_array<char_int_type>('F', 'H', 'N', 'S', 'T', 'Z', '[', '{')
12807
12808#define JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_ \
12809    make_array<bjd_type>(                      \
12810    bjd_type{'B', "byte"},                     \
12811    bjd_type{'C', "char"},                     \
12812    bjd_type{'D', "double"},                   \
12813    bjd_type{'I', "int16"},                    \
12814    bjd_type{'L', "int64"},                    \
12815    bjd_type{'M', "uint64"},                   \
12816    bjd_type{'U', "uint8"},                    \
12817    bjd_type{'d', "single"},                   \
12818    bjd_type{'i', "int8"},                     \
12819    bjd_type{'l', "int32"},                    \
12820    bjd_type{'m', "uint32"},                   \
12821    bjd_type{'u', "uint16"})
12822
12823  JSON_PRIVATE_UNLESS_TESTED:
12824    // lookup tables
12825    // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12826    const decltype(JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_) bjd_optimized_type_markers =
12827        JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_;
12828
12829    using bjd_type = std::pair<char_int_type, string_t>;
12830    // NOLINTNEXTLINE(cppcoreguidelines-non-private-member-variables-in-classes)
12831    const decltype(JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_) bjd_types_map =
12832        JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_;
12833
12834#undef JSON_BINARY_READER_MAKE_BJD_OPTIMIZED_TYPE_MARKERS_
12835#undef JSON_BINARY_READER_MAKE_BJD_TYPES_MAP_
12836};
12837
12838#ifndef JSON_HAS_CPP_17
12839    template<typename BasicJsonType, typename InputAdapterType, typename SAX>
12840    constexpr std::size_t binary_reader<BasicJsonType, InputAdapterType, SAX>::npos;
12841#endif
12842
12843}  // namespace detail
12844NLOHMANN_JSON_NAMESPACE_END
12845
12846// #include <nlohmann/detail/input/input_adapters.hpp>
12847
12848// #include <nlohmann/detail/input/lexer.hpp>
12849
12850// #include <nlohmann/detail/input/parser.hpp>
12851//     __ _____ _____ _____
12852//  __|  |   __|     |   | |  JSON for Modern C++
12853// |  |  |__   |  |  | | | |  version 3.12.0
12854// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
12855//
12856// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
12857// SPDX-License-Identifier: MIT
12858
12859
12860
12861#include <cmath> // isfinite
12862#include <cstdint> // uint8_t
12863#include <functional> // function
12864#include <string> // string
12865#include <utility> // move
12866#include <vector> // vector
12867
12868// #include <nlohmann/detail/exceptions.hpp>
12869
12870// #include <nlohmann/detail/input/input_adapters.hpp>
12871
12872// #include <nlohmann/detail/input/json_sax.hpp>
12873
12874// #include <nlohmann/detail/input/lexer.hpp>
12875
12876// #include <nlohmann/detail/macro_scope.hpp>
12877
12878// #include <nlohmann/detail/meta/is_sax.hpp>
12879
12880// #include <nlohmann/detail/string_concat.hpp>
12881
12882// #include <nlohmann/detail/value_t.hpp>
12883
12884
12885NLOHMANN_JSON_NAMESPACE_BEGIN
12886namespace detail
12887{
12888////////////
12889// parser //
12890////////////
12891
12892enum class parse_event_t : std::uint8_t
12893{
12894    /// the parser read `{` and started to process a JSON object
12895    object_start,
12896    /// the parser read `}` and finished processing a JSON object
12897    object_end,
12898    /// the parser read `[` and started to process a JSON array
12899    array_start,
12900    /// the parser read `]` and finished processing a JSON array
12901    array_end,
12902    /// the parser read a key of a value in an object
12903    key,
12904    /// the parser finished reading a JSON value
12905    value
12906};
12907
12908template<typename BasicJsonType>
12909using parser_callback_t =
12910    std::function<bool(int /*depth*/, parse_event_t /*event*/, BasicJsonType& /*parsed*/)>;
12911
12912/*!
12913@brief syntax analysis
12914
12915This class implements a recursive descent parser.
12916*/
12917template<typename BasicJsonType, typename InputAdapterType>
12918class parser
12919{
12920    using number_integer_t = typename BasicJsonType::number_integer_t;
12921    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
12922    using number_float_t = typename BasicJsonType::number_float_t;
12923    using string_t = typename BasicJsonType::string_t;
12924    using lexer_t = lexer<BasicJsonType, InputAdapterType>;
12925    using token_type = typename lexer_t::token_type;
12926
12927  public:
12928    /// a parser reading from an input adapter
12929    explicit parser(InputAdapterType&& adapter,
12930                    parser_callback_t<BasicJsonType> cb = nullptr,
12931                    const bool allow_exceptions_ = true,
12932                    const bool skip_comments = false)
12933        : callback(std::move(cb))
12934        , m_lexer(std::move(adapter), skip_comments)
12935        , allow_exceptions(allow_exceptions_)
12936    {
12937        // read first token
12938        get_token();
12939    }
12940
12941    /*!
12942    @brief public parser interface
12943
12944    @param[in] strict      whether to expect the last token to be EOF
12945    @param[in,out] result  parsed JSON value
12946
12947    @throw parse_error.101 in case of an unexpected token
12948    @throw parse_error.102 if to_unicode fails or surrogate error
12949    @throw parse_error.103 if to_unicode fails
12950    */
12951    void parse(const bool strict, BasicJsonType& result)
12952    {
12953        if (callback)
12954        {
12955            json_sax_dom_callback_parser<BasicJsonType, InputAdapterType> sdp(result, callback, allow_exceptions, &m_lexer);
12956            sax_parse_internal(&sdp);
12957
12958            // in strict mode, input must be completely read
12959            if (strict && (get_token() != token_type::end_of_input))
12960            {
12961                sdp.parse_error(m_lexer.get_position(),
12962                                m_lexer.get_token_string(),
12963                                parse_error::create(101, m_lexer.get_position(),
12964                                                    exception_message(token_type::end_of_input, "value"), nullptr));
12965            }
12966
12967            // in case of an error, return discarded value
12968            if (sdp.is_errored())
12969            {
12970                result = value_t::discarded;
12971                return;
12972            }
12973
12974            // set top-level value to null if it was discarded by the callback
12975            // function
12976            if (result.is_discarded())
12977            {
12978                result = nullptr;
12979            }
12980        }
12981        else
12982        {
12983            json_sax_dom_parser<BasicJsonType, InputAdapterType> sdp(result, allow_exceptions, &m_lexer);
12984            sax_parse_internal(&sdp);
12985
12986            // in strict mode, input must be completely read
12987            if (strict && (get_token() != token_type::end_of_input))
12988            {
12989                sdp.parse_error(m_lexer.get_position(),
12990                                m_lexer.get_token_string(),
12991                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
12992            }
12993
12994            // in case of an error, return discarded value
12995            if (sdp.is_errored())
12996            {
12997                result = value_t::discarded;
12998                return;
12999            }
13000        }
13001
13002        result.assert_invariant();
13003    }
13004
13005    /*!
13006    @brief public accept interface
13007
13008    @param[in] strict  whether to expect the last token to be EOF
13009    @return whether the input is a proper JSON text
13010    */
13011    bool accept(const bool strict = true)
13012    {
13013        json_sax_acceptor<BasicJsonType> sax_acceptor;
13014        return sax_parse(&sax_acceptor, strict);
13015    }
13016
13017    template<typename SAX>
13018    JSON_HEDLEY_NON_NULL(2)
13019    bool sax_parse(SAX* sax, const bool strict = true)
13020    {
13021        (void)detail::is_sax_static_asserts<SAX, BasicJsonType> {};
13022        const bool result = sax_parse_internal(sax);
13023
13024        // strict mode: next byte must be EOF
13025        if (result && strict && (get_token() != token_type::end_of_input))
13026        {
13027            return sax->parse_error(m_lexer.get_position(),
13028                                    m_lexer.get_token_string(),
13029                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_of_input, "value"), nullptr));
13030        }
13031
13032        return result;
13033    }
13034
13035  private:
13036    template<typename SAX>
13037    JSON_HEDLEY_NON_NULL(2)
13038    bool sax_parse_internal(SAX* sax)
13039    {
13040        // stack to remember the hierarchy of structured values we are parsing
13041        // true = array; false = object
13042        std::vector<bool> states;
13043        // value to avoid a goto (see comment where set to true)
13044        bool skip_to_state_evaluation = false;
13045
13046        while (true)
13047        {
13048            if (!skip_to_state_evaluation)
13049            {
13050                // invariant: get_token() was called before each iteration
13051                switch (last_token)
13052                {
13053                    case token_type::begin_object:
13054                    {
13055                        if (JSON_HEDLEY_UNLIKELY(!sax->start_object(detail::unknown_size())))
13056                        {
13057                            return false;
13058                        }
13059
13060                        // closing } -> we are done
13061                        if (get_token() == token_type::end_object)
13062                        {
13063                            if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13064                            {
13065                                return false;
13066                            }
13067                            break;
13068                        }
13069
13070                        // parse key
13071                        if (JSON_HEDLEY_UNLIKELY(last_token != token_type::value_string))
13072                        {
13073                            return sax->parse_error(m_lexer.get_position(),
13074                                                    m_lexer.get_token_string(),
13075                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13076                        }
13077                        if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13078                        {
13079                            return false;
13080                        }
13081
13082                        // parse separator (:)
13083                        if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13084                        {
13085                            return sax->parse_error(m_lexer.get_position(),
13086                                                    m_lexer.get_token_string(),
13087                                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13088                        }
13089
13090                        // remember we are now inside an object
13091                        states.push_back(false);
13092
13093                        // parse values
13094                        get_token();
13095                        continue;
13096                    }
13097
13098                    case token_type::begin_array:
13099                    {
13100                        if (JSON_HEDLEY_UNLIKELY(!sax->start_array(detail::unknown_size())))
13101                        {
13102                            return false;
13103                        }
13104
13105                        // closing ] -> we are done
13106                        if (get_token() == token_type::end_array)
13107                        {
13108                            if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13109                            {
13110                                return false;
13111                            }
13112                            break;
13113                        }
13114
13115                        // remember we are now inside an array
13116                        states.push_back(true);
13117
13118                        // parse values (no need to call get_token)
13119                        continue;
13120                    }
13121
13122                    case token_type::value_float:
13123                    {
13124                        const auto res = m_lexer.get_number_float();
13125
13126                        if (JSON_HEDLEY_UNLIKELY(!std::isfinite(res)))
13127                        {
13128                            return sax->parse_error(m_lexer.get_position(),
13129                                                    m_lexer.get_token_string(),
13130                                                    out_of_range::create(406, concat("number overflow parsing '", m_lexer.get_token_string(), '\''), nullptr));
13131                        }
13132
13133                        if (JSON_HEDLEY_UNLIKELY(!sax->number_float(res, m_lexer.get_string())))
13134                        {
13135                            return false;
13136                        }
13137
13138                        break;
13139                    }
13140
13141                    case token_type::literal_false:
13142                    {
13143                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(false)))
13144                        {
13145                            return false;
13146                        }
13147                        break;
13148                    }
13149
13150                    case token_type::literal_null:
13151                    {
13152                        if (JSON_HEDLEY_UNLIKELY(!sax->null()))
13153                        {
13154                            return false;
13155                        }
13156                        break;
13157                    }
13158
13159                    case token_type::literal_true:
13160                    {
13161                        if (JSON_HEDLEY_UNLIKELY(!sax->boolean(true)))
13162                        {
13163                            return false;
13164                        }
13165                        break;
13166                    }
13167
13168                    case token_type::value_integer:
13169                    {
13170                        if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(m_lexer.get_number_integer())))
13171                        {
13172                            return false;
13173                        }
13174                        break;
13175                    }
13176
13177                    case token_type::value_string:
13178                    {
13179                        if (JSON_HEDLEY_UNLIKELY(!sax->string(m_lexer.get_string())))
13180                        {
13181                            return false;
13182                        }
13183                        break;
13184                    }
13185
13186                    case token_type::value_unsigned:
13187                    {
13188                        if (JSON_HEDLEY_UNLIKELY(!sax->number_unsigned(m_lexer.get_number_unsigned())))
13189                        {
13190                            return false;
13191                        }
13192                        break;
13193                    }
13194
13195                    case token_type::parse_error:
13196                    {
13197                        // using "uninitialized" to avoid "expected" message
13198                        return sax->parse_error(m_lexer.get_position(),
13199                                                m_lexer.get_token_string(),
13200                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::uninitialized, "value"), nullptr));
13201                    }
13202                    case token_type::end_of_input:
13203                    {
13204                        if (JSON_HEDLEY_UNLIKELY(m_lexer.get_position().chars_read_total == 1))
13205                        {
13206                            return sax->parse_error(m_lexer.get_position(),
13207                                                    m_lexer.get_token_string(),
13208                                                    parse_error::create(101, m_lexer.get_position(),
13209                                                            "attempting to parse an empty input; check that your input string or stream contains the expected JSON", nullptr));
13210                        }
13211
13212                        return sax->parse_error(m_lexer.get_position(),
13213                                                m_lexer.get_token_string(),
13214                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13215                    }
13216                    case token_type::uninitialized:
13217                    case token_type::end_array:
13218                    case token_type::end_object:
13219                    case token_type::name_separator:
13220                    case token_type::value_separator:
13221                    case token_type::literal_or_value:
13222                    default: // the last token was unexpected
13223                    {
13224                        return sax->parse_error(m_lexer.get_position(),
13225                                                m_lexer.get_token_string(),
13226                                                parse_error::create(101, m_lexer.get_position(), exception_message(token_type::literal_or_value, "value"), nullptr));
13227                    }
13228                }
13229            }
13230            else
13231            {
13232                skip_to_state_evaluation = false;
13233            }
13234
13235            // we reached this line after we successfully parsed a value
13236            if (states.empty())
13237            {
13238                // empty stack: we reached the end of the hierarchy: done
13239                return true;
13240            }
13241
13242            if (states.back())  // array
13243            {
13244                // comma -> next value
13245                if (get_token() == token_type::value_separator)
13246                {
13247                    // parse a new value
13248                    get_token();
13249                    continue;
13250                }
13251
13252                // closing ]
13253                if (JSON_HEDLEY_LIKELY(last_token == token_type::end_array))
13254                {
13255                    if (JSON_HEDLEY_UNLIKELY(!sax->end_array()))
13256                    {
13257                        return false;
13258                    }
13259
13260                    // We are done with this array. Before we can parse a
13261                    // new value, we need to evaluate the new state first.
13262                    // By setting skip_to_state_evaluation to false, we
13263                    // are effectively jumping to the beginning of this if.
13264                    JSON_ASSERT(!states.empty());
13265                    states.pop_back();
13266                    skip_to_state_evaluation = true;
13267                    continue;
13268                }
13269
13270                return sax->parse_error(m_lexer.get_position(),
13271                                        m_lexer.get_token_string(),
13272                                        parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_array, "array"), nullptr));
13273            }
13274
13275            // states.back() is false -> object
13276
13277            // comma -> next value
13278            if (get_token() == token_type::value_separator)
13279            {
13280                // parse key
13281                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::value_string))
13282                {
13283                    return sax->parse_error(m_lexer.get_position(),
13284                                            m_lexer.get_token_string(),
13285                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::value_string, "object key"), nullptr));
13286                }
13287
13288                if (JSON_HEDLEY_UNLIKELY(!sax->key(m_lexer.get_string())))
13289                {
13290                    return false;
13291                }
13292
13293                // parse separator (:)
13294                if (JSON_HEDLEY_UNLIKELY(get_token() != token_type::name_separator))
13295                {
13296                    return sax->parse_error(m_lexer.get_position(),
13297                                            m_lexer.get_token_string(),
13298                                            parse_error::create(101, m_lexer.get_position(), exception_message(token_type::name_separator, "object separator"), nullptr));
13299                }
13300
13301                // parse values
13302                get_token();
13303                continue;
13304            }
13305
13306            // closing }
13307            if (JSON_HEDLEY_LIKELY(last_token == token_type::end_object))
13308            {
13309                if (JSON_HEDLEY_UNLIKELY(!sax->end_object()))
13310                {
13311                    return false;
13312                }
13313
13314                // We are done with this object. Before we can parse a
13315                // new value, we need to evaluate the new state first.
13316                // By setting skip_to_state_evaluation to false, we
13317                // are effectively jumping to the beginning of this if.
13318                JSON_ASSERT(!states.empty());
13319                states.pop_back();
13320                skip_to_state_evaluation = true;
13321                continue;
13322            }
13323
13324            return sax->parse_error(m_lexer.get_position(),
13325                                    m_lexer.get_token_string(),
13326                                    parse_error::create(101, m_lexer.get_position(), exception_message(token_type::end_object, "object"), nullptr));
13327        }
13328    }
13329
13330    /// get next token from lexer
13331    token_type get_token()
13332    {
13333        return last_token = m_lexer.scan();
13334    }
13335
13336    std::string exception_message(const token_type expected, const std::string& context)
13337    {
13338        std::string error_msg = "syntax error ";
13339
13340        if (!context.empty())
13341        {
13342            error_msg += concat("while parsing ", context, ' ');
13343        }
13344
13345        error_msg += "- ";
13346
13347        if (last_token == token_type::parse_error)
13348        {
13349            error_msg += concat(m_lexer.get_error_message(), "; last read: '",
13350                                m_lexer.get_token_string(), '\'');
13351        }
13352        else
13353        {
13354            error_msg += concat("unexpected ", lexer_t::token_type_name(last_token));
13355        }
13356
13357        if (expected != token_type::uninitialized)
13358        {
13359            error_msg += concat("; expected ", lexer_t::token_type_name(expected));
13360        }
13361
13362        return error_msg;
13363    }
13364
13365  private:
13366    /// callback function
13367    const parser_callback_t<BasicJsonType> callback = nullptr;
13368    /// the type of the last read token
13369    token_type last_token = token_type::uninitialized;
13370    /// the lexer
13371    lexer_t m_lexer;
13372    /// whether to throw exceptions in case of errors
13373    const bool allow_exceptions = true;
13374};
13375
13376}  // namespace detail
13377NLOHMANN_JSON_NAMESPACE_END
13378
13379// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13380//     __ _____ _____ _____
13381//  __|  |   __|     |   | |  JSON for Modern C++
13382// |  |  |__   |  |  | | | |  version 3.12.0
13383// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13384//
13385// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13386// SPDX-License-Identifier: MIT
13387
13388
13389
13390// #include <nlohmann/detail/abi_macros.hpp>
13391
13392// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13393//     __ _____ _____ _____
13394//  __|  |   __|     |   | |  JSON for Modern C++
13395// |  |  |__   |  |  | | | |  version 3.12.0
13396// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13397//
13398// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13399// SPDX-License-Identifier: MIT
13400
13401
13402
13403#include <cstddef> // ptrdiff_t
13404#include <limits>  // numeric_limits
13405
13406// #include <nlohmann/detail/macro_scope.hpp>
13407
13408
13409NLOHMANN_JSON_NAMESPACE_BEGIN
13410namespace detail
13411{
13412
13413/*
13414@brief an iterator for primitive JSON types
13415
13416This class models an iterator for primitive JSON types (boolean, number,
13417string). It's only purpose is to allow the iterator/const_iterator classes
13418to "iterate" over primitive values. Internally, the iterator is modeled by
13419a `difference_type` variable. Value begin_value (`0`) models the begin,
13420end_value (`1`) models past the end.
13421*/
13422class primitive_iterator_t
13423{
13424  private:
13425    using difference_type = std::ptrdiff_t;
13426    static constexpr difference_type begin_value = 0;
13427    static constexpr difference_type end_value = begin_value + 1;
13428
13429  JSON_PRIVATE_UNLESS_TESTED:
13430    /// iterator as signed integer type
13431    difference_type m_it = (std::numeric_limits<std::ptrdiff_t>::min)();
13432
13433  public:
13434    constexpr difference_type get_value() const noexcept
13435    {
13436        return m_it;
13437    }
13438
13439    /// set iterator to a defined beginning
13440    void set_begin() noexcept
13441    {
13442        m_it = begin_value;
13443    }
13444
13445    /// set iterator to a defined past the end
13446    void set_end() noexcept
13447    {
13448        m_it = end_value;
13449    }
13450
13451    /// return whether the iterator can be dereferenced
13452    constexpr bool is_begin() const noexcept
13453    {
13454        return m_it == begin_value;
13455    }
13456
13457    /// return whether the iterator is at end
13458    constexpr bool is_end() const noexcept
13459    {
13460        return m_it == end_value;
13461    }
13462
13463    friend constexpr bool operator==(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13464    {
13465        return lhs.m_it == rhs.m_it;
13466    }
13467
13468    friend constexpr bool operator<(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13469    {
13470        return lhs.m_it < rhs.m_it;
13471    }
13472
13473    primitive_iterator_t operator+(difference_type n) noexcept
13474    {
13475        auto result = *this;
13476        result += n;
13477        return result;
13478    }
13479
13480    friend constexpr difference_type operator-(primitive_iterator_t lhs, primitive_iterator_t rhs) noexcept
13481    {
13482        return lhs.m_it - rhs.m_it;
13483    }
13484
13485    primitive_iterator_t& operator++() noexcept
13486    {
13487        ++m_it;
13488        return *this;
13489    }
13490
13491    primitive_iterator_t operator++(int)& noexcept // NOLINT(cert-dcl21-cpp)
13492    {
13493        auto result = *this;
13494        ++m_it;
13495        return result;
13496    }
13497
13498    primitive_iterator_t& operator--() noexcept
13499    {
13500        --m_it;
13501        return *this;
13502    }
13503
13504    primitive_iterator_t operator--(int)& noexcept // NOLINT(cert-dcl21-cpp)
13505    {
13506        auto result = *this;
13507        --m_it;
13508        return result;
13509    }
13510
13511    primitive_iterator_t& operator+=(difference_type n) noexcept
13512    {
13513        m_it += n;
13514        return *this;
13515    }
13516
13517    primitive_iterator_t& operator-=(difference_type n) noexcept
13518    {
13519        m_it -= n;
13520        return *this;
13521    }
13522};
13523
13524}  // namespace detail
13525NLOHMANN_JSON_NAMESPACE_END
13526
13527
13528NLOHMANN_JSON_NAMESPACE_BEGIN
13529namespace detail
13530{
13531
13532/*!
13533@brief an iterator value
13534
13535@note This structure could easily be a union, but MSVC currently does not allow
13536unions members with complex constructors, see https://github.com/nlohmann/json/pull/105.
13537*/
13538template<typename BasicJsonType> struct internal_iterator
13539{
13540    /// iterator for JSON objects
13541    typename BasicJsonType::object_t::iterator object_iterator {};
13542    /// iterator for JSON arrays
13543    typename BasicJsonType::array_t::iterator array_iterator {};
13544    /// generic iterator for all other types
13545    primitive_iterator_t primitive_iterator {};
13546};
13547
13548}  // namespace detail
13549NLOHMANN_JSON_NAMESPACE_END
13550
13551// #include <nlohmann/detail/iterators/iter_impl.hpp>
13552//     __ _____ _____ _____
13553//  __|  |   __|     |   | |  JSON for Modern C++
13554// |  |  |__   |  |  | | | |  version 3.12.0
13555// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
13556//
13557// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
13558// SPDX-License-Identifier: MIT
13559
13560
13561
13562#include <iterator> // iterator, random_access_iterator_tag, bidirectional_iterator_tag, advance, next
13563#include <type_traits> // conditional, is_const, remove_const
13564
13565// #include <nlohmann/detail/exceptions.hpp>
13566
13567// #include <nlohmann/detail/iterators/internal_iterator.hpp>
13568
13569// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
13570
13571// #include <nlohmann/detail/macro_scope.hpp>
13572
13573// #include <nlohmann/detail/meta/cpp_future.hpp>
13574
13575// #include <nlohmann/detail/meta/type_traits.hpp>
13576
13577// #include <nlohmann/detail/value_t.hpp>
13578
13579
13580NLOHMANN_JSON_NAMESPACE_BEGIN
13581namespace detail
13582{
13583
13584// forward declare, to be able to friend it later on
13585template<typename IteratorType> class iteration_proxy;
13586template<typename IteratorType> class iteration_proxy_value;
13587
13588/*!
13589@brief a template for a bidirectional iterator for the @ref basic_json class
13590This class implements a both iterators (iterator and const_iterator) for the
13591@ref basic_json class.
13592@note An iterator is called *initialized* when a pointer to a JSON value has
13593      been set (e.g., by a constructor or a copy assignment). If the iterator is
13594      default-constructed, it is *uninitialized* and most methods are undefined.
13595      **The library uses assertions to detect calls on uninitialized iterators.**
13596@requirement The class satisfies the following concept requirements:
13597-
13598[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
13599  The iterator that can be moved can be moved in both directions (i.e.
13600  incremented and decremented).
13601@since version 1.0.0, simplified in version 2.0.9, change to bidirectional
13602       iterators in version 3.0.0 (see https://github.com/nlohmann/json/issues/593)
13603*/
13604template<typename BasicJsonType>
13605class iter_impl // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
13606{
13607    /// the iterator with BasicJsonType of different const-ness
13608    using other_iter_impl = iter_impl<typename std::conditional<std::is_const<BasicJsonType>::value, typename std::remove_const<BasicJsonType>::type, const BasicJsonType>::type>;
13609    /// allow basic_json to access private members
13610    friend other_iter_impl;
13611    friend BasicJsonType;
13612    friend iteration_proxy<iter_impl>;
13613    friend iteration_proxy_value<iter_impl>;
13614
13615    using object_t = typename BasicJsonType::object_t;
13616    using array_t = typename BasicJsonType::array_t;
13617    // make sure BasicJsonType is basic_json or const basic_json
13618    static_assert(is_basic_json<typename std::remove_const<BasicJsonType>::type>::value,
13619                  "iter_impl only accepts (const) basic_json");
13620    // superficial check for the LegacyBidirectionalIterator named requirement
13621    static_assert(std::is_base_of<std::bidirectional_iterator_tag, std::bidirectional_iterator_tag>::value
13622                  &&  std::is_base_of<std::bidirectional_iterator_tag, typename std::iterator_traits<typename array_t::iterator>::iterator_category>::value,
13623                  "basic_json iterator assumes array and object type iterators satisfy the LegacyBidirectionalIterator named requirement.");
13624
13625  public:
13626    /// The std::iterator class template (used as a base class to provide typedefs) is deprecated in C++17.
13627    /// The C++ Standard has never required user-defined iterators to derive from std::iterator.
13628    /// A user-defined iterator should provide publicly accessible typedefs named
13629    /// iterator_category, value_type, difference_type, pointer, and reference.
13630    /// Note that value_type is required to be non-const, even for constant iterators.
13631    using iterator_category = std::bidirectional_iterator_tag;
13632
13633    /// the type of the values when the iterator is dereferenced
13634    using value_type = typename BasicJsonType::value_type;
13635    /// a type to represent differences between iterators
13636    using difference_type = typename BasicJsonType::difference_type;
13637    /// defines a pointer to the type iterated over (value_type)
13638    using pointer = typename std::conditional<std::is_const<BasicJsonType>::value,
13639          typename BasicJsonType::const_pointer,
13640          typename BasicJsonType::pointer>::type;
13641    /// defines a reference to the type iterated over (value_type)
13642    using reference =
13643        typename std::conditional<std::is_const<BasicJsonType>::value,
13644        typename BasicJsonType::const_reference,
13645        typename BasicJsonType::reference>::type;
13646
13647    iter_impl() = default;
13648    ~iter_impl() = default;
13649    iter_impl(iter_impl&&) noexcept = default;
13650    iter_impl& operator=(iter_impl&&) noexcept = default;
13651
13652    /*!
13653    @brief constructor for a given JSON instance
13654    @param[in] object  pointer to a JSON object for this iterator
13655    @pre object != nullptr
13656    @post The iterator is initialized; i.e. `m_object != nullptr`.
13657    */
13658    explicit iter_impl(pointer object) noexcept : m_object(object)
13659    {
13660        JSON_ASSERT(m_object != nullptr);
13661
13662        switch (m_object->m_data.m_type)
13663        {
13664            case value_t::object:
13665            {
13666                m_it.object_iterator = typename object_t::iterator();
13667                break;
13668            }
13669
13670            case value_t::array:
13671            {
13672                m_it.array_iterator = typename array_t::iterator();
13673                break;
13674            }
13675
13676            case value_t::null:
13677            case value_t::string:
13678            case value_t::boolean:
13679            case value_t::number_integer:
13680            case value_t::number_unsigned:
13681            case value_t::number_float:
13682            case value_t::binary:
13683            case value_t::discarded:
13684            default:
13685            {
13686                m_it.primitive_iterator = primitive_iterator_t();
13687                break;
13688            }
13689        }
13690    }
13691
13692    /*!
13693    @note The conventional copy constructor and copy assignment are implicitly
13694          defined. Combined with the following converting constructor and
13695          assignment, they support: (1) copy from iterator to iterator, (2)
13696          copy from const iterator to const iterator, and (3) conversion from
13697          iterator to const iterator. However conversion from const iterator
13698          to iterator is not defined.
13699    */
13700
13701    /*!
13702    @brief const copy constructor
13703    @param[in] other const iterator to copy from
13704    @note This copy constructor had to be defined explicitly to circumvent a bug
13705          occurring on msvc v19.0 compiler (VS 2015) debug build. For more
13706          information refer to: https://github.com/nlohmann/json/issues/1608
13707    */
13708    iter_impl(const iter_impl<const BasicJsonType>& other) noexcept
13709        : m_object(other.m_object), m_it(other.m_it)
13710    {}
13711
13712    /*!
13713    @brief converting assignment
13714    @param[in] other const iterator to copy from
13715    @return const/non-const iterator
13716    @note It is not checked whether @a other is initialized.
13717    */
13718    iter_impl& operator=(const iter_impl<const BasicJsonType>& other) noexcept
13719    {
13720        if (&other != this)
13721        {
13722            m_object = other.m_object;
13723            m_it = other.m_it;
13724        }
13725        return *this;
13726    }
13727
13728    /*!
13729    @brief converting constructor
13730    @param[in] other  non-const iterator to copy from
13731    @note It is not checked whether @a other is initialized.
13732    */
13733    iter_impl(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept
13734        : m_object(other.m_object), m_it(other.m_it)
13735    {}
13736
13737    /*!
13738    @brief converting assignment
13739    @param[in] other  non-const iterator to copy from
13740    @return const/non-const iterator
13741    @note It is not checked whether @a other is initialized.
13742    */
13743    iter_impl& operator=(const iter_impl<typename std::remove_const<BasicJsonType>::type>& other) noexcept // NOLINT(cert-oop54-cpp)
13744    {
13745        m_object = other.m_object;
13746        m_it = other.m_it;
13747        return *this;
13748    }
13749
13750  JSON_PRIVATE_UNLESS_TESTED:
13751    /*!
13752    @brief set the iterator to the first value
13753    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13754    */
13755    void set_begin() noexcept
13756    {
13757        JSON_ASSERT(m_object != nullptr);
13758
13759        switch (m_object->m_data.m_type)
13760        {
13761            case value_t::object:
13762            {
13763                m_it.object_iterator = m_object->m_data.m_value.object->begin();
13764                break;
13765            }
13766
13767            case value_t::array:
13768            {
13769                m_it.array_iterator = m_object->m_data.m_value.array->begin();
13770                break;
13771            }
13772
13773            case value_t::null:
13774            {
13775                // set to end so begin()==end() is true: null is empty
13776                m_it.primitive_iterator.set_end();
13777                break;
13778            }
13779
13780            case value_t::string:
13781            case value_t::boolean:
13782            case value_t::number_integer:
13783            case value_t::number_unsigned:
13784            case value_t::number_float:
13785            case value_t::binary:
13786            case value_t::discarded:
13787            default:
13788            {
13789                m_it.primitive_iterator.set_begin();
13790                break;
13791            }
13792        }
13793    }
13794
13795    /*!
13796    @brief set the iterator past the last value
13797    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13798    */
13799    void set_end() noexcept
13800    {
13801        JSON_ASSERT(m_object != nullptr);
13802
13803        switch (m_object->m_data.m_type)
13804        {
13805            case value_t::object:
13806            {
13807                m_it.object_iterator = m_object->m_data.m_value.object->end();
13808                break;
13809            }
13810
13811            case value_t::array:
13812            {
13813                m_it.array_iterator = m_object->m_data.m_value.array->end();
13814                break;
13815            }
13816
13817            case value_t::null:
13818            case value_t::string:
13819            case value_t::boolean:
13820            case value_t::number_integer:
13821            case value_t::number_unsigned:
13822            case value_t::number_float:
13823            case value_t::binary:
13824            case value_t::discarded:
13825            default:
13826            {
13827                m_it.primitive_iterator.set_end();
13828                break;
13829            }
13830        }
13831    }
13832
13833  public:
13834    /*!
13835    @brief return a reference to the value pointed to by the iterator
13836    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13837    */
13838    reference operator*() const
13839    {
13840        JSON_ASSERT(m_object != nullptr);
13841
13842        switch (m_object->m_data.m_type)
13843        {
13844            case value_t::object:
13845            {
13846                JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13847                return m_it.object_iterator->second;
13848            }
13849
13850            case value_t::array:
13851            {
13852                JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13853                return *m_it.array_iterator;
13854            }
13855
13856            case value_t::null:
13857                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13858
13859            case value_t::string:
13860            case value_t::boolean:
13861            case value_t::number_integer:
13862            case value_t::number_unsigned:
13863            case value_t::number_float:
13864            case value_t::binary:
13865            case value_t::discarded:
13866            default:
13867            {
13868                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13869                {
13870                    return *m_object;
13871                }
13872
13873                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13874            }
13875        }
13876    }
13877
13878    /*!
13879    @brief dereference the iterator
13880    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13881    */
13882    pointer operator->() const
13883    {
13884        JSON_ASSERT(m_object != nullptr);
13885
13886        switch (m_object->m_data.m_type)
13887        {
13888            case value_t::object:
13889            {
13890                JSON_ASSERT(m_it.object_iterator != m_object->m_data.m_value.object->end());
13891                return &(m_it.object_iterator->second);
13892            }
13893
13894            case value_t::array:
13895            {
13896                JSON_ASSERT(m_it.array_iterator != m_object->m_data.m_value.array->end());
13897                return &*m_it.array_iterator;
13898            }
13899
13900            case value_t::null:
13901            case value_t::string:
13902            case value_t::boolean:
13903            case value_t::number_integer:
13904            case value_t::number_unsigned:
13905            case value_t::number_float:
13906            case value_t::binary:
13907            case value_t::discarded:
13908            default:
13909            {
13910                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.is_begin()))
13911                {
13912                    return m_object;
13913                }
13914
13915                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
13916            }
13917        }
13918    }
13919
13920    /*!
13921    @brief post-increment (it++)
13922    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13923    */
13924    iter_impl operator++(int)& // NOLINT(cert-dcl21-cpp)
13925    {
13926        auto result = *this;
13927        ++(*this);
13928        return result;
13929    }
13930
13931    /*!
13932    @brief pre-increment (++it)
13933    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13934    */
13935    iter_impl& operator++()
13936    {
13937        JSON_ASSERT(m_object != nullptr);
13938
13939        switch (m_object->m_data.m_type)
13940        {
13941            case value_t::object:
13942            {
13943                std::advance(m_it.object_iterator, 1);
13944                break;
13945            }
13946
13947            case value_t::array:
13948            {
13949                std::advance(m_it.array_iterator, 1);
13950                break;
13951            }
13952
13953            case value_t::null:
13954            case value_t::string:
13955            case value_t::boolean:
13956            case value_t::number_integer:
13957            case value_t::number_unsigned:
13958            case value_t::number_float:
13959            case value_t::binary:
13960            case value_t::discarded:
13961            default:
13962            {
13963                ++m_it.primitive_iterator;
13964                break;
13965            }
13966        }
13967
13968        return *this;
13969    }
13970
13971    /*!
13972    @brief post-decrement (it--)
13973    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13974    */
13975    iter_impl operator--(int)& // NOLINT(cert-dcl21-cpp)
13976    {
13977        auto result = *this;
13978        --(*this);
13979        return result;
13980    }
13981
13982    /*!
13983    @brief pre-decrement (--it)
13984    @pre The iterator is initialized; i.e. `m_object != nullptr`.
13985    */
13986    iter_impl& operator--()
13987    {
13988        JSON_ASSERT(m_object != nullptr);
13989
13990        switch (m_object->m_data.m_type)
13991        {
13992            case value_t::object:
13993            {
13994                std::advance(m_it.object_iterator, -1);
13995                break;
13996            }
13997
13998            case value_t::array:
13999            {
14000                std::advance(m_it.array_iterator, -1);
14001                break;
14002            }
14003
14004            case value_t::null:
14005            case value_t::string:
14006            case value_t::boolean:
14007            case value_t::number_integer:
14008            case value_t::number_unsigned:
14009            case value_t::number_float:
14010            case value_t::binary:
14011            case value_t::discarded:
14012            default:
14013            {
14014                --m_it.primitive_iterator;
14015                break;
14016            }
14017        }
14018
14019        return *this;
14020    }
14021
14022    /*!
14023    @brief comparison: equal
14024    @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14025    */
14026    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 >
14027    bool operator==(const IterImpl& other) const
14028    {
14029        // if objects are not the same, the comparison is undefined
14030        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14031        {
14032            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14033        }
14034
14035        // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14036        if (m_object == nullptr)
14037        {
14038            return true;
14039        }
14040
14041        switch (m_object->m_data.m_type)
14042        {
14043            case value_t::object:
14044                return (m_it.object_iterator == other.m_it.object_iterator);
14045
14046            case value_t::array:
14047                return (m_it.array_iterator == other.m_it.array_iterator);
14048
14049            case value_t::null:
14050            case value_t::string:
14051            case value_t::boolean:
14052            case value_t::number_integer:
14053            case value_t::number_unsigned:
14054            case value_t::number_float:
14055            case value_t::binary:
14056            case value_t::discarded:
14057            default:
14058                return (m_it.primitive_iterator == other.m_it.primitive_iterator);
14059        }
14060    }
14061
14062    /*!
14063    @brief comparison: not equal
14064    @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14065    */
14066    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 >
14067    bool operator!=(const IterImpl& other) const
14068    {
14069        return !operator==(other);
14070    }
14071
14072    /*!
14073    @brief comparison: smaller
14074    @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14075    */
14076    bool operator<(const iter_impl& other) const
14077    {
14078        // if objects are not the same, the comparison is undefined
14079        if (JSON_HEDLEY_UNLIKELY(m_object != other.m_object))
14080        {
14081            JSON_THROW(invalid_iterator::create(212, "cannot compare iterators of different containers", m_object));
14082        }
14083
14084        // value-initialized forward iterators can be compared, and must compare equal to other value-initialized iterators of the same type #4493
14085        if (m_object == nullptr)
14086        {
14087            // the iterators are both value-initialized and are to be considered equal, but this function checks for smaller, so we return false
14088            return false;
14089        }
14090
14091        switch (m_object->m_data.m_type)
14092        {
14093            case value_t::object:
14094                JSON_THROW(invalid_iterator::create(213, "cannot compare order of object iterators", m_object));
14095
14096            case value_t::array:
14097                return (m_it.array_iterator < other.m_it.array_iterator);
14098
14099            case value_t::null:
14100            case value_t::string:
14101            case value_t::boolean:
14102            case value_t::number_integer:
14103            case value_t::number_unsigned:
14104            case value_t::number_float:
14105            case value_t::binary:
14106            case value_t::discarded:
14107            default:
14108                return (m_it.primitive_iterator < other.m_it.primitive_iterator);
14109        }
14110    }
14111
14112    /*!
14113    @brief comparison: less than or equal
14114    @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14115    */
14116    bool operator<=(const iter_impl& other) const
14117    {
14118        return !other.operator < (*this);
14119    }
14120
14121    /*!
14122    @brief comparison: greater than
14123    @pre (1) Both iterators are initialized to point to the same object, or (2) both iterators are value-initialized.
14124    */
14125    bool operator>(const iter_impl& other) const
14126    {
14127        return !operator<=(other);
14128    }
14129
14130    /*!
14131    @brief comparison: greater than or equal
14132    @pre (1) The iterator is initialized; i.e. `m_object != nullptr`, or (2) both iterators are value-initialized.
14133    */
14134    bool operator>=(const iter_impl& other) const
14135    {
14136        return !operator<(other);
14137    }
14138
14139    /*!
14140    @brief add to iterator
14141    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14142    */
14143    iter_impl& operator+=(difference_type i)
14144    {
14145        JSON_ASSERT(m_object != nullptr);
14146
14147        switch (m_object->m_data.m_type)
14148        {
14149            case value_t::object:
14150                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14151
14152            case value_t::array:
14153            {
14154                std::advance(m_it.array_iterator, i);
14155                break;
14156            }
14157
14158            case value_t::null:
14159            case value_t::string:
14160            case value_t::boolean:
14161            case value_t::number_integer:
14162            case value_t::number_unsigned:
14163            case value_t::number_float:
14164            case value_t::binary:
14165            case value_t::discarded:
14166            default:
14167            {
14168                m_it.primitive_iterator += i;
14169                break;
14170            }
14171        }
14172
14173        return *this;
14174    }
14175
14176    /*!
14177    @brief subtract from iterator
14178    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14179    */
14180    iter_impl& operator-=(difference_type i)
14181    {
14182        return operator+=(-i);
14183    }
14184
14185    /*!
14186    @brief add to iterator
14187    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14188    */
14189    iter_impl operator+(difference_type i) const
14190    {
14191        auto result = *this;
14192        result += i;
14193        return result;
14194    }
14195
14196    /*!
14197    @brief addition of distance and iterator
14198    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14199    */
14200    friend iter_impl operator+(difference_type i, const iter_impl& it)
14201    {
14202        auto result = it;
14203        result += i;
14204        return result;
14205    }
14206
14207    /*!
14208    @brief subtract from iterator
14209    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14210    */
14211    iter_impl operator-(difference_type i) const
14212    {
14213        auto result = *this;
14214        result -= i;
14215        return result;
14216    }
14217
14218    /*!
14219    @brief return difference
14220    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14221    */
14222    difference_type operator-(const iter_impl& other) const
14223    {
14224        JSON_ASSERT(m_object != nullptr);
14225
14226        switch (m_object->m_data.m_type)
14227        {
14228            case value_t::object:
14229                JSON_THROW(invalid_iterator::create(209, "cannot use offsets with object iterators", m_object));
14230
14231            case value_t::array:
14232                return m_it.array_iterator - other.m_it.array_iterator;
14233
14234            case value_t::null:
14235            case value_t::string:
14236            case value_t::boolean:
14237            case value_t::number_integer:
14238            case value_t::number_unsigned:
14239            case value_t::number_float:
14240            case value_t::binary:
14241            case value_t::discarded:
14242            default:
14243                return m_it.primitive_iterator - other.m_it.primitive_iterator;
14244        }
14245    }
14246
14247    /*!
14248    @brief access to successor
14249    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14250    */
14251    reference operator[](difference_type n) const
14252    {
14253        JSON_ASSERT(m_object != nullptr);
14254
14255        switch (m_object->m_data.m_type)
14256        {
14257            case value_t::object:
14258                JSON_THROW(invalid_iterator::create(208, "cannot use operator[] for object iterators", m_object));
14259
14260            case value_t::array:
14261                return *std::next(m_it.array_iterator, n);
14262
14263            case value_t::null:
14264                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14265
14266            case value_t::string:
14267            case value_t::boolean:
14268            case value_t::number_integer:
14269            case value_t::number_unsigned:
14270            case value_t::number_float:
14271            case value_t::binary:
14272            case value_t::discarded:
14273            default:
14274            {
14275                if (JSON_HEDLEY_LIKELY(m_it.primitive_iterator.get_value() == -n))
14276                {
14277                    return *m_object;
14278                }
14279
14280                JSON_THROW(invalid_iterator::create(214, "cannot get value", m_object));
14281            }
14282        }
14283    }
14284
14285    /*!
14286    @brief return the key of an object iterator
14287    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14288    */
14289    const typename object_t::key_type& key() const
14290    {
14291        JSON_ASSERT(m_object != nullptr);
14292
14293        if (JSON_HEDLEY_LIKELY(m_object->is_object()))
14294        {
14295            return m_it.object_iterator->first;
14296        }
14297
14298        JSON_THROW(invalid_iterator::create(207, "cannot use key() for non-object iterators", m_object));
14299    }
14300
14301    /*!
14302    @brief return the value of an iterator
14303    @pre The iterator is initialized; i.e. `m_object != nullptr`.
14304    */
14305    reference value() const
14306    {
14307        return operator*();
14308    }
14309
14310  JSON_PRIVATE_UNLESS_TESTED:
14311    /// associated JSON instance
14312    pointer m_object = nullptr;
14313    /// the actual iterator of the associated instance
14314    internal_iterator<typename std::remove_const<BasicJsonType>::type> m_it {};
14315};
14316
14317}  // namespace detail
14318NLOHMANN_JSON_NAMESPACE_END
14319
14320// #include <nlohmann/detail/iterators/iteration_proxy.hpp>
14321
14322// #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
14323//     __ _____ _____ _____
14324//  __|  |   __|     |   | |  JSON for Modern C++
14325// |  |  |__   |  |  | | | |  version 3.12.0
14326// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14327//
14328// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14329// SPDX-License-Identifier: MIT
14330
14331
14332
14333#include <cstddef> // ptrdiff_t
14334#include <iterator> // reverse_iterator
14335#include <utility> // declval
14336
14337// #include <nlohmann/detail/abi_macros.hpp>
14338
14339
14340NLOHMANN_JSON_NAMESPACE_BEGIN
14341namespace detail
14342{
14343
14344//////////////////////
14345// reverse_iterator //
14346//////////////////////
14347
14348/*!
14349@brief a template for a reverse iterator class
14350
14351@tparam Base the base iterator type to reverse. Valid types are @ref
14352iterator (to create @ref reverse_iterator) and @ref const_iterator (to
14353create @ref const_reverse_iterator).
14354
14355@requirement The class satisfies the following concept requirements:
14356-
14357[BidirectionalIterator](https://en.cppreference.com/w/cpp/named_req/BidirectionalIterator):
14358  The iterator that can be moved can be moved in both directions (i.e.
14359  incremented and decremented).
14360- [OutputIterator](https://en.cppreference.com/w/cpp/named_req/OutputIterator):
14361  It is possible to write to the pointed-to element (only if @a Base is
14362  @ref iterator).
14363
14364@since version 1.0.0
14365*/
14366template<typename Base>
14367class json_reverse_iterator : public std::reverse_iterator<Base>
14368{
14369  public:
14370    using difference_type = std::ptrdiff_t;
14371    /// shortcut to the reverse iterator adapter
14372    using base_iterator = std::reverse_iterator<Base>;
14373    /// the reference type for the pointed-to element
14374    using reference = typename Base::reference;
14375
14376    /// create reverse iterator from iterator
14377    explicit json_reverse_iterator(const typename base_iterator::iterator_type& it) noexcept
14378        : base_iterator(it) {}
14379
14380    /// create reverse iterator from base class
14381    explicit json_reverse_iterator(const base_iterator& it) noexcept : base_iterator(it) {}
14382
14383    /// post-increment (it++)
14384    json_reverse_iterator operator++(int)& // NOLINT(cert-dcl21-cpp)
14385    {
14386        return static_cast<json_reverse_iterator>(base_iterator::operator++(1));
14387    }
14388
14389    /// pre-increment (++it)
14390    json_reverse_iterator& operator++()
14391    {
14392        return static_cast<json_reverse_iterator&>(base_iterator::operator++());
14393    }
14394
14395    /// post-decrement (it--)
14396    json_reverse_iterator operator--(int)& // NOLINT(cert-dcl21-cpp)
14397    {
14398        return static_cast<json_reverse_iterator>(base_iterator::operator--(1));
14399    }
14400
14401    /// pre-decrement (--it)
14402    json_reverse_iterator& operator--()
14403    {
14404        return static_cast<json_reverse_iterator&>(base_iterator::operator--());
14405    }
14406
14407    /// add to iterator
14408    json_reverse_iterator& operator+=(difference_type i)
14409    {
14410        return static_cast<json_reverse_iterator&>(base_iterator::operator+=(i));
14411    }
14412
14413    /// add to iterator
14414    json_reverse_iterator operator+(difference_type i) const
14415    {
14416        return static_cast<json_reverse_iterator>(base_iterator::operator+(i));
14417    }
14418
14419    /// subtract from iterator
14420    json_reverse_iterator operator-(difference_type i) const
14421    {
14422        return static_cast<json_reverse_iterator>(base_iterator::operator-(i));
14423    }
14424
14425    /// return difference
14426    difference_type operator-(const json_reverse_iterator& other) const
14427    {
14428        return base_iterator(*this) - base_iterator(other);
14429    }
14430
14431    /// access to successor
14432    reference operator[](difference_type n) const
14433    {
14434        return *(this->operator+(n));
14435    }
14436
14437    /// return the key of an object iterator
14438    auto key() const -> decltype(std::declval<Base>().key())
14439    {
14440        auto it = --this->base();
14441        return it.key();
14442    }
14443
14444    /// return the value of an iterator
14445    reference value() const
14446    {
14447        auto it = --this->base();
14448        return it.operator * ();
14449    }
14450};
14451
14452}  // namespace detail
14453NLOHMANN_JSON_NAMESPACE_END
14454
14455// #include <nlohmann/detail/iterators/primitive_iterator.hpp>
14456
14457// #include <nlohmann/detail/json_custom_base_class.hpp>
14458//     __ _____ _____ _____
14459//  __|  |   __|     |   | |  JSON for Modern C++
14460// |  |  |__   |  |  | | | |  version 3.12.0
14461// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14462//
14463// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14464// SPDX-License-Identifier: MIT
14465
14466
14467
14468#include <type_traits> // conditional, is_same
14469
14470// #include <nlohmann/detail/abi_macros.hpp>
14471
14472
14473NLOHMANN_JSON_NAMESPACE_BEGIN
14474namespace detail
14475{
14476
14477/*!
14478@brief Default base class of the @ref basic_json class.
14479
14480So that the correct implementations of the copy / move ctors / assign operators
14481of @ref basic_json do not require complex case distinctions
14482(no base class / custom base class used as customization point),
14483@ref basic_json always has a base class.
14484By default, this class is used because it is empty and thus has no effect
14485on the behavior of @ref basic_json.
14486*/
14487struct json_default_base {};
14488
14489template<class T>
14490using json_base_class = typename std::conditional <
14491                        std::is_same<T, void>::value,
14492                        json_default_base,
14493                        T
14494                        >::type;
14495
14496}  // namespace detail
14497NLOHMANN_JSON_NAMESPACE_END
14498
14499// #include <nlohmann/detail/json_pointer.hpp>
14500//     __ _____ _____ _____
14501//  __|  |   __|     |   | |  JSON for Modern C++
14502// |  |  |__   |  |  | | | |  version 3.12.0
14503// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
14504//
14505// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
14506// SPDX-License-Identifier: MIT
14507
14508
14509
14510#include <algorithm> // all_of
14511#include <cctype> // isdigit
14512#include <cerrno> // errno, ERANGE
14513#include <cstdlib> // strtoull
14514#ifndef JSON_NO_IO
14515    #include <iosfwd> // ostream
14516#endif  // JSON_NO_IO
14517#include <limits> // max
14518#include <numeric> // accumulate
14519#include <string> // string
14520#include <utility> // move
14521#include <vector> // vector
14522
14523// #include <nlohmann/detail/exceptions.hpp>
14524
14525// #include <nlohmann/detail/macro_scope.hpp>
14526
14527// #include <nlohmann/detail/string_concat.hpp>
14528
14529// #include <nlohmann/detail/string_escape.hpp>
14530
14531// #include <nlohmann/detail/value_t.hpp>
14532
14533
14534NLOHMANN_JSON_NAMESPACE_BEGIN
14535
14536/// @brief JSON Pointer defines a string syntax for identifying a specific value within a JSON document
14537/// @sa https://json.nlohmann.me/api/json_pointer/
14538template<typename RefStringType>
14539class json_pointer
14540{
14541    // allow basic_json to access private members
14542    NLOHMANN_BASIC_JSON_TPL_DECLARATION
14543    friend class basic_json;
14544
14545    template<typename>
14546    friend class json_pointer;
14547
14548    template<typename T>
14549    struct string_t_helper
14550    {
14551        using type = T;
14552    };
14553
14554    NLOHMANN_BASIC_JSON_TPL_DECLARATION
14555    struct string_t_helper<NLOHMANN_BASIC_JSON_TPL>
14556    {
14557        using type = StringType;
14558    };
14559
14560  public:
14561    // for backwards compatibility accept BasicJsonType
14562    using string_t = typename string_t_helper<RefStringType>::type;
14563
14564    /// @brief create JSON pointer
14565    /// @sa https://json.nlohmann.me/api/json_pointer/json_pointer/
14566    explicit json_pointer(const string_t& s = "")
14567        : reference_tokens(split(s))
14568    {}
14569
14570    /// @brief return a string representation of the JSON pointer
14571    /// @sa https://json.nlohmann.me/api/json_pointer/to_string/
14572    string_t to_string() const
14573    {
14574        return std::accumulate(reference_tokens.begin(), reference_tokens.end(),
14575                               string_t{},
14576                               [](const string_t& a, const string_t& b)
14577        {
14578            return detail::concat(a, '/', detail::escape(b));
14579        });
14580    }
14581
14582    /// @brief return a string representation of the JSON pointer
14583    /// @sa https://json.nlohmann.me/api/json_pointer/operator_string/
14584    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, to_string())
14585    operator string_t() const
14586    {
14587        return to_string();
14588    }
14589
14590#ifndef JSON_NO_IO
14591    /// @brief write string representation of the JSON pointer to stream
14592    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
14593    friend std::ostream& operator<<(std::ostream& o, const json_pointer& ptr)
14594    {
14595        o << ptr.to_string();
14596        return o;
14597    }
14598#endif
14599
14600    /// @brief append another JSON pointer at the end of this JSON pointer
14601    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14602    json_pointer& operator/=(const json_pointer& ptr)
14603    {
14604        reference_tokens.insert(reference_tokens.end(),
14605                                ptr.reference_tokens.begin(),
14606                                ptr.reference_tokens.end());
14607        return *this;
14608    }
14609
14610    /// @brief append an unescaped reference token at the end of this JSON pointer
14611    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14612    json_pointer& operator/=(string_t token)
14613    {
14614        push_back(std::move(token));
14615        return *this;
14616    }
14617
14618    /// @brief append an array index at the end of this JSON pointer
14619    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slasheq/
14620    json_pointer& operator/=(std::size_t array_idx)
14621    {
14622        return *this /= std::to_string(array_idx);
14623    }
14624
14625    /// @brief create a new JSON pointer by appending the right JSON pointer at the end of the left JSON pointer
14626    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14627    friend json_pointer operator/(const json_pointer& lhs,
14628                                  const json_pointer& rhs)
14629    {
14630        return json_pointer(lhs) /= rhs;
14631    }
14632
14633    /// @brief create a new JSON pointer by appending the unescaped token at the end of the JSON pointer
14634    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14635    friend json_pointer operator/(const json_pointer& lhs, string_t token) // NOLINT(performance-unnecessary-value-param)
14636    {
14637        return json_pointer(lhs) /= std::move(token);
14638    }
14639
14640    /// @brief create a new JSON pointer by appending the array-index-token at the end of the JSON pointer
14641    /// @sa https://json.nlohmann.me/api/json_pointer/operator_slash/
14642    friend json_pointer operator/(const json_pointer& lhs, std::size_t array_idx)
14643    {
14644        return json_pointer(lhs) /= array_idx;
14645    }
14646
14647    /// @brief returns the parent of this JSON pointer
14648    /// @sa https://json.nlohmann.me/api/json_pointer/parent_pointer/
14649    json_pointer parent_pointer() const
14650    {
14651        if (empty())
14652        {
14653            return *this;
14654        }
14655
14656        json_pointer res = *this;
14657        res.pop_back();
14658        return res;
14659    }
14660
14661    /// @brief remove last reference token
14662    /// @sa https://json.nlohmann.me/api/json_pointer/pop_back/
14663    void pop_back()
14664    {
14665        if (JSON_HEDLEY_UNLIKELY(empty()))
14666        {
14667            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14668        }
14669
14670        reference_tokens.pop_back();
14671    }
14672
14673    /// @brief return last reference token
14674    /// @sa https://json.nlohmann.me/api/json_pointer/back/
14675    const string_t& back() const
14676    {
14677        if (JSON_HEDLEY_UNLIKELY(empty()))
14678        {
14679            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14680        }
14681
14682        return reference_tokens.back();
14683    }
14684
14685    /// @brief append an unescaped token at the end of the reference pointer
14686    /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14687    void push_back(const string_t& token)
14688    {
14689        reference_tokens.push_back(token);
14690    }
14691
14692    /// @brief append an unescaped token at the end of the reference pointer
14693    /// @sa https://json.nlohmann.me/api/json_pointer/push_back/
14694    void push_back(string_t&& token)
14695    {
14696        reference_tokens.push_back(std::move(token));
14697    }
14698
14699    /// @brief return whether pointer points to the root document
14700    /// @sa https://json.nlohmann.me/api/json_pointer/empty/
14701    bool empty() const noexcept
14702    {
14703        return reference_tokens.empty();
14704    }
14705
14706  private:
14707    /*!
14708    @param[in] s  reference token to be converted into an array index
14709
14710    @return integer representation of @a s
14711
14712    @throw parse_error.106  if an array index begins with '0'
14713    @throw parse_error.109  if an array index begins not with a digit
14714    @throw out_of_range.404 if string @a s could not be converted to an integer
14715    @throw out_of_range.410 if an array index exceeds size_type
14716    */
14717    template<typename BasicJsonType>
14718    static typename BasicJsonType::size_type array_index(const string_t& s)
14719    {
14720        using size_type = typename BasicJsonType::size_type;
14721
14722        // error condition (cf. RFC 6901, Sect. 4)
14723        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && s[0] == '0'))
14724        {
14725            JSON_THROW(detail::parse_error::create(106, 0, detail::concat("array index '", s, "' must not begin with '0'"), nullptr));
14726        }
14727
14728        // error condition (cf. RFC 6901, Sect. 4)
14729        if (JSON_HEDLEY_UNLIKELY(s.size() > 1 && !(s[0] >= '1' && s[0] <= '9')))
14730        {
14731            JSON_THROW(detail::parse_error::create(109, 0, detail::concat("array index '", s, "' is not a number"), nullptr));
14732        }
14733
14734        const char* p = s.c_str();
14735        char* p_end = nullptr; // NOLINT(misc-const-correctness)
14736        errno = 0; // strtoull doesn't reset errno
14737        const unsigned long long res = std::strtoull(p, &p_end, 10); // NOLINT(runtime/int)
14738        if (p == p_end // invalid input or empty string
14739                || errno == ERANGE // out of range
14740                || JSON_HEDLEY_UNLIKELY(static_cast<std::size_t>(p_end - p) != s.size())) // incomplete read
14741        {
14742            JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", s, "'"), nullptr));
14743        }
14744
14745        // only triggered on special platforms (like 32bit), see also
14746        // https://github.com/nlohmann/json/pull/2203
14747        if (res >= static_cast<unsigned long long>((std::numeric_limits<size_type>::max)()))  // NOLINT(runtime/int)
14748        {
14749            JSON_THROW(detail::out_of_range::create(410, detail::concat("array index ", s, " exceeds size_type"), nullptr));   // LCOV_EXCL_LINE
14750        }
14751
14752        return static_cast<size_type>(res);
14753    }
14754
14755  JSON_PRIVATE_UNLESS_TESTED:
14756    json_pointer top() const
14757    {
14758        if (JSON_HEDLEY_UNLIKELY(empty()))
14759        {
14760            JSON_THROW(detail::out_of_range::create(405, "JSON pointer has no parent", nullptr));
14761        }
14762
14763        json_pointer result = *this;
14764        result.reference_tokens = {reference_tokens[0]};
14765        return result;
14766    }
14767
14768  private:
14769    /*!
14770    @brief create and return a reference to the pointed to value
14771
14772    @complexity Linear in the number of reference tokens.
14773
14774    @throw parse_error.109 if array index is not a number
14775    @throw type_error.313 if value cannot be unflattened
14776    */
14777    template<typename BasicJsonType>
14778    BasicJsonType& get_and_create(BasicJsonType& j) const
14779    {
14780        auto* result = &j;
14781
14782        // in case no reference tokens exist, return a reference to the JSON value
14783        // j which will be overwritten by a primitive value
14784        for (const auto& reference_token : reference_tokens)
14785        {
14786            switch (result->type())
14787            {
14788                case detail::value_t::null:
14789                {
14790                    if (reference_token == "0")
14791                    {
14792                        // start a new array if reference token is 0
14793                        result = &result->operator[](0);
14794                    }
14795                    else
14796                    {
14797                        // start a new object otherwise
14798                        result = &result->operator[](reference_token);
14799                    }
14800                    break;
14801                }
14802
14803                case detail::value_t::object:
14804                {
14805                    // create an entry in the object
14806                    result = &result->operator[](reference_token);
14807                    break;
14808                }
14809
14810                case detail::value_t::array:
14811                {
14812                    // create an entry in the array
14813                    result = &result->operator[](array_index<BasicJsonType>(reference_token));
14814                    break;
14815                }
14816
14817                /*
14818                The following code is only reached if there exists a reference
14819                token _and_ the current value is primitive. In this case, we have
14820                an error situation, because primitive values may only occur as
14821                single value; that is, with an empty list of reference tokens.
14822                */
14823                case detail::value_t::string:
14824                case detail::value_t::boolean:
14825                case detail::value_t::number_integer:
14826                case detail::value_t::number_unsigned:
14827                case detail::value_t::number_float:
14828                case detail::value_t::binary:
14829                case detail::value_t::discarded:
14830                default:
14831                    JSON_THROW(detail::type_error::create(313, "invalid value to unflatten", &j));
14832            }
14833        }
14834
14835        return *result;
14836    }
14837
14838    /*!
14839    @brief return a reference to the pointed to value
14840
14841    @note This version does not throw if a value is not present, but tries to
14842          create nested values instead. For instance, calling this function
14843          with pointer `"/this/that"` on a null value is equivalent to calling
14844          `operator[]("this").operator[]("that")` on that value, effectively
14845          changing the null value to an object.
14846
14847    @param[in] ptr  a JSON value
14848
14849    @return reference to the JSON value pointed to by the JSON pointer
14850
14851    @complexity Linear in the length of the JSON pointer.
14852
14853    @throw parse_error.106   if an array index begins with '0'
14854    @throw parse_error.109   if an array index was not a number
14855    @throw out_of_range.404  if the JSON pointer can not be resolved
14856    */
14857    template<typename BasicJsonType>
14858    BasicJsonType& get_unchecked(BasicJsonType* ptr) const
14859    {
14860        for (const auto& reference_token : reference_tokens)
14861        {
14862            // convert null values to arrays or objects before continuing
14863            if (ptr->is_null())
14864            {
14865                // check if reference token is a number
14866                const bool nums =
14867                    std::all_of(reference_token.begin(), reference_token.end(),
14868                                [](const unsigned char x)
14869                {
14870                    return std::isdigit(x);
14871                });
14872
14873                // change value to array for numbers or "-" or to object otherwise
14874                *ptr = (nums || reference_token == "-")
14875                       ? detail::value_t::array
14876                       : detail::value_t::object;
14877            }
14878
14879            switch (ptr->type())
14880            {
14881                case detail::value_t::object:
14882                {
14883                    // use unchecked object access
14884                    ptr = &ptr->operator[](reference_token);
14885                    break;
14886                }
14887
14888                case detail::value_t::array:
14889                {
14890                    if (reference_token == "-")
14891                    {
14892                        // explicitly treat "-" as index beyond the end
14893                        ptr = &ptr->operator[](ptr->m_data.m_value.array->size());
14894                    }
14895                    else
14896                    {
14897                        // convert array index to number; unchecked access
14898                        ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
14899                    }
14900                    break;
14901                }
14902
14903                case detail::value_t::null:
14904                case detail::value_t::string:
14905                case detail::value_t::boolean:
14906                case detail::value_t::number_integer:
14907                case detail::value_t::number_unsigned:
14908                case detail::value_t::number_float:
14909                case detail::value_t::binary:
14910                case detail::value_t::discarded:
14911                default:
14912                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14913            }
14914        }
14915
14916        return *ptr;
14917    }
14918
14919    /*!
14920    @throw parse_error.106   if an array index begins with '0'
14921    @throw parse_error.109   if an array index was not a number
14922    @throw out_of_range.402  if the array index '-' is used
14923    @throw out_of_range.404  if the JSON pointer can not be resolved
14924    */
14925    template<typename BasicJsonType>
14926    BasicJsonType& get_checked(BasicJsonType* ptr) const
14927    {
14928        for (const auto& reference_token : reference_tokens)
14929        {
14930            switch (ptr->type())
14931            {
14932                case detail::value_t::object:
14933                {
14934                    // note: at performs range check
14935                    ptr = &ptr->at(reference_token);
14936                    break;
14937                }
14938
14939                case detail::value_t::array:
14940                {
14941                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
14942                    {
14943                        // "-" always fails the range check
14944                        JSON_THROW(detail::out_of_range::create(402, detail::concat(
14945                                "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
14946                                ") is out of range"), ptr));
14947                    }
14948
14949                    // note: at performs range check
14950                    ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
14951                    break;
14952                }
14953
14954                case detail::value_t::null:
14955                case detail::value_t::string:
14956                case detail::value_t::boolean:
14957                case detail::value_t::number_integer:
14958                case detail::value_t::number_unsigned:
14959                case detail::value_t::number_float:
14960                case detail::value_t::binary:
14961                case detail::value_t::discarded:
14962                default:
14963                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
14964            }
14965        }
14966
14967        return *ptr;
14968    }
14969
14970    /*!
14971    @brief return a const reference to the pointed to value
14972
14973    @param[in] ptr  a JSON value
14974
14975    @return const reference to the JSON value pointed to by the JSON
14976    pointer
14977
14978    @throw parse_error.106   if an array index begins with '0'
14979    @throw parse_error.109   if an array index was not a number
14980    @throw out_of_range.402  if the array index '-' is used
14981    @throw out_of_range.404  if the JSON pointer can not be resolved
14982    */
14983    template<typename BasicJsonType>
14984    const BasicJsonType& get_unchecked(const BasicJsonType* ptr) const
14985    {
14986        for (const auto& reference_token : reference_tokens)
14987        {
14988            switch (ptr->type())
14989            {
14990                case detail::value_t::object:
14991                {
14992                    // use unchecked object access
14993                    ptr = &ptr->operator[](reference_token);
14994                    break;
14995                }
14996
14997                case detail::value_t::array:
14998                {
14999                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15000                    {
15001                        // "-" cannot be used for const access
15002                        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));
15003                    }
15004
15005                    // use unchecked array access
15006                    ptr = &ptr->operator[](array_index<BasicJsonType>(reference_token));
15007                    break;
15008                }
15009
15010                case detail::value_t::null:
15011                case detail::value_t::string:
15012                case detail::value_t::boolean:
15013                case detail::value_t::number_integer:
15014                case detail::value_t::number_unsigned:
15015                case detail::value_t::number_float:
15016                case detail::value_t::binary:
15017                case detail::value_t::discarded:
15018                default:
15019                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15020            }
15021        }
15022
15023        return *ptr;
15024    }
15025
15026    /*!
15027    @throw parse_error.106   if an array index begins with '0'
15028    @throw parse_error.109   if an array index was not a number
15029    @throw out_of_range.402  if the array index '-' is used
15030    @throw out_of_range.404  if the JSON pointer can not be resolved
15031    */
15032    template<typename BasicJsonType>
15033    const BasicJsonType& get_checked(const BasicJsonType* ptr) const
15034    {
15035        for (const auto& reference_token : reference_tokens)
15036        {
15037            switch (ptr->type())
15038            {
15039                case detail::value_t::object:
15040                {
15041                    // note: at performs range check
15042                    ptr = &ptr->at(reference_token);
15043                    break;
15044                }
15045
15046                case detail::value_t::array:
15047                {
15048                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15049                    {
15050                        // "-" always fails the range check
15051                        JSON_THROW(detail::out_of_range::create(402, detail::concat(
15052                                "array index '-' (", std::to_string(ptr->m_data.m_value.array->size()),
15053                                ") is out of range"), ptr));
15054                    }
15055
15056                    // note: at performs range check
15057                    ptr = &ptr->at(array_index<BasicJsonType>(reference_token));
15058                    break;
15059                }
15060
15061                case detail::value_t::null:
15062                case detail::value_t::string:
15063                case detail::value_t::boolean:
15064                case detail::value_t::number_integer:
15065                case detail::value_t::number_unsigned:
15066                case detail::value_t::number_float:
15067                case detail::value_t::binary:
15068                case detail::value_t::discarded:
15069                default:
15070                    JSON_THROW(detail::out_of_range::create(404, detail::concat("unresolved reference token '", reference_token, "'"), ptr));
15071            }
15072        }
15073
15074        return *ptr;
15075    }
15076
15077    /*!
15078    @throw parse_error.106   if an array index begins with '0'
15079    @throw parse_error.109   if an array index was not a number
15080    */
15081    template<typename BasicJsonType>
15082    bool contains(const BasicJsonType* ptr) const
15083    {
15084        for (const auto& reference_token : reference_tokens)
15085        {
15086            switch (ptr->type())
15087            {
15088                case detail::value_t::object:
15089                {
15090                    if (!ptr->contains(reference_token))
15091                    {
15092                        // we did not find the key in the object
15093                        return false;
15094                    }
15095
15096                    ptr = &ptr->operator[](reference_token);
15097                    break;
15098                }
15099
15100                case detail::value_t::array:
15101                {
15102                    if (JSON_HEDLEY_UNLIKELY(reference_token == "-"))
15103                    {
15104                        // "-" always fails the range check
15105                        return false;
15106                    }
15107                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() == 1 && !("0" <= reference_token && reference_token <= "9")))
15108                    {
15109                        // invalid char
15110                        return false;
15111                    }
15112                    if (JSON_HEDLEY_UNLIKELY(reference_token.size() > 1))
15113                    {
15114                        if (JSON_HEDLEY_UNLIKELY(!('1' <= reference_token[0] && reference_token[0] <= '9')))
15115                        {
15116                            // first char should be between '1' and '9'
15117                            return false;
15118                        }
15119                        for (std::size_t i = 1; i < reference_token.size(); i++)
15120                        {
15121                            if (JSON_HEDLEY_UNLIKELY(!('0' <= reference_token[i] && reference_token[i] <= '9')))
15122                            {
15123                                // other char should be between '0' and '9'
15124                                return false;
15125                            }
15126                        }
15127                    }
15128
15129                    const auto idx = array_index<BasicJsonType>(reference_token);
15130                    if (idx >= ptr->size())
15131                    {
15132                        // index out of range
15133                        return false;
15134                    }
15135
15136                    ptr = &ptr->operator[](idx);
15137                    break;
15138                }
15139
15140                case detail::value_t::null:
15141                case detail::value_t::string:
15142                case detail::value_t::boolean:
15143                case detail::value_t::number_integer:
15144                case detail::value_t::number_unsigned:
15145                case detail::value_t::number_float:
15146                case detail::value_t::binary:
15147                case detail::value_t::discarded:
15148                default:
15149                {
15150                    // we do not expect primitive values if there is still a
15151                    // reference token to process
15152                    return false;
15153                }
15154            }
15155        }
15156
15157        // no reference token left means we found a primitive value
15158        return true;
15159    }
15160
15161    /*!
15162    @brief split the string input to reference tokens
15163
15164    @note This function is only called by the json_pointer constructor.
15165          All exceptions below are documented there.
15166
15167    @throw parse_error.107  if the pointer is not empty or begins with '/'
15168    @throw parse_error.108  if character '~' is not followed by '0' or '1'
15169    */
15170    static std::vector<string_t> split(const string_t& reference_string)
15171    {
15172        std::vector<string_t> result;
15173
15174        // special case: empty reference string -> no reference tokens
15175        if (reference_string.empty())
15176        {
15177            return result;
15178        }
15179
15180        // check if nonempty reference string begins with slash
15181        if (JSON_HEDLEY_UNLIKELY(reference_string[0] != '/'))
15182        {
15183            JSON_THROW(detail::parse_error::create(107, 1, detail::concat("JSON pointer must be empty or begin with '/' - was: '", reference_string, "'"), nullptr));
15184        }
15185
15186        // extract the reference tokens:
15187        // - slash: position of the last read slash (or end of string)
15188        // - start: position after the previous slash
15189        for (
15190            // search for the first slash after the first character
15191            std::size_t slash = reference_string.find_first_of('/', 1),
15192            // set the beginning of the first reference token
15193            start = 1;
15194            // we can stop if start == 0 (if slash == string_t::npos)
15195            start != 0;
15196            // set the beginning of the next reference token
15197            // (will eventually be 0 if slash == string_t::npos)
15198            start = (slash == string_t::npos) ? 0 : slash + 1,
15199            // find next slash
15200            slash = reference_string.find_first_of('/', start))
15201        {
15202            // use the text between the beginning of the reference token
15203            // (start) and the last slash (slash).
15204            auto reference_token = reference_string.substr(start, slash - start);
15205
15206            // check reference tokens are properly escaped
15207            for (std::size_t pos = reference_token.find_first_of('~');
15208                    pos != string_t::npos;
15209                    pos = reference_token.find_first_of('~', pos + 1))
15210            {
15211                JSON_ASSERT(reference_token[pos] == '~');
15212
15213                // ~ must be followed by 0 or 1
15214                if (JSON_HEDLEY_UNLIKELY(pos == reference_token.size() - 1 ||
15215                                         (reference_token[pos + 1] != '0' &&
15216                                          reference_token[pos + 1] != '1')))
15217                {
15218                    JSON_THROW(detail::parse_error::create(108, 0, "escape character '~' must be followed with '0' or '1'", nullptr));
15219                }
15220            }
15221
15222            // finally, store the reference token
15223            detail::unescape(reference_token);
15224            result.push_back(reference_token);
15225        }
15226
15227        return result;
15228    }
15229
15230  private:
15231    /*!
15232    @param[in] reference_string  the reference string to the current value
15233    @param[in] value             the value to consider
15234    @param[in,out] result        the result object to insert values to
15235
15236    @note Empty objects or arrays are flattened to `null`.
15237    */
15238    template<typename BasicJsonType>
15239    static void flatten(const string_t& reference_string,
15240                        const BasicJsonType& value,
15241                        BasicJsonType& result)
15242    {
15243        switch (value.type())
15244        {
15245            case detail::value_t::array:
15246            {
15247                if (value.m_data.m_value.array->empty())
15248                {
15249                    // flatten empty array as null
15250                    result[reference_string] = nullptr;
15251                }
15252                else
15253                {
15254                    // iterate array and use index as reference string
15255                    for (std::size_t i = 0; i < value.m_data.m_value.array->size(); ++i)
15256                    {
15257                        flatten(detail::concat<string_t>(reference_string, '/', std::to_string(i)),
15258                                value.m_data.m_value.array->operator[](i), result);
15259                    }
15260                }
15261                break;
15262            }
15263
15264            case detail::value_t::object:
15265            {
15266                if (value.m_data.m_value.object->empty())
15267                {
15268                    // flatten empty object as null
15269                    result[reference_string] = nullptr;
15270                }
15271                else
15272                {
15273                    // iterate object and use keys as reference string
15274                    for (const auto& element : *value.m_data.m_value.object)
15275                    {
15276                        flatten(detail::concat<string_t>(reference_string, '/', detail::escape(element.first)), element.second, result);
15277                    }
15278                }
15279                break;
15280            }
15281
15282            case detail::value_t::null:
15283            case detail::value_t::string:
15284            case detail::value_t::boolean:
15285            case detail::value_t::number_integer:
15286            case detail::value_t::number_unsigned:
15287            case detail::value_t::number_float:
15288            case detail::value_t::binary:
15289            case detail::value_t::discarded:
15290            default:
15291            {
15292                // add primitive value with its reference string
15293                result[reference_string] = value;
15294                break;
15295            }
15296        }
15297    }
15298
15299    /*!
15300    @param[in] value  flattened JSON
15301
15302    @return unflattened JSON
15303
15304    @throw parse_error.109 if array index is not a number
15305    @throw type_error.314  if value is not an object
15306    @throw type_error.315  if object values are not primitive
15307    @throw type_error.313  if value cannot be unflattened
15308    */
15309    template<typename BasicJsonType>
15310    static BasicJsonType
15311    unflatten(const BasicJsonType& value)
15312    {
15313        if (JSON_HEDLEY_UNLIKELY(!value.is_object()))
15314        {
15315            JSON_THROW(detail::type_error::create(314, "only objects can be unflattened", &value));
15316        }
15317
15318        BasicJsonType result;
15319
15320        // iterate the JSON object values
15321        for (const auto& element : *value.m_data.m_value.object)
15322        {
15323            if (JSON_HEDLEY_UNLIKELY(!element.second.is_primitive()))
15324            {
15325                JSON_THROW(detail::type_error::create(315, "values in object must be primitive", &element.second));
15326            }
15327
15328            // assign value to reference pointed to by JSON pointer; Note that if
15329            // the JSON pointer is "" (i.e., points to the whole value), function
15330            // get_and_create returns a reference to result itself. An assignment
15331            // will then create a primitive value.
15332            json_pointer(element.first).get_and_create(result) = element.second;
15333        }
15334
15335        return result;
15336    }
15337
15338    // can't use conversion operator because of ambiguity
15339    json_pointer<string_t> convert() const&
15340    {
15341        json_pointer<string_t> result;
15342        result.reference_tokens = reference_tokens;
15343        return result;
15344    }
15345
15346    json_pointer<string_t> convert()&&
15347    {
15348        json_pointer<string_t> result;
15349        result.reference_tokens = std::move(reference_tokens);
15350        return result;
15351    }
15352
15353  public:
15354#if JSON_HAS_THREE_WAY_COMPARISON
15355    /// @brief compares two JSON pointers for equality
15356    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15357    template<typename RefStringTypeRhs>
15358    bool operator==(const json_pointer<RefStringTypeRhs>& rhs) const noexcept
15359    {
15360        return reference_tokens == rhs.reference_tokens;
15361    }
15362
15363    /// @brief compares JSON pointer and string for equality
15364    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15365    JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer))
15366    bool operator==(const string_t& rhs) const
15367    {
15368        return *this == json_pointer(rhs);
15369    }
15370
15371    /// @brief 3-way compares two JSON pointers
15372    template<typename RefStringTypeRhs>
15373    std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept // *NOPAD*
15374    {
15375        return  reference_tokens <=> rhs.reference_tokens; // *NOPAD*
15376    }
15377#else
15378    /// @brief compares two JSON pointers for equality
15379    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15380    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15381    // NOLINTNEXTLINE(readability-redundant-declaration)
15382    friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15383                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15384
15385    /// @brief compares JSON pointer and string for equality
15386    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15387    template<typename RefStringTypeLhs, typename StringType>
15388    // NOLINTNEXTLINE(readability-redundant-declaration)
15389    friend bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15390                           const StringType& rhs);
15391
15392    /// @brief compares string and JSON pointer for equality
15393    /// @sa https://json.nlohmann.me/api/json_pointer/operator_eq/
15394    template<typename RefStringTypeRhs, typename StringType>
15395    // NOLINTNEXTLINE(readability-redundant-declaration)
15396    friend bool operator==(const StringType& lhs,
15397                           const json_pointer<RefStringTypeRhs>& rhs);
15398
15399    /// @brief compares two JSON pointers for inequality
15400    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15401    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15402    // NOLINTNEXTLINE(readability-redundant-declaration)
15403    friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15404                           const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15405
15406    /// @brief compares JSON pointer and string for inequality
15407    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15408    template<typename RefStringTypeLhs, typename StringType>
15409    // NOLINTNEXTLINE(readability-redundant-declaration)
15410    friend bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15411                           const StringType& rhs);
15412
15413    /// @brief compares string and JSON pointer for inequality
15414    /// @sa https://json.nlohmann.me/api/json_pointer/operator_ne/
15415    template<typename RefStringTypeRhs, typename StringType>
15416    // NOLINTNEXTLINE(readability-redundant-declaration)
15417    friend bool operator!=(const StringType& lhs,
15418                           const json_pointer<RefStringTypeRhs>& rhs);
15419
15420    /// @brief compares two JSON pointer for less-than
15421    template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15422    // NOLINTNEXTLINE(readability-redundant-declaration)
15423    friend bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15424                          const json_pointer<RefStringTypeRhs>& rhs) noexcept;
15425#endif
15426
15427  private:
15428    /// the reference tokens
15429    std::vector<string_t> reference_tokens;
15430};
15431
15432#if !JSON_HAS_THREE_WAY_COMPARISON
15433// functions cannot be defined inside class due to ODR violations
15434template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15435inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15436                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
15437{
15438    return lhs.reference_tokens == rhs.reference_tokens;
15439}
15440
15441template<typename RefStringTypeLhs,
15442         typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15443JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15444inline bool operator==(const json_pointer<RefStringTypeLhs>& lhs,
15445                       const StringType& rhs)
15446{
15447    return lhs == json_pointer<RefStringTypeLhs>(rhs);
15448}
15449
15450template<typename RefStringTypeRhs,
15451         typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15452JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator==(json_pointer, json_pointer))
15453inline bool operator==(const StringType& lhs,
15454                       const json_pointer<RefStringTypeRhs>& rhs)
15455{
15456    return json_pointer<RefStringTypeRhs>(lhs) == rhs;
15457}
15458
15459template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15460inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15461                       const json_pointer<RefStringTypeRhs>& rhs) noexcept
15462{
15463    return !(lhs == rhs);
15464}
15465
15466template<typename RefStringTypeLhs,
15467         typename StringType = typename json_pointer<RefStringTypeLhs>::string_t>
15468JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15469inline bool operator!=(const json_pointer<RefStringTypeLhs>& lhs,
15470                       const StringType& rhs)
15471{
15472    return !(lhs == rhs);
15473}
15474
15475template<typename RefStringTypeRhs,
15476         typename StringType = typename json_pointer<RefStringTypeRhs>::string_t>
15477JSON_HEDLEY_DEPRECATED_FOR(3.11.2, operator!=(json_pointer, json_pointer))
15478inline bool operator!=(const StringType& lhs,
15479                       const json_pointer<RefStringTypeRhs>& rhs)
15480{
15481    return !(lhs == rhs);
15482}
15483
15484template<typename RefStringTypeLhs, typename RefStringTypeRhs>
15485inline bool operator<(const json_pointer<RefStringTypeLhs>& lhs,
15486                      const json_pointer<RefStringTypeRhs>& rhs) noexcept
15487{
15488    return lhs.reference_tokens < rhs.reference_tokens;
15489}
15490#endif
15491
15492NLOHMANN_JSON_NAMESPACE_END
15493
15494// #include <nlohmann/detail/json_ref.hpp>
15495//     __ _____ _____ _____
15496//  __|  |   __|     |   | |  JSON for Modern C++
15497// |  |  |__   |  |  | | | |  version 3.12.0
15498// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
15499//
15500// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15501// SPDX-License-Identifier: MIT
15502
15503
15504
15505#include <initializer_list>
15506#include <utility>
15507
15508// #include <nlohmann/detail/abi_macros.hpp>
15509
15510// #include <nlohmann/detail/meta/type_traits.hpp>
15511
15512
15513NLOHMANN_JSON_NAMESPACE_BEGIN
15514namespace detail
15515{
15516
15517template<typename BasicJsonType>
15518class json_ref
15519{
15520  public:
15521    using value_type = BasicJsonType;
15522
15523    json_ref(value_type&& value)
15524        : owned_value(std::move(value))
15525    {}
15526
15527    json_ref(const value_type& value)
15528        : value_ref(&value)
15529    {}
15530
15531    json_ref(std::initializer_list<json_ref> init)
15532        : owned_value(init)
15533    {}
15534
15535    template <
15536        class... Args,
15537        enable_if_t<std::is_constructible<value_type, Args...>::value, int> = 0 >
15538    json_ref(Args && ... args)
15539        : owned_value(std::forward<Args>(args)...)
15540    {}
15541
15542    // class should be movable only
15543    json_ref(json_ref&&) noexcept = default;
15544    json_ref(const json_ref&) = delete;
15545    json_ref& operator=(const json_ref&) = delete;
15546    json_ref& operator=(json_ref&&) = delete;
15547    ~json_ref() = default;
15548
15549    value_type moved_or_copied() const
15550    {
15551        if (value_ref == nullptr)
15552        {
15553            return std::move(owned_value);
15554        }
15555        return *value_ref;
15556    }
15557
15558    value_type const& operator*() const
15559    {
15560        return value_ref ? *value_ref : owned_value;
15561    }
15562
15563    value_type const* operator->() const
15564    {
15565        return &** this;
15566    }
15567
15568  private:
15569    mutable value_type owned_value = nullptr;
15570    value_type const* value_ref = nullptr;
15571};
15572
15573}  // namespace detail
15574NLOHMANN_JSON_NAMESPACE_END
15575
15576// #include <nlohmann/detail/macro_scope.hpp>
15577
15578// #include <nlohmann/detail/string_concat.hpp>
15579
15580// #include <nlohmann/detail/string_escape.hpp>
15581
15582// #include <nlohmann/detail/string_utils.hpp>
15583
15584// #include <nlohmann/detail/meta/cpp_future.hpp>
15585
15586// #include <nlohmann/detail/meta/type_traits.hpp>
15587
15588// #include <nlohmann/detail/output/binary_writer.hpp>
15589//     __ _____ _____ _____
15590//  __|  |   __|     |   | |  JSON for Modern C++
15591// |  |  |__   |  |  | | | |  version 3.12.0
15592// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
15593//
15594// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15595// SPDX-License-Identifier: MIT
15596
15597
15598
15599#include <algorithm> // reverse
15600#include <array> // array
15601#include <map> // map
15602#include <cmath> // isnan, isinf
15603#include <cstdint> // uint8_t, uint16_t, uint32_t, uint64_t
15604#include <cstring> // memcpy
15605#include <limits> // numeric_limits
15606#include <string> // string
15607#include <utility> // move
15608#include <vector> // vector
15609
15610// #include <nlohmann/detail/input/binary_reader.hpp>
15611
15612// #include <nlohmann/detail/macro_scope.hpp>
15613
15614// #include <nlohmann/detail/output/output_adapters.hpp>
15615//     __ _____ _____ _____
15616//  __|  |   __|     |   | |  JSON for Modern C++
15617// |  |  |__   |  |  | | | |  version 3.12.0
15618// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
15619//
15620// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
15621// SPDX-License-Identifier: MIT
15622
15623
15624
15625#include <algorithm> // copy
15626#include <cstddef> // size_t
15627#include <iterator> // back_inserter
15628#include <memory> // shared_ptr, make_shared
15629#include <string> // basic_string
15630#include <vector> // vector
15631
15632#ifndef JSON_NO_IO
15633    #include <ios>      // streamsize
15634    #include <ostream>  // basic_ostream
15635#endif  // JSON_NO_IO
15636
15637// #include <nlohmann/detail/macro_scope.hpp>
15638
15639
15640NLOHMANN_JSON_NAMESPACE_BEGIN
15641namespace detail
15642{
15643
15644/// abstract output adapter interface
15645template<typename CharType> struct output_adapter_protocol
15646{
15647    virtual void write_character(CharType c) = 0;
15648    virtual void write_characters(const CharType* s, std::size_t length) = 0;
15649    virtual ~output_adapter_protocol() = default;
15650
15651    output_adapter_protocol() = default;
15652    output_adapter_protocol(const output_adapter_protocol&) = default;
15653    output_adapter_protocol(output_adapter_protocol&&) noexcept = default;
15654    output_adapter_protocol& operator=(const output_adapter_protocol&) = default;
15655    output_adapter_protocol& operator=(output_adapter_protocol&&) noexcept = default;
15656};
15657
15658/// a type to simplify interfaces
15659template<typename CharType>
15660using output_adapter_t = std::shared_ptr<output_adapter_protocol<CharType>>;
15661
15662/// output adapter for byte vectors
15663template<typename CharType, typename AllocatorType = std::allocator<CharType>>
15664class output_vector_adapter : public output_adapter_protocol<CharType>
15665{
15666  public:
15667    explicit output_vector_adapter(std::vector<CharType, AllocatorType>& vec) noexcept
15668        : v(vec)
15669    {}
15670
15671    void write_character(CharType c) override
15672    {
15673        v.push_back(c);
15674    }
15675
15676    JSON_HEDLEY_NON_NULL(2)
15677    void write_characters(const CharType* s, std::size_t length) override
15678    {
15679        v.insert(v.end(), s, s + length);
15680    }
15681
15682  private:
15683    std::vector<CharType, AllocatorType>& v;
15684};
15685
15686#ifndef JSON_NO_IO
15687/// output adapter for output streams
15688template<typename CharType>
15689class output_stream_adapter : public output_adapter_protocol<CharType>
15690{
15691  public:
15692    explicit output_stream_adapter(std::basic_ostream<CharType>& s) noexcept
15693        : stream(s)
15694    {}
15695
15696    void write_character(CharType c) override
15697    {
15698        stream.put(c);
15699    }
15700
15701    JSON_HEDLEY_NON_NULL(2)
15702    void write_characters(const CharType* s, std::size_t length) override
15703    {
15704        stream.write(s, static_cast<std::streamsize>(length));
15705    }
15706
15707  private:
15708    std::basic_ostream<CharType>& stream;
15709};
15710#endif  // JSON_NO_IO
15711
15712/// output adapter for basic_string
15713template<typename CharType, typename StringType = std::basic_string<CharType>>
15714class output_string_adapter : public output_adapter_protocol<CharType>
15715{
15716  public:
15717    explicit output_string_adapter(StringType& s) noexcept
15718        : str(s)
15719    {}
15720
15721    void write_character(CharType c) override
15722    {
15723        str.push_back(c);
15724    }
15725
15726    JSON_HEDLEY_NON_NULL(2)
15727    void write_characters(const CharType* s, std::size_t length) override
15728    {
15729        str.append(s, length);
15730    }
15731
15732  private:
15733    StringType& str;
15734};
15735
15736template<typename CharType, typename StringType = std::basic_string<CharType>>
15737class output_adapter
15738{
15739  public:
15740    template<typename AllocatorType = std::allocator<CharType>>
15741    output_adapter(std::vector<CharType, AllocatorType>& vec)
15742        : oa(std::make_shared<output_vector_adapter<CharType, AllocatorType>>(vec)) {}
15743
15744#ifndef JSON_NO_IO
15745    output_adapter(std::basic_ostream<CharType>& s)
15746        : oa(std::make_shared<output_stream_adapter<CharType>>(s)) {}
15747#endif  // JSON_NO_IO
15748
15749    output_adapter(StringType& s)
15750        : oa(std::make_shared<output_string_adapter<CharType, StringType>>(s)) {}
15751
15752    operator output_adapter_t<CharType>()
15753    {
15754        return oa;
15755    }
15756
15757  private:
15758    output_adapter_t<CharType> oa = nullptr;
15759};
15760
15761}  // namespace detail
15762NLOHMANN_JSON_NAMESPACE_END
15763
15764// #include <nlohmann/detail/string_concat.hpp>
15765
15766
15767NLOHMANN_JSON_NAMESPACE_BEGIN
15768namespace detail
15769{
15770
15771/// how to encode BJData
15772enum class bjdata_version_t
15773{
15774    draft2,
15775    draft3,
15776};
15777
15778///////////////////
15779// binary writer //
15780///////////////////
15781
15782/*!
15783@brief serialization to CBOR and MessagePack values
15784*/
15785template<typename BasicJsonType, typename CharType>
15786class binary_writer
15787{
15788    using string_t = typename BasicJsonType::string_t;
15789    using binary_t = typename BasicJsonType::binary_t;
15790    using number_float_t = typename BasicJsonType::number_float_t;
15791
15792  public:
15793    /*!
15794    @brief create a binary writer
15795
15796    @param[in] adapter  output adapter to write to
15797    */
15798    explicit binary_writer(output_adapter_t<CharType> adapter) : oa(std::move(adapter))
15799    {
15800        JSON_ASSERT(oa);
15801    }
15802
15803    /*!
15804    @param[in] j  JSON value to serialize
15805    @pre       j.type() == value_t::object
15806    */
15807    void write_bson(const BasicJsonType& j)
15808    {
15809        switch (j.type())
15810        {
15811            case value_t::object:
15812            {
15813                write_bson_object(*j.m_data.m_value.object);
15814                break;
15815            }
15816
15817            case value_t::null:
15818            case value_t::array:
15819            case value_t::string:
15820            case value_t::boolean:
15821            case value_t::number_integer:
15822            case value_t::number_unsigned:
15823            case value_t::number_float:
15824            case value_t::binary:
15825            case value_t::discarded:
15826            default:
15827            {
15828                JSON_THROW(type_error::create(317, concat("to serialize to BSON, top-level type must be object, but is ", j.type_name()), &j));
15829            }
15830        }
15831    }
15832
15833    /*!
15834    @param[in] j  JSON value to serialize
15835    */
15836    void write_cbor(const BasicJsonType& j)
15837    {
15838        switch (j.type())
15839        {
15840            case value_t::null:
15841            {
15842                oa->write_character(to_char_type(0xF6));
15843                break;
15844            }
15845
15846            case value_t::boolean:
15847            {
15848                oa->write_character(j.m_data.m_value.boolean
15849                                    ? to_char_type(0xF5)
15850                                    : to_char_type(0xF4));
15851                break;
15852            }
15853
15854            case value_t::number_integer:
15855            {
15856                if (j.m_data.m_value.number_integer >= 0)
15857                {
15858                    // CBOR does not differentiate between positive signed
15859                    // integers and unsigned integers. Therefore, we used the
15860                    // code from the value_t::number_unsigned case here.
15861                    if (j.m_data.m_value.number_integer <= 0x17)
15862                    {
15863                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15864                    }
15865                    else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint8_t>::max)())
15866                    {
15867                        oa->write_character(to_char_type(0x18));
15868                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
15869                    }
15870                    else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint16_t>::max)())
15871                    {
15872                        oa->write_character(to_char_type(0x19));
15873                        write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
15874                    }
15875                    else if (j.m_data.m_value.number_integer <= (std::numeric_limits<std::uint32_t>::max)())
15876                    {
15877                        oa->write_character(to_char_type(0x1A));
15878                        write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
15879                    }
15880                    else
15881                    {
15882                        oa->write_character(to_char_type(0x1B));
15883                        write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
15884                    }
15885                }
15886                else
15887                {
15888                    // The conversions below encode the sign in the first
15889                    // byte, and the value is converted to a positive number.
15890                    const auto positive_number = -1 - j.m_data.m_value.number_integer;
15891                    if (j.m_data.m_value.number_integer >= -24)
15892                    {
15893                        write_number(static_cast<std::uint8_t>(0x20 + positive_number));
15894                    }
15895                    else if (positive_number <= (std::numeric_limits<std::uint8_t>::max)())
15896                    {
15897                        oa->write_character(to_char_type(0x38));
15898                        write_number(static_cast<std::uint8_t>(positive_number));
15899                    }
15900                    else if (positive_number <= (std::numeric_limits<std::uint16_t>::max)())
15901                    {
15902                        oa->write_character(to_char_type(0x39));
15903                        write_number(static_cast<std::uint16_t>(positive_number));
15904                    }
15905                    else if (positive_number <= (std::numeric_limits<std::uint32_t>::max)())
15906                    {
15907                        oa->write_character(to_char_type(0x3A));
15908                        write_number(static_cast<std::uint32_t>(positive_number));
15909                    }
15910                    else
15911                    {
15912                        oa->write_character(to_char_type(0x3B));
15913                        write_number(static_cast<std::uint64_t>(positive_number));
15914                    }
15915                }
15916                break;
15917            }
15918
15919            case value_t::number_unsigned:
15920            {
15921                if (j.m_data.m_value.number_unsigned <= 0x17)
15922                {
15923                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15924                }
15925                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
15926                {
15927                    oa->write_character(to_char_type(0x18));
15928                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_unsigned));
15929                }
15930                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
15931                {
15932                    oa->write_character(to_char_type(0x19));
15933                    write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_unsigned));
15934                }
15935                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
15936                {
15937                    oa->write_character(to_char_type(0x1A));
15938                    write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_unsigned));
15939                }
15940                else
15941                {
15942                    oa->write_character(to_char_type(0x1B));
15943                    write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned));
15944                }
15945                break;
15946            }
15947
15948            case value_t::number_float:
15949            {
15950                if (std::isnan(j.m_data.m_value.number_float))
15951                {
15952                    // NaN is 0xf97e00 in CBOR
15953                    oa->write_character(to_char_type(0xF9));
15954                    oa->write_character(to_char_type(0x7E));
15955                    oa->write_character(to_char_type(0x00));
15956                }
15957                else if (std::isinf(j.m_data.m_value.number_float))
15958                {
15959                    // Infinity is 0xf97c00, -Infinity is 0xf9fc00
15960                    oa->write_character(to_char_type(0xf9));
15961                    oa->write_character(j.m_data.m_value.number_float > 0 ? to_char_type(0x7C) : to_char_type(0xFC));
15962                    oa->write_character(to_char_type(0x00));
15963                }
15964                else
15965                {
15966                    write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::cbor);
15967                }
15968                break;
15969            }
15970
15971            case value_t::string:
15972            {
15973                // step 1: write control byte and the string length
15974                const auto N = j.m_data.m_value.string->size();
15975                if (N <= 0x17)
15976                {
15977                    write_number(static_cast<std::uint8_t>(0x60 + N));
15978                }
15979                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
15980                {
15981                    oa->write_character(to_char_type(0x78));
15982                    write_number(static_cast<std::uint8_t>(N));
15983                }
15984                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
15985                {
15986                    oa->write_character(to_char_type(0x79));
15987                    write_number(static_cast<std::uint16_t>(N));
15988                }
15989                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
15990                {
15991                    oa->write_character(to_char_type(0x7A));
15992                    write_number(static_cast<std::uint32_t>(N));
15993                }
15994                // LCOV_EXCL_START
15995                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
15996                {
15997                    oa->write_character(to_char_type(0x7B));
15998                    write_number(static_cast<std::uint64_t>(N));
15999                }
16000                // LCOV_EXCL_STOP
16001
16002                // step 2: write the string
16003                oa->write_characters(
16004                    reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16005                    j.m_data.m_value.string->size());
16006                break;
16007            }
16008
16009            case value_t::array:
16010            {
16011                // step 1: write control byte and the array size
16012                const auto N = j.m_data.m_value.array->size();
16013                if (N <= 0x17)
16014                {
16015                    write_number(static_cast<std::uint8_t>(0x80 + N));
16016                }
16017                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16018                {
16019                    oa->write_character(to_char_type(0x98));
16020                    write_number(static_cast<std::uint8_t>(N));
16021                }
16022                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16023                {
16024                    oa->write_character(to_char_type(0x99));
16025                    write_number(static_cast<std::uint16_t>(N));
16026                }
16027                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16028                {
16029                    oa->write_character(to_char_type(0x9A));
16030                    write_number(static_cast<std::uint32_t>(N));
16031                }
16032                // LCOV_EXCL_START
16033                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16034                {
16035                    oa->write_character(to_char_type(0x9B));
16036                    write_number(static_cast<std::uint64_t>(N));
16037                }
16038                // LCOV_EXCL_STOP
16039
16040                // step 2: write each element
16041                for (const auto& el : *j.m_data.m_value.array)
16042                {
16043                    write_cbor(el);
16044                }
16045                break;
16046            }
16047
16048            case value_t::binary:
16049            {
16050                if (j.m_data.m_value.binary->has_subtype())
16051                {
16052                    if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint8_t>::max)())
16053                    {
16054                        write_number(static_cast<std::uint8_t>(0xd8));
16055                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.binary->subtype()));
16056                    }
16057                    else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint16_t>::max)())
16058                    {
16059                        write_number(static_cast<std::uint8_t>(0xd9));
16060                        write_number(static_cast<std::uint16_t>(j.m_data.m_value.binary->subtype()));
16061                    }
16062                    else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint32_t>::max)())
16063                    {
16064                        write_number(static_cast<std::uint8_t>(0xda));
16065                        write_number(static_cast<std::uint32_t>(j.m_data.m_value.binary->subtype()));
16066                    }
16067                    else if (j.m_data.m_value.binary->subtype() <= (std::numeric_limits<std::uint64_t>::max)())
16068                    {
16069                        write_number(static_cast<std::uint8_t>(0xdb));
16070                        write_number(static_cast<std::uint64_t>(j.m_data.m_value.binary->subtype()));
16071                    }
16072                }
16073
16074                // step 1: write control byte and the binary array size
16075                const auto N = j.m_data.m_value.binary->size();
16076                if (N <= 0x17)
16077                {
16078                    write_number(static_cast<std::uint8_t>(0x40 + N));
16079                }
16080                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16081                {
16082                    oa->write_character(to_char_type(0x58));
16083                    write_number(static_cast<std::uint8_t>(N));
16084                }
16085                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16086                {
16087                    oa->write_character(to_char_type(0x59));
16088                    write_number(static_cast<std::uint16_t>(N));
16089                }
16090                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16091                {
16092                    oa->write_character(to_char_type(0x5A));
16093                    write_number(static_cast<std::uint32_t>(N));
16094                }
16095                // LCOV_EXCL_START
16096                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16097                {
16098                    oa->write_character(to_char_type(0x5B));
16099                    write_number(static_cast<std::uint64_t>(N));
16100                }
16101                // LCOV_EXCL_STOP
16102
16103                // step 2: write each element
16104                oa->write_characters(
16105                    reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16106                    N);
16107
16108                break;
16109            }
16110
16111            case value_t::object:
16112            {
16113                // step 1: write control byte and the object size
16114                const auto N = j.m_data.m_value.object->size();
16115                if (N <= 0x17)
16116                {
16117                    write_number(static_cast<std::uint8_t>(0xA0 + N));
16118                }
16119                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16120                {
16121                    oa->write_character(to_char_type(0xB8));
16122                    write_number(static_cast<std::uint8_t>(N));
16123                }
16124                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16125                {
16126                    oa->write_character(to_char_type(0xB9));
16127                    write_number(static_cast<std::uint16_t>(N));
16128                }
16129                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16130                {
16131                    oa->write_character(to_char_type(0xBA));
16132                    write_number(static_cast<std::uint32_t>(N));
16133                }
16134                // LCOV_EXCL_START
16135                else if (N <= (std::numeric_limits<std::uint64_t>::max)())
16136                {
16137                    oa->write_character(to_char_type(0xBB));
16138                    write_number(static_cast<std::uint64_t>(N));
16139                }
16140                // LCOV_EXCL_STOP
16141
16142                // step 2: write each element
16143                for (const auto& el : *j.m_data.m_value.object)
16144                {
16145                    write_cbor(el.first);
16146                    write_cbor(el.second);
16147                }
16148                break;
16149            }
16150
16151            case value_t::discarded:
16152            default:
16153                break;
16154        }
16155    }
16156
16157    /*!
16158    @param[in] j  JSON value to serialize
16159    */
16160    void write_msgpack(const BasicJsonType& j)
16161    {
16162        switch (j.type())
16163        {
16164            case value_t::null: // nil
16165            {
16166                oa->write_character(to_char_type(0xC0));
16167                break;
16168            }
16169
16170            case value_t::boolean: // true and false
16171            {
16172                oa->write_character(j.m_data.m_value.boolean
16173                                    ? to_char_type(0xC3)
16174                                    : to_char_type(0xC2));
16175                break;
16176            }
16177
16178            case value_t::number_integer:
16179            {
16180                if (j.m_data.m_value.number_integer >= 0)
16181                {
16182                    // MessagePack does not differentiate between positive
16183                    // signed integers and unsigned integers. Therefore, we used
16184                    // the code from the value_t::number_unsigned case here.
16185                    if (j.m_data.m_value.number_unsigned < 128)
16186                    {
16187                        // positive fixnum
16188                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16189                    }
16190                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16191                    {
16192                        // uint 8
16193                        oa->write_character(to_char_type(0xCC));
16194                        write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16195                    }
16196                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16197                    {
16198                        // uint 16
16199                        oa->write_character(to_char_type(0xCD));
16200                        write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16201                    }
16202                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16203                    {
16204                        // uint 32
16205                        oa->write_character(to_char_type(0xCE));
16206                        write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16207                    }
16208                    else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16209                    {
16210                        // uint 64
16211                        oa->write_character(to_char_type(0xCF));
16212                        write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16213                    }
16214                }
16215                else
16216                {
16217                    if (j.m_data.m_value.number_integer >= -32)
16218                    {
16219                        // negative fixnum
16220                        write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16221                    }
16222                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int8_t>::min)() &&
16223                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int8_t>::max)())
16224                    {
16225                        // int 8
16226                        oa->write_character(to_char_type(0xD0));
16227                        write_number(static_cast<std::int8_t>(j.m_data.m_value.number_integer));
16228                    }
16229                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int16_t>::min)() &&
16230                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int16_t>::max)())
16231                    {
16232                        // int 16
16233                        oa->write_character(to_char_type(0xD1));
16234                        write_number(static_cast<std::int16_t>(j.m_data.m_value.number_integer));
16235                    }
16236                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int32_t>::min)() &&
16237                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int32_t>::max)())
16238                    {
16239                        // int 32
16240                        oa->write_character(to_char_type(0xD2));
16241                        write_number(static_cast<std::int32_t>(j.m_data.m_value.number_integer));
16242                    }
16243                    else if (j.m_data.m_value.number_integer >= (std::numeric_limits<std::int64_t>::min)() &&
16244                             j.m_data.m_value.number_integer <= (std::numeric_limits<std::int64_t>::max)())
16245                    {
16246                        // int 64
16247                        oa->write_character(to_char_type(0xD3));
16248                        write_number(static_cast<std::int64_t>(j.m_data.m_value.number_integer));
16249                    }
16250                }
16251                break;
16252            }
16253
16254            case value_t::number_unsigned:
16255            {
16256                if (j.m_data.m_value.number_unsigned < 128)
16257                {
16258                    // positive fixnum
16259                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16260                }
16261                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint8_t>::max)())
16262                {
16263                    // uint 8
16264                    oa->write_character(to_char_type(0xCC));
16265                    write_number(static_cast<std::uint8_t>(j.m_data.m_value.number_integer));
16266                }
16267                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint16_t>::max)())
16268                {
16269                    // uint 16
16270                    oa->write_character(to_char_type(0xCD));
16271                    write_number(static_cast<std::uint16_t>(j.m_data.m_value.number_integer));
16272                }
16273                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint32_t>::max)())
16274                {
16275                    // uint 32
16276                    oa->write_character(to_char_type(0xCE));
16277                    write_number(static_cast<std::uint32_t>(j.m_data.m_value.number_integer));
16278                }
16279                else if (j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
16280                {
16281                    // uint 64
16282                    oa->write_character(to_char_type(0xCF));
16283                    write_number(static_cast<std::uint64_t>(j.m_data.m_value.number_integer));
16284                }
16285                break;
16286            }
16287
16288            case value_t::number_float:
16289            {
16290                write_compact_float(j.m_data.m_value.number_float, detail::input_format_t::msgpack);
16291                break;
16292            }
16293
16294            case value_t::string:
16295            {
16296                // step 1: write control byte and the string length
16297                const auto N = j.m_data.m_value.string->size();
16298                if (N <= 31)
16299                {
16300                    // fixstr
16301                    write_number(static_cast<std::uint8_t>(0xA0 | N));
16302                }
16303                else if (N <= (std::numeric_limits<std::uint8_t>::max)())
16304                {
16305                    // str 8
16306                    oa->write_character(to_char_type(0xD9));
16307                    write_number(static_cast<std::uint8_t>(N));
16308                }
16309                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16310                {
16311                    // str 16
16312                    oa->write_character(to_char_type(0xDA));
16313                    write_number(static_cast<std::uint16_t>(N));
16314                }
16315                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16316                {
16317                    // str 32
16318                    oa->write_character(to_char_type(0xDB));
16319                    write_number(static_cast<std::uint32_t>(N));
16320                }
16321
16322                // step 2: write the string
16323                oa->write_characters(
16324                    reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16325                    j.m_data.m_value.string->size());
16326                break;
16327            }
16328
16329            case value_t::array:
16330            {
16331                // step 1: write control byte and the array size
16332                const auto N = j.m_data.m_value.array->size();
16333                if (N <= 15)
16334                {
16335                    // fixarray
16336                    write_number(static_cast<std::uint8_t>(0x90 | N));
16337                }
16338                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16339                {
16340                    // array 16
16341                    oa->write_character(to_char_type(0xDC));
16342                    write_number(static_cast<std::uint16_t>(N));
16343                }
16344                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16345                {
16346                    // array 32
16347                    oa->write_character(to_char_type(0xDD));
16348                    write_number(static_cast<std::uint32_t>(N));
16349                }
16350
16351                // step 2: write each element
16352                for (const auto& el : *j.m_data.m_value.array)
16353                {
16354                    write_msgpack(el);
16355                }
16356                break;
16357            }
16358
16359            case value_t::binary:
16360            {
16361                // step 0: determine if the binary type has a set subtype to
16362                // determine whether to use the ext or fixext types
16363                const bool use_ext = j.m_data.m_value.binary->has_subtype();
16364
16365                // step 1: write control byte and the byte string length
16366                const auto N = j.m_data.m_value.binary->size();
16367                if (N <= (std::numeric_limits<std::uint8_t>::max)())
16368                {
16369                    std::uint8_t output_type{};
16370                    bool fixed = true;
16371                    if (use_ext)
16372                    {
16373                        switch (N)
16374                        {
16375                            case 1:
16376                                output_type = 0xD4; // fixext 1
16377                                break;
16378                            case 2:
16379                                output_type = 0xD5; // fixext 2
16380                                break;
16381                            case 4:
16382                                output_type = 0xD6; // fixext 4
16383                                break;
16384                            case 8:
16385                                output_type = 0xD7; // fixext 8
16386                                break;
16387                            case 16:
16388                                output_type = 0xD8; // fixext 16
16389                                break;
16390                            default:
16391                                output_type = 0xC7; // ext 8
16392                                fixed = false;
16393                                break;
16394                        }
16395
16396                    }
16397                    else
16398                    {
16399                        output_type = 0xC4; // bin 8
16400                        fixed = false;
16401                    }
16402
16403                    oa->write_character(to_char_type(output_type));
16404                    if (!fixed)
16405                    {
16406                        write_number(static_cast<std::uint8_t>(N));
16407                    }
16408                }
16409                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16410                {
16411                    const std::uint8_t output_type = use_ext
16412                                                     ? 0xC8 // ext 16
16413                                                     : 0xC5; // bin 16
16414
16415                    oa->write_character(to_char_type(output_type));
16416                    write_number(static_cast<std::uint16_t>(N));
16417                }
16418                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16419                {
16420                    const std::uint8_t output_type = use_ext
16421                                                     ? 0xC9 // ext 32
16422                                                     : 0xC6; // bin 32
16423
16424                    oa->write_character(to_char_type(output_type));
16425                    write_number(static_cast<std::uint32_t>(N));
16426                }
16427
16428                // step 1.5: if this is an ext type, write the subtype
16429                if (use_ext)
16430                {
16431                    write_number(static_cast<std::int8_t>(j.m_data.m_value.binary->subtype()));
16432                }
16433
16434                // step 2: write the byte string
16435                oa->write_characters(
16436                    reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16437                    N);
16438
16439                break;
16440            }
16441
16442            case value_t::object:
16443            {
16444                // step 1: write control byte and the object size
16445                const auto N = j.m_data.m_value.object->size();
16446                if (N <= 15)
16447                {
16448                    // fixmap
16449                    write_number(static_cast<std::uint8_t>(0x80 | (N & 0xF)));
16450                }
16451                else if (N <= (std::numeric_limits<std::uint16_t>::max)())
16452                {
16453                    // map 16
16454                    oa->write_character(to_char_type(0xDE));
16455                    write_number(static_cast<std::uint16_t>(N));
16456                }
16457                else if (N <= (std::numeric_limits<std::uint32_t>::max)())
16458                {
16459                    // map 32
16460                    oa->write_character(to_char_type(0xDF));
16461                    write_number(static_cast<std::uint32_t>(N));
16462                }
16463
16464                // step 2: write each element
16465                for (const auto& el : *j.m_data.m_value.object)
16466                {
16467                    write_msgpack(el.first);
16468                    write_msgpack(el.second);
16469                }
16470                break;
16471            }
16472
16473            case value_t::discarded:
16474            default:
16475                break;
16476        }
16477    }
16478
16479    /*!
16480    @param[in] j  JSON value to serialize
16481    @param[in] use_count   whether to use '#' prefixes (optimized format)
16482    @param[in] use_type    whether to use '$' prefixes (optimized format)
16483    @param[in] add_prefix  whether prefixes need to be used for this value
16484    @param[in] use_bjdata  whether write in BJData format, default is false
16485    @param[in] bjdata_version  which BJData version to use, default is draft2
16486    */
16487    void write_ubjson(const BasicJsonType& j, const bool use_count,
16488                      const bool use_type, const bool add_prefix = true,
16489                      const bool use_bjdata = false, const bjdata_version_t bjdata_version = bjdata_version_t::draft2)
16490    {
16491        const bool bjdata_draft3 = use_bjdata && bjdata_version == bjdata_version_t::draft3;
16492
16493        switch (j.type())
16494        {
16495            case value_t::null:
16496            {
16497                if (add_prefix)
16498                {
16499                    oa->write_character(to_char_type('Z'));
16500                }
16501                break;
16502            }
16503
16504            case value_t::boolean:
16505            {
16506                if (add_prefix)
16507                {
16508                    oa->write_character(j.m_data.m_value.boolean
16509                                        ? to_char_type('T')
16510                                        : to_char_type('F'));
16511                }
16512                break;
16513            }
16514
16515            case value_t::number_integer:
16516            {
16517                write_number_with_ubjson_prefix(j.m_data.m_value.number_integer, add_prefix, use_bjdata);
16518                break;
16519            }
16520
16521            case value_t::number_unsigned:
16522            {
16523                write_number_with_ubjson_prefix(j.m_data.m_value.number_unsigned, add_prefix, use_bjdata);
16524                break;
16525            }
16526
16527            case value_t::number_float:
16528            {
16529                write_number_with_ubjson_prefix(j.m_data.m_value.number_float, add_prefix, use_bjdata);
16530                break;
16531            }
16532
16533            case value_t::string:
16534            {
16535                if (add_prefix)
16536                {
16537                    oa->write_character(to_char_type('S'));
16538                }
16539                write_number_with_ubjson_prefix(j.m_data.m_value.string->size(), true, use_bjdata);
16540                oa->write_characters(
16541                    reinterpret_cast<const CharType*>(j.m_data.m_value.string->c_str()),
16542                    j.m_data.m_value.string->size());
16543                break;
16544            }
16545
16546            case value_t::array:
16547            {
16548                if (add_prefix)
16549                {
16550                    oa->write_character(to_char_type('['));
16551                }
16552
16553                bool prefix_required = true;
16554                if (use_type && !j.m_data.m_value.array->empty())
16555                {
16556                    JSON_ASSERT(use_count);
16557                    const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16558                    const bool same_prefix = std::all_of(j.begin() + 1, j.end(),
16559                                                         [this, first_prefix, use_bjdata](const BasicJsonType & v)
16560                    {
16561                        return ubjson_prefix(v, use_bjdata) == first_prefix;
16562                    });
16563
16564                    std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16565
16566                    if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16567                    {
16568                        prefix_required = false;
16569                        oa->write_character(to_char_type('$'));
16570                        oa->write_character(first_prefix);
16571                    }
16572                }
16573
16574                if (use_count)
16575                {
16576                    oa->write_character(to_char_type('#'));
16577                    write_number_with_ubjson_prefix(j.m_data.m_value.array->size(), true, use_bjdata);
16578                }
16579
16580                for (const auto& el : *j.m_data.m_value.array)
16581                {
16582                    write_ubjson(el, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16583                }
16584
16585                if (!use_count)
16586                {
16587                    oa->write_character(to_char_type(']'));
16588                }
16589
16590                break;
16591            }
16592
16593            case value_t::binary:
16594            {
16595                if (add_prefix)
16596                {
16597                    oa->write_character(to_char_type('['));
16598                }
16599
16600                if (use_type && (bjdata_draft3 || !j.m_data.m_value.binary->empty()))
16601                {
16602                    JSON_ASSERT(use_count);
16603                    oa->write_character(to_char_type('$'));
16604                    oa->write_character(bjdata_draft3 ? 'B' : 'U');
16605                }
16606
16607                if (use_count)
16608                {
16609                    oa->write_character(to_char_type('#'));
16610                    write_number_with_ubjson_prefix(j.m_data.m_value.binary->size(), true, use_bjdata);
16611                }
16612
16613                if (use_type)
16614                {
16615                    oa->write_characters(
16616                        reinterpret_cast<const CharType*>(j.m_data.m_value.binary->data()),
16617                        j.m_data.m_value.binary->size());
16618                }
16619                else
16620                {
16621                    for (size_t i = 0; i < j.m_data.m_value.binary->size(); ++i)
16622                    {
16623                        oa->write_character(to_char_type(bjdata_draft3 ? 'B' : 'U'));
16624                        oa->write_character(j.m_data.m_value.binary->data()[i]);
16625                    }
16626                }
16627
16628                if (!use_count)
16629                {
16630                    oa->write_character(to_char_type(']'));
16631                }
16632
16633                break;
16634            }
16635
16636            case value_t::object:
16637            {
16638                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())
16639                {
16640                    if (!write_bjdata_ndarray(*j.m_data.m_value.object, use_count, use_type, bjdata_version))  // decode bjdata ndarray in the JData format (https://github.com/NeuroJSON/jdata)
16641                    {
16642                        break;
16643                    }
16644                }
16645
16646                if (add_prefix)
16647                {
16648                    oa->write_character(to_char_type('{'));
16649                }
16650
16651                bool prefix_required = true;
16652                if (use_type && !j.m_data.m_value.object->empty())
16653                {
16654                    JSON_ASSERT(use_count);
16655                    const CharType first_prefix = ubjson_prefix(j.front(), use_bjdata);
16656                    const bool same_prefix = std::all_of(j.begin(), j.end(),
16657                                                         [this, first_prefix, use_bjdata](const BasicJsonType & v)
16658                    {
16659                        return ubjson_prefix(v, use_bjdata) == first_prefix;
16660                    });
16661
16662                    std::vector<CharType> bjdx = {'[', '{', 'S', 'H', 'T', 'F', 'N', 'Z'}; // excluded markers in bjdata optimized type
16663
16664                    if (same_prefix && !(use_bjdata && std::find(bjdx.begin(), bjdx.end(), first_prefix) != bjdx.end()))
16665                    {
16666                        prefix_required = false;
16667                        oa->write_character(to_char_type('$'));
16668                        oa->write_character(first_prefix);
16669                    }
16670                }
16671
16672                if (use_count)
16673                {
16674                    oa->write_character(to_char_type('#'));
16675                    write_number_with_ubjson_prefix(j.m_data.m_value.object->size(), true, use_bjdata);
16676                }
16677
16678                for (const auto& el : *j.m_data.m_value.object)
16679                {
16680                    write_number_with_ubjson_prefix(el.first.size(), true, use_bjdata);
16681                    oa->write_characters(
16682                        reinterpret_cast<const CharType*>(el.first.c_str()),
16683                        el.first.size());
16684                    write_ubjson(el.second, use_count, use_type, prefix_required, use_bjdata, bjdata_version);
16685                }
16686
16687                if (!use_count)
16688                {
16689                    oa->write_character(to_char_type('}'));
16690                }
16691
16692                break;
16693            }
16694
16695            case value_t::discarded:
16696            default:
16697                break;
16698        }
16699    }
16700
16701  private:
16702    //////////
16703    // BSON //
16704    //////////
16705
16706    /*!
16707    @return The size of a BSON document entry header, including the id marker
16708            and the entry name size (and its null-terminator).
16709    */
16710    static std::size_t calc_bson_entry_header_size(const string_t& name, const BasicJsonType& j)
16711    {
16712        const auto it = name.find(static_cast<typename string_t::value_type>(0));
16713        if (JSON_HEDLEY_UNLIKELY(it != BasicJsonType::string_t::npos))
16714        {
16715            JSON_THROW(out_of_range::create(409, concat("BSON key cannot contain code point U+0000 (at byte ", std::to_string(it), ")"), &j));
16716            static_cast<void>(j);
16717        }
16718
16719        return /*id*/ 1ul + name.size() + /*zero-terminator*/1u;
16720    }
16721
16722    /*!
16723    @brief Writes the given @a element_type and @a name to the output adapter
16724    */
16725    void write_bson_entry_header(const string_t& name,
16726                                 const std::uint8_t element_type)
16727    {
16728        oa->write_character(to_char_type(element_type)); // boolean
16729        oa->write_characters(
16730            reinterpret_cast<const CharType*>(name.c_str()),
16731            name.size() + 1u);
16732    }
16733
16734    /*!
16735    @brief Writes a BSON element with key @a name and boolean value @a value
16736    */
16737    void write_bson_boolean(const string_t& name,
16738                            const bool value)
16739    {
16740        write_bson_entry_header(name, 0x08);
16741        oa->write_character(value ? to_char_type(0x01) : to_char_type(0x00));
16742    }
16743
16744    /*!
16745    @brief Writes a BSON element with key @a name and double value @a value
16746    */
16747    void write_bson_double(const string_t& name,
16748                           const double value)
16749    {
16750        write_bson_entry_header(name, 0x01);
16751        write_number<double>(value, true);
16752    }
16753
16754    /*!
16755    @return The size of the BSON-encoded string in @a value
16756    */
16757    static std::size_t calc_bson_string_size(const string_t& value)
16758    {
16759        return sizeof(std::int32_t) + value.size() + 1ul;
16760    }
16761
16762    /*!
16763    @brief Writes a BSON element with key @a name and string value @a value
16764    */
16765    void write_bson_string(const string_t& name,
16766                           const string_t& value)
16767    {
16768        write_bson_entry_header(name, 0x02);
16769
16770        write_number<std::int32_t>(static_cast<std::int32_t>(value.size() + 1ul), true);
16771        oa->write_characters(
16772            reinterpret_cast<const CharType*>(value.c_str()),
16773            value.size() + 1);
16774    }
16775
16776    /*!
16777    @brief Writes a BSON element with key @a name and null value
16778    */
16779    void write_bson_null(const string_t& name)
16780    {
16781        write_bson_entry_header(name, 0x0A);
16782    }
16783
16784    /*!
16785    @return The size of the BSON-encoded integer @a value
16786    */
16787    static std::size_t calc_bson_integer_size(const std::int64_t value)
16788    {
16789        return (std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)()
16790               ? sizeof(std::int32_t)
16791               : sizeof(std::int64_t);
16792    }
16793
16794    /*!
16795    @brief Writes a BSON element with key @a name and integer @a value
16796    */
16797    void write_bson_integer(const string_t& name,
16798                            const std::int64_t value)
16799    {
16800        if ((std::numeric_limits<std::int32_t>::min)() <= value && value <= (std::numeric_limits<std::int32_t>::max)())
16801        {
16802            write_bson_entry_header(name, 0x10); // int32
16803            write_number<std::int32_t>(static_cast<std::int32_t>(value), true);
16804        }
16805        else
16806        {
16807            write_bson_entry_header(name, 0x12); // int64
16808            write_number<std::int64_t>(static_cast<std::int64_t>(value), true);
16809        }
16810    }
16811
16812    /*!
16813    @return The size of the BSON-encoded unsigned integer in @a j
16814    */
16815    static constexpr std::size_t calc_bson_unsigned_size(const std::uint64_t value) noexcept
16816    {
16817        return (value <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16818               ? sizeof(std::int32_t)
16819               : sizeof(std::int64_t);
16820    }
16821
16822    /*!
16823    @brief Writes a BSON element with key @a name and unsigned @a value
16824    */
16825    void write_bson_unsigned(const string_t& name,
16826                             const BasicJsonType& j)
16827    {
16828        if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
16829        {
16830            write_bson_entry_header(name, 0x10 /* int32 */);
16831            write_number<std::int32_t>(static_cast<std::int32_t>(j.m_data.m_value.number_unsigned), true);
16832        }
16833        else if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
16834        {
16835            write_bson_entry_header(name, 0x12 /* int64 */);
16836            write_number<std::int64_t>(static_cast<std::int64_t>(j.m_data.m_value.number_unsigned), true);
16837        }
16838        else
16839        {
16840            write_bson_entry_header(name, 0x11 /* uint64 */);
16841            write_number<std::uint64_t>(static_cast<std::uint64_t>(j.m_data.m_value.number_unsigned), true);
16842        }
16843    }
16844
16845    /*!
16846    @brief Writes a BSON element with key @a name and object @a value
16847    */
16848    void write_bson_object_entry(const string_t& name,
16849                                 const typename BasicJsonType::object_t& value)
16850    {
16851        write_bson_entry_header(name, 0x03); // object
16852        write_bson_object(value);
16853    }
16854
16855    /*!
16856    @return The size of the BSON-encoded array @a value
16857    */
16858    static std::size_t calc_bson_array_size(const typename BasicJsonType::array_t& value)
16859    {
16860        std::size_t array_index = 0ul;
16861
16862        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)
16863        {
16864            return result + calc_bson_element_size(std::to_string(array_index++), el);
16865        });
16866
16867        return sizeof(std::int32_t) + embedded_document_size + 1ul;
16868    }
16869
16870    /*!
16871    @return The size of the BSON-encoded binary array @a value
16872    */
16873    static std::size_t calc_bson_binary_size(const typename BasicJsonType::binary_t& value)
16874    {
16875        return sizeof(std::int32_t) + value.size() + 1ul;
16876    }
16877
16878    /*!
16879    @brief Writes a BSON element with key @a name and array @a value
16880    */
16881    void write_bson_array(const string_t& name,
16882                          const typename BasicJsonType::array_t& value)
16883    {
16884        write_bson_entry_header(name, 0x04); // array
16885        write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_array_size(value)), true);
16886
16887        std::size_t array_index = 0ul;
16888
16889        for (const auto& el : value)
16890        {
16891            write_bson_element(std::to_string(array_index++), el);
16892        }
16893
16894        oa->write_character(to_char_type(0x00));
16895    }
16896
16897    /*!
16898    @brief Writes a BSON element with key @a name and binary value @a value
16899    */
16900    void write_bson_binary(const string_t& name,
16901                           const binary_t& value)
16902    {
16903        write_bson_entry_header(name, 0x05);
16904
16905        write_number<std::int32_t>(static_cast<std::int32_t>(value.size()), true);
16906        write_number(value.has_subtype() ? static_cast<std::uint8_t>(value.subtype()) : static_cast<std::uint8_t>(0x00));
16907
16908        oa->write_characters(reinterpret_cast<const CharType*>(value.data()), value.size());
16909    }
16910
16911    /*!
16912    @brief Calculates the size necessary to serialize the JSON value @a j with its @a name
16913    @return The calculated size for the BSON document entry for @a j with the given @a name.
16914    */
16915    static std::size_t calc_bson_element_size(const string_t& name,
16916            const BasicJsonType& j)
16917    {
16918        const auto header_size = calc_bson_entry_header_size(name, j);
16919        switch (j.type())
16920        {
16921            case value_t::object:
16922                return header_size + calc_bson_object_size(*j.m_data.m_value.object);
16923
16924            case value_t::array:
16925                return header_size + calc_bson_array_size(*j.m_data.m_value.array);
16926
16927            case value_t::binary:
16928                return header_size + calc_bson_binary_size(*j.m_data.m_value.binary);
16929
16930            case value_t::boolean:
16931                return header_size + 1ul;
16932
16933            case value_t::number_float:
16934                return header_size + 8ul;
16935
16936            case value_t::number_integer:
16937                return header_size + calc_bson_integer_size(j.m_data.m_value.number_integer);
16938
16939            case value_t::number_unsigned:
16940                return header_size + calc_bson_unsigned_size(j.m_data.m_value.number_unsigned);
16941
16942            case value_t::string:
16943                return header_size + calc_bson_string_size(*j.m_data.m_value.string);
16944
16945            case value_t::null:
16946                return header_size + 0ul;
16947
16948            // LCOV_EXCL_START
16949            case value_t::discarded:
16950            default:
16951                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16952                return 0ul;
16953                // LCOV_EXCL_STOP
16954        }
16955    }
16956
16957    /*!
16958    @brief Serializes the JSON value @a j to BSON and associates it with the
16959           key @a name.
16960    @param name The name to associate with the JSON entity @a j within the
16961                current BSON document
16962    */
16963    void write_bson_element(const string_t& name,
16964                            const BasicJsonType& j)
16965    {
16966        switch (j.type())
16967        {
16968            case value_t::object:
16969                return write_bson_object_entry(name, *j.m_data.m_value.object);
16970
16971            case value_t::array:
16972                return write_bson_array(name, *j.m_data.m_value.array);
16973
16974            case value_t::binary:
16975                return write_bson_binary(name, *j.m_data.m_value.binary);
16976
16977            case value_t::boolean:
16978                return write_bson_boolean(name, j.m_data.m_value.boolean);
16979
16980            case value_t::number_float:
16981                return write_bson_double(name, j.m_data.m_value.number_float);
16982
16983            case value_t::number_integer:
16984                return write_bson_integer(name, j.m_data.m_value.number_integer);
16985
16986            case value_t::number_unsigned:
16987                return write_bson_unsigned(name, j);
16988
16989            case value_t::string:
16990                return write_bson_string(name, *j.m_data.m_value.string);
16991
16992            case value_t::null:
16993                return write_bson_null(name);
16994
16995            // LCOV_EXCL_START
16996            case value_t::discarded:
16997            default:
16998                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert)
16999                return;
17000                // LCOV_EXCL_STOP
17001        }
17002    }
17003
17004    /*!
17005    @brief Calculates the size of the BSON serialization of the given
17006           JSON-object @a j.
17007    @param[in] value  JSON value to serialize
17008    @pre       value.type() == value_t::object
17009    */
17010    static std::size_t calc_bson_object_size(const typename BasicJsonType::object_t& value)
17011    {
17012        const std::size_t document_size = std::accumulate(value.begin(), value.end(), static_cast<std::size_t>(0),
17013                                          [](size_t result, const typename BasicJsonType::object_t::value_type & el)
17014        {
17015            return result += calc_bson_element_size(el.first, el.second);
17016        });
17017
17018        return sizeof(std::int32_t) + document_size + 1ul;
17019    }
17020
17021    /*!
17022    @param[in] value  JSON value to serialize
17023    @pre       value.type() == value_t::object
17024    */
17025    void write_bson_object(const typename BasicJsonType::object_t& value)
17026    {
17027        write_number<std::int32_t>(static_cast<std::int32_t>(calc_bson_object_size(value)), true);
17028
17029        for (const auto& el : value)
17030        {
17031            write_bson_element(el.first, el.second);
17032        }
17033
17034        oa->write_character(to_char_type(0x00));
17035    }
17036
17037    //////////
17038    // CBOR //
17039    //////////
17040
17041    static constexpr CharType get_cbor_float_prefix(float /*unused*/)
17042    {
17043        return to_char_type(0xFA);  // Single-Precision Float
17044    }
17045
17046    static constexpr CharType get_cbor_float_prefix(double /*unused*/)
17047    {
17048        return to_char_type(0xFB);  // Double-Precision Float
17049    }
17050
17051    /////////////
17052    // MsgPack //
17053    /////////////
17054
17055    static constexpr CharType get_msgpack_float_prefix(float /*unused*/)
17056    {
17057        return to_char_type(0xCA);  // float 32
17058    }
17059
17060    static constexpr CharType get_msgpack_float_prefix(double /*unused*/)
17061    {
17062        return to_char_type(0xCB);  // float 64
17063    }
17064
17065    ////////////
17066    // UBJSON //
17067    ////////////
17068
17069    // UBJSON: write number (floating point)
17070    template<typename NumberType, typename std::enable_if<
17071                 std::is_floating_point<NumberType>::value, int>::type = 0>
17072    void write_number_with_ubjson_prefix(const NumberType n,
17073                                         const bool add_prefix,
17074                                         const bool use_bjdata)
17075    {
17076        if (add_prefix)
17077        {
17078            oa->write_character(get_ubjson_float_prefix(n));
17079        }
17080        write_number(n, use_bjdata);
17081    }
17082
17083    // UBJSON: write number (unsigned integer)
17084    template<typename NumberType, typename std::enable_if<
17085                 std::is_unsigned<NumberType>::value, int>::type = 0>
17086    void write_number_with_ubjson_prefix(const NumberType n,
17087                                         const bool add_prefix,
17088                                         const bool use_bjdata)
17089    {
17090        if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17091        {
17092            if (add_prefix)
17093            {
17094                oa->write_character(to_char_type('i'));  // int8
17095            }
17096            write_number(static_cast<std::uint8_t>(n), use_bjdata);
17097        }
17098        else if (n <= (std::numeric_limits<std::uint8_t>::max)())
17099        {
17100            if (add_prefix)
17101            {
17102                oa->write_character(to_char_type('U'));  // uint8
17103            }
17104            write_number(static_cast<std::uint8_t>(n), use_bjdata);
17105        }
17106        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17107        {
17108            if (add_prefix)
17109            {
17110                oa->write_character(to_char_type('I'));  // int16
17111            }
17112            write_number(static_cast<std::int16_t>(n), use_bjdata);
17113        }
17114        else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint16_t>::max)()))
17115        {
17116            if (add_prefix)
17117            {
17118                oa->write_character(to_char_type('u'));  // uint16 - bjdata only
17119            }
17120            write_number(static_cast<std::uint16_t>(n), use_bjdata);
17121        }
17122        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17123        {
17124            if (add_prefix)
17125            {
17126                oa->write_character(to_char_type('l'));  // int32
17127            }
17128            write_number(static_cast<std::int32_t>(n), use_bjdata);
17129        }
17130        else if (use_bjdata && n <= static_cast<uint64_t>((std::numeric_limits<uint32_t>::max)()))
17131        {
17132            if (add_prefix)
17133            {
17134                oa->write_character(to_char_type('m'));  // uint32 - bjdata only
17135            }
17136            write_number(static_cast<std::uint32_t>(n), use_bjdata);
17137        }
17138        else if (n <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17139        {
17140            if (add_prefix)
17141            {
17142                oa->write_character(to_char_type('L'));  // int64
17143            }
17144            write_number(static_cast<std::int64_t>(n), use_bjdata);
17145        }
17146        else if (use_bjdata && n <= (std::numeric_limits<uint64_t>::max)())
17147        {
17148            if (add_prefix)
17149            {
17150                oa->write_character(to_char_type('M'));  // uint64 - bjdata only
17151            }
17152            write_number(static_cast<std::uint64_t>(n), use_bjdata);
17153        }
17154        else
17155        {
17156            if (add_prefix)
17157            {
17158                oa->write_character(to_char_type('H'));  // high-precision number
17159            }
17160
17161            const auto number = BasicJsonType(n).dump();
17162            write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17163            for (std::size_t i = 0; i < number.size(); ++i)
17164            {
17165                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17166            }
17167        }
17168    }
17169
17170    // UBJSON: write number (signed integer)
17171    template < typename NumberType, typename std::enable_if <
17172                   std::is_signed<NumberType>::value&&
17173                   !std::is_floating_point<NumberType>::value, int >::type = 0 >
17174    void write_number_with_ubjson_prefix(const NumberType n,
17175                                         const bool add_prefix,
17176                                         const bool use_bjdata)
17177    {
17178        if ((std::numeric_limits<std::int8_t>::min)() <= n && n <= (std::numeric_limits<std::int8_t>::max)())
17179        {
17180            if (add_prefix)
17181            {
17182                oa->write_character(to_char_type('i'));  // int8
17183            }
17184            write_number(static_cast<std::int8_t>(n), use_bjdata);
17185        }
17186        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)()))
17187        {
17188            if (add_prefix)
17189            {
17190                oa->write_character(to_char_type('U'));  // uint8
17191            }
17192            write_number(static_cast<std::uint8_t>(n), use_bjdata);
17193        }
17194        else if ((std::numeric_limits<std::int16_t>::min)() <= n && n <= (std::numeric_limits<std::int16_t>::max)())
17195        {
17196            if (add_prefix)
17197            {
17198                oa->write_character(to_char_type('I'));  // int16
17199            }
17200            write_number(static_cast<std::int16_t>(n), use_bjdata);
17201        }
17202        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)())))
17203        {
17204            if (add_prefix)
17205            {
17206                oa->write_character(to_char_type('u'));  // uint16 - bjdata only
17207            }
17208            write_number(static_cast<uint16_t>(n), use_bjdata);
17209        }
17210        else if ((std::numeric_limits<std::int32_t>::min)() <= n && n <= (std::numeric_limits<std::int32_t>::max)())
17211        {
17212            if (add_prefix)
17213            {
17214                oa->write_character(to_char_type('l'));  // int32
17215            }
17216            write_number(static_cast<std::int32_t>(n), use_bjdata);
17217        }
17218        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)())))
17219        {
17220            if (add_prefix)
17221            {
17222                oa->write_character(to_char_type('m'));  // uint32 - bjdata only
17223            }
17224            write_number(static_cast<uint32_t>(n), use_bjdata);
17225        }
17226        else if ((std::numeric_limits<std::int64_t>::min)() <= n && n <= (std::numeric_limits<std::int64_t>::max)())
17227        {
17228            if (add_prefix)
17229            {
17230                oa->write_character(to_char_type('L'));  // int64
17231            }
17232            write_number(static_cast<std::int64_t>(n), use_bjdata);
17233        }
17234        // LCOV_EXCL_START
17235        else
17236        {
17237            if (add_prefix)
17238            {
17239                oa->write_character(to_char_type('H'));  // high-precision number
17240            }
17241
17242            const auto number = BasicJsonType(n).dump();
17243            write_number_with_ubjson_prefix(number.size(), true, use_bjdata);
17244            for (std::size_t i = 0; i < number.size(); ++i)
17245            {
17246                oa->write_character(to_char_type(static_cast<std::uint8_t>(number[i])));
17247            }
17248        }
17249        // LCOV_EXCL_STOP
17250    }
17251
17252    /*!
17253    @brief determine the type prefix of container values
17254    */
17255    CharType ubjson_prefix(const BasicJsonType& j, const bool use_bjdata) const noexcept
17256    {
17257        switch (j.type())
17258        {
17259            case value_t::null:
17260                return 'Z';
17261
17262            case value_t::boolean:
17263                return j.m_data.m_value.boolean ? 'T' : 'F';
17264
17265            case value_t::number_integer:
17266            {
17267                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)())
17268                {
17269                    return 'i';
17270                }
17271                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)())
17272                {
17273                    return 'U';
17274                }
17275                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)())
17276                {
17277                    return 'I';
17278                }
17279                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)()))
17280                {
17281                    return 'u';
17282                }
17283                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)())
17284                {
17285                    return 'l';
17286                }
17287                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)()))
17288                {
17289                    return 'm';
17290                }
17291                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)())
17292                {
17293                    return 'L';
17294                }
17295                // anything else is treated as high-precision number
17296                return 'H'; // LCOV_EXCL_LINE
17297            }
17298
17299            case value_t::number_unsigned:
17300            {
17301                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int8_t>::max)()))
17302                {
17303                    return 'i';
17304                }
17305                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint8_t>::max)()))
17306                {
17307                    return 'U';
17308                }
17309                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int16_t>::max)()))
17310                {
17311                    return 'I';
17312                }
17313                if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint16_t>::max)()))
17314                {
17315                    return 'u';
17316                }
17317                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int32_t>::max)()))
17318                {
17319                    return 'l';
17320                }
17321                if (use_bjdata && j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::uint32_t>::max)()))
17322                {
17323                    return 'm';
17324                }
17325                if (j.m_data.m_value.number_unsigned <= static_cast<std::uint64_t>((std::numeric_limits<std::int64_t>::max)()))
17326                {
17327                    return 'L';
17328                }
17329                if (use_bjdata && j.m_data.m_value.number_unsigned <= (std::numeric_limits<std::uint64_t>::max)())
17330                {
17331                    return 'M';
17332                }
17333                // anything else is treated as high-precision number
17334                return 'H'; // LCOV_EXCL_LINE
17335            }
17336
17337            case value_t::number_float:
17338                return get_ubjson_float_prefix(j.m_data.m_value.number_float);
17339
17340            case value_t::string:
17341                return 'S';
17342
17343            case value_t::array: // fallthrough
17344            case value_t::binary:
17345                return '[';
17346
17347            case value_t::object:
17348                return '{';
17349
17350            case value_t::discarded:
17351            default:  // discarded values
17352                return 'N';
17353        }
17354    }
17355
17356    static constexpr CharType get_ubjson_float_prefix(float /*unused*/)
17357    {
17358        return 'd';  // float 32
17359    }
17360
17361    static constexpr CharType get_ubjson_float_prefix(double /*unused*/)
17362    {
17363        return 'D';  // float 64
17364    }
17365
17366    /*!
17367    @return false if the object is successfully converted to a bjdata ndarray, true if the type or size is invalid
17368    */
17369    bool write_bjdata_ndarray(const typename BasicJsonType::object_t& value, const bool use_count, const bool use_type, const bjdata_version_t bjdata_version)
17370    {
17371        std::map<string_t, CharType> bjdtype = {{"uint8", 'U'},  {"int8", 'i'},  {"uint16", 'u'}, {"int16", 'I'},
17372            {"uint32", 'm'}, {"int32", 'l'}, {"uint64", 'M'}, {"int64", 'L'}, {"single", 'd'}, {"double", 'D'},
17373            {"char", 'C'}, {"byte", 'B'}
17374        };
17375
17376        string_t key = "_ArrayType_";
17377        auto it = bjdtype.find(static_cast<string_t>(value.at(key)));
17378        if (it == bjdtype.end())
17379        {
17380            return true;
17381        }
17382        CharType dtype = it->second;
17383
17384        key = "_ArraySize_";
17385        std::size_t len = (value.at(key).empty() ? 0 : 1);
17386        for (const auto& el : value.at(key))
17387        {
17388            len *= static_cast<std::size_t>(el.m_data.m_value.number_unsigned);
17389        }
17390
17391        key = "_ArrayData_";
17392        if (value.at(key).size() != len)
17393        {
17394            return true;
17395        }
17396
17397        oa->write_character('[');
17398        oa->write_character('$');
17399        oa->write_character(dtype);
17400        oa->write_character('#');
17401
17402        key = "_ArraySize_";
17403        write_ubjson(value.at(key), use_count, use_type, true,  true, bjdata_version);
17404
17405        key = "_ArrayData_";
17406        if (dtype == 'U' || dtype == 'C' || dtype == 'B')
17407        {
17408            for (const auto& el : value.at(key))
17409            {
17410                write_number(static_cast<std::uint8_t>(el.m_data.m_value.number_unsigned), true);
17411            }
17412        }
17413        else if (dtype == 'i')
17414        {
17415            for (const auto& el : value.at(key))
17416            {
17417                write_number(static_cast<std::int8_t>(el.m_data.m_value.number_integer), true);
17418            }
17419        }
17420        else if (dtype == 'u')
17421        {
17422            for (const auto& el : value.at(key))
17423            {
17424                write_number(static_cast<std::uint16_t>(el.m_data.m_value.number_unsigned), true);
17425            }
17426        }
17427        else if (dtype == 'I')
17428        {
17429            for (const auto& el : value.at(key))
17430            {
17431                write_number(static_cast<std::int16_t>(el.m_data.m_value.number_integer), true);
17432            }
17433        }
17434        else if (dtype == 'm')
17435        {
17436            for (const auto& el : value.at(key))
17437            {
17438                write_number(static_cast<std::uint32_t>(el.m_data.m_value.number_unsigned), true);
17439            }
17440        }
17441        else if (dtype == 'l')
17442        {
17443            for (const auto& el : value.at(key))
17444            {
17445                write_number(static_cast<std::int32_t>(el.m_data.m_value.number_integer), true);
17446            }
17447        }
17448        else if (dtype == 'M')
17449        {
17450            for (const auto& el : value.at(key))
17451            {
17452                write_number(static_cast<std::uint64_t>(el.m_data.m_value.number_unsigned), true);
17453            }
17454        }
17455        else if (dtype == 'L')
17456        {
17457            for (const auto& el : value.at(key))
17458            {
17459                write_number(static_cast<std::int64_t>(el.m_data.m_value.number_integer), true);
17460            }
17461        }
17462        else if (dtype == 'd')
17463        {
17464            for (const auto& el : value.at(key))
17465            {
17466                write_number(static_cast<float>(el.m_data.m_value.number_float), true);
17467            }
17468        }
17469        else if (dtype == 'D')
17470        {
17471            for (const auto& el : value.at(key))
17472            {
17473                write_number(static_cast<double>(el.m_data.m_value.number_float), true);
17474            }
17475        }
17476        return false;
17477    }
17478
17479    ///////////////////////
17480    // Utility functions //
17481    ///////////////////////
17482
17483    /*
17484    @brief write a number to output input
17485    @param[in] n number of type @a NumberType
17486    @param[in] OutputIsLittleEndian Set to true if output data is
17487                                 required to be little endian
17488    @tparam NumberType the type of the number
17489
17490    @note This function needs to respect the system's endianness, because bytes
17491          in CBOR, MessagePack, and UBJSON are stored in network order (big
17492          endian) and therefore need reordering on little endian systems.
17493          On the other hand, BSON and BJData use little endian and should reorder
17494          on big endian systems.
17495    */
17496    template<typename NumberType>
17497    void write_number(const NumberType n, const bool OutputIsLittleEndian = false)
17498    {
17499        // step 1: write number to array of length NumberType
17500        std::array<CharType, sizeof(NumberType)> vec{};
17501        std::memcpy(vec.data(), &n, sizeof(NumberType));
17502
17503        // step 2: write array to output (with possible reordering)
17504        if (is_little_endian != OutputIsLittleEndian)
17505        {
17506            // reverse byte order prior to conversion if necessary
17507            std::reverse(vec.begin(), vec.end());
17508        }
17509
17510        oa->write_characters(vec.data(), sizeof(NumberType));
17511    }
17512
17513    void write_compact_float(const number_float_t n, detail::input_format_t format)
17514    {
17515#ifdef __GNUC__
17516#pragma GCC diagnostic push
17517#pragma GCC diagnostic ignored "-Wfloat-equal"
17518#endif
17519        if (static_cast<double>(n) >= static_cast<double>(std::numeric_limits<float>::lowest()) &&
17520                static_cast<double>(n) <= static_cast<double>((std::numeric_limits<float>::max)()) &&
17521                static_cast<double>(static_cast<float>(n)) == static_cast<double>(n))
17522        {
17523            oa->write_character(format == detail::input_format_t::cbor
17524                                ? get_cbor_float_prefix(static_cast<float>(n))
17525                                : get_msgpack_float_prefix(static_cast<float>(n)));
17526            write_number(static_cast<float>(n));
17527        }
17528        else
17529        {
17530            oa->write_character(format == detail::input_format_t::cbor
17531                                ? get_cbor_float_prefix(n)
17532                                : get_msgpack_float_prefix(n));
17533            write_number(n);
17534        }
17535#ifdef __GNUC__
17536#pragma GCC diagnostic pop
17537#endif
17538    }
17539
17540  public:
17541    // The following to_char_type functions are implement the conversion
17542    // between uint8_t and CharType. In case CharType is not unsigned,
17543    // such a conversion is required to allow values greater than 128.
17544    // See <https://github.com/nlohmann/json/issues/1286> for a discussion.
17545    template < typename C = CharType,
17546               enable_if_t < std::is_signed<C>::value && std::is_signed<char>::value > * = nullptr >
17547    static constexpr CharType to_char_type(std::uint8_t x) noexcept
17548    {
17549        return *reinterpret_cast<char*>(&x);
17550    }
17551
17552    template < typename C = CharType,
17553               enable_if_t < std::is_signed<C>::value && std::is_unsigned<char>::value > * = nullptr >
17554    static CharType to_char_type(std::uint8_t x) noexcept
17555    {
17556        static_assert(sizeof(std::uint8_t) == sizeof(CharType), "size of CharType must be equal to std::uint8_t");
17557        static_assert(std::is_trivial<CharType>::value, "CharType must be trivial");
17558        CharType result;
17559        std::memcpy(&result, &x, sizeof(x));
17560        return result;
17561    }
17562
17563    template<typename C = CharType,
17564             enable_if_t<std::is_unsigned<C>::value>* = nullptr>
17565    static constexpr CharType to_char_type(std::uint8_t x) noexcept
17566    {
17567        return x;
17568    }
17569
17570    template < typename InputCharType, typename C = CharType,
17571               enable_if_t <
17572                   std::is_signed<C>::value &&
17573                   std::is_signed<char>::value &&
17574                   std::is_same<char, typename std::remove_cv<InputCharType>::type>::value
17575                   > * = nullptr >
17576    static constexpr CharType to_char_type(InputCharType x) noexcept
17577    {
17578        return x;
17579    }
17580
17581  private:
17582    /// whether we can assume little endianness
17583    const bool is_little_endian = little_endianness();
17584
17585    /// the output
17586    output_adapter_t<CharType> oa = nullptr;
17587};
17588
17589}  // namespace detail
17590NLOHMANN_JSON_NAMESPACE_END
17591
17592// #include <nlohmann/detail/output/output_adapters.hpp>
17593
17594// #include <nlohmann/detail/output/serializer.hpp>
17595//     __ _____ _____ _____
17596//  __|  |   __|     |   | |  JSON for Modern C++
17597// |  |  |__   |  |  | | | |  version 3.12.0
17598// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
17599//
17600// SPDX-FileCopyrightText: 2008 - 2009 Bjรถrn Hoehrmann <bjoern@hoehrmann.de>
17601// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17602// SPDX-License-Identifier: MIT
17603
17604
17605
17606#include <algorithm> // reverse, remove, fill, find, none_of
17607#include <array> // array
17608#include <clocale> // localeconv, lconv
17609#include <cmath> // labs, isfinite, isnan, signbit
17610#include <cstddef> // size_t, ptrdiff_t
17611#include <cstdint> // uint8_t
17612#include <cstdio> // snprintf
17613#include <limits> // numeric_limits
17614#include <string> // string, char_traits
17615#include <iomanip> // setfill, setw
17616#include <type_traits> // is_same
17617#include <utility> // move
17618
17619// #include <nlohmann/detail/conversions/to_chars.hpp>
17620//     __ _____ _____ _____
17621//  __|  |   __|     |   | |  JSON for Modern C++
17622// |  |  |__   |  |  | | | |  version 3.12.0
17623// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
17624//
17625// SPDX-FileCopyrightText: 2009 Florian Loitsch <https://florian.loitsch.com/>
17626// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
17627// SPDX-License-Identifier: MIT
17628
17629
17630
17631#include <array> // array
17632#include <cmath>   // signbit, isfinite
17633#include <cstdint> // intN_t, uintN_t
17634#include <cstring> // memcpy, memmove
17635#include <limits> // numeric_limits
17636#include <type_traits> // conditional
17637
17638// #include <nlohmann/detail/macro_scope.hpp>
17639
17640
17641NLOHMANN_JSON_NAMESPACE_BEGIN
17642namespace detail
17643{
17644
17645/*!
17646@brief implements the Grisu2 algorithm for binary to decimal floating-point
17647conversion.
17648
17649This implementation is a slightly modified version of the reference
17650implementation which may be obtained from
17651http://florian.loitsch.com/publications (bench.tar.gz).
17652
17653The code is distributed under the MIT license, Copyright (c) 2009 Florian Loitsch.
17654
17655For a detailed description of the algorithm see:
17656
17657[1] Loitsch, "Printing Floating-Point Numbers Quickly and Accurately with
17658    Integers", Proceedings of the ACM SIGPLAN 2010 Conference on Programming
17659    Language Design and Implementation, PLDI 2010
17660[2] Burger, Dybvig, "Printing Floating-Point Numbers Quickly and Accurately",
17661    Proceedings of the ACM SIGPLAN 1996 Conference on Programming Language
17662    Design and Implementation, PLDI 1996
17663*/
17664namespace dtoa_impl
17665{
17666
17667template<typename Target, typename Source>
17668Target reinterpret_bits(const Source source)
17669{
17670    static_assert(sizeof(Target) == sizeof(Source), "size mismatch");
17671
17672    Target target;
17673    std::memcpy(&target, &source, sizeof(Source));
17674    return target;
17675}
17676
17677struct diyfp // f * 2^e
17678{
17679    static constexpr int kPrecision = 64; // = q
17680
17681    std::uint64_t f = 0;
17682    int e = 0;
17683
17684    constexpr diyfp(std::uint64_t f_, int e_) noexcept : f(f_), e(e_) {}
17685
17686    /*!
17687    @brief returns x - y
17688    @pre x.e == y.e and x.f >= y.f
17689    */
17690    static diyfp sub(const diyfp& x, const diyfp& y) noexcept
17691    {
17692        JSON_ASSERT(x.e == y.e);
17693        JSON_ASSERT(x.f >= y.f);
17694
17695        return {x.f - y.f, x.e};
17696    }
17697
17698    /*!
17699    @brief returns x * y
17700    @note The result is rounded. (Only the upper q bits are returned.)
17701    */
17702    static diyfp mul(const diyfp& x, const diyfp& y) noexcept
17703    {
17704        static_assert(kPrecision == 64, "internal error");
17705
17706        // Computes:
17707        //  f = round((x.f * y.f) / 2^q)
17708        //  e = x.e + y.e + q
17709
17710        // Emulate the 64-bit * 64-bit multiplication:
17711        //
17712        // p = u * v
17713        //   = (u_lo + 2^32 u_hi) (v_lo + 2^32 v_hi)
17714        //   = (u_lo v_lo         ) + 2^32 ((u_lo v_hi         ) + (u_hi v_lo         )) + 2^64 (u_hi v_hi         )
17715        //   = (p0                ) + 2^32 ((p1                ) + (p2                )) + 2^64 (p3                )
17716        //   = (p0_lo + 2^32 p0_hi) + 2^32 ((p1_lo + 2^32 p1_hi) + (p2_lo + 2^32 p2_hi)) + 2^64 (p3                )
17717        //   = (p0_lo             ) + 2^32 (p0_hi + p1_lo + p2_lo                      ) + 2^64 (p1_hi + p2_hi + p3)
17718        //   = (p0_lo             ) + 2^32 (Q                                          ) + 2^64 (H                 )
17719        //   = (p0_lo             ) + 2^32 (Q_lo + 2^32 Q_hi                           ) + 2^64 (H                 )
17720        //
17721        // (Since Q might be larger than 2^32 - 1)
17722        //
17723        //   = (p0_lo + 2^32 Q_lo) + 2^64 (Q_hi + H)
17724        //
17725        // (Q_hi + H does not overflow a 64-bit int)
17726        //
17727        //   = p_lo + 2^64 p_hi
17728
17729        const std::uint64_t u_lo = x.f & 0xFFFFFFFFu;
17730        const std::uint64_t u_hi = x.f >> 32u;
17731        const std::uint64_t v_lo = y.f & 0xFFFFFFFFu;
17732        const std::uint64_t v_hi = y.f >> 32u;
17733
17734        const std::uint64_t p0 = u_lo * v_lo;
17735        const std::uint64_t p1 = u_lo * v_hi;
17736        const std::uint64_t p2 = u_hi * v_lo;
17737        const std::uint64_t p3 = u_hi * v_hi;
17738
17739        const std::uint64_t p0_hi = p0 >> 32u;
17740        const std::uint64_t p1_lo = p1 & 0xFFFFFFFFu;
17741        const std::uint64_t p1_hi = p1 >> 32u;
17742        const std::uint64_t p2_lo = p2 & 0xFFFFFFFFu;
17743        const std::uint64_t p2_hi = p2 >> 32u;
17744
17745        std::uint64_t Q = p0_hi + p1_lo + p2_lo;
17746
17747        // The full product might now be computed as
17748        //
17749        // p_hi = p3 + p2_hi + p1_hi + (Q >> 32)
17750        // p_lo = p0_lo + (Q << 32)
17751        //
17752        // But in this particular case here, the full p_lo is not required.
17753        // Effectively we only need to add the highest bit in p_lo to p_hi (and
17754        // Q_hi + 1 does not overflow).
17755
17756        Q += std::uint64_t{1} << (64u - 32u - 1u); // round, ties up
17757
17758        const std::uint64_t h = p3 + p2_hi + p1_hi + (Q >> 32u);
17759
17760        return {h, x.e + y.e + 64};
17761    }
17762
17763    /*!
17764    @brief normalize x such that the significand is >= 2^(q-1)
17765    @pre x.f != 0
17766    */
17767    static diyfp normalize(diyfp x) noexcept
17768    {
17769        JSON_ASSERT(x.f != 0);
17770
17771        while ((x.f >> 63u) == 0)
17772        {
17773            x.f <<= 1u;
17774            x.e--;
17775        }
17776
17777        return x;
17778    }
17779
17780    /*!
17781    @brief normalize x such that the result has the exponent E
17782    @pre e >= x.e and the upper e - x.e bits of x.f must be zero.
17783    */
17784    static diyfp normalize_to(const diyfp& x, const int target_exponent) noexcept
17785    {
17786        const int delta = x.e - target_exponent;
17787
17788        JSON_ASSERT(delta >= 0);
17789        JSON_ASSERT(((x.f << delta) >> delta) == x.f);
17790
17791        return {x.f << delta, target_exponent};
17792    }
17793};
17794
17795struct boundaries
17796{
17797    diyfp w;
17798    diyfp minus;
17799    diyfp plus;
17800};
17801
17802/*!
17803Compute the (normalized) diyfp representing the input number 'value' and its
17804boundaries.
17805
17806@pre value must be finite and positive
17807*/
17808template<typename FloatType>
17809boundaries compute_boundaries(FloatType value)
17810{
17811    JSON_ASSERT(std::isfinite(value));
17812    JSON_ASSERT(value > 0);
17813
17814    // Convert the IEEE representation into a diyfp.
17815    //
17816    // If v is denormal:
17817    //      value = 0.F * 2^(1 - bias) = (          F) * 2^(1 - bias - (p-1))
17818    // If v is normalized:
17819    //      value = 1.F * 2^(E - bias) = (2^(p-1) + F) * 2^(E - bias - (p-1))
17820
17821    static_assert(std::numeric_limits<FloatType>::is_iec559,
17822                  "internal error: dtoa_short requires an IEEE-754 floating-point implementation");
17823
17824    constexpr int      kPrecision = std::numeric_limits<FloatType>::digits; // = p (includes the hidden bit)
17825    constexpr int      kBias      = std::numeric_limits<FloatType>::max_exponent - 1 + (kPrecision - 1);
17826    constexpr int      kMinExp    = 1 - kBias;
17827    constexpr std::uint64_t kHiddenBit = std::uint64_t{1} << (kPrecision - 1); // = 2^(p-1)
17828
17829    using bits_type = typename std::conditional<kPrecision == 24, std::uint32_t, std::uint64_t >::type;
17830
17831    const auto bits = static_cast<std::uint64_t>(reinterpret_bits<bits_type>(value));
17832    const std::uint64_t E = bits >> (kPrecision - 1);
17833    const std::uint64_t F = bits & (kHiddenBit - 1);
17834
17835    const bool is_denormal = E == 0;
17836    const diyfp v = is_denormal
17837                    ? diyfp(F, kMinExp)
17838                    : diyfp(F + kHiddenBit, static_cast<int>(E) - kBias);
17839
17840    // Compute the boundaries m- and m+ of the floating-point value
17841    // v = f * 2^e.
17842    //
17843    // Determine v- and v+, the floating-point predecessor and successor if v,
17844    // respectively.
17845    //
17846    //      v- = v - 2^e        if f != 2^(p-1) or e == e_min                (A)
17847    //         = v - 2^(e-1)    if f == 2^(p-1) and e > e_min                (B)
17848    //
17849    //      v+ = v + 2^e
17850    //
17851    // Let m- = (v- + v) / 2 and m+ = (v + v+) / 2. All real numbers _strictly_
17852    // between m- and m+ round to v, regardless of how the input rounding
17853    // algorithm breaks ties.
17854    //
17855    //      ---+-------------+-------------+-------------+-------------+---  (A)
17856    //         v-            m-            v             m+            v+
17857    //
17858    //      -----------------+------+------+-------------+-------------+---  (B)
17859    //                       v-     m-     v             m+            v+
17860
17861    const bool lower_boundary_is_closer = F == 0 && E > 1;
17862    const diyfp m_plus = diyfp((2 * v.f) + 1, v.e - 1);
17863    const diyfp m_minus = lower_boundary_is_closer
17864                          ? diyfp((4 * v.f) - 1, v.e - 2)  // (B)
17865                          : diyfp((2 * v.f) - 1, v.e - 1); // (A)
17866
17867    // Determine the normalized w+ = m+.
17868    const diyfp w_plus = diyfp::normalize(m_plus);
17869
17870    // Determine w- = m- such that e_(w-) = e_(w+).
17871    const diyfp w_minus = diyfp::normalize_to(m_minus, w_plus.e);
17872
17873    return {diyfp::normalize(v), w_minus, w_plus};
17874}
17875
17876// Given normalized diyfp w, Grisu needs to find a (normalized) cached
17877// power-of-ten c, such that the exponent of the product c * w = f * 2^e lies
17878// within a certain range [alpha, gamma] (Definition 3.2 from [1])
17879//
17880//      alpha <= e = e_c + e_w + q <= gamma
17881//
17882// or
17883//
17884//      f_c * f_w * 2^alpha <= f_c 2^(e_c) * f_w 2^(e_w) * 2^q
17885//                          <= f_c * f_w * 2^gamma
17886//
17887// Since c and w are normalized, i.e. 2^(q-1) <= f < 2^q, this implies
17888//
17889//      2^(q-1) * 2^(q-1) * 2^alpha <= c * w * 2^q < 2^q * 2^q * 2^gamma
17890//
17891// or
17892//
17893//      2^(q - 2 + alpha) <= c * w < 2^(q + gamma)
17894//
17895// The choice of (alpha,gamma) determines the size of the table and the form of
17896// the digit generation procedure. Using (alpha,gamma)=(-60,-32) works out well
17897// in practice:
17898//
17899// The idea is to cut the number c * w = f * 2^e into two parts, which can be
17900// processed independently: An integral part p1, and a fractional part p2:
17901//
17902//      f * 2^e = ( (f div 2^-e) * 2^-e + (f mod 2^-e) ) * 2^e
17903//              = (f div 2^-e) + (f mod 2^-e) * 2^e
17904//              = p1 + p2 * 2^e
17905//
17906// The conversion of p1 into decimal form requires a series of divisions and
17907// modulos by (a power of) 10. These operations are faster for 32-bit than for
17908// 64-bit integers, so p1 should ideally fit into a 32-bit integer. This can be
17909// achieved by choosing
17910//
17911//      -e >= 32   or   e <= -32 := gamma
17912//
17913// In order to convert the fractional part
17914//
17915//      p2 * 2^e = p2 / 2^-e = d[-1] / 10^1 + d[-2] / 10^2 + ...
17916//
17917// into decimal form, the fraction is repeatedly multiplied by 10 and the digits
17918// d[-i] are extracted in order:
17919//
17920//      (10 * p2) div 2^-e = d[-1]
17921//      (10 * p2) mod 2^-e = d[-2] / 10^1 + ...
17922//
17923// The multiplication by 10 must not overflow. It is sufficient to choose
17924//
17925//      10 * p2 < 16 * p2 = 2^4 * p2 <= 2^64.
17926//
17927// Since p2 = f mod 2^-e < 2^-e,
17928//
17929//      -e <= 60   or   e >= -60 := alpha
17930
17931constexpr int kAlpha = -60;
17932constexpr int kGamma = -32;
17933
17934struct cached_power // c = f * 2^e ~= 10^k
17935{
17936    std::uint64_t f;
17937    int e;
17938    int k;
17939};
17940
17941/*!
17942For a normalized diyfp w = f * 2^e, this function returns a (normalized) cached
17943power-of-ten c = f_c * 2^e_c, such that the exponent of the product w * c
17944satisfies (Definition 3.2 from [1])
17945
17946     alpha <= e_c + e + q <= gamma.
17947*/
17948inline cached_power get_cached_power_for_binary_exponent(int e)
17949{
17950    // Now
17951    //
17952    //      alpha <= e_c + e + q <= gamma                                    (1)
17953    //      ==> f_c * 2^alpha <= c * 2^e * 2^q
17954    //
17955    // and since the c's are normalized, 2^(q-1) <= f_c,
17956    //
17957    //      ==> 2^(q - 1 + alpha) <= c * 2^(e + q)
17958    //      ==> 2^(alpha - e - 1) <= c
17959    //
17960    // If c were an exact power of ten, i.e. c = 10^k, one may determine k as
17961    //
17962    //      k = ceil( log_10( 2^(alpha - e - 1) ) )
17963    //        = ceil( (alpha - e - 1) * log_10(2) )
17964    //
17965    // From the paper:
17966    // "In theory the result of the procedure could be wrong since c is rounded,
17967    //  and the computation itself is approximated [...]. In practice, however,
17968    //  this simple function is sufficient."
17969    //
17970    // For IEEE double precision floating-point numbers converted into
17971    // normalized diyfp's w = f * 2^e, with q = 64,
17972    //
17973    //      e >= -1022      (min IEEE exponent)
17974    //           -52        (p - 1)
17975    //           -52        (p - 1, possibly normalize denormal IEEE numbers)
17976    //           -11        (normalize the diyfp)
17977    //         = -1137
17978    //
17979    // and
17980    //
17981    //      e <= +1023      (max IEEE exponent)
17982    //           -52        (p - 1)
17983    //           -11        (normalize the diyfp)
17984    //         = 960
17985    //
17986    // This binary exponent range [-1137,960] results in a decimal exponent
17987    // range [-307,324]. One does not need to store a cached power for each
17988    // k in this range. For each such k it suffices to find a cached power
17989    // such that the exponent of the product lies in [alpha,gamma].
17990    // This implies that the difference of the decimal exponents of adjacent
17991    // table entries must be less than or equal to
17992    //
17993    //      floor( (gamma - alpha) * log_10(2) ) = 8.
17994    //
17995    // (A smaller distance gamma-alpha would require a larger table.)
17996
17997    // NB:
17998    // Actually this function returns c, such that -60 <= e_c + e + 64 <= -34.
17999
18000    constexpr int kCachedPowersMinDecExp = -300;
18001    constexpr int kCachedPowersDecStep = 8;
18002
18003    static constexpr std::array<cached_power, 79> kCachedPowers =
18004    {
18005        {
18006            { 0xAB70FE17C79AC6CA, -1060, -300 },
18007            { 0xFF77B1FCBEBCDC4F, -1034, -292 },
18008            { 0xBE5691EF416BD60C, -1007, -284 },
18009            { 0x8DD01FAD907FFC3C,  -980, -276 },
18010            { 0xD3515C2831559A83,  -954, -268 },
18011            { 0x9D71AC8FADA6C9B5,  -927, -260 },
18012            { 0xEA9C227723EE8BCB,  -901, -252 },
18013            { 0xAECC49914078536D,  -874, -244 },
18014            { 0x823C12795DB6CE57,  -847, -236 },
18015            { 0xC21094364DFB5637,  -821, -228 },
18016            { 0x9096EA6F3848984F,  -794, -220 },
18017            { 0xD77485CB25823AC7,  -768, -212 },
18018            { 0xA086CFCD97BF97F4,  -741, -204 },
18019            { 0xEF340A98172AACE5,  -715, -196 },
18020            { 0xB23867FB2A35B28E,  -688, -188 },
18021            { 0x84C8D4DFD2C63F3B,  -661, -180 },
18022            { 0xC5DD44271AD3CDBA,  -635, -172 },
18023            { 0x936B9FCEBB25C996,  -608, -164 },
18024            { 0xDBAC6C247D62A584,  -582, -156 },
18025            { 0xA3AB66580D5FDAF6,  -555, -148 },
18026            { 0xF3E2F893DEC3F126,  -529, -140 },
18027            { 0xB5B5ADA8AAFF80B8,  -502, -132 },
18028            { 0x87625F056C7C4A8B,  -475, -124 },
18029            { 0xC9BCFF6034C13053,  -449, -116 },
18030            { 0x964E858C91BA2655,  -422, -108 },
18031            { 0xDFF9772470297EBD,  -396, -100 },
18032            { 0xA6DFBD9FB8E5B88F,  -369,  -92 },
18033            { 0xF8A95FCF88747D94,  -343,  -84 },
18034            { 0xB94470938FA89BCF,  -316,  -76 },
18035            { 0x8A08F0F8BF0F156B,  -289,  -68 },
18036            { 0xCDB02555653131B6,  -263,  -60 },
18037            { 0x993FE2C6D07B7FAC,  -236,  -52 },
18038            { 0xE45C10C42A2B3B06,  -210,  -44 },
18039            { 0xAA242499697392D3,  -183,  -36 },
18040            { 0xFD87B5F28300CA0E,  -157,  -28 },
18041            { 0xBCE5086492111AEB,  -130,  -20 },
18042            { 0x8CBCCC096F5088CC,  -103,  -12 },
18043            { 0xD1B71758E219652C,   -77,   -4 },
18044            { 0x9C40000000000000,   -50,    4 },
18045            { 0xE8D4A51000000000,   -24,   12 },
18046            { 0xAD78EBC5AC620000,     3,   20 },
18047            { 0x813F3978F8940984,    30,   28 },
18048            { 0xC097CE7BC90715B3,    56,   36 },
18049            { 0x8F7E32CE7BEA5C70,    83,   44 },
18050            { 0xD5D238A4ABE98068,   109,   52 },
18051            { 0x9F4F2726179A2245,   136,   60 },
18052            { 0xED63A231D4C4FB27,   162,   68 },
18053            { 0xB0DE65388CC8ADA8,   189,   76 },
18054            { 0x83C7088E1AAB65DB,   216,   84 },
18055            { 0xC45D1DF942711D9A,   242,   92 },
18056            { 0x924D692CA61BE758,   269,  100 },
18057            { 0xDA01EE641A708DEA,   295,  108 },
18058            { 0xA26DA3999AEF774A,   322,  116 },
18059            { 0xF209787BB47D6B85,   348,  124 },
18060            { 0xB454E4A179DD1877,   375,  132 },
18061            { 0x865B86925B9BC5C2,   402,  140 },
18062            { 0xC83553C5C8965D3D,   428,  148 },
18063            { 0x952AB45CFA97A0B3,   455,  156 },
18064            { 0xDE469FBD99A05FE3,   481,  164 },
18065            { 0xA59BC234DB398C25,   508,  172 },
18066            { 0xF6C69A72A3989F5C,   534,  180 },
18067            { 0xB7DCBF5354E9BECE,   561,  188 },
18068            { 0x88FCF317F22241E2,   588,  196 },
18069            { 0xCC20CE9BD35C78A5,   614,  204 },
18070            { 0x98165AF37B2153DF,   641,  212 },
18071            { 0xE2A0B5DC971F303A,   667,  220 },
18072            { 0xA8D9D1535CE3B396,   694,  228 },
18073            { 0xFB9B7CD9A4A7443C,   720,  236 },
18074            { 0xBB764C4CA7A44410,   747,  244 },
18075            { 0x8BAB8EEFB6409C1A,   774,  252 },
18076            { 0xD01FEF10A657842C,   800,  260 },
18077            { 0x9B10A4E5E9913129,   827,  268 },
18078            { 0xE7109BFBA19C0C9D,   853,  276 },
18079            { 0xAC2820D9623BF429,   880,  284 },
18080            { 0x80444B5E7AA7CF85,   907,  292 },
18081            { 0xBF21E44003ACDD2D,   933,  300 },
18082            { 0x8E679C2F5E44FF8F,   960,  308 },
18083            { 0xD433179D9C8CB841,   986,  316 },
18084            { 0x9E19DB92B4E31BA9,  1013,  324 },
18085        }
18086    };
18087
18088    // This computation gives exactly the same results for k as
18089    //      k = ceil((kAlpha - e - 1) * 0.30102999566398114)
18090    // for |e| <= 1500, but doesn't require floating-point operations.
18091    // NB: log_10(2) ~= 78913 / 2^18
18092    JSON_ASSERT(e >= -1500);
18093    JSON_ASSERT(e <=  1500);
18094    const int f = kAlpha - e - 1;
18095    const int k = ((f * 78913) / (1 << 18)) + static_cast<int>(f > 0);
18096
18097    const int index = (-kCachedPowersMinDecExp + k + (kCachedPowersDecStep - 1)) / kCachedPowersDecStep;
18098    JSON_ASSERT(index >= 0);
18099    JSON_ASSERT(static_cast<std::size_t>(index) < kCachedPowers.size());
18100
18101    const cached_power cached = kCachedPowers[static_cast<std::size_t>(index)];
18102    JSON_ASSERT(kAlpha <= cached.e + e + 64);
18103    JSON_ASSERT(kGamma >= cached.e + e + 64);
18104
18105    return cached;
18106}
18107
18108/*!
18109For n != 0, returns k, such that pow10 := 10^(k-1) <= n < 10^k.
18110For n == 0, returns 1 and sets pow10 := 1.
18111*/
18112inline int find_largest_pow10(const std::uint32_t n, std::uint32_t& pow10)
18113{
18114    // LCOV_EXCL_START
18115    if (n >= 1000000000)
18116    {
18117        pow10 = 1000000000;
18118        return 10;
18119    }
18120    // LCOV_EXCL_STOP
18121    if (n >= 100000000)
18122    {
18123        pow10 = 100000000;
18124        return  9;
18125    }
18126    if (n >= 10000000)
18127    {
18128        pow10 = 10000000;
18129        return  8;
18130    }
18131    if (n >= 1000000)
18132    {
18133        pow10 = 1000000;
18134        return  7;
18135    }
18136    if (n >= 100000)
18137    {
18138        pow10 = 100000;
18139        return  6;
18140    }
18141    if (n >= 10000)
18142    {
18143        pow10 = 10000;
18144        return  5;
18145    }
18146    if (n >= 1000)
18147    {
18148        pow10 = 1000;
18149        return  4;
18150    }
18151    if (n >= 100)
18152    {
18153        pow10 = 100;
18154        return  3;
18155    }
18156    if (n >= 10)
18157    {
18158        pow10 = 10;
18159        return  2;
18160    }
18161
18162    pow10 = 1;
18163    return 1;
18164}
18165
18166inline void grisu2_round(char* buf, int len, std::uint64_t dist, std::uint64_t delta,
18167                         std::uint64_t rest, std::uint64_t ten_k)
18168{
18169    JSON_ASSERT(len >= 1);
18170    JSON_ASSERT(dist <= delta);
18171    JSON_ASSERT(rest <= delta);
18172    JSON_ASSERT(ten_k > 0);
18173
18174    //               <--------------------------- delta ---->
18175    //                                  <---- dist --------->
18176    // --------------[------------------+-------------------]--------------
18177    //               M-                 w                   M+
18178    //
18179    //                                  ten_k
18180    //                                <------>
18181    //                                       <---- rest ---->
18182    // --------------[------------------+----+--------------]--------------
18183    //                                  w    V
18184    //                                       = buf * 10^k
18185    //
18186    // ten_k represents a unit-in-the-last-place in the decimal representation
18187    // stored in buf.
18188    // Decrement buf by ten_k while this takes buf closer to w.
18189
18190    // The tests are written in this order to avoid overflow in unsigned
18191    // integer arithmetic.
18192
18193    while (rest < dist
18194            && delta - rest >= ten_k
18195            && (rest + ten_k < dist || dist - rest > rest + ten_k - dist))
18196    {
18197        JSON_ASSERT(buf[len - 1] != '0');
18198        buf[len - 1]--;
18199        rest += ten_k;
18200    }
18201}
18202
18203/*!
18204Generates V = buffer * 10^decimal_exponent, such that M- <= V <= M+.
18205M- and M+ must be normalized and share the same exponent -60 <= e <= -32.
18206*/
18207inline void grisu2_digit_gen(char* buffer, int& length, int& decimal_exponent,
18208                             diyfp M_minus, diyfp w, diyfp M_plus)
18209{
18210    static_assert(kAlpha >= -60, "internal error");
18211    static_assert(kGamma <= -32, "internal error");
18212
18213    // Generates the digits (and the exponent) of a decimal floating-point
18214    // number V = buffer * 10^decimal_exponent in the range [M-, M+]. The diyfp's
18215    // w, M- and M+ share the same exponent e, which satisfies alpha <= e <= gamma.
18216    //
18217    //               <--------------------------- delta ---->
18218    //                                  <---- dist --------->
18219    // --------------[------------------+-------------------]--------------
18220    //               M-                 w                   M+
18221    //
18222    // Grisu2 generates the digits of M+ from left to right and stops as soon as
18223    // V is in [M-,M+].
18224
18225    JSON_ASSERT(M_plus.e >= kAlpha);
18226    JSON_ASSERT(M_plus.e <= kGamma);
18227
18228    std::uint64_t delta = diyfp::sub(M_plus, M_minus).f; // (significand of (M+ - M-), implicit exponent is e)
18229    std::uint64_t dist  = diyfp::sub(M_plus, w      ).f; // (significand of (M+ - w ), implicit exponent is e)
18230
18231    // Split M+ = f * 2^e into two parts p1 and p2 (note: e < 0):
18232    //
18233    //      M+ = f * 2^e
18234    //         = ((f div 2^-e) * 2^-e + (f mod 2^-e)) * 2^e
18235    //         = ((p1        ) * 2^-e + (p2        )) * 2^e
18236    //         = p1 + p2 * 2^e
18237
18238    const diyfp one(std::uint64_t{1} << -M_plus.e, M_plus.e);
18239
18240    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.)
18241    std::uint64_t p2 = M_plus.f & (one.f - 1);                    // p2 = f mod 2^-e
18242
18243    // 1)
18244    //
18245    // Generate the digits of the integral part p1 = d[n-1]...d[1]d[0]
18246
18247    JSON_ASSERT(p1 > 0);
18248
18249    std::uint32_t pow10{};
18250    const int k = find_largest_pow10(p1, pow10);
18251
18252    //      10^(k-1) <= p1 < 10^k, pow10 = 10^(k-1)
18253    //
18254    //      p1 = (p1 div 10^(k-1)) * 10^(k-1) + (p1 mod 10^(k-1))
18255    //         = (d[k-1]         ) * 10^(k-1) + (p1 mod 10^(k-1))
18256    //
18257    //      M+ = p1                                             + p2 * 2^e
18258    //         = d[k-1] * 10^(k-1) + (p1 mod 10^(k-1))          + p2 * 2^e
18259    //         = d[k-1] * 10^(k-1) + ((p1 mod 10^(k-1)) * 2^-e + p2) * 2^e
18260    //         = d[k-1] * 10^(k-1) + (                         rest) * 2^e
18261    //
18262    // Now generate the digits d[n] of p1 from left to right (n = k-1,...,0)
18263    //
18264    //      p1 = d[k-1]...d[n] * 10^n + d[n-1]...d[0]
18265    //
18266    // but stop as soon as
18267    //
18268    //      rest * 2^e = (d[n-1]...d[0] * 2^-e + p2) * 2^e <= delta * 2^e
18269
18270    int n = k;
18271    while (n > 0)
18272    {
18273        // Invariants:
18274        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)    (buffer = 0 for n = k)
18275        //      pow10 = 10^(n-1) <= p1 < 10^n
18276        //
18277        const std::uint32_t d = p1 / pow10;  // d = p1 div 10^(n-1)
18278        const std::uint32_t r = p1 % pow10;  // r = p1 mod 10^(n-1)
18279        //
18280        //      M+ = buffer * 10^n + (d * 10^(n-1) + r) + p2 * 2^e
18281        //         = (buffer * 10 + d) * 10^(n-1) + (r + p2 * 2^e)
18282        //
18283        JSON_ASSERT(d <= 9);
18284        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18285        //
18286        //      M+ = buffer * 10^(n-1) + (r + p2 * 2^e)
18287        //
18288        p1 = r;
18289        n--;
18290        //
18291        //      M+ = buffer * 10^n + (p1 + p2 * 2^e)
18292        //      pow10 = 10^n
18293        //
18294
18295        // Now check if enough digits have been generated.
18296        // Compute
18297        //
18298        //      p1 + p2 * 2^e = (p1 * 2^-e + p2) * 2^e = rest * 2^e
18299        //
18300        // Note:
18301        // Since rest and delta share the same exponent e, it suffices to
18302        // compare the significands.
18303        const std::uint64_t rest = (std::uint64_t{p1} << -one.e) + p2;
18304        if (rest <= delta)
18305        {
18306            // V = buffer * 10^n, with M- <= V <= M+.
18307
18308            decimal_exponent += n;
18309
18310            // We may now just stop. But instead look if the buffer could be
18311            // decremented to bring V closer to w.
18312            //
18313            // pow10 = 10^n is now 1 ulp in the decimal representation V.
18314            // The rounding procedure works with diyfp's with an implicit
18315            // exponent of e.
18316            //
18317            //      10^n = (10^n * 2^-e) * 2^e = ulp * 2^e
18318            //
18319            const std::uint64_t ten_n = std::uint64_t{pow10} << -one.e;
18320            grisu2_round(buffer, length, dist, delta, rest, ten_n);
18321
18322            return;
18323        }
18324
18325        pow10 /= 10;
18326        //
18327        //      pow10 = 10^(n-1) <= p1 < 10^n
18328        // Invariants restored.
18329    }
18330
18331    // 2)
18332    //
18333    // The digits of the integral part have been generated:
18334    //
18335    //      M+ = d[k-1]...d[1]d[0] + p2 * 2^e
18336    //         = buffer            + p2 * 2^e
18337    //
18338    // Now generate the digits of the fractional part p2 * 2^e.
18339    //
18340    // Note:
18341    // No decimal point is generated: the exponent is adjusted instead.
18342    //
18343    // p2 actually represents the fraction
18344    //
18345    //      p2 * 2^e
18346    //          = p2 / 2^-e
18347    //          = d[-1] / 10^1 + d[-2] / 10^2 + ...
18348    //
18349    // Now generate the digits d[-m] of p1 from left to right (m = 1,2,...)
18350    //
18351    //      p2 * 2^e = d[-1]d[-2]...d[-m] * 10^-m
18352    //                      + 10^-m * (d[-m-1] / 10^1 + d[-m-2] / 10^2 + ...)
18353    //
18354    // using
18355    //
18356    //      10^m * p2 = ((10^m * p2) div 2^-e) * 2^-e + ((10^m * p2) mod 2^-e)
18357    //                = (                   d) * 2^-e + (                   r)
18358    //
18359    // or
18360    //      10^m * p2 * 2^e = d + r * 2^e
18361    //
18362    // i.e.
18363    //
18364    //      M+ = buffer + p2 * 2^e
18365    //         = buffer + 10^-m * (d + r * 2^e)
18366    //         = (buffer * 10^m + d) * 10^-m + 10^-m * r * 2^e
18367    //
18368    // and stop as soon as 10^-m * r * 2^e <= delta * 2^e
18369
18370    JSON_ASSERT(p2 > delta);
18371
18372    int m = 0;
18373    for (;;)
18374    {
18375        // Invariant:
18376        //      M+ = buffer * 10^-m + 10^-m * (d[-m-1] / 10 + d[-m-2] / 10^2 + ...) * 2^e
18377        //         = buffer * 10^-m + 10^-m * (p2                                 ) * 2^e
18378        //         = buffer * 10^-m + 10^-m * (1/10 * (10 * p2)                   ) * 2^e
18379        //         = buffer * 10^-m + 10^-m * (1/10 * ((10*p2 div 2^-e) * 2^-e + (10*p2 mod 2^-e)) * 2^e
18380        //
18381        JSON_ASSERT(p2 <= (std::numeric_limits<std::uint64_t>::max)() / 10);
18382        p2 *= 10;
18383        const std::uint64_t d = p2 >> -one.e;     // d = (10 * p2) div 2^-e
18384        const std::uint64_t r = p2 & (one.f - 1); // r = (10 * p2) mod 2^-e
18385        //
18386        //      M+ = buffer * 10^-m + 10^-m * (1/10 * (d * 2^-e + r) * 2^e
18387        //         = buffer * 10^-m + 10^-m * (1/10 * (d + r * 2^e))
18388        //         = (buffer * 10 + d) * 10^(-m-1) + 10^(-m-1) * r * 2^e
18389        //
18390        JSON_ASSERT(d <= 9);
18391        buffer[length++] = static_cast<char>('0' + d); // buffer := buffer * 10 + d
18392        //
18393        //      M+ = buffer * 10^(-m-1) + 10^(-m-1) * r * 2^e
18394        //
18395        p2 = r;
18396        m++;
18397        //
18398        //      M+ = buffer * 10^-m + 10^-m * p2 * 2^e
18399        // Invariant restored.
18400
18401        // Check if enough digits have been generated.
18402        //
18403        //      10^-m * p2 * 2^e <= delta * 2^e
18404        //              p2 * 2^e <= 10^m * delta * 2^e
18405        //                    p2 <= 10^m * delta
18406        delta *= 10;
18407        dist  *= 10;
18408        if (p2 <= delta)
18409        {
18410            break;
18411        }
18412    }
18413
18414    // V = buffer * 10^-m, with M- <= V <= M+.
18415
18416    decimal_exponent -= m;
18417
18418    // 1 ulp in the decimal representation is now 10^-m.
18419    // Since delta and dist are now scaled by 10^m, we need to do the
18420    // same with ulp in order to keep the units in sync.
18421    //
18422    //      10^m * 10^-m = 1 = 2^-e * 2^e = ten_m * 2^e
18423    //
18424    const std::uint64_t ten_m = one.f;
18425    grisu2_round(buffer, length, dist, delta, p2, ten_m);
18426
18427    // By construction this algorithm generates the shortest possible decimal
18428    // number (Loitsch, Theorem 6.2) which rounds back to w.
18429    // For an input number of precision p, at least
18430    //
18431    //      N = 1 + ceil(p * log_10(2))
18432    //
18433    // decimal digits are sufficient to identify all binary floating-point
18434    // numbers (Matula, "In-and-Out conversions").
18435    // This implies that the algorithm does not produce more than N decimal
18436    // digits.
18437    //
18438    //      N = 17 for p = 53 (IEEE double precision)
18439    //      N = 9  for p = 24 (IEEE single precision)
18440}
18441
18442/*!
18443v = buf * 10^decimal_exponent
18444len is the length of the buffer (number of decimal digits)
18445The buffer must be large enough, i.e. >= max_digits10.
18446*/
18447JSON_HEDLEY_NON_NULL(1)
18448inline void grisu2(char* buf, int& len, int& decimal_exponent,
18449                   diyfp m_minus, diyfp v, diyfp m_plus)
18450{
18451    JSON_ASSERT(m_plus.e == m_minus.e);
18452    JSON_ASSERT(m_plus.e == v.e);
18453
18454    //  --------(-----------------------+-----------------------)--------    (A)
18455    //          m-                      v                       m+
18456    //
18457    //  --------------------(-----------+-----------------------)--------    (B)
18458    //                      m-          v                       m+
18459    //
18460    // First scale v (and m- and m+) such that the exponent is in the range
18461    // [alpha, gamma].
18462
18463    const cached_power cached = get_cached_power_for_binary_exponent(m_plus.e);
18464
18465    const diyfp c_minus_k(cached.f, cached.e); // = c ~= 10^-k
18466
18467    // The exponent of the products is = v.e + c_minus_k.e + q and is in the range [alpha,gamma]
18468    const diyfp w       = diyfp::mul(v,       c_minus_k);
18469    const diyfp w_minus = diyfp::mul(m_minus, c_minus_k);
18470    const diyfp w_plus  = diyfp::mul(m_plus,  c_minus_k);
18471
18472    //  ----(---+---)---------------(---+---)---------------(---+---)----
18473    //          w-                      w                       w+
18474    //          = c*m-                  = c*v                   = c*m+
18475    //
18476    // diyfp::mul rounds its result and c_minus_k is approximated too. w, w- and
18477    // w+ are now off by a small amount.
18478    // In fact:
18479    //
18480    //      w - v * 10^k < 1 ulp
18481    //
18482    // To account for this inaccuracy, add resp. subtract 1 ulp.
18483    //
18484    //  --------+---[---------------(---+---)---------------]---+--------
18485    //          w-  M-                  w                   M+  w+
18486    //
18487    // Now any number in [M-, M+] (bounds included) will round to w when input,
18488    // regardless of how the input rounding algorithm breaks ties.
18489    //
18490    // And digit_gen generates the shortest possible such number in [M-, M+].
18491    // Note that this does not mean that Grisu2 always generates the shortest
18492    // possible number in the interval (m-, m+).
18493    const diyfp M_minus(w_minus.f + 1, w_minus.e);
18494    const diyfp M_plus (w_plus.f  - 1, w_plus.e );
18495
18496    decimal_exponent = -cached.k; // = -(-k) = k
18497
18498    grisu2_digit_gen(buf, len, decimal_exponent, M_minus, w, M_plus);
18499}
18500
18501/*!
18502v = buf * 10^decimal_exponent
18503len is the length of the buffer (number of decimal digits)
18504The buffer must be large enough, i.e. >= max_digits10.
18505*/
18506template<typename FloatType>
18507JSON_HEDLEY_NON_NULL(1)
18508void grisu2(char* buf, int& len, int& decimal_exponent, FloatType value)
18509{
18510    static_assert(diyfp::kPrecision >= std::numeric_limits<FloatType>::digits + 3,
18511                  "internal error: not enough precision");
18512
18513    JSON_ASSERT(std::isfinite(value));
18514    JSON_ASSERT(value > 0);
18515
18516    // If the neighbors (and boundaries) of 'value' are always computed for double-precision
18517    // numbers, all float's can be recovered using strtod (and strtof). However, the resulting
18518    // decimal representations are not exactly "short".
18519    //
18520    // The documentation for 'std::to_chars' (https://en.cppreference.com/w/cpp/utility/to_chars)
18521    // says "value is converted to a string as if by std::sprintf in the default ("C") locale"
18522    // and since sprintf promotes floats to doubles, I think this is exactly what 'std::to_chars'
18523    // does.
18524    // On the other hand, the documentation for 'std::to_chars' requires that "parsing the
18525    // representation using the corresponding std::from_chars function recovers value exactly". That
18526    // indicates that single precision floating-point numbers should be recovered using
18527    // 'std::strtof'.
18528    //
18529    // NB: If the neighbors are computed for single-precision numbers, there is a single float
18530    //     (7.0385307e-26f) which can't be recovered using strtod. The resulting double precision
18531    //     value is off by 1 ulp.
18532#if 0 // NOLINT(readability-avoid-unconditional-preprocessor-if)
18533    const boundaries w = compute_boundaries(static_cast<double>(value));
18534#else
18535    const boundaries w = compute_boundaries(value);
18536#endif
18537
18538    grisu2(buf, len, decimal_exponent, w.minus, w.w, w.plus);
18539}
18540
18541/*!
18542@brief appends a decimal representation of e to buf
18543@return a pointer to the element following the exponent.
18544@pre -1000 < e < 1000
18545*/
18546JSON_HEDLEY_NON_NULL(1)
18547JSON_HEDLEY_RETURNS_NON_NULL
18548inline char* append_exponent(char* buf, int e)
18549{
18550    JSON_ASSERT(e > -1000);
18551    JSON_ASSERT(e <  1000);
18552
18553    if (e < 0)
18554    {
18555        e = -e;
18556        *buf++ = '-';
18557    }
18558    else
18559    {
18560        *buf++ = '+';
18561    }
18562
18563    auto k = static_cast<std::uint32_t>(e);
18564    if (k < 10)
18565    {
18566        // Always print at least two digits in the exponent.
18567        // This is for compatibility with printf("%g").
18568        *buf++ = '0';
18569        *buf++ = static_cast<char>('0' + k);
18570    }
18571    else if (k < 100)
18572    {
18573        *buf++ = static_cast<char>('0' + (k / 10));
18574        k %= 10;
18575        *buf++ = static_cast<char>('0' + k);
18576    }
18577    else
18578    {
18579        *buf++ = static_cast<char>('0' + (k / 100));
18580        k %= 100;
18581        *buf++ = static_cast<char>('0' + (k / 10));
18582        k %= 10;
18583        *buf++ = static_cast<char>('0' + k);
18584    }
18585
18586    return buf;
18587}
18588
18589/*!
18590@brief prettify v = buf * 10^decimal_exponent
18591
18592If v is in the range [10^min_exp, 10^max_exp) it will be printed in fixed-point
18593notation. Otherwise it will be printed in exponential notation.
18594
18595@pre min_exp < 0
18596@pre max_exp > 0
18597*/
18598JSON_HEDLEY_NON_NULL(1)
18599JSON_HEDLEY_RETURNS_NON_NULL
18600inline char* format_buffer(char* buf, int len, int decimal_exponent,
18601                           int min_exp, int max_exp)
18602{
18603    JSON_ASSERT(min_exp < 0);
18604    JSON_ASSERT(max_exp > 0);
18605
18606    const int k = len;
18607    const int n = len + decimal_exponent;
18608
18609    // v = buf * 10^(n-k)
18610    // k is the length of the buffer (number of decimal digits)
18611    // n is the position of the decimal point relative to the start of the buffer.
18612
18613    if (k <= n && n <= max_exp)
18614    {
18615        // digits[000]
18616        // len <= max_exp + 2
18617
18618        std::memset(buf + k, '0', static_cast<size_t>(n) - static_cast<size_t>(k));
18619        // Make it look like a floating-point number (#362, #378)
18620        buf[n + 0] = '.';
18621        buf[n + 1] = '0';
18622        return buf + (static_cast<size_t>(n) + 2);
18623    }
18624
18625    if (0 < n && n <= max_exp)
18626    {
18627        // dig.its
18628        // len <= max_digits10 + 1
18629
18630        JSON_ASSERT(k > n);
18631
18632        std::memmove(buf + (static_cast<size_t>(n) + 1), buf + n, static_cast<size_t>(k) - static_cast<size_t>(n));
18633        buf[n] = '.';
18634        return buf + (static_cast<size_t>(k) + 1U);
18635    }
18636
18637    if (min_exp < n && n <= 0)
18638    {
18639        // 0.[000]digits
18640        // len <= 2 + (-min_exp - 1) + max_digits10
18641
18642        std::memmove(buf + (2 + static_cast<size_t>(-n)), buf, static_cast<size_t>(k));
18643        buf[0] = '0';
18644        buf[1] = '.';
18645        std::memset(buf + 2, '0', static_cast<size_t>(-n));
18646        return buf + (2U + static_cast<size_t>(-n) + static_cast<size_t>(k));
18647    }
18648
18649    if (k == 1)
18650    {
18651        // dE+123
18652        // len <= 1 + 5
18653
18654        buf += 1;
18655    }
18656    else
18657    {
18658        // d.igitsE+123
18659        // len <= max_digits10 + 1 + 5
18660
18661        std::memmove(buf + 2, buf + 1, static_cast<size_t>(k) - 1);
18662        buf[1] = '.';
18663        buf += 1 + static_cast<size_t>(k);
18664    }
18665
18666    *buf++ = 'e';
18667    return append_exponent(buf, n - 1);
18668}
18669
18670}  // namespace dtoa_impl
18671
18672/*!
18673@brief generates a decimal representation of the floating-point number value in [first, last).
18674
18675The format of the resulting decimal representation is similar to printf's %g
18676format. Returns an iterator pointing past-the-end of the decimal representation.
18677
18678@note The input number must be finite, i.e. NaN's and Inf's are not supported.
18679@note The buffer must be large enough.
18680@note The result is NOT null-terminated.
18681*/
18682template<typename FloatType>
18683JSON_HEDLEY_NON_NULL(1, 2)
18684JSON_HEDLEY_RETURNS_NON_NULL
18685char* to_chars(char* first, const char* last, FloatType value)
18686{
18687    static_cast<void>(last); // maybe unused - fix warning
18688    JSON_ASSERT(std::isfinite(value));
18689
18690    // Use signbit(value) instead of (value < 0) since signbit works for -0.
18691    if (std::signbit(value))
18692    {
18693        value = -value;
18694        *first++ = '-';
18695    }
18696
18697#ifdef __GNUC__
18698#pragma GCC diagnostic push
18699#pragma GCC diagnostic ignored "-Wfloat-equal"
18700#endif
18701    if (value == 0) // +-0
18702    {
18703        *first++ = '0';
18704        // Make it look like a floating-point number (#362, #378)
18705        *first++ = '.';
18706        *first++ = '0';
18707        return first;
18708    }
18709#ifdef __GNUC__
18710#pragma GCC diagnostic pop
18711#endif
18712
18713    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10);
18714
18715    // Compute v = buffer * 10^decimal_exponent.
18716    // The decimal digits are stored in the buffer, which needs to be interpreted
18717    // as an unsigned decimal integer.
18718    // len is the length of the buffer, i.e. the number of decimal digits.
18719    int len = 0;
18720    int decimal_exponent = 0;
18721    dtoa_impl::grisu2(first, len, decimal_exponent, value);
18722
18723    JSON_ASSERT(len <= std::numeric_limits<FloatType>::max_digits10);
18724
18725    // Format the buffer like printf("%.*g", prec, value)
18726    constexpr int kMinExp = -4;
18727    // Use digits10 here to increase compatibility with version 2.
18728    constexpr int kMaxExp = std::numeric_limits<FloatType>::digits10;
18729
18730    JSON_ASSERT(last - first >= kMaxExp + 2);
18731    JSON_ASSERT(last - first >= 2 + (-kMinExp - 1) + std::numeric_limits<FloatType>::max_digits10);
18732    JSON_ASSERT(last - first >= std::numeric_limits<FloatType>::max_digits10 + 6);
18733
18734    return dtoa_impl::format_buffer(first, len, decimal_exponent, kMinExp, kMaxExp);
18735}
18736
18737}  // namespace detail
18738NLOHMANN_JSON_NAMESPACE_END
18739
18740// #include <nlohmann/detail/exceptions.hpp>
18741
18742// #include <nlohmann/detail/macro_scope.hpp>
18743
18744// #include <nlohmann/detail/meta/cpp_future.hpp>
18745
18746// #include <nlohmann/detail/output/binary_writer.hpp>
18747
18748// #include <nlohmann/detail/output/output_adapters.hpp>
18749
18750// #include <nlohmann/detail/string_concat.hpp>
18751
18752// #include <nlohmann/detail/value_t.hpp>
18753
18754
18755NLOHMANN_JSON_NAMESPACE_BEGIN
18756namespace detail
18757{
18758
18759///////////////////
18760// serialization //
18761///////////////////
18762
18763/// how to treat decoding errors
18764enum class error_handler_t
18765{
18766    strict,  ///< throw a type_error exception in case of invalid UTF-8
18767    replace, ///< replace invalid UTF-8 sequences with U+FFFD
18768    ignore   ///< ignore invalid UTF-8 sequences
18769};
18770
18771template<typename BasicJsonType>
18772class serializer
18773{
18774    using string_t = typename BasicJsonType::string_t;
18775    using number_float_t = typename BasicJsonType::number_float_t;
18776    using number_integer_t = typename BasicJsonType::number_integer_t;
18777    using number_unsigned_t = typename BasicJsonType::number_unsigned_t;
18778    using binary_char_t = typename BasicJsonType::binary_t::value_type;
18779    static constexpr std::uint8_t UTF8_ACCEPT = 0;
18780    static constexpr std::uint8_t UTF8_REJECT = 1;
18781
18782  public:
18783    /*!
18784    @param[in] s  output stream to serialize to
18785    @param[in] ichar  indentation character to use
18786    @param[in] error_handler_  how to react on decoding errors
18787    */
18788    serializer(output_adapter_t<char> s, const char ichar,
18789               error_handler_t error_handler_ = error_handler_t::strict)
18790        : o(std::move(s))
18791        , loc(std::localeconv())
18792        , thousands_sep(loc->thousands_sep == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->thousands_sep)))
18793        , decimal_point(loc->decimal_point == nullptr ? '\0' : std::char_traits<char>::to_char_type(* (loc->decimal_point)))
18794        , indent_char(ichar)
18795        , indent_string(512, indent_char)
18796        , error_handler(error_handler_)
18797    {}
18798
18799    // delete because of pointer members
18800    serializer(const serializer&) = delete;
18801    serializer& operator=(const serializer&) = delete;
18802    serializer(serializer&&) = delete;
18803    serializer& operator=(serializer&&) = delete;
18804    ~serializer() = default;
18805
18806    /*!
18807    @brief internal implementation of the serialization function
18808
18809    This function is called by the public member function dump and organizes
18810    the serialization internally. The indentation level is propagated as
18811    additional parameter. In case of arrays and objects, the function is
18812    called recursively.
18813
18814    - strings and object keys are escaped using `escape_string()`
18815    - integer numbers are converted implicitly via `operator<<`
18816    - floating-point numbers are converted to a string using `"%g"` format
18817    - binary values are serialized as objects containing the subtype and the
18818      byte array
18819
18820    @param[in] val               value to serialize
18821    @param[in] pretty_print      whether the output shall be pretty-printed
18822    @param[in] ensure_ascii If @a ensure_ascii is true, all non-ASCII characters
18823    in the output are escaped with `\uXXXX` sequences, and the result consists
18824    of ASCII characters only.
18825    @param[in] indent_step       the indent level
18826    @param[in] current_indent    the current indent level (only used internally)
18827    */
18828    void dump(const BasicJsonType& val,
18829              const bool pretty_print,
18830              const bool ensure_ascii,
18831              const unsigned int indent_step,
18832              const unsigned int current_indent = 0)
18833    {
18834        switch (val.m_data.m_type)
18835        {
18836            case value_t::object:
18837            {
18838                if (val.m_data.m_value.object->empty())
18839                {
18840                    o->write_characters("{}", 2);
18841                    return;
18842                }
18843
18844                if (pretty_print)
18845                {
18846                    o->write_characters("{\n", 2);
18847
18848                    // variable to hold indentation for recursive calls
18849                    const auto new_indent = current_indent + indent_step;
18850                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18851                    {
18852                        indent_string.resize(indent_string.size() * 2, ' ');
18853                    }
18854
18855                    // first n-1 elements
18856                    auto i = val.m_data.m_value.object->cbegin();
18857                    for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18858                    {
18859                        o->write_characters(indent_string.c_str(), new_indent);
18860                        o->write_character('\"');
18861                        dump_escaped(i->first, ensure_ascii);
18862                        o->write_characters("\": ", 3);
18863                        dump(i->second, true, ensure_ascii, indent_step, new_indent);
18864                        o->write_characters(",\n", 2);
18865                    }
18866
18867                    // last element
18868                    JSON_ASSERT(i != val.m_data.m_value.object->cend());
18869                    JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18870                    o->write_characters(indent_string.c_str(), new_indent);
18871                    o->write_character('\"');
18872                    dump_escaped(i->first, ensure_ascii);
18873                    o->write_characters("\": ", 3);
18874                    dump(i->second, true, ensure_ascii, indent_step, new_indent);
18875
18876                    o->write_character('\n');
18877                    o->write_characters(indent_string.c_str(), current_indent);
18878                    o->write_character('}');
18879                }
18880                else
18881                {
18882                    o->write_character('{');
18883
18884                    // first n-1 elements
18885                    auto i = val.m_data.m_value.object->cbegin();
18886                    for (std::size_t cnt = 0; cnt < val.m_data.m_value.object->size() - 1; ++cnt, ++i)
18887                    {
18888                        o->write_character('\"');
18889                        dump_escaped(i->first, ensure_ascii);
18890                        o->write_characters("\":", 2);
18891                        dump(i->second, false, ensure_ascii, indent_step, current_indent);
18892                        o->write_character(',');
18893                    }
18894
18895                    // last element
18896                    JSON_ASSERT(i != val.m_data.m_value.object->cend());
18897                    JSON_ASSERT(std::next(i) == val.m_data.m_value.object->cend());
18898                    o->write_character('\"');
18899                    dump_escaped(i->first, ensure_ascii);
18900                    o->write_characters("\":", 2);
18901                    dump(i->second, false, ensure_ascii, indent_step, current_indent);
18902
18903                    o->write_character('}');
18904                }
18905
18906                return;
18907            }
18908
18909            case value_t::array:
18910            {
18911                if (val.m_data.m_value.array->empty())
18912                {
18913                    o->write_characters("[]", 2);
18914                    return;
18915                }
18916
18917                if (pretty_print)
18918                {
18919                    o->write_characters("[\n", 2);
18920
18921                    // variable to hold indentation for recursive calls
18922                    const auto new_indent = current_indent + indent_step;
18923                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18924                    {
18925                        indent_string.resize(indent_string.size() * 2, ' ');
18926                    }
18927
18928                    // first n-1 elements
18929                    for (auto i = val.m_data.m_value.array->cbegin();
18930                            i != val.m_data.m_value.array->cend() - 1; ++i)
18931                    {
18932                        o->write_characters(indent_string.c_str(), new_indent);
18933                        dump(*i, true, ensure_ascii, indent_step, new_indent);
18934                        o->write_characters(",\n", 2);
18935                    }
18936
18937                    // last element
18938                    JSON_ASSERT(!val.m_data.m_value.array->empty());
18939                    o->write_characters(indent_string.c_str(), new_indent);
18940                    dump(val.m_data.m_value.array->back(), true, ensure_ascii, indent_step, new_indent);
18941
18942                    o->write_character('\n');
18943                    o->write_characters(indent_string.c_str(), current_indent);
18944                    o->write_character(']');
18945                }
18946                else
18947                {
18948                    o->write_character('[');
18949
18950                    // first n-1 elements
18951                    for (auto i = val.m_data.m_value.array->cbegin();
18952                            i != val.m_data.m_value.array->cend() - 1; ++i)
18953                    {
18954                        dump(*i, false, ensure_ascii, indent_step, current_indent);
18955                        o->write_character(',');
18956                    }
18957
18958                    // last element
18959                    JSON_ASSERT(!val.m_data.m_value.array->empty());
18960                    dump(val.m_data.m_value.array->back(), false, ensure_ascii, indent_step, current_indent);
18961
18962                    o->write_character(']');
18963                }
18964
18965                return;
18966            }
18967
18968            case value_t::string:
18969            {
18970                o->write_character('\"');
18971                dump_escaped(*val.m_data.m_value.string, ensure_ascii);
18972                o->write_character('\"');
18973                return;
18974            }
18975
18976            case value_t::binary:
18977            {
18978                if (pretty_print)
18979                {
18980                    o->write_characters("{\n", 2);
18981
18982                    // variable to hold indentation for recursive calls
18983                    const auto new_indent = current_indent + indent_step;
18984                    if (JSON_HEDLEY_UNLIKELY(indent_string.size() < new_indent))
18985                    {
18986                        indent_string.resize(indent_string.size() * 2, ' ');
18987                    }
18988
18989                    o->write_characters(indent_string.c_str(), new_indent);
18990
18991                    o->write_characters("\"bytes\": [", 10);
18992
18993                    if (!val.m_data.m_value.binary->empty())
18994                    {
18995                        for (auto i = val.m_data.m_value.binary->cbegin();
18996                                i != val.m_data.m_value.binary->cend() - 1; ++i)
18997                        {
18998                            dump_integer(*i);
18999                            o->write_characters(", ", 2);
19000                        }
19001                        dump_integer(val.m_data.m_value.binary->back());
19002                    }
19003
19004                    o->write_characters("],\n", 3);
19005                    o->write_characters(indent_string.c_str(), new_indent);
19006
19007                    o->write_characters("\"subtype\": ", 11);
19008                    if (val.m_data.m_value.binary->has_subtype())
19009                    {
19010                        dump_integer(val.m_data.m_value.binary->subtype());
19011                    }
19012                    else
19013                    {
19014                        o->write_characters("null", 4);
19015                    }
19016                    o->write_character('\n');
19017                    o->write_characters(indent_string.c_str(), current_indent);
19018                    o->write_character('}');
19019                }
19020                else
19021                {
19022                    o->write_characters("{\"bytes\":[", 10);
19023
19024                    if (!val.m_data.m_value.binary->empty())
19025                    {
19026                        for (auto i = val.m_data.m_value.binary->cbegin();
19027                                i != val.m_data.m_value.binary->cend() - 1; ++i)
19028                        {
19029                            dump_integer(*i);
19030                            o->write_character(',');
19031                        }
19032                        dump_integer(val.m_data.m_value.binary->back());
19033                    }
19034
19035                    o->write_characters("],\"subtype\":", 12);
19036                    if (val.m_data.m_value.binary->has_subtype())
19037                    {
19038                        dump_integer(val.m_data.m_value.binary->subtype());
19039                        o->write_character('}');
19040                    }
19041                    else
19042                    {
19043                        o->write_characters("null}", 5);
19044                    }
19045                }
19046                return;
19047            }
19048
19049            case value_t::boolean:
19050            {
19051                if (val.m_data.m_value.boolean)
19052                {
19053                    o->write_characters("true", 4);
19054                }
19055                else
19056                {
19057                    o->write_characters("false", 5);
19058                }
19059                return;
19060            }
19061
19062            case value_t::number_integer:
19063            {
19064                dump_integer(val.m_data.m_value.number_integer);
19065                return;
19066            }
19067
19068            case value_t::number_unsigned:
19069            {
19070                dump_integer(val.m_data.m_value.number_unsigned);
19071                return;
19072            }
19073
19074            case value_t::number_float:
19075            {
19076                dump_float(val.m_data.m_value.number_float);
19077                return;
19078            }
19079
19080            case value_t::discarded:
19081            {
19082                o->write_characters("<discarded>", 11);
19083                return;
19084            }
19085
19086            case value_t::null:
19087            {
19088                o->write_characters("null", 4);
19089                return;
19090            }
19091
19092            default:            // LCOV_EXCL_LINE
19093                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19094        }
19095    }
19096
19097  JSON_PRIVATE_UNLESS_TESTED:
19098    /*!
19099    @brief dump escaped string
19100
19101    Escape a string by replacing certain special characters by a sequence of an
19102    escape character (backslash) and another character and other control
19103    characters by a sequence of "\u" followed by a four-digit hex
19104    representation. The escaped string is written to output stream @a o.
19105
19106    @param[in] s  the string to escape
19107    @param[in] ensure_ascii  whether to escape non-ASCII characters with
19108                             \uXXXX sequences
19109
19110    @complexity Linear in the length of string @a s.
19111    */
19112    void dump_escaped(const string_t& s, const bool ensure_ascii)
19113    {
19114        std::uint32_t codepoint{};
19115        std::uint8_t state = UTF8_ACCEPT;
19116        std::size_t bytes = 0;  // number of bytes written to string_buffer
19117
19118        // number of bytes written at the point of the last valid byte
19119        std::size_t bytes_after_last_accept = 0;
19120        std::size_t undumped_chars = 0;
19121
19122        for (std::size_t i = 0; i < s.size(); ++i)
19123        {
19124            const auto byte = static_cast<std::uint8_t>(s[i]);
19125
19126            switch (decode(state, codepoint, byte))
19127            {
19128                case UTF8_ACCEPT:  // decode found a new code point
19129                {
19130                    switch (codepoint)
19131                    {
19132                        case 0x08: // backspace
19133                        {
19134                            string_buffer[bytes++] = '\\';
19135                            string_buffer[bytes++] = 'b';
19136                            break;
19137                        }
19138
19139                        case 0x09: // horizontal tab
19140                        {
19141                            string_buffer[bytes++] = '\\';
19142                            string_buffer[bytes++] = 't';
19143                            break;
19144                        }
19145
19146                        case 0x0A: // newline
19147                        {
19148                            string_buffer[bytes++] = '\\';
19149                            string_buffer[bytes++] = 'n';
19150                            break;
19151                        }
19152
19153                        case 0x0C: // formfeed
19154                        {
19155                            string_buffer[bytes++] = '\\';
19156                            string_buffer[bytes++] = 'f';
19157                            break;
19158                        }
19159
19160                        case 0x0D: // carriage return
19161                        {
19162                            string_buffer[bytes++] = '\\';
19163                            string_buffer[bytes++] = 'r';
19164                            break;
19165                        }
19166
19167                        case 0x22: // quotation mark
19168                        {
19169                            string_buffer[bytes++] = '\\';
19170                            string_buffer[bytes++] = '\"';
19171                            break;
19172                        }
19173
19174                        case 0x5C: // reverse solidus
19175                        {
19176                            string_buffer[bytes++] = '\\';
19177                            string_buffer[bytes++] = '\\';
19178                            break;
19179                        }
19180
19181                        default:
19182                        {
19183                            // escape control characters (0x00..0x1F) or, if
19184                            // ensure_ascii parameter is used, non-ASCII characters
19185                            if ((codepoint <= 0x1F) || (ensure_ascii && (codepoint >= 0x7F)))
19186                            {
19187                                if (codepoint <= 0xFFFF)
19188                                {
19189                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19190                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 7, "\\u%04x",
19191                                                                      static_cast<std::uint16_t>(codepoint)));
19192                                    bytes += 6;
19193                                }
19194                                else
19195                                {
19196                                    // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19197                                    static_cast<void>((std::snprintf)(string_buffer.data() + bytes, 13, "\\u%04x\\u%04x",
19198                                                                      static_cast<std::uint16_t>(0xD7C0u + (codepoint >> 10u)),
19199                                                                      static_cast<std::uint16_t>(0xDC00u + (codepoint & 0x3FFu))));
19200                                    bytes += 12;
19201                                }
19202                            }
19203                            else
19204                            {
19205                                // copy byte to buffer (all previous bytes
19206                                // been copied have in default case above)
19207                                string_buffer[bytes++] = s[i];
19208                            }
19209                            break;
19210                        }
19211                    }
19212
19213                    // write buffer and reset index; there must be 13 bytes
19214                    // left, as this is the maximal number of bytes to be
19215                    // written ("\uxxxx\uxxxx\0") for one code point
19216                    if (string_buffer.size() - bytes < 13)
19217                    {
19218                        o->write_characters(string_buffer.data(), bytes);
19219                        bytes = 0;
19220                    }
19221
19222                    // remember the byte position of this accept
19223                    bytes_after_last_accept = bytes;
19224                    undumped_chars = 0;
19225                    break;
19226                }
19227
19228                case UTF8_REJECT:  // decode found invalid UTF-8 byte
19229                {
19230                    switch (error_handler)
19231                    {
19232                        case error_handler_t::strict:
19233                        {
19234                            JSON_THROW(type_error::create(316, concat("invalid UTF-8 byte at index ", std::to_string(i), ": 0x", hex_bytes(byte | 0)), nullptr));
19235                        }
19236
19237                        case error_handler_t::ignore:
19238                        case error_handler_t::replace:
19239                        {
19240                            // in case we saw this character the first time, we
19241                            // would like to read it again, because the byte
19242                            // may be OK for itself, but just not OK for the
19243                            // previous sequence
19244                            if (undumped_chars > 0)
19245                            {
19246                                --i;
19247                            }
19248
19249                            // reset length buffer to the last accepted index;
19250                            // thus removing/ignoring the invalid characters
19251                            bytes = bytes_after_last_accept;
19252
19253                            if (error_handler == error_handler_t::replace)
19254                            {
19255                                // add a replacement character
19256                                if (ensure_ascii)
19257                                {
19258                                    string_buffer[bytes++] = '\\';
19259                                    string_buffer[bytes++] = 'u';
19260                                    string_buffer[bytes++] = 'f';
19261                                    string_buffer[bytes++] = 'f';
19262                                    string_buffer[bytes++] = 'f';
19263                                    string_buffer[bytes++] = 'd';
19264                                }
19265                                else
19266                                {
19267                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xEF');
19268                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBF');
19269                                    string_buffer[bytes++] = detail::binary_writer<BasicJsonType, char>::to_char_type('\xBD');
19270                                }
19271
19272                                // write buffer and reset index; there must be 13 bytes
19273                                // left, as this is the maximal number of bytes to be
19274                                // written ("\uxxxx\uxxxx\0") for one code point
19275                                if (string_buffer.size() - bytes < 13)
19276                                {
19277                                    o->write_characters(string_buffer.data(), bytes);
19278                                    bytes = 0;
19279                                }
19280
19281                                bytes_after_last_accept = bytes;
19282                            }
19283
19284                            undumped_chars = 0;
19285
19286                            // continue processing the string
19287                            state = UTF8_ACCEPT;
19288                            break;
19289                        }
19290
19291                        default:            // LCOV_EXCL_LINE
19292                            JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19293                    }
19294                    break;
19295                }
19296
19297                default:  // decode found yet incomplete multi-byte code point
19298                {
19299                    if (!ensure_ascii)
19300                    {
19301                        // code point will not be escaped - copy byte to buffer
19302                        string_buffer[bytes++] = s[i];
19303                    }
19304                    ++undumped_chars;
19305                    break;
19306                }
19307            }
19308        }
19309
19310        // we finished processing the string
19311        if (JSON_HEDLEY_LIKELY(state == UTF8_ACCEPT))
19312        {
19313            // write buffer
19314            if (bytes > 0)
19315            {
19316                o->write_characters(string_buffer.data(), bytes);
19317            }
19318        }
19319        else
19320        {
19321            // we finish reading, but do not accept: string was incomplete
19322            switch (error_handler)
19323            {
19324                case error_handler_t::strict:
19325                {
19326                    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));
19327                }
19328
19329                case error_handler_t::ignore:
19330                {
19331                    // write all accepted bytes
19332                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
19333                    break;
19334                }
19335
19336                case error_handler_t::replace:
19337                {
19338                    // write all accepted bytes
19339                    o->write_characters(string_buffer.data(), bytes_after_last_accept);
19340                    // add a replacement character
19341                    if (ensure_ascii)
19342                    {
19343                        o->write_characters("\\ufffd", 6);
19344                    }
19345                    else
19346                    {
19347                        o->write_characters("\xEF\xBF\xBD", 3);
19348                    }
19349                    break;
19350                }
19351
19352                default:            // LCOV_EXCL_LINE
19353                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19354            }
19355        }
19356    }
19357
19358  private:
19359    /*!
19360    @brief count digits
19361
19362    Count the number of decimal (base 10) digits for an input unsigned integer.
19363
19364    @param[in] x  unsigned integer number to count its digits
19365    @return    number of decimal digits
19366    */
19367    unsigned int count_digits(number_unsigned_t x) noexcept
19368    {
19369        unsigned int n_digits = 1;
19370        for (;;)
19371        {
19372            if (x < 10)
19373            {
19374                return n_digits;
19375            }
19376            if (x < 100)
19377            {
19378                return n_digits + 1;
19379            }
19380            if (x < 1000)
19381            {
19382                return n_digits + 2;
19383            }
19384            if (x < 10000)
19385            {
19386                return n_digits + 3;
19387            }
19388            x = x / 10000u;
19389            n_digits += 4;
19390        }
19391    }
19392
19393    /*!
19394     * @brief convert a byte to a uppercase hex representation
19395     * @param[in] byte byte to represent
19396     * @return representation ("00".."FF")
19397     */
19398    static std::string hex_bytes(std::uint8_t byte)
19399    {
19400        std::string result = "FF";
19401        constexpr const char* nibble_to_hex = "0123456789ABCDEF";
19402        result[0] = nibble_to_hex[byte / 16];
19403        result[1] = nibble_to_hex[byte % 16];
19404        return result;
19405    }
19406
19407    // templates to avoid warnings about useless casts
19408    template <typename NumberType, enable_if_t<std::is_signed<NumberType>::value, int> = 0>
19409    bool is_negative_number(NumberType x)
19410    {
19411        return x < 0;
19412    }
19413
19414    template < typename NumberType, enable_if_t <std::is_unsigned<NumberType>::value, int > = 0 >
19415    bool is_negative_number(NumberType /*unused*/)
19416    {
19417        return false;
19418    }
19419
19420    /*!
19421    @brief dump an integer
19422
19423    Dump a given integer to output stream @a o. Works internally with
19424    @a number_buffer.
19425
19426    @param[in] x  integer number (signed or unsigned) to dump
19427    @tparam NumberType either @a number_integer_t or @a number_unsigned_t
19428    */
19429    template < typename NumberType, detail::enable_if_t <
19430                   std::is_integral<NumberType>::value ||
19431                   std::is_same<NumberType, number_unsigned_t>::value ||
19432                   std::is_same<NumberType, number_integer_t>::value ||
19433                   std::is_same<NumberType, binary_char_t>::value,
19434                   int > = 0 >
19435    void dump_integer(NumberType x)
19436    {
19437        static constexpr std::array<std::array<char, 2>, 100> digits_to_99
19438        {
19439            {
19440                {{'0', '0'}}, {{'0', '1'}}, {{'0', '2'}}, {{'0', '3'}}, {{'0', '4'}}, {{'0', '5'}}, {{'0', '6'}}, {{'0', '7'}}, {{'0', '8'}}, {{'0', '9'}},
19441                {{'1', '0'}}, {{'1', '1'}}, {{'1', '2'}}, {{'1', '3'}}, {{'1', '4'}}, {{'1', '5'}}, {{'1', '6'}}, {{'1', '7'}}, {{'1', '8'}}, {{'1', '9'}},
19442                {{'2', '0'}}, {{'2', '1'}}, {{'2', '2'}}, {{'2', '3'}}, {{'2', '4'}}, {{'2', '5'}}, {{'2', '6'}}, {{'2', '7'}}, {{'2', '8'}}, {{'2', '9'}},
19443                {{'3', '0'}}, {{'3', '1'}}, {{'3', '2'}}, {{'3', '3'}}, {{'3', '4'}}, {{'3', '5'}}, {{'3', '6'}}, {{'3', '7'}}, {{'3', '8'}}, {{'3', '9'}},
19444                {{'4', '0'}}, {{'4', '1'}}, {{'4', '2'}}, {{'4', '3'}}, {{'4', '4'}}, {{'4', '5'}}, {{'4', '6'}}, {{'4', '7'}}, {{'4', '8'}}, {{'4', '9'}},
19445                {{'5', '0'}}, {{'5', '1'}}, {{'5', '2'}}, {{'5', '3'}}, {{'5', '4'}}, {{'5', '5'}}, {{'5', '6'}}, {{'5', '7'}}, {{'5', '8'}}, {{'5', '9'}},
19446                {{'6', '0'}}, {{'6', '1'}}, {{'6', '2'}}, {{'6', '3'}}, {{'6', '4'}}, {{'6', '5'}}, {{'6', '6'}}, {{'6', '7'}}, {{'6', '8'}}, {{'6', '9'}},
19447                {{'7', '0'}}, {{'7', '1'}}, {{'7', '2'}}, {{'7', '3'}}, {{'7', '4'}}, {{'7', '5'}}, {{'7', '6'}}, {{'7', '7'}}, {{'7', '8'}}, {{'7', '9'}},
19448                {{'8', '0'}}, {{'8', '1'}}, {{'8', '2'}}, {{'8', '3'}}, {{'8', '4'}}, {{'8', '5'}}, {{'8', '6'}}, {{'8', '7'}}, {{'8', '8'}}, {{'8', '9'}},
19449                {{'9', '0'}}, {{'9', '1'}}, {{'9', '2'}}, {{'9', '3'}}, {{'9', '4'}}, {{'9', '5'}}, {{'9', '6'}}, {{'9', '7'}}, {{'9', '8'}}, {{'9', '9'}},
19450            }
19451        };
19452
19453        // special case for "0"
19454        if (x == 0)
19455        {
19456            o->write_character('0');
19457            return;
19458        }
19459
19460        // use a pointer to fill the buffer
19461        auto buffer_ptr = number_buffer.begin(); // NOLINT(llvm-qualified-auto,readability-qualified-auto,cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19462
19463        number_unsigned_t abs_value;
19464
19465        unsigned int n_chars{};
19466
19467        if (is_negative_number(x))
19468        {
19469            *buffer_ptr = '-';
19470            abs_value = remove_sign(static_cast<number_integer_t>(x));
19471
19472            // account one more byte for the minus sign
19473            n_chars = 1 + count_digits(abs_value);
19474        }
19475        else
19476        {
19477            abs_value = static_cast<number_unsigned_t>(x);
19478            n_chars = count_digits(abs_value);
19479        }
19480
19481        // spare 1 byte for '\0'
19482        JSON_ASSERT(n_chars < number_buffer.size() - 1);
19483
19484        // jump to the end to generate the string from backward,
19485        // so we later avoid reversing the result
19486        buffer_ptr += n_chars;
19487
19488        // Fast int2ascii implementation inspired by "Fastware" talk by Andrei Alexandrescu
19489        // See: https://www.youtube.com/watch?v=o4-CwDo2zpg
19490        while (abs_value >= 100)
19491        {
19492            const auto digits_index = static_cast<unsigned>((abs_value % 100));
19493            abs_value /= 100;
19494            *(--buffer_ptr) = digits_to_99[digits_index][1];
19495            *(--buffer_ptr) = digits_to_99[digits_index][0];
19496        }
19497
19498        if (abs_value >= 10)
19499        {
19500            const auto digits_index = static_cast<unsigned>(abs_value);
19501            *(--buffer_ptr) = digits_to_99[digits_index][1];
19502            *(--buffer_ptr) = digits_to_99[digits_index][0];
19503        }
19504        else
19505        {
19506            *(--buffer_ptr) = static_cast<char>('0' + abs_value);
19507        }
19508
19509        o->write_characters(number_buffer.data(), n_chars);
19510    }
19511
19512    /*!
19513    @brief dump a floating-point number
19514
19515    Dump a given floating-point number to output stream @a o. Works internally
19516    with @a number_buffer.
19517
19518    @param[in] x  floating-point number to dump
19519    */
19520    void dump_float(number_float_t x)
19521    {
19522        // NaN / inf
19523        if (!std::isfinite(x))
19524        {
19525            o->write_characters("null", 4);
19526            return;
19527        }
19528
19529        // If number_float_t is an IEEE-754 single or double precision number,
19530        // use the Grisu2 algorithm to produce short numbers which are
19531        // guaranteed to round-trip, using strtof and strtod, resp.
19532        //
19533        // NB: The test below works if <long double> == <double>.
19534        static constexpr bool is_ieee_single_or_double
19535            = (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) ||
19536              (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);
19537
19538        dump_float(x, std::integral_constant<bool, is_ieee_single_or_double>());
19539    }
19540
19541    void dump_float(number_float_t x, std::true_type /*is_ieee_single_or_double*/)
19542    {
19543        auto* begin = number_buffer.data();
19544        auto* end = ::nlohmann::detail::to_chars(begin, begin + number_buffer.size(), x);
19545
19546        o->write_characters(begin, static_cast<size_t>(end - begin));
19547    }
19548
19549    void dump_float(number_float_t x, std::false_type /*is_ieee_single_or_double*/)
19550    {
19551        // get number of digits for a float -> text -> float round-trip
19552        static constexpr auto d = std::numeric_limits<number_float_t>::max_digits10;
19553
19554        // the actual conversion
19555        // NOLINTNEXTLINE(cppcoreguidelines-pro-type-vararg,hicpp-vararg)
19556        std::ptrdiff_t len = (std::snprintf)(number_buffer.data(), number_buffer.size(), "%.*g", d, x);
19557
19558        // negative value indicates an error
19559        JSON_ASSERT(len > 0);
19560        // check if buffer was large enough
19561        JSON_ASSERT(static_cast<std::size_t>(len) < number_buffer.size());
19562
19563        // erase thousands separator
19564        if (thousands_sep != '\0')
19565        {
19566            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::remove returns an iterator, see https://github.com/nlohmann/json/issues/3081
19567            const auto end = std::remove(number_buffer.begin(), number_buffer.begin() + len, thousands_sep);
19568            std::fill(end, number_buffer.end(), '\0');
19569            JSON_ASSERT((end - number_buffer.begin()) <= len);
19570            len = (end - number_buffer.begin());
19571        }
19572
19573        // convert decimal point to '.'
19574        if (decimal_point != '\0' && decimal_point != '.')
19575        {
19576            // NOLINTNEXTLINE(readability-qualified-auto,llvm-qualified-auto): std::find returns an iterator, see https://github.com/nlohmann/json/issues/3081
19577            const auto dec_pos = std::find(number_buffer.begin(), number_buffer.end(), decimal_point);
19578            if (dec_pos != number_buffer.end())
19579            {
19580                *dec_pos = '.';
19581            }
19582        }
19583
19584        o->write_characters(number_buffer.data(), static_cast<std::size_t>(len));
19585
19586        // determine if we need to append ".0"
19587        const bool value_is_int_like =
19588            std::none_of(number_buffer.begin(), number_buffer.begin() + len + 1,
19589                         [](char c)
19590        {
19591            return c == '.' || c == 'e';
19592        });
19593
19594        if (value_is_int_like)
19595        {
19596            o->write_characters(".0", 2);
19597        }
19598    }
19599
19600    /*!
19601    @brief check whether a string is UTF-8 encoded
19602
19603    The function checks each byte of a string whether it is UTF-8 encoded. The
19604    result of the check is stored in the @a state parameter. The function must
19605    be called initially with state 0 (accept). State 1 means the string must
19606    be rejected, because the current byte is not allowed. If the string is
19607    completely processed, but the state is non-zero, the string ended
19608    prematurely; that is, the last byte indicated more bytes should have
19609    followed.
19610
19611    @param[in,out] state  the state of the decoding
19612    @param[in,out] codep  codepoint (valid only if resulting state is UTF8_ACCEPT)
19613    @param[in] byte       next byte to decode
19614    @return               new state
19615
19616    @note The function has been edited: a std::array is used.
19617
19618    @copyright Copyright (c) 2008-2009 Bjoern Hoehrmann <bjoern@hoehrmann.de>
19619    @sa http://bjoern.hoehrmann.de/utf-8/decoder/dfa/
19620    */
19621    static std::uint8_t decode(std::uint8_t& state, std::uint32_t& codep, const std::uint8_t byte) noexcept
19622    {
19623        static const std::array<std::uint8_t, 400> utf8d =
19624        {
19625            {
19626                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
19627                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
19628                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
19629                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
19630                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
19631                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
19632                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
19633                0xA, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x3, 0x4, 0x3, 0x3, // E0..EF
19634                0xB, 0x6, 0x6, 0x6, 0x5, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, 0x8, // F0..FF
19635                0x0, 0x1, 0x2, 0x3, 0x5, 0x8, 0x7, 0x1, 0x1, 0x1, 0x4, 0x6, 0x1, 0x1, 0x1, 0x1, // s0..s0
19636                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
19637                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
19638                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
19639                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
19640            }
19641        };
19642
19643        JSON_ASSERT(byte < utf8d.size());
19644        const std::uint8_t type = utf8d[byte];
19645
19646        codep = (state != UTF8_ACCEPT)
19647                ? (byte & 0x3fu) | (codep << 6u)
19648                : (0xFFu >> type) & (byte);
19649
19650        const std::size_t index = 256u + (static_cast<size_t>(state) * 16u) + static_cast<size_t>(type);
19651        JSON_ASSERT(index < utf8d.size());
19652        state = utf8d[index];
19653        return state;
19654    }
19655
19656    /*
19657     * Overload to make the compiler happy while it is instantiating
19658     * dump_integer for number_unsigned_t.
19659     * Must never be called.
19660     */
19661    number_unsigned_t remove_sign(number_unsigned_t x)
19662    {
19663        JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
19664        return x; // LCOV_EXCL_LINE
19665    }
19666
19667    /*
19668     * Helper function for dump_integer
19669     *
19670     * This function takes a negative signed integer and returns its absolute
19671     * value as unsigned integer. The plus/minus shuffling is necessary as we can
19672     * not directly remove the sign of an arbitrary signed integer as the
19673     * absolute values of INT_MIN and INT_MAX are usually not the same. See
19674     * #1708 for details.
19675     */
19676    number_unsigned_t remove_sign(number_integer_t x) noexcept
19677    {
19678        JSON_ASSERT(x < 0 && x < (std::numeric_limits<number_integer_t>::max)()); // NOLINT(misc-redundant-expression)
19679        return static_cast<number_unsigned_t>(-(x + 1)) + 1;
19680    }
19681
19682  private:
19683    /// the output of the serializer
19684    output_adapter_t<char> o = nullptr;
19685
19686    /// a (hopefully) large enough character buffer
19687    std::array<char, 64> number_buffer{{}};
19688
19689    /// the locale
19690    const std::lconv* loc = nullptr;
19691    /// the locale's thousand separator character
19692    const char thousands_sep = '\0';
19693    /// the locale's decimal point character
19694    const char decimal_point = '\0';
19695
19696    /// string buffer
19697    std::array<char, 512> string_buffer{{}};
19698
19699    /// the indentation character
19700    const char indent_char;
19701    /// the indentation string
19702    string_t indent_string;
19703
19704    /// error_handler how to react on decoding errors
19705    const error_handler_t error_handler;
19706};
19707
19708}  // namespace detail
19709NLOHMANN_JSON_NAMESPACE_END
19710
19711// #include <nlohmann/detail/value_t.hpp>
19712
19713// #include <nlohmann/json_fwd.hpp>
19714
19715// #include <nlohmann/ordered_map.hpp>
19716//     __ _____ _____ _____
19717//  __|  |   __|     |   | |  JSON for Modern C++
19718// |  |  |__   |  |  | | | |  version 3.12.0
19719// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
19720//
19721// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
19722// SPDX-License-Identifier: MIT
19723
19724
19725
19726#include <functional> // equal_to, less
19727#include <initializer_list> // initializer_list
19728#include <iterator> // input_iterator_tag, iterator_traits
19729#include <memory> // allocator
19730#include <stdexcept> // for out_of_range
19731#include <type_traits> // enable_if, is_convertible
19732#include <utility> // pair
19733#include <vector> // vector
19734
19735// #include <nlohmann/detail/macro_scope.hpp>
19736
19737// #include <nlohmann/detail/meta/type_traits.hpp>
19738
19739
19740NLOHMANN_JSON_NAMESPACE_BEGIN
19741
19742/// ordered_map: a minimal map-like container that preserves insertion order
19743/// for use within nlohmann::basic_json<ordered_map>
19744template <class Key, class T, class IgnoredLess = std::less<Key>,
19745          class Allocator = std::allocator<std::pair<const Key, T>>>
19746              struct ordered_map : std::vector<std::pair<const Key, T>, Allocator>
19747{
19748    using key_type = Key;
19749    using mapped_type = T;
19750    using Container = std::vector<std::pair<const Key, T>, Allocator>;
19751    using iterator = typename Container::iterator;
19752    using const_iterator = typename Container::const_iterator;
19753    using size_type = typename Container::size_type;
19754    using value_type = typename Container::value_type;
19755#ifdef JSON_HAS_CPP_14
19756    using key_compare = std::equal_to<>;
19757#else
19758    using key_compare = std::equal_to<Key>;
19759#endif
19760
19761    // Explicit constructors instead of `using Container::Container`
19762    // otherwise older compilers choke on it (GCC <= 5.5, xcode <= 9.4)
19763    ordered_map() noexcept(noexcept(Container())) : Container{} {}
19764    explicit ordered_map(const Allocator& alloc) noexcept(noexcept(Container(alloc))) : Container{alloc} {}
19765    template <class It>
19766    ordered_map(It first, It last, const Allocator& alloc = Allocator())
19767        : Container{first, last, alloc} {}
19768    ordered_map(std::initializer_list<value_type> init, const Allocator& alloc = Allocator() )
19769        : Container{init, alloc} {}
19770
19771    std::pair<iterator, bool> emplace(const key_type& key, T&& t)
19772    {
19773        for (auto it = this->begin(); it != this->end(); ++it)
19774        {
19775            if (m_compare(it->first, key))
19776            {
19777                return {it, false};
19778            }
19779        }
19780        Container::emplace_back(key, std::forward<T>(t));
19781        return {std::prev(this->end()), true};
19782    }
19783
19784    template<class KeyType, detail::enable_if_t<
19785                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19786    std::pair<iterator, bool> emplace(KeyType && key, T && t)
19787    {
19788        for (auto it = this->begin(); it != this->end(); ++it)
19789        {
19790            if (m_compare(it->first, key))
19791            {
19792                return {it, false};
19793            }
19794        }
19795        Container::emplace_back(std::forward<KeyType>(key), std::forward<T>(t));
19796        return {std::prev(this->end()), true};
19797    }
19798
19799    T& operator[](const key_type& key)
19800    {
19801        return emplace(key, T{}).first->second;
19802    }
19803
19804    template<class KeyType, detail::enable_if_t<
19805                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19806    T & operator[](KeyType && key)
19807    {
19808        return emplace(std::forward<KeyType>(key), T{}).first->second;
19809    }
19810
19811    const T& operator[](const key_type& key) const
19812    {
19813        return at(key);
19814    }
19815
19816    template<class KeyType, detail::enable_if_t<
19817                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19818    const T & operator[](KeyType && key) const
19819    {
19820        return at(std::forward<KeyType>(key));
19821    }
19822
19823    T& at(const key_type& key)
19824    {
19825        for (auto it = this->begin(); it != this->end(); ++it)
19826        {
19827            if (m_compare(it->first, key))
19828            {
19829                return it->second;
19830            }
19831        }
19832
19833        JSON_THROW(std::out_of_range("key not found"));
19834    }
19835
19836    template<class KeyType, detail::enable_if_t<
19837                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19838    T & at(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19839    {
19840        for (auto it = this->begin(); it != this->end(); ++it)
19841        {
19842            if (m_compare(it->first, key))
19843            {
19844                return it->second;
19845            }
19846        }
19847
19848        JSON_THROW(std::out_of_range("key not found"));
19849    }
19850
19851    const T& at(const key_type& key) const
19852    {
19853        for (auto it = this->begin(); it != this->end(); ++it)
19854        {
19855            if (m_compare(it->first, key))
19856            {
19857                return it->second;
19858            }
19859        }
19860
19861        JSON_THROW(std::out_of_range("key not found"));
19862    }
19863
19864    template<class KeyType, detail::enable_if_t<
19865                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19866    const T & at(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19867    {
19868        for (auto it = this->begin(); it != this->end(); ++it)
19869        {
19870            if (m_compare(it->first, key))
19871            {
19872                return it->second;
19873            }
19874        }
19875
19876        JSON_THROW(std::out_of_range("key not found"));
19877    }
19878
19879    size_type erase(const key_type& key)
19880    {
19881        for (auto it = this->begin(); it != this->end(); ++it)
19882        {
19883            if (m_compare(it->first, key))
19884            {
19885                // Since we cannot move const Keys, re-construct them in place
19886                for (auto next = it; ++next != this->end(); ++it)
19887                {
19888                    it->~value_type(); // Destroy but keep allocation
19889                    new (&*it) value_type{std::move(*next)};
19890                }
19891                Container::pop_back();
19892                return 1;
19893            }
19894        }
19895        return 0;
19896    }
19897
19898    template<class KeyType, detail::enable_if_t<
19899                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19900    size_type erase(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
19901    {
19902        for (auto it = this->begin(); it != this->end(); ++it)
19903        {
19904            if (m_compare(it->first, key))
19905            {
19906                // Since we cannot move const Keys, re-construct them in place
19907                for (auto next = it; ++next != this->end(); ++it)
19908                {
19909                    it->~value_type(); // Destroy but keep allocation
19910                    new (&*it) value_type{std::move(*next)};
19911                }
19912                Container::pop_back();
19913                return 1;
19914            }
19915        }
19916        return 0;
19917    }
19918
19919    iterator erase(iterator pos)
19920    {
19921        return erase(pos, std::next(pos));
19922    }
19923
19924    iterator erase(iterator first, iterator last)
19925    {
19926        if (first == last)
19927        {
19928            return first;
19929        }
19930
19931        const auto elements_affected = std::distance(first, last);
19932        const auto offset = std::distance(Container::begin(), first);
19933
19934        // This is the start situation. We need to delete elements_affected
19935        // elements (3 in this example: e, f, g), and need to return an
19936        // iterator past the last deleted element (h in this example).
19937        // Note that offset is the distance from the start of the vector
19938        // to first. We will need this later.
19939
19940        // [ a, b, c, d, e, f, g, h, i, j ]
19941        //               ^        ^
19942        //             first    last
19943
19944        // Since we cannot move const Keys, we re-construct them in place.
19945        // We start at first and re-construct (viz. copy) the elements from
19946        // the back of the vector. Example for first iteration:
19947
19948        //               ,--------.
19949        //               v        |   destroy e and re-construct with h
19950        // [ a, b, c, d, e, f, g, h, i, j ]
19951        //               ^        ^
19952        //               it       it + elements_affected
19953
19954        for (auto it = first; std::next(it, elements_affected) != Container::end(); ++it)
19955        {
19956            it->~value_type(); // destroy but keep allocation
19957            new (&*it) value_type{std::move(*std::next(it, elements_affected))}; // "move" next element to it
19958        }
19959
19960        // [ a, b, c, d, h, i, j, h, i, j ]
19961        //               ^        ^
19962        //             first    last
19963
19964        // remove the unneeded elements at the end of the vector
19965        Container::resize(this->size() - static_cast<size_type>(elements_affected));
19966
19967        // [ a, b, c, d, h, i, j ]
19968        //               ^        ^
19969        //             first    last
19970
19971        // first is now pointing past the last deleted element, but we cannot
19972        // use this iterator, because it may have been invalidated by the
19973        // resize call. Instead, we can return begin() + offset.
19974        return Container::begin() + offset;
19975    }
19976
19977    size_type count(const key_type& key) const
19978    {
19979        for (auto it = this->begin(); it != this->end(); ++it)
19980        {
19981            if (m_compare(it->first, key))
19982            {
19983                return 1;
19984            }
19985        }
19986        return 0;
19987    }
19988
19989    template<class KeyType, detail::enable_if_t<
19990                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
19991    size_type count(KeyType && key) const // NOLINT(cppcoreguidelines-missing-std-forward)
19992    {
19993        for (auto it = this->begin(); it != this->end(); ++it)
19994        {
19995            if (m_compare(it->first, key))
19996            {
19997                return 1;
19998            }
19999        }
20000        return 0;
20001    }
20002
20003    iterator find(const key_type& key)
20004    {
20005        for (auto it = this->begin(); it != this->end(); ++it)
20006        {
20007            if (m_compare(it->first, key))
20008            {
20009                return it;
20010            }
20011        }
20012        return Container::end();
20013    }
20014
20015    template<class KeyType, detail::enable_if_t<
20016                 detail::is_usable_as_key_type<key_compare, key_type, KeyType>::value, int> = 0>
20017    iterator find(KeyType && key) // NOLINT(cppcoreguidelines-missing-std-forward)
20018    {
20019        for (auto it = this->begin(); it != this->end(); ++it)
20020        {
20021            if (m_compare(it->first, key))
20022            {
20023                return it;
20024            }
20025        }
20026        return Container::end();
20027    }
20028
20029    const_iterator find(const key_type& key) const
20030    {
20031        for (auto it = this->begin(); it != this->end(); ++it)
20032        {
20033            if (m_compare(it->first, key))
20034            {
20035                return it;
20036            }
20037        }
20038        return Container::end();
20039    }
20040
20041    std::pair<iterator, bool> insert( value_type&& value )
20042    {
20043        return emplace(value.first, std::move(value.second));
20044    }
20045
20046    std::pair<iterator, bool> insert( const value_type& value )
20047    {
20048        for (auto it = this->begin(); it != this->end(); ++it)
20049        {
20050            if (m_compare(it->first, value.first))
20051            {
20052                return {it, false};
20053            }
20054        }
20055        Container::push_back(value);
20056        return {--this->end(), true};
20057    }
20058
20059    template<typename InputIt>
20060    using require_input_iter = typename std::enable_if<std::is_convertible<typename std::iterator_traits<InputIt>::iterator_category,
20061        std::input_iterator_tag>::value>::type;
20062
20063    template<typename InputIt, typename = require_input_iter<InputIt>>
20064    void insert(InputIt first, InputIt last)
20065    {
20066        for (auto it = first; it != last; ++it)
20067        {
20068            insert(*it);
20069        }
20070    }
20071
20072private:
20073    JSON_NO_UNIQUE_ADDRESS key_compare m_compare = key_compare();
20074};
20075
20076NLOHMANN_JSON_NAMESPACE_END
20077
20078
20079#if defined(JSON_HAS_CPP_17)
20080    #if JSON_HAS_STATIC_RTTI
20081        #include <any>
20082    #endif
20083    #include <string_view>
20084#endif
20085
20086/*!
20087@brief namespace for Niels Lohmann
20088@see https://github.com/nlohmann
20089@since version 1.0.0
20090*/
20091NLOHMANN_JSON_NAMESPACE_BEGIN
20092
20093/*!
20094@brief a class to store JSON values
20095
20096@internal
20097@invariant The member variables @a m_value and @a m_type have the following
20098relationship:
20099- If `m_type == value_t::object`, then `m_value.object != nullptr`.
20100- If `m_type == value_t::array`, then `m_value.array != nullptr`.
20101- If `m_type == value_t::string`, then `m_value.string != nullptr`.
20102The invariants are checked by member function assert_invariant().
20103
20104@note ObjectType trick from https://stackoverflow.com/a/9860911
20105@endinternal
20106
20107@since version 1.0.0
20108
20109@nosubgrouping
20110*/
20111NLOHMANN_BASIC_JSON_TPL_DECLARATION
20112class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
20113    : public ::nlohmann::detail::json_base_class<CustomBaseClass>
20114{
20115  private:
20116    template<detail::value_t> friend struct detail::external_constructor;
20117
20118    template<typename>
20119    friend class ::nlohmann::json_pointer;
20120    // can be restored when json_pointer backwards compatibility is removed
20121    // friend ::nlohmann::json_pointer<StringType>;
20122
20123    template<typename BasicJsonType, typename InputType>
20124    friend class ::nlohmann::detail::parser;
20125    friend ::nlohmann::detail::serializer<basic_json>;
20126    template<typename BasicJsonType>
20127    friend class ::nlohmann::detail::iter_impl;
20128    template<typename BasicJsonType, typename CharType>
20129    friend class ::nlohmann::detail::binary_writer;
20130    template<typename BasicJsonType, typename InputType, typename SAX>
20131    friend class ::nlohmann::detail::binary_reader;
20132    template<typename BasicJsonType, typename InputAdapterType>
20133    friend class ::nlohmann::detail::json_sax_dom_parser;
20134    template<typename BasicJsonType, typename InputAdapterType>
20135    friend class ::nlohmann::detail::json_sax_dom_callback_parser;
20136    friend class ::nlohmann::detail::exception;
20137
20138    /// workaround type for MSVC
20139    using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
20140    using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
20141
20142  JSON_PRIVATE_UNLESS_TESTED:
20143    // convenience aliases for types residing in namespace detail;
20144    using lexer = ::nlohmann::detail::lexer_base<basic_json>;
20145
20146    template<typename InputAdapterType>
20147    static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
20148        InputAdapterType adapter,
20149        detail::parser_callback_t<basic_json>cb = nullptr,
20150        const bool allow_exceptions = true,
20151        const bool ignore_comments = false
20152                                 )
20153    {
20154        return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
20155            std::move(cb), allow_exceptions, ignore_comments);
20156    }
20157
20158  private:
20159    using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
20160    template<typename BasicJsonType>
20161    using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
20162    template<typename BasicJsonType>
20163    using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
20164    template<typename Iterator>
20165    using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
20166    template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
20167
20168    template<typename CharType>
20169    using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
20170
20171    template<typename InputType>
20172    using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
20173    template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
20174
20175  JSON_PRIVATE_UNLESS_TESTED:
20176    using serializer = ::nlohmann::detail::serializer<basic_json>;
20177
20178  public:
20179    using value_t = detail::value_t;
20180    /// JSON Pointer, see @ref nlohmann::json_pointer
20181    using json_pointer = ::nlohmann::json_pointer<StringType>;
20182    template<typename T, typename SFINAE>
20183    using json_serializer = JSONSerializer<T, SFINAE>;
20184    /// how to treat decoding errors
20185    using error_handler_t = detail::error_handler_t;
20186    /// how to treat CBOR tags
20187    using cbor_tag_handler_t = detail::cbor_tag_handler_t;
20188    /// how to encode BJData
20189    using bjdata_version_t = detail::bjdata_version_t;
20190    /// helper type for initializer lists of basic_json values
20191    using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
20192
20193    using input_format_t = detail::input_format_t;
20194    /// SAX interface type, see @ref nlohmann::json_sax
20195    using json_sax_t = json_sax<basic_json>;
20196
20197    ////////////////
20198    // exceptions //
20199    ////////////////
20200
20201    /// @name exceptions
20202    /// Classes to implement user-defined exceptions.
20203    /// @{
20204
20205    using exception = detail::exception;
20206    using parse_error = detail::parse_error;
20207    using invalid_iterator = detail::invalid_iterator;
20208    using type_error = detail::type_error;
20209    using out_of_range = detail::out_of_range;
20210    using other_error = detail::other_error;
20211
20212    /// @}
20213
20214    /////////////////////
20215    // container types //
20216    /////////////////////
20217
20218    /// @name container types
20219    /// The canonic container types to use @ref basic_json like any other STL
20220    /// container.
20221    /// @{
20222
20223    /// the type of elements in a basic_json container
20224    using value_type = basic_json;
20225
20226    /// the type of an element reference
20227    using reference = value_type&;
20228    /// the type of an element const reference
20229    using const_reference = const value_type&;
20230
20231    /// a type to represent differences between iterators
20232    using difference_type = std::ptrdiff_t;
20233    /// a type to represent container sizes
20234    using size_type = std::size_t;
20235
20236    /// the allocator type
20237    using allocator_type = AllocatorType<basic_json>;
20238
20239    /// the type of an element pointer
20240    using pointer = typename std::allocator_traits<allocator_type>::pointer;
20241    /// the type of an element const pointer
20242    using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
20243
20244    /// an iterator for a basic_json container
20245    using iterator = iter_impl<basic_json>;
20246    /// a const iterator for a basic_json container
20247    using const_iterator = iter_impl<const basic_json>;
20248    /// a reverse iterator for a basic_json container
20249    using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
20250    /// a const reverse iterator for a basic_json container
20251    using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
20252
20253    /// @}
20254
20255    /// @brief returns the allocator associated with the container
20256    /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
20257    static allocator_type get_allocator()
20258    {
20259        return allocator_type();
20260    }
20261
20262    /// @brief returns version information on the library
20263    /// @sa https://json.nlohmann.me/api/basic_json/meta/
20264    JSON_HEDLEY_WARN_UNUSED_RESULT
20265    static basic_json meta()
20266    {
20267        basic_json result;
20268
20269        result["copyright"] = "(C) 2013-2025 Niels Lohmann";
20270        result["name"] = "JSON for Modern C++";
20271        result["url"] = "https://github.com/nlohmann/json";
20272        result["version"]["string"] =
20273            detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
20274                           std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
20275                           std::to_string(NLOHMANN_JSON_VERSION_PATCH));
20276        result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
20277        result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
20278        result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
20279
20280#ifdef _WIN32
20281        result["platform"] = "win32";
20282#elif defined __linux__
20283        result["platform"] = "linux";
20284#elif defined __APPLE__
20285        result["platform"] = "apple";
20286#elif defined __unix__
20287        result["platform"] = "unix";
20288#else
20289        result["platform"] = "unknown";
20290#endif
20291
20292#if defined(__ICC) || defined(__INTEL_COMPILER)
20293        result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
20294#elif defined(__clang__)
20295        result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
20296#elif defined(__GNUC__) || defined(__GNUG__)
20297        result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
20298                    std::to_string(__GNUC__), '.',
20299                    std::to_string(__GNUC_MINOR__), '.',
20300                    std::to_string(__GNUC_PATCHLEVEL__))
20301            }
20302        };
20303#elif defined(__HP_cc) || defined(__HP_aCC)
20304        result["compiler"] = "hp"
20305#elif defined(__IBMCPP__)
20306        result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
20307#elif defined(_MSC_VER)
20308        result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
20309#elif defined(__PGI)
20310        result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
20311#elif defined(__SUNPRO_CC)
20312        result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
20313#else
20314        result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
20315#endif
20316
20317#if defined(_MSVC_LANG)
20318        result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
20319#elif defined(__cplusplus)
20320        result["compiler"]["c++"] = std::to_string(__cplusplus);
20321#else
20322        result["compiler"]["c++"] = "unknown";
20323#endif
20324        return result;
20325    }
20326
20327    ///////////////////////////
20328    // JSON value data types //
20329    ///////////////////////////
20330
20331    /// @name JSON value data types
20332    /// The data types to store a JSON value. These types are derived from
20333    /// the template arguments passed to class @ref basic_json.
20334    /// @{
20335
20336    /// @brief default object key comparator type
20337    /// The actual object key comparator type (@ref object_comparator_t) may be
20338    /// different.
20339    /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
20340#if defined(JSON_HAS_CPP_14)
20341    // use of transparent comparator avoids unnecessary repeated construction of temporaries
20342    // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
20343    using default_object_comparator_t = std::less<>;
20344#else
20345    using default_object_comparator_t = std::less<StringType>;
20346#endif
20347
20348    /// @brief a type for an object
20349    /// @sa https://json.nlohmann.me/api/basic_json/object_t/
20350    using object_t = ObjectType<StringType,
20351          basic_json,
20352          default_object_comparator_t,
20353          AllocatorType<std::pair<const StringType,
20354          basic_json>>>;
20355
20356    /// @brief a type for an array
20357    /// @sa https://json.nlohmann.me/api/basic_json/array_t/
20358    using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
20359
20360    /// @brief a type for a string
20361    /// @sa https://json.nlohmann.me/api/basic_json/string_t/
20362    using string_t = StringType;
20363
20364    /// @brief a type for a boolean
20365    /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
20366    using boolean_t = BooleanType;
20367
20368    /// @brief a type for a number (integer)
20369    /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
20370    using number_integer_t = NumberIntegerType;
20371
20372    /// @brief a type for a number (unsigned)
20373    /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
20374    using number_unsigned_t = NumberUnsignedType;
20375
20376    /// @brief a type for a number (floating-point)
20377    /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
20378    using number_float_t = NumberFloatType;
20379
20380    /// @brief a type for a packed binary type
20381    /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
20382    using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
20383
20384    /// @brief object key comparator type
20385    /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
20386    using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
20387
20388    /// @}
20389
20390  private:
20391
20392    /// helper for exception-safe object creation
20393    template<typename T, typename... Args>
20394    JSON_HEDLEY_RETURNS_NON_NULL
20395    static T* create(Args&& ... args)
20396    {
20397        AllocatorType<T> alloc;
20398        using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
20399
20400        auto deleter = [&](T * obj)
20401        {
20402            AllocatorTraits::deallocate(alloc, obj, 1);
20403        };
20404        std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
20405        AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
20406        JSON_ASSERT(obj != nullptr);
20407        return obj.release();
20408    }
20409
20410    ////////////////////////
20411    // JSON value storage //
20412    ////////////////////////
20413
20414  JSON_PRIVATE_UNLESS_TESTED:
20415    /*!
20416    @brief a JSON value
20417
20418    The actual storage for a JSON value of the @ref basic_json class. This
20419    union combines the different storage types for the JSON value types
20420    defined in @ref value_t.
20421
20422    JSON type | value_t type    | used type
20423    --------- | --------------- | ------------------------
20424    object    | object          | pointer to @ref object_t
20425    array     | array           | pointer to @ref array_t
20426    string    | string          | pointer to @ref string_t
20427    boolean   | boolean         | @ref boolean_t
20428    number    | number_integer  | @ref number_integer_t
20429    number    | number_unsigned | @ref number_unsigned_t
20430    number    | number_float    | @ref number_float_t
20431    binary    | binary          | pointer to @ref binary_t
20432    null      | null            | *no value is stored*
20433
20434    @note Variable-length types (objects, arrays, and strings) are stored as
20435    pointers. The size of the union should not exceed 64 bits if the default
20436    value types are used.
20437
20438    @since version 1.0.0
20439    */
20440    union json_value
20441    {
20442        /// object (stored with pointer to save storage)
20443        object_t* object;
20444        /// array (stored with pointer to save storage)
20445        array_t* array;
20446        /// string (stored with pointer to save storage)
20447        string_t* string;
20448        /// binary (stored with pointer to save storage)
20449        binary_t* binary;
20450        /// boolean
20451        boolean_t boolean;
20452        /// number (integer)
20453        number_integer_t number_integer;
20454        /// number (unsigned integer)
20455        number_unsigned_t number_unsigned;
20456        /// number (floating-point)
20457        number_float_t number_float;
20458
20459        /// default constructor (for null values)
20460        json_value() = default;
20461        /// constructor for booleans
20462        json_value(boolean_t v) noexcept : boolean(v) {}
20463        /// constructor for numbers (integer)
20464        json_value(number_integer_t v) noexcept : number_integer(v) {}
20465        /// constructor for numbers (unsigned)
20466        json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
20467        /// constructor for numbers (floating-point)
20468        json_value(number_float_t v) noexcept : number_float(v) {}
20469        /// constructor for empty values of a given type
20470        json_value(value_t t)
20471        {
20472            switch (t)
20473            {
20474                case value_t::object:
20475                {
20476                    object = create<object_t>();
20477                    break;
20478                }
20479
20480                case value_t::array:
20481                {
20482                    array = create<array_t>();
20483                    break;
20484                }
20485
20486                case value_t::string:
20487                {
20488                    string = create<string_t>("");
20489                    break;
20490                }
20491
20492                case value_t::binary:
20493                {
20494                    binary = create<binary_t>();
20495                    break;
20496                }
20497
20498                case value_t::boolean:
20499                {
20500                    boolean = static_cast<boolean_t>(false);
20501                    break;
20502                }
20503
20504                case value_t::number_integer:
20505                {
20506                    number_integer = static_cast<number_integer_t>(0);
20507                    break;
20508                }
20509
20510                case value_t::number_unsigned:
20511                {
20512                    number_unsigned = static_cast<number_unsigned_t>(0);
20513                    break;
20514                }
20515
20516                case value_t::number_float:
20517                {
20518                    number_float = static_cast<number_float_t>(0.0);
20519                    break;
20520                }
20521
20522                case value_t::null:
20523                {
20524                    object = nullptr;  // silence warning, see #821
20525                    break;
20526                }
20527
20528                case value_t::discarded:
20529                default:
20530                {
20531                    object = nullptr;  // silence warning, see #821
20532                    if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
20533                    {
20534                        JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.12.0", nullptr)); // LCOV_EXCL_LINE
20535                    }
20536                    break;
20537                }
20538            }
20539        }
20540
20541        /// constructor for strings
20542        json_value(const string_t& value) : string(create<string_t>(value)) {}
20543
20544        /// constructor for rvalue strings
20545        json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
20546
20547        /// constructor for objects
20548        json_value(const object_t& value) : object(create<object_t>(value)) {}
20549
20550        /// constructor for rvalue objects
20551        json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
20552
20553        /// constructor for arrays
20554        json_value(const array_t& value) : array(create<array_t>(value)) {}
20555
20556        /// constructor for rvalue arrays
20557        json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
20558
20559        /// constructor for binary arrays
20560        json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
20561
20562        /// constructor for rvalue binary arrays
20563        json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
20564
20565        /// constructor for binary arrays (internal type)
20566        json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
20567
20568        /// constructor for rvalue binary arrays (internal type)
20569        json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
20570
20571        void destroy(value_t t)
20572        {
20573            if (
20574                (t == value_t::object && object == nullptr) ||
20575                (t == value_t::array && array == nullptr) ||
20576                (t == value_t::string && string == nullptr) ||
20577                (t == value_t::binary && binary == nullptr)
20578            )
20579            {
20580                //not initialized (e.g. due to exception in the ctor)
20581                return;
20582            }
20583            if (t == value_t::array || t == value_t::object)
20584            {
20585                // flatten the current json_value to a heap-allocated stack
20586                std::vector<basic_json> stack;
20587
20588                // move the top-level items to stack
20589                if (t == value_t::array)
20590                {
20591                    stack.reserve(array->size());
20592                    std::move(array->begin(), array->end(), std::back_inserter(stack));
20593                }
20594                else
20595                {
20596                    stack.reserve(object->size());
20597                    for (auto&& it : *object)
20598                    {
20599                        stack.push_back(std::move(it.second));
20600                    }
20601                }
20602
20603                while (!stack.empty())
20604                {
20605                    // move the last item to local variable to be processed
20606                    basic_json current_item(std::move(stack.back()));
20607                    stack.pop_back();
20608
20609                    // if current_item is array/object, move
20610                    // its children to the stack to be processed later
20611                    if (current_item.is_array())
20612                    {
20613                        std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
20614
20615                        current_item.m_data.m_value.array->clear();
20616                    }
20617                    else if (current_item.is_object())
20618                    {
20619                        for (auto&& it : *current_item.m_data.m_value.object)
20620                        {
20621                            stack.push_back(std::move(it.second));
20622                        }
20623
20624                        current_item.m_data.m_value.object->clear();
20625                    }
20626
20627                    // it's now safe that current_item get destructed
20628                    // since it doesn't have any children
20629                }
20630            }
20631
20632            switch (t)
20633            {
20634                case value_t::object:
20635                {
20636                    AllocatorType<object_t> alloc;
20637                    std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
20638                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
20639                    break;
20640                }
20641
20642                case value_t::array:
20643                {
20644                    AllocatorType<array_t> alloc;
20645                    std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
20646                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
20647                    break;
20648                }
20649
20650                case value_t::string:
20651                {
20652                    AllocatorType<string_t> alloc;
20653                    std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
20654                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
20655                    break;
20656                }
20657
20658                case value_t::binary:
20659                {
20660                    AllocatorType<binary_t> alloc;
20661                    std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
20662                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
20663                    break;
20664                }
20665
20666                case value_t::null:
20667                case value_t::boolean:
20668                case value_t::number_integer:
20669                case value_t::number_unsigned:
20670                case value_t::number_float:
20671                case value_t::discarded:
20672                default:
20673                {
20674                    break;
20675                }
20676            }
20677        }
20678    };
20679
20680  private:
20681    /*!
20682    @brief checks the class invariants
20683
20684    This function asserts the class invariants. It needs to be called at the
20685    end of every constructor to make sure that created objects respect the
20686    invariant. Furthermore, it has to be called each time the type of a JSON
20687    value is changed, because the invariant expresses a relationship between
20688    @a m_type and @a m_value.
20689
20690    Furthermore, the parent relation is checked for arrays and objects: If
20691    @a check_parents true and the value is an array or object, then the
20692    container's elements must have the current value as parent.
20693
20694    @param[in] check_parents  whether the parent relation should be checked.
20695               The value is true by default and should only be set to false
20696               during destruction of objects when the invariant does not
20697               need to hold.
20698    */
20699    void assert_invariant(bool check_parents = true) const noexcept
20700    {
20701        JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
20702        JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
20703        JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
20704        JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
20705
20706#if JSON_DIAGNOSTICS
20707        JSON_TRY
20708        {
20709            // cppcheck-suppress assertWithSideEffect
20710            JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
20711            {
20712                return j.m_parent == this;
20713            }));
20714        }
20715        JSON_CATCH(...) {} // LCOV_EXCL_LINE
20716#endif
20717        static_cast<void>(check_parents);
20718    }
20719
20720    void set_parents()
20721    {
20722#if JSON_DIAGNOSTICS
20723        switch (m_data.m_type)
20724        {
20725            case value_t::array:
20726            {
20727                for (auto& element : *m_data.m_value.array)
20728                {
20729                    element.m_parent = this;
20730                }
20731                break;
20732            }
20733
20734            case value_t::object:
20735            {
20736                for (auto& element : *m_data.m_value.object)
20737                {
20738                    element.second.m_parent = this;
20739                }
20740                break;
20741            }
20742
20743            case value_t::null:
20744            case value_t::string:
20745            case value_t::boolean:
20746            case value_t::number_integer:
20747            case value_t::number_unsigned:
20748            case value_t::number_float:
20749            case value_t::binary:
20750            case value_t::discarded:
20751            default:
20752                break;
20753        }
20754#endif
20755    }
20756
20757    iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
20758    {
20759#if JSON_DIAGNOSTICS
20760        for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
20761        {
20762            (it + i)->m_parent = this;
20763        }
20764#else
20765        static_cast<void>(count_set_parents);
20766#endif
20767        return it;
20768    }
20769
20770    reference set_parent(reference j, std::size_t old_capacity = detail::unknown_size())
20771    {
20772#if JSON_DIAGNOSTICS
20773        if (old_capacity != detail::unknown_size())
20774        {
20775            // see https://github.com/nlohmann/json/issues/2838
20776            JSON_ASSERT(type() == value_t::array);
20777            if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
20778            {
20779                // capacity has changed: update all parents
20780                set_parents();
20781                return j;
20782            }
20783        }
20784
20785        // ordered_json uses a vector internally, so pointers could have
20786        // been invalidated; see https://github.com/nlohmann/json/issues/2962
20787#ifdef JSON_HEDLEY_MSVC_VERSION
20788#pragma warning(push )
20789#pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
20790#endif
20791        if (detail::is_ordered_map<object_t>::value)
20792        {
20793            set_parents();
20794            return j;
20795        }
20796#ifdef JSON_HEDLEY_MSVC_VERSION
20797#pragma warning( pop )
20798#endif
20799
20800        j.m_parent = this;
20801#else
20802        static_cast<void>(j);
20803        static_cast<void>(old_capacity);
20804#endif
20805        return j;
20806    }
20807
20808  public:
20809    //////////////////////////
20810    // JSON parser callback //
20811    //////////////////////////
20812
20813    /// @brief parser event types
20814    /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
20815    using parse_event_t = detail::parse_event_t;
20816
20817    /// @brief per-element parser callback type
20818    /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
20819    using parser_callback_t = detail::parser_callback_t<basic_json>;
20820
20821    //////////////////
20822    // constructors //
20823    //////////////////
20824
20825    /// @name constructors and destructors
20826    /// Constructors of class @ref basic_json, copy/move constructor, copy
20827    /// assignment, static functions creating objects, and the destructor.
20828    /// @{
20829
20830    /// @brief create an empty value with a given type
20831    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20832    basic_json(const value_t v)
20833        : m_data(v)
20834    {
20835        assert_invariant();
20836    }
20837
20838    /// @brief create a null object
20839    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20840    basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
20841        : basic_json(value_t::null)
20842    {
20843        assert_invariant();
20844    }
20845
20846    /// @brief create a JSON value from compatible types
20847    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20848    template < typename CompatibleType,
20849               typename U = detail::uncvref_t<CompatibleType>,
20850               detail::enable_if_t <
20851                   !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
20852    basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
20853            JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
20854                                       std::forward<CompatibleType>(val))))
20855    {
20856        JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
20857        set_parents();
20858        assert_invariant();
20859    }
20860
20861    /// @brief create a JSON value from an existing one
20862    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20863    template < typename BasicJsonType,
20864               detail::enable_if_t <
20865                   detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
20866    basic_json(const BasicJsonType& val)
20867#if JSON_DIAGNOSTIC_POSITIONS
20868        : start_position(val.start_pos()),
20869          end_position(val.end_pos())
20870#endif
20871    {
20872        using other_boolean_t = typename BasicJsonType::boolean_t;
20873        using other_number_float_t = typename BasicJsonType::number_float_t;
20874        using other_number_integer_t = typename BasicJsonType::number_integer_t;
20875        using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
20876        using other_string_t = typename BasicJsonType::string_t;
20877        using other_object_t = typename BasicJsonType::object_t;
20878        using other_array_t = typename BasicJsonType::array_t;
20879        using other_binary_t = typename BasicJsonType::binary_t;
20880
20881        switch (val.type())
20882        {
20883            case value_t::boolean:
20884                JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
20885                break;
20886            case value_t::number_float:
20887                JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
20888                break;
20889            case value_t::number_integer:
20890                JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
20891                break;
20892            case value_t::number_unsigned:
20893                JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
20894                break;
20895            case value_t::string:
20896                JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
20897                break;
20898            case value_t::object:
20899                JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
20900                break;
20901            case value_t::array:
20902                JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
20903                break;
20904            case value_t::binary:
20905                JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
20906                break;
20907            case value_t::null:
20908                *this = nullptr;
20909                break;
20910            case value_t::discarded:
20911                m_data.m_type = value_t::discarded;
20912                break;
20913            default:            // LCOV_EXCL_LINE
20914                JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
20915        }
20916        JSON_ASSERT(m_data.m_type == val.type());
20917
20918        set_parents();
20919        assert_invariant();
20920    }
20921
20922    /// @brief create a container (array or object) from an initializer list
20923    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
20924    basic_json(initializer_list_t init,
20925               bool type_deduction = true,
20926               value_t manual_type = value_t::array)
20927    {
20928        // check if each element is an array with two elements whose first
20929        // element is a string
20930        bool is_an_object = std::all_of(init.begin(), init.end(),
20931                                        [](const detail::json_ref<basic_json>& element_ref)
20932        {
20933            // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
20934            // (many string types can be constructed from 0 via its null-pointer guise, so we get a
20935            // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
20936            return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
20937        });
20938
20939        // adjust type if type deduction is not wanted
20940        if (!type_deduction)
20941        {
20942            // if array is wanted, do not create an object though possible
20943            if (manual_type == value_t::array)
20944            {
20945                is_an_object = false;
20946            }
20947
20948            // if object is wanted but impossible, throw an exception
20949            if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
20950            {
20951                JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
20952            }
20953        }
20954
20955        if (is_an_object)
20956        {
20957            // the initializer list is a list of pairs -> create object
20958            m_data.m_type = value_t::object;
20959            m_data.m_value = value_t::object;
20960
20961            for (auto& element_ref : init)
20962            {
20963                auto element = element_ref.moved_or_copied();
20964                m_data.m_value.object->emplace(
20965                    std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
20966                    std::move((*element.m_data.m_value.array)[1]));
20967            }
20968        }
20969        else
20970        {
20971            // the initializer list describes an array -> create array
20972            m_data.m_type = value_t::array;
20973            m_data.m_value.array = create<array_t>(init.begin(), init.end());
20974        }
20975
20976        set_parents();
20977        assert_invariant();
20978    }
20979
20980    /// @brief explicitly create a binary array (without subtype)
20981    /// @sa https://json.nlohmann.me/api/basic_json/binary/
20982    JSON_HEDLEY_WARN_UNUSED_RESULT
20983    static basic_json binary(const typename binary_t::container_type& init)
20984    {
20985        auto res = basic_json();
20986        res.m_data.m_type = value_t::binary;
20987        res.m_data.m_value = init;
20988        return res;
20989    }
20990
20991    /// @brief explicitly create a binary array (with subtype)
20992    /// @sa https://json.nlohmann.me/api/basic_json/binary/
20993    JSON_HEDLEY_WARN_UNUSED_RESULT
20994    static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
20995    {
20996        auto res = basic_json();
20997        res.m_data.m_type = value_t::binary;
20998        res.m_data.m_value = binary_t(init, subtype);
20999        return res;
21000    }
21001
21002    /// @brief explicitly create a binary array
21003    /// @sa https://json.nlohmann.me/api/basic_json/binary/
21004    JSON_HEDLEY_WARN_UNUSED_RESULT
21005    static basic_json binary(typename binary_t::container_type&& init)
21006    {
21007        auto res = basic_json();
21008        res.m_data.m_type = value_t::binary;
21009        res.m_data.m_value = std::move(init);
21010        return res;
21011    }
21012
21013    /// @brief explicitly create a binary array (with subtype)
21014    /// @sa https://json.nlohmann.me/api/basic_json/binary/
21015    JSON_HEDLEY_WARN_UNUSED_RESULT
21016    static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
21017    {
21018        auto res = basic_json();
21019        res.m_data.m_type = value_t::binary;
21020        res.m_data.m_value = binary_t(std::move(init), subtype);
21021        return res;
21022    }
21023
21024    /// @brief explicitly create an array from an initializer list
21025    /// @sa https://json.nlohmann.me/api/basic_json/array/
21026    JSON_HEDLEY_WARN_UNUSED_RESULT
21027    static basic_json array(initializer_list_t init = {})
21028    {
21029        return basic_json(init, false, value_t::array);
21030    }
21031
21032    /// @brief explicitly create an object from an initializer list
21033    /// @sa https://json.nlohmann.me/api/basic_json/object/
21034    JSON_HEDLEY_WARN_UNUSED_RESULT
21035    static basic_json object(initializer_list_t init = {})
21036    {
21037        return basic_json(init, false, value_t::object);
21038    }
21039
21040    /// @brief construct an array with count copies of given value
21041    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21042    basic_json(size_type cnt, const basic_json& val):
21043        m_data{cnt, val}
21044    {
21045        set_parents();
21046        assert_invariant();
21047    }
21048
21049    /// @brief construct a JSON container given an iterator range
21050    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21051    template < class InputIT, typename std::enable_if <
21052                   std::is_same<InputIT, typename basic_json_t::iterator>::value ||
21053                   std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
21054    basic_json(InputIT first, InputIT last) // NOLINT(performance-unnecessary-value-param)
21055    {
21056        JSON_ASSERT(first.m_object != nullptr);
21057        JSON_ASSERT(last.m_object != nullptr);
21058
21059        // make sure iterator fits the current value
21060        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
21061        {
21062            JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
21063        }
21064
21065        // copy type from first iterator
21066        m_data.m_type = first.m_object->m_data.m_type;
21067
21068        // check if iterator range is complete for primitive values
21069        switch (m_data.m_type)
21070        {
21071            case value_t::boolean:
21072            case value_t::number_float:
21073            case value_t::number_integer:
21074            case value_t::number_unsigned:
21075            case value_t::string:
21076            {
21077                if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
21078                                         || !last.m_it.primitive_iterator.is_end()))
21079                {
21080                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
21081                }
21082                break;
21083            }
21084
21085            case value_t::null:
21086            case value_t::object:
21087            case value_t::array:
21088            case value_t::binary:
21089            case value_t::discarded:
21090            default:
21091                break;
21092        }
21093
21094        switch (m_data.m_type)
21095        {
21096            case value_t::number_integer:
21097            {
21098                m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
21099                break;
21100            }
21101
21102            case value_t::number_unsigned:
21103            {
21104                m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
21105                break;
21106            }
21107
21108            case value_t::number_float:
21109            {
21110                m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
21111                break;
21112            }
21113
21114            case value_t::boolean:
21115            {
21116                m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
21117                break;
21118            }
21119
21120            case value_t::string:
21121            {
21122                m_data.m_value = *first.m_object->m_data.m_value.string;
21123                break;
21124            }
21125
21126            case value_t::object:
21127            {
21128                m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
21129                                        last.m_it.object_iterator);
21130                break;
21131            }
21132
21133            case value_t::array:
21134            {
21135                m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
21136                                                       last.m_it.array_iterator);
21137                break;
21138            }
21139
21140            case value_t::binary:
21141            {
21142                m_data.m_value = *first.m_object->m_data.m_value.binary;
21143                break;
21144            }
21145
21146            case value_t::null:
21147            case value_t::discarded:
21148            default:
21149                JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
21150        }
21151
21152        set_parents();
21153        assert_invariant();
21154    }
21155
21156    ///////////////////////////////////////
21157    // other constructors and destructor //
21158    ///////////////////////////////////////
21159
21160    template<typename JsonRef,
21161             detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
21162                                 std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
21163    basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
21164
21165    /// @brief copy constructor
21166    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21167    basic_json(const basic_json& other)
21168        : json_base_class_t(other)
21169#if JSON_DIAGNOSTIC_POSITIONS
21170        , start_position(other.start_position)
21171        , end_position(other.end_position)
21172#endif
21173    {
21174        m_data.m_type = other.m_data.m_type;
21175        // check of passed value is valid
21176        other.assert_invariant();
21177
21178        switch (m_data.m_type)
21179        {
21180            case value_t::object:
21181            {
21182                m_data.m_value = *other.m_data.m_value.object;
21183                break;
21184            }
21185
21186            case value_t::array:
21187            {
21188                m_data.m_value = *other.m_data.m_value.array;
21189                break;
21190            }
21191
21192            case value_t::string:
21193            {
21194                m_data.m_value = *other.m_data.m_value.string;
21195                break;
21196            }
21197
21198            case value_t::boolean:
21199            {
21200                m_data.m_value = other.m_data.m_value.boolean;
21201                break;
21202            }
21203
21204            case value_t::number_integer:
21205            {
21206                m_data.m_value = other.m_data.m_value.number_integer;
21207                break;
21208            }
21209
21210            case value_t::number_unsigned:
21211            {
21212                m_data.m_value = other.m_data.m_value.number_unsigned;
21213                break;
21214            }
21215
21216            case value_t::number_float:
21217            {
21218                m_data.m_value = other.m_data.m_value.number_float;
21219                break;
21220            }
21221
21222            case value_t::binary:
21223            {
21224                m_data.m_value = *other.m_data.m_value.binary;
21225                break;
21226            }
21227
21228            case value_t::null:
21229            case value_t::discarded:
21230            default:
21231                break;
21232        }
21233
21234        set_parents();
21235        assert_invariant();
21236    }
21237
21238    /// @brief move constructor
21239    /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
21240    basic_json(basic_json&& other) noexcept
21241        : json_base_class_t(std::forward<json_base_class_t>(other)),
21242          m_data(std::move(other.m_data)) // cppcheck-suppress[accessForwarded] TODO check
21243#if JSON_DIAGNOSTIC_POSITIONS
21244        , start_position(other.start_position) // cppcheck-suppress[accessForwarded] TODO check
21245        , end_position(other.end_position) // cppcheck-suppress[accessForwarded] TODO check
21246#endif
21247    {
21248        // check that passed value is valid
21249        other.assert_invariant(false); // cppcheck-suppress[accessForwarded]
21250
21251        // invalidate payload
21252        other.m_data.m_type = value_t::null;
21253        other.m_data.m_value = {};
21254
21255#if JSON_DIAGNOSTIC_POSITIONS
21256        other.start_position = std::string::npos;
21257        other.end_position = std::string::npos;
21258#endif
21259
21260        set_parents();
21261        assert_invariant();
21262    }
21263
21264    /// @brief copy assignment
21265    /// @sa https://json.nlohmann.me/api/basic_json/operator=/
21266    basic_json& operator=(basic_json other) noexcept (
21267        std::is_nothrow_move_constructible<value_t>::value&&
21268        std::is_nothrow_move_assignable<value_t>::value&&
21269        std::is_nothrow_move_constructible<json_value>::value&&
21270        std::is_nothrow_move_assignable<json_value>::value&&
21271        std::is_nothrow_move_assignable<json_base_class_t>::value
21272    )
21273    {
21274        // check that passed value is valid
21275        other.assert_invariant();
21276
21277        using std::swap;
21278        swap(m_data.m_type, other.m_data.m_type);
21279        swap(m_data.m_value, other.m_data.m_value);
21280
21281#if JSON_DIAGNOSTIC_POSITIONS
21282        swap(start_position, other.start_position);
21283        swap(end_position, other.end_position);
21284#endif
21285
21286        json_base_class_t::operator=(std::move(other));
21287
21288        set_parents();
21289        assert_invariant();
21290        return *this;
21291    }
21292
21293    /// @brief destructor
21294    /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
21295    ~basic_json() noexcept
21296    {
21297        assert_invariant(false);
21298    }
21299
21300    /// @}
21301
21302  public:
21303    ///////////////////////
21304    // object inspection //
21305    ///////////////////////
21306
21307    /// @name object inspection
21308    /// Functions to inspect the type of a JSON value.
21309    /// @{
21310
21311    /// @brief serialization
21312    /// @sa https://json.nlohmann.me/api/basic_json/dump/
21313    string_t dump(const int indent = -1,
21314                  const char indent_char = ' ',
21315                  const bool ensure_ascii = false,
21316                  const error_handler_t error_handler = error_handler_t::strict) const
21317    {
21318        string_t result;
21319        serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
21320
21321        if (indent >= 0)
21322        {
21323            s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
21324        }
21325        else
21326        {
21327            s.dump(*this, false, ensure_ascii, 0);
21328        }
21329
21330        return result;
21331    }
21332
21333    /// @brief return the type of the JSON value (explicit)
21334    /// @sa https://json.nlohmann.me/api/basic_json/type/
21335    constexpr value_t type() const noexcept
21336    {
21337        return m_data.m_type;
21338    }
21339
21340    /// @brief return whether type is primitive
21341    /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
21342    constexpr bool is_primitive() const noexcept
21343    {
21344        return is_null() || is_string() || is_boolean() || is_number() || is_binary();
21345    }
21346
21347    /// @brief return whether type is structured
21348    /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
21349    constexpr bool is_structured() const noexcept
21350    {
21351        return is_array() || is_object();
21352    }
21353
21354    /// @brief return whether value is null
21355    /// @sa https://json.nlohmann.me/api/basic_json/is_null/
21356    constexpr bool is_null() const noexcept
21357    {
21358        return m_data.m_type == value_t::null;
21359    }
21360
21361    /// @brief return whether value is a boolean
21362    /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
21363    constexpr bool is_boolean() const noexcept
21364    {
21365        return m_data.m_type == value_t::boolean;
21366    }
21367
21368    /// @brief return whether value is a number
21369    /// @sa https://json.nlohmann.me/api/basic_json/is_number/
21370    constexpr bool is_number() const noexcept
21371    {
21372        return is_number_integer() || is_number_float();
21373    }
21374
21375    /// @brief return whether value is an integer number
21376    /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
21377    constexpr bool is_number_integer() const noexcept
21378    {
21379        return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
21380    }
21381
21382    /// @brief return whether value is an unsigned integer number
21383    /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
21384    constexpr bool is_number_unsigned() const noexcept
21385    {
21386        return m_data.m_type == value_t::number_unsigned;
21387    }
21388
21389    /// @brief return whether value is a floating-point number
21390    /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
21391    constexpr bool is_number_float() const noexcept
21392    {
21393        return m_data.m_type == value_t::number_float;
21394    }
21395
21396    /// @brief return whether value is an object
21397    /// @sa https://json.nlohmann.me/api/basic_json/is_object/
21398    constexpr bool is_object() const noexcept
21399    {
21400        return m_data.m_type == value_t::object;
21401    }
21402
21403    /// @brief return whether value is an array
21404    /// @sa https://json.nlohmann.me/api/basic_json/is_array/
21405    constexpr bool is_array() const noexcept
21406    {
21407        return m_data.m_type == value_t::array;
21408    }
21409
21410    /// @brief return whether value is a string
21411    /// @sa https://json.nlohmann.me/api/basic_json/is_string/
21412    constexpr bool is_string() const noexcept
21413    {
21414        return m_data.m_type == value_t::string;
21415    }
21416
21417    /// @brief return whether value is a binary array
21418    /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
21419    constexpr bool is_binary() const noexcept
21420    {
21421        return m_data.m_type == value_t::binary;
21422    }
21423
21424    /// @brief return whether value is discarded
21425    /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
21426    constexpr bool is_discarded() const noexcept
21427    {
21428        return m_data.m_type == value_t::discarded;
21429    }
21430
21431    /// @brief return the type of the JSON value (implicit)
21432    /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
21433    constexpr operator value_t() const noexcept
21434    {
21435        return m_data.m_type;
21436    }
21437
21438    /// @}
21439
21440  private:
21441    //////////////////
21442    // value access //
21443    //////////////////
21444
21445    /// get a boolean (explicit)
21446    boolean_t get_impl(boolean_t* /*unused*/) const
21447    {
21448        if (JSON_HEDLEY_LIKELY(is_boolean()))
21449        {
21450            return m_data.m_value.boolean;
21451        }
21452
21453        JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
21454    }
21455
21456    /// get a pointer to the value (object)
21457    object_t* get_impl_ptr(object_t* /*unused*/) noexcept
21458    {
21459        return is_object() ? m_data.m_value.object : nullptr;
21460    }
21461
21462    /// get a pointer to the value (object)
21463    constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
21464    {
21465        return is_object() ? m_data.m_value.object : nullptr;
21466    }
21467
21468    /// get a pointer to the value (array)
21469    array_t* get_impl_ptr(array_t* /*unused*/) noexcept
21470    {
21471        return is_array() ? m_data.m_value.array : nullptr;
21472    }
21473
21474    /// get a pointer to the value (array)
21475    constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
21476    {
21477        return is_array() ? m_data.m_value.array : nullptr;
21478    }
21479
21480    /// get a pointer to the value (string)
21481    string_t* get_impl_ptr(string_t* /*unused*/) noexcept
21482    {
21483        return is_string() ? m_data.m_value.string : nullptr;
21484    }
21485
21486    /// get a pointer to the value (string)
21487    constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
21488    {
21489        return is_string() ? m_data.m_value.string : nullptr;
21490    }
21491
21492    /// get a pointer to the value (boolean)
21493    boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
21494    {
21495        return is_boolean() ? &m_data.m_value.boolean : nullptr;
21496    }
21497
21498    /// get a pointer to the value (boolean)
21499    constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
21500    {
21501        return is_boolean() ? &m_data.m_value.boolean : nullptr;
21502    }
21503
21504    /// get a pointer to the value (integer number)
21505    number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
21506    {
21507        return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21508    }
21509
21510    /// get a pointer to the value (integer number)
21511    constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
21512    {
21513        return m_data.m_type == value_t::number_integer ? &m_data.m_value.number_integer : nullptr;
21514    }
21515
21516    /// get a pointer to the value (unsigned number)
21517    number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
21518    {
21519        return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21520    }
21521
21522    /// get a pointer to the value (unsigned number)
21523    constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
21524    {
21525        return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
21526    }
21527
21528    /// get a pointer to the value (floating-point number)
21529    number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
21530    {
21531        return is_number_float() ? &m_data.m_value.number_float : nullptr;
21532    }
21533
21534    /// get a pointer to the value (floating-point number)
21535    constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
21536    {
21537        return is_number_float() ? &m_data.m_value.number_float : nullptr;
21538    }
21539
21540    /// get a pointer to the value (binary)
21541    binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
21542    {
21543        return is_binary() ? m_data.m_value.binary : nullptr;
21544    }
21545
21546    /// get a pointer to the value (binary)
21547    constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
21548    {
21549        return is_binary() ? m_data.m_value.binary : nullptr;
21550    }
21551
21552    /*!
21553    @brief helper function to implement get_ref()
21554
21555    This function helps to implement get_ref() without code duplication for
21556    const and non-const overloads
21557
21558    @tparam ThisType will be deduced as `basic_json` or `const basic_json`
21559
21560    @throw type_error.303 if ReferenceType does not match underlying value
21561    type of the current JSON
21562    */
21563    template<typename ReferenceType, typename ThisType>
21564    static ReferenceType get_ref_impl(ThisType& obj)
21565    {
21566        // delegate the call to get_ptr<>()
21567        auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
21568
21569        if (JSON_HEDLEY_LIKELY(ptr != nullptr))
21570        {
21571            return *ptr;
21572        }
21573
21574        JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
21575    }
21576
21577  public:
21578    /// @name value access
21579    /// Direct access to the stored value of a JSON value.
21580    /// @{
21581
21582    /// @brief get a pointer value (implicit)
21583    /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21584    template<typename PointerType, typename std::enable_if<
21585                 std::is_pointer<PointerType>::value, int>::type = 0>
21586    auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21587    {
21588        // delegate the call to get_impl_ptr<>()
21589        return get_impl_ptr(static_cast<PointerType>(nullptr));
21590    }
21591
21592    /// @brief get a pointer value (implicit)
21593    /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
21594    template < typename PointerType, typename std::enable_if <
21595                   std::is_pointer<PointerType>::value&&
21596                   std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
21597    constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
21598    {
21599        // delegate the call to get_impl_ptr<>() const
21600        return get_impl_ptr(static_cast<PointerType>(nullptr));
21601    }
21602
21603  private:
21604    /*!
21605    @brief get a value (explicit)
21606
21607    Explicit type conversion between the JSON value and a compatible value
21608    which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
21609    and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
21610    The value is converted by calling the @ref json_serializer<ValueType>
21611    `from_json()` method.
21612
21613    The function is equivalent to executing
21614    @code {.cpp}
21615    ValueType ret;
21616    JSONSerializer<ValueType>::from_json(*this, ret);
21617    return ret;
21618    @endcode
21619
21620    This overloads is chosen if:
21621    - @a ValueType is not @ref basic_json,
21622    - @ref json_serializer<ValueType> has a `from_json()` method of the form
21623      `void from_json(const basic_json&, ValueType&)`, and
21624    - @ref json_serializer<ValueType> does not have a `from_json()` method of
21625      the form `ValueType from_json(const basic_json&)`
21626
21627    @tparam ValueType the returned value type
21628
21629    @return copy of the JSON value, converted to @a ValueType
21630
21631    @throw what @ref json_serializer<ValueType> `from_json()` method throws
21632
21633    @liveexample{The example below shows several conversions from JSON values
21634    to other types. There a few things to note: (1) Floating-point numbers can
21635    be converted to integers\, (2) A JSON array can be converted to a standard
21636    `std::vector<short>`\, (3) A JSON object can be converted to C++
21637    associative containers such as `std::unordered_map<std::string\,
21638    json>`.,get__ValueType_const}
21639
21640    @since version 2.1.0
21641    */
21642    template < typename ValueType,
21643               detail::enable_if_t <
21644                   detail::is_default_constructible<ValueType>::value&&
21645                   detail::has_from_json<basic_json_t, ValueType>::value,
21646                   int > = 0 >
21647    ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
21648            JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
21649    {
21650        auto ret = ValueType();
21651        JSONSerializer<ValueType>::from_json(*this, ret);
21652        return ret;
21653    }
21654
21655    /*!
21656    @brief get a value (explicit); special case
21657
21658    Explicit type conversion between the JSON value and a compatible value
21659    which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
21660    and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
21661    The value is converted by calling the @ref json_serializer<ValueType>
21662    `from_json()` method.
21663
21664    The function is equivalent to executing
21665    @code {.cpp}
21666    return JSONSerializer<ValueType>::from_json(*this);
21667    @endcode
21668
21669    This overloads is chosen if:
21670    - @a ValueType is not @ref basic_json and
21671    - @ref json_serializer<ValueType> has a `from_json()` method of the form
21672      `ValueType from_json(const basic_json&)`
21673
21674    @note If @ref json_serializer<ValueType> has both overloads of
21675    `from_json()`, this one is chosen.
21676
21677    @tparam ValueType the returned value type
21678
21679    @return copy of the JSON value, converted to @a ValueType
21680
21681    @throw what @ref json_serializer<ValueType> `from_json()` method throws
21682
21683    @since version 2.1.0
21684    */
21685    template < typename ValueType,
21686               detail::enable_if_t <
21687                   detail::has_non_default_from_json<basic_json_t, ValueType>::value,
21688                   int > = 0 >
21689    ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
21690            JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
21691    {
21692        return JSONSerializer<ValueType>::from_json(*this);
21693    }
21694
21695    /*!
21696    @brief get special-case overload
21697
21698    This overloads converts the current @ref basic_json in a different
21699    @ref basic_json type
21700
21701    @tparam BasicJsonType == @ref basic_json
21702
21703    @return a copy of *this, converted into @a BasicJsonType
21704
21705    @complexity Depending on the implementation of the called `from_json()`
21706                method.
21707
21708    @since version 3.2.0
21709    */
21710    template < typename BasicJsonType,
21711               detail::enable_if_t <
21712                   detail::is_basic_json<BasicJsonType>::value,
21713                   int > = 0 >
21714    BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
21715    {
21716        return *this;
21717    }
21718
21719    /*!
21720    @brief get special-case overload
21721
21722    This overloads avoids a lot of template boilerplate, it can be seen as the
21723    identity method
21724
21725    @tparam BasicJsonType == @ref basic_json
21726
21727    @return a copy of *this
21728
21729    @complexity Constant.
21730
21731    @since version 2.1.0
21732    */
21733    template<typename BasicJsonType,
21734             detail::enable_if_t<
21735                 std::is_same<BasicJsonType, basic_json_t>::value,
21736                 int> = 0>
21737    basic_json get_impl(detail::priority_tag<3> /*unused*/) const
21738    {
21739        return *this;
21740    }
21741
21742    /*!
21743    @brief get a pointer value (explicit)
21744    @copydoc get()
21745    */
21746    template<typename PointerType,
21747             detail::enable_if_t<
21748                 std::is_pointer<PointerType>::value,
21749                 int> = 0>
21750    constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
21751    -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
21752    {
21753        // delegate the call to get_ptr
21754        return get_ptr<PointerType>();
21755    }
21756
21757  public:
21758    /*!
21759    @brief get a (pointer) value (explicit)
21760
21761    Performs explicit type conversion between the JSON value and a compatible value if required.
21762
21763    - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
21764    No copies are made.
21765
21766    - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
21767    from the current @ref basic_json.
21768
21769    - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
21770    method.
21771
21772    @tparam ValueTypeCV the provided value type
21773    @tparam ValueType the returned value type
21774
21775    @return copy of the JSON value, converted to @tparam ValueType if necessary
21776
21777    @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
21778
21779    @since version 2.1.0
21780    */
21781    template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
21782#if defined(JSON_HAS_CPP_14)
21783    constexpr
21784#endif
21785    auto get() const noexcept(
21786    noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
21787    -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
21788    {
21789        // we cannot static_assert on ValueTypeCV being non-const, because
21790        // there is support for get<const basic_json_t>(), which is why we
21791        // still need the uncvref
21792        static_assert(!std::is_reference<ValueTypeCV>::value,
21793                      "get() cannot be used with reference types, you might want to use get_ref()");
21794        return get_impl<ValueType>(detail::priority_tag<4> {});
21795    }
21796
21797    /*!
21798    @brief get a pointer value (explicit)
21799
21800    Explicit pointer access to the internally stored JSON value. No copies are
21801    made.
21802
21803    @warning The pointer becomes invalid if the underlying JSON object
21804    changes.
21805
21806    @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
21807    object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
21808    @ref number_unsigned_t, or @ref number_float_t.
21809
21810    @return pointer to the internally stored JSON value if the requested
21811    pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
21812
21813    @complexity Constant.
21814
21815    @liveexample{The example below shows how pointers to internal values of a
21816    JSON value can be requested. Note that no type conversions are made and a
21817    `nullptr` is returned if the value and the requested pointer type does not
21818    match.,get__PointerType}
21819
21820    @sa see @ref get_ptr() for explicit pointer-member access
21821
21822    @since version 1.0.0
21823    */
21824    template<typename PointerType, typename std::enable_if<
21825                 std::is_pointer<PointerType>::value, int>::type = 0>
21826    auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
21827    {
21828        // delegate the call to get_ptr
21829        return get_ptr<PointerType>();
21830    }
21831
21832    /// @brief get a value (explicit)
21833    /// @sa https://json.nlohmann.me/api/basic_json/get_to/
21834    template < typename ValueType,
21835               detail::enable_if_t <
21836                   !detail::is_basic_json<ValueType>::value&&
21837                   detail::has_from_json<basic_json_t, ValueType>::value,
21838                   int > = 0 >
21839    ValueType & get_to(ValueType& v) const noexcept(noexcept(
21840            JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
21841    {
21842        JSONSerializer<ValueType>::from_json(*this, v);
21843        return v;
21844    }
21845
21846    // specialization to allow calling get_to with a basic_json value
21847    // see https://github.com/nlohmann/json/issues/2175
21848    template<typename ValueType,
21849             detail::enable_if_t <
21850                 detail::is_basic_json<ValueType>::value,
21851                 int> = 0>
21852    ValueType & get_to(ValueType& v) const
21853    {
21854        v = *this;
21855        return v;
21856    }
21857
21858    template <
21859        typename T, std::size_t N,
21860        typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21861        detail::enable_if_t <
21862            detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
21863    Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
21864    noexcept(noexcept(JSONSerializer<Array>::from_json(
21865                          std::declval<const basic_json_t&>(), v)))
21866    {
21867        JSONSerializer<Array>::from_json(*this, v);
21868        return v;
21869    }
21870
21871    /// @brief get a reference value (implicit)
21872    /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21873    template<typename ReferenceType, typename std::enable_if<
21874                 std::is_reference<ReferenceType>::value, int>::type = 0>
21875    ReferenceType get_ref()
21876    {
21877        // delegate call to get_ref_impl
21878        return get_ref_impl<ReferenceType>(*this);
21879    }
21880
21881    /// @brief get a reference value (implicit)
21882    /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
21883    template < typename ReferenceType, typename std::enable_if <
21884                   std::is_reference<ReferenceType>::value&&
21885                   std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
21886    ReferenceType get_ref() const
21887    {
21888        // delegate call to get_ref_impl
21889        return get_ref_impl<ReferenceType>(*this);
21890    }
21891
21892    /*!
21893    @brief get a value (implicit)
21894
21895    Implicit type conversion between the JSON value and a compatible value.
21896    The call is realized by calling @ref get() const.
21897
21898    @tparam ValueType non-pointer type compatible to the JSON value, for
21899    instance `int` for JSON integer numbers, `bool` for JSON booleans, or
21900    `std::vector` types for JSON arrays. The character type of @ref string_t
21901    as well as an initializer list of this type is excluded to avoid
21902    ambiguities as these types implicitly convert to `std::string`.
21903
21904    @return copy of the JSON value, converted to type @a ValueType
21905
21906    @throw type_error.302 in case passed type @a ValueType is incompatible
21907    to the JSON value type (e.g., the JSON value is of type boolean, but a
21908    string is requested); see example below
21909
21910    @complexity Linear in the size of the JSON value.
21911
21912    @liveexample{The example below shows several conversions from JSON values
21913    to other types. There a few things to note: (1) Floating-point numbers can
21914    be converted to integers\, (2) A JSON array can be converted to a standard
21915    `std::vector<short>`\, (3) A JSON object can be converted to C++
21916    associative containers such as `std::unordered_map<std::string\,
21917    json>`.,operator__ValueType}
21918
21919    @since version 1.0.0
21920    */
21921    template < typename ValueType, typename std::enable_if <
21922                   detail::conjunction <
21923                       detail::negation<std::is_pointer<ValueType>>,
21924                       detail::negation<std::is_same<ValueType, std::nullptr_t>>,
21925                       detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
21926                                        detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
21927                                        detail::negation<detail::is_basic_json<ValueType>>,
21928                                        detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
21929#if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
21930                                                detail::negation<std::is_same<ValueType, std::string_view>>,
21931#endif
21932#if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
21933                                                detail::negation<std::is_same<ValueType, std::any>>,
21934#endif
21935                                                detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
21936                                                >::value, int >::type = 0 >
21937                                        JSON_EXPLICIT operator ValueType() const
21938    {
21939        // delegate the call to get<>() const
21940        return get<ValueType>();
21941    }
21942
21943    /// @brief get a binary value
21944    /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21945    binary_t& get_binary()
21946    {
21947        if (!is_binary())
21948        {
21949            JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21950        }
21951
21952        return *get_ptr<binary_t*>();
21953    }
21954
21955    /// @brief get a binary value
21956    /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
21957    const binary_t& get_binary() const
21958    {
21959        if (!is_binary())
21960        {
21961            JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
21962        }
21963
21964        return *get_ptr<const binary_t*>();
21965    }
21966
21967    /// @}
21968
21969    ////////////////////
21970    // element access //
21971    ////////////////////
21972
21973    /// @name element access
21974    /// Access to the JSON value.
21975    /// @{
21976
21977    /// @brief access specified array element with bounds checking
21978    /// @sa https://json.nlohmann.me/api/basic_json/at/
21979    reference at(size_type idx)
21980    {
21981        // at only works for arrays
21982        if (JSON_HEDLEY_LIKELY(is_array()))
21983        {
21984            JSON_TRY
21985            {
21986                return set_parent(m_data.m_value.array->at(idx));
21987            }
21988            JSON_CATCH (std::out_of_range&)
21989            {
21990                // create better exception explanation
21991                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
21992            } // cppcheck-suppress[missingReturn]
21993        }
21994        else
21995        {
21996            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
21997        }
21998    }
21999
22000    /// @brief access specified array element with bounds checking
22001    /// @sa https://json.nlohmann.me/api/basic_json/at/
22002    const_reference at(size_type idx) const
22003    {
22004        // at only works for arrays
22005        if (JSON_HEDLEY_LIKELY(is_array()))
22006        {
22007            JSON_TRY
22008            {
22009                return m_data.m_value.array->at(idx);
22010            }
22011            JSON_CATCH (std::out_of_range&)
22012            {
22013                // create better exception explanation
22014                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22015            } // cppcheck-suppress[missingReturn]
22016        }
22017        else
22018        {
22019            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22020        }
22021    }
22022
22023    /// @brief access specified object element with bounds checking
22024    /// @sa https://json.nlohmann.me/api/basic_json/at/
22025    reference at(const typename object_t::key_type& key)
22026    {
22027        // at only works for objects
22028        if (JSON_HEDLEY_UNLIKELY(!is_object()))
22029        {
22030            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22031        }
22032
22033        auto it = m_data.m_value.object->find(key);
22034        if (it == m_data.m_value.object->end())
22035        {
22036            JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22037        }
22038        return set_parent(it->second);
22039    }
22040
22041    /// @brief access specified object element with bounds checking
22042    /// @sa https://json.nlohmann.me/api/basic_json/at/
22043    template<class KeyType, detail::enable_if_t<
22044                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22045    reference at(KeyType && key)
22046    {
22047        // at only works for objects
22048        if (JSON_HEDLEY_UNLIKELY(!is_object()))
22049        {
22050            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22051        }
22052
22053        auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22054        if (it == m_data.m_value.object->end())
22055        {
22056            JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22057        }
22058        return set_parent(it->second);
22059    }
22060
22061    /// @brief access specified object element with bounds checking
22062    /// @sa https://json.nlohmann.me/api/basic_json/at/
22063    const_reference at(const typename object_t::key_type& key) const
22064    {
22065        // at only works for objects
22066        if (JSON_HEDLEY_UNLIKELY(!is_object()))
22067        {
22068            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22069        }
22070
22071        auto it = m_data.m_value.object->find(key);
22072        if (it == m_data.m_value.object->end())
22073        {
22074            JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
22075        }
22076        return it->second;
22077    }
22078
22079    /// @brief access specified object element with bounds checking
22080    /// @sa https://json.nlohmann.me/api/basic_json/at/
22081    template<class KeyType, detail::enable_if_t<
22082                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22083    const_reference at(KeyType && key) const
22084    {
22085        // at only works for objects
22086        if (JSON_HEDLEY_UNLIKELY(!is_object()))
22087        {
22088            JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
22089        }
22090
22091        auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22092        if (it == m_data.m_value.object->end())
22093        {
22094            JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
22095        }
22096        return it->second;
22097    }
22098
22099    /// @brief access specified array element
22100    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22101    reference operator[](size_type idx)
22102    {
22103        // implicitly convert null value to an empty array
22104        if (is_null())
22105        {
22106            m_data.m_type = value_t::array;
22107            m_data.m_value.array = create<array_t>();
22108            assert_invariant();
22109        }
22110
22111        // operator[] only works for arrays
22112        if (JSON_HEDLEY_LIKELY(is_array()))
22113        {
22114            // fill up array with null values if given idx is outside range
22115            if (idx >= m_data.m_value.array->size())
22116            {
22117#if JSON_DIAGNOSTICS
22118                // remember array size & capacity before resizing
22119                const auto old_size = m_data.m_value.array->size();
22120                const auto old_capacity = m_data.m_value.array->capacity();
22121#endif
22122                m_data.m_value.array->resize(idx + 1);
22123
22124#if JSON_DIAGNOSTICS
22125                if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
22126                {
22127                    // capacity has changed: update all parents
22128                    set_parents();
22129                }
22130                else
22131                {
22132                    // set parent for values added above
22133                    set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
22134                }
22135#endif
22136                assert_invariant();
22137            }
22138
22139            return m_data.m_value.array->operator[](idx);
22140        }
22141
22142        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22143    }
22144
22145    /// @brief access specified array element
22146    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22147    const_reference operator[](size_type idx) const
22148    {
22149        // const operator[] only works for arrays
22150        if (JSON_HEDLEY_LIKELY(is_array()))
22151        {
22152            return m_data.m_value.array->operator[](idx);
22153        }
22154
22155        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
22156    }
22157
22158    /// @brief access specified object element
22159    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22160    reference operator[](typename object_t::key_type key) // NOLINT(performance-unnecessary-value-param)
22161    {
22162        // implicitly convert null value to an empty object
22163        if (is_null())
22164        {
22165            m_data.m_type = value_t::object;
22166            m_data.m_value.object = create<object_t>();
22167            assert_invariant();
22168        }
22169
22170        // operator[] only works for objects
22171        if (JSON_HEDLEY_LIKELY(is_object()))
22172        {
22173            auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
22174            return set_parent(result.first->second);
22175        }
22176
22177        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22178    }
22179
22180    /// @brief access specified object element
22181    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22182    const_reference operator[](const typename object_t::key_type& key) const
22183    {
22184        // const operator[] only works for objects
22185        if (JSON_HEDLEY_LIKELY(is_object()))
22186        {
22187            auto it = m_data.m_value.object->find(key);
22188            JSON_ASSERT(it != m_data.m_value.object->end());
22189            return it->second;
22190        }
22191
22192        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22193    }
22194
22195    // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
22196    // (they seemingly cannot be constrained to resolve the ambiguity)
22197    template<typename T>
22198    reference operator[](T* key)
22199    {
22200        return operator[](typename object_t::key_type(key));
22201    }
22202
22203    template<typename T>
22204    const_reference operator[](T* key) const
22205    {
22206        return operator[](typename object_t::key_type(key));
22207    }
22208
22209    /// @brief access specified object element
22210    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22211    template<class KeyType, detail::enable_if_t<
22212                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22213    reference operator[](KeyType && key)
22214    {
22215        // implicitly convert null value to an empty object
22216        if (is_null())
22217        {
22218            m_data.m_type = value_t::object;
22219            m_data.m_value.object = create<object_t>();
22220            assert_invariant();
22221        }
22222
22223        // operator[] only works for objects
22224        if (JSON_HEDLEY_LIKELY(is_object()))
22225        {
22226            auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
22227            return set_parent(result.first->second);
22228        }
22229
22230        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22231    }
22232
22233    /// @brief access specified object element
22234    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
22235    template<class KeyType, detail::enable_if_t<
22236                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
22237    const_reference operator[](KeyType && key) const
22238    {
22239        // const operator[] only works for objects
22240        if (JSON_HEDLEY_LIKELY(is_object()))
22241        {
22242            auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22243            JSON_ASSERT(it != m_data.m_value.object->end());
22244            return it->second;
22245        }
22246
22247        JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
22248    }
22249
22250  private:
22251    template<typename KeyType>
22252    using is_comparable_with_object_key = detail::is_comparable <
22253        object_comparator_t, const typename object_t::key_type&, KeyType >;
22254
22255    template<typename ValueType>
22256    using value_return_type = std::conditional <
22257        detail::is_c_string_uncvref<ValueType>::value,
22258        string_t, typename std::decay<ValueType>::type >;
22259
22260  public:
22261    /// @brief access specified object element with default value
22262    /// @sa https://json.nlohmann.me/api/basic_json/value/
22263    template < class ValueType, detail::enable_if_t <
22264                   !detail::is_transparent<object_comparator_t>::value
22265                   && detail::is_getable<basic_json_t, ValueType>::value
22266                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22267    ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
22268    {
22269        // value only works for objects
22270        if (JSON_HEDLEY_LIKELY(is_object()))
22271        {
22272            // if key is found, return value and given default value otherwise
22273            const auto it = find(key);
22274            if (it != end())
22275            {
22276                return it->template get<ValueType>();
22277            }
22278
22279            return default_value;
22280        }
22281
22282        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22283    }
22284
22285    /// @brief access specified object element with default value
22286    /// @sa https://json.nlohmann.me/api/basic_json/value/
22287    template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22288               detail::enable_if_t <
22289                   !detail::is_transparent<object_comparator_t>::value
22290                   && detail::is_getable<basic_json_t, ReturnType>::value
22291                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22292    ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
22293    {
22294        // value only works for objects
22295        if (JSON_HEDLEY_LIKELY(is_object()))
22296        {
22297            // if key is found, return value and given default value otherwise
22298            const auto it = find(key);
22299            if (it != end())
22300            {
22301                return it->template get<ReturnType>();
22302            }
22303
22304            return std::forward<ValueType>(default_value);
22305        }
22306
22307        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22308    }
22309
22310    /// @brief access specified object element with default value
22311    /// @sa https://json.nlohmann.me/api/basic_json/value/
22312    template < class ValueType, class KeyType, detail::enable_if_t <
22313                   detail::is_transparent<object_comparator_t>::value
22314                   && !detail::is_json_pointer<KeyType>::value
22315                   && is_comparable_with_object_key<KeyType>::value
22316                   && detail::is_getable<basic_json_t, ValueType>::value
22317                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22318    ValueType value(KeyType && key, const ValueType& default_value) const
22319    {
22320        // value only works for objects
22321        if (JSON_HEDLEY_LIKELY(is_object()))
22322        {
22323            // if key is found, return value and given default value otherwise
22324            const auto it = find(std::forward<KeyType>(key));
22325            if (it != end())
22326            {
22327                return it->template get<ValueType>();
22328            }
22329
22330            return default_value;
22331        }
22332
22333        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22334    }
22335
22336    /// @brief access specified object element via JSON Pointer with default value
22337    /// @sa https://json.nlohmann.me/api/basic_json/value/
22338    template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
22339               detail::enable_if_t <
22340                   detail::is_transparent<object_comparator_t>::value
22341                   && !detail::is_json_pointer<KeyType>::value
22342                   && is_comparable_with_object_key<KeyType>::value
22343                   && detail::is_getable<basic_json_t, ReturnType>::value
22344                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22345    ReturnType value(KeyType && key, ValueType && default_value) const
22346    {
22347        // value only works for objects
22348        if (JSON_HEDLEY_LIKELY(is_object()))
22349        {
22350            // if key is found, return value and given default value otherwise
22351            const auto it = find(std::forward<KeyType>(key));
22352            if (it != end())
22353            {
22354                return it->template get<ReturnType>();
22355            }
22356
22357            return std::forward<ValueType>(default_value);
22358        }
22359
22360        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22361    }
22362
22363    /// @brief access specified object element via JSON Pointer with default value
22364    /// @sa https://json.nlohmann.me/api/basic_json/value/
22365    template < class ValueType, detail::enable_if_t <
22366                   detail::is_getable<basic_json_t, ValueType>::value
22367                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22368    ValueType value(const json_pointer& ptr, const ValueType& default_value) const
22369    {
22370        // value only works for objects
22371        if (JSON_HEDLEY_LIKELY(is_object()))
22372        {
22373            // if pointer resolves a value, return it or use default value
22374            JSON_TRY
22375            {
22376                return ptr.get_checked(this).template get<ValueType>();
22377            }
22378            JSON_INTERNAL_CATCH (out_of_range&)
22379            {
22380                return default_value;
22381            }
22382        }
22383
22384        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22385    }
22386
22387    /// @brief access specified object element via JSON Pointer with default value
22388    /// @sa https://json.nlohmann.me/api/basic_json/value/
22389    template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
22390               detail::enable_if_t <
22391                   detail::is_getable<basic_json_t, ReturnType>::value
22392                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22393    ReturnType value(const json_pointer& ptr, ValueType && default_value) const
22394    {
22395        // value only works for objects
22396        if (JSON_HEDLEY_LIKELY(is_object()))
22397        {
22398            // if pointer resolves a value, return it or use default value
22399            JSON_TRY
22400            {
22401                return ptr.get_checked(this).template get<ReturnType>();
22402            }
22403            JSON_INTERNAL_CATCH (out_of_range&)
22404            {
22405                return std::forward<ValueType>(default_value);
22406            }
22407        }
22408
22409        JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
22410    }
22411
22412    template < class ValueType, class BasicJsonType, detail::enable_if_t <
22413                   detail::is_basic_json<BasicJsonType>::value
22414                   && detail::is_getable<basic_json_t, ValueType>::value
22415                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22416    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22417    ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
22418    {
22419        return value(ptr.convert(), default_value);
22420    }
22421
22422    template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
22423               detail::enable_if_t <
22424                   detail::is_basic_json<BasicJsonType>::value
22425                   && detail::is_getable<basic_json_t, ReturnType>::value
22426                   && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
22427    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22428    ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
22429    {
22430        return value(ptr.convert(), std::forward<ValueType>(default_value));
22431    }
22432
22433    /// @brief access the first element
22434    /// @sa https://json.nlohmann.me/api/basic_json/front/
22435    reference front()
22436    {
22437        return *begin();
22438    }
22439
22440    /// @brief access the first element
22441    /// @sa https://json.nlohmann.me/api/basic_json/front/
22442    const_reference front() const
22443    {
22444        return *cbegin();
22445    }
22446
22447    /// @brief access the last element
22448    /// @sa https://json.nlohmann.me/api/basic_json/back/
22449    reference back()
22450    {
22451        auto tmp = end();
22452        --tmp;
22453        return *tmp;
22454    }
22455
22456    /// @brief access the last element
22457    /// @sa https://json.nlohmann.me/api/basic_json/back/
22458    const_reference back() const
22459    {
22460        auto tmp = cend();
22461        --tmp;
22462        return *tmp;
22463    }
22464
22465    /// @brief remove element given an iterator
22466    /// @sa https://json.nlohmann.me/api/basic_json/erase/
22467    template < class IteratorType, detail::enable_if_t <
22468                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22469                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22470    IteratorType erase(IteratorType pos) // NOLINT(performance-unnecessary-value-param)
22471    {
22472        // make sure iterator fits the current value
22473        if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
22474        {
22475            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
22476        }
22477
22478        IteratorType result = end();
22479
22480        switch (m_data.m_type)
22481        {
22482            case value_t::boolean:
22483            case value_t::number_float:
22484            case value_t::number_integer:
22485            case value_t::number_unsigned:
22486            case value_t::string:
22487            case value_t::binary:
22488            {
22489                if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
22490                {
22491                    JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
22492                }
22493
22494                if (is_string())
22495                {
22496                    AllocatorType<string_t> alloc;
22497                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22498                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22499                    m_data.m_value.string = nullptr;
22500                }
22501                else if (is_binary())
22502                {
22503                    AllocatorType<binary_t> alloc;
22504                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22505                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22506                    m_data.m_value.binary = nullptr;
22507                }
22508
22509                m_data.m_type = value_t::null;
22510                assert_invariant();
22511                break;
22512            }
22513
22514            case value_t::object:
22515            {
22516                result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
22517                break;
22518            }
22519
22520            case value_t::array:
22521            {
22522                result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
22523                break;
22524            }
22525
22526            case value_t::null:
22527            case value_t::discarded:
22528            default:
22529                JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22530        }
22531
22532        return result;
22533    }
22534
22535    /// @brief remove elements given an iterator range
22536    /// @sa https://json.nlohmann.me/api/basic_json/erase/
22537    template < class IteratorType, detail::enable_if_t <
22538                   std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
22539                   std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
22540    IteratorType erase(IteratorType first, IteratorType last) // NOLINT(performance-unnecessary-value-param)
22541    {
22542        // make sure iterator fits the current value
22543        if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
22544        {
22545            JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
22546        }
22547
22548        IteratorType result = end();
22549
22550        switch (m_data.m_type)
22551        {
22552            case value_t::boolean:
22553            case value_t::number_float:
22554            case value_t::number_integer:
22555            case value_t::number_unsigned:
22556            case value_t::string:
22557            case value_t::binary:
22558            {
22559                if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
22560                                       || !last.m_it.primitive_iterator.is_end()))
22561                {
22562                    JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
22563                }
22564
22565                if (is_string())
22566                {
22567                    AllocatorType<string_t> alloc;
22568                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
22569                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
22570                    m_data.m_value.string = nullptr;
22571                }
22572                else if (is_binary())
22573                {
22574                    AllocatorType<binary_t> alloc;
22575                    std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
22576                    std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
22577                    m_data.m_value.binary = nullptr;
22578                }
22579
22580                m_data.m_type = value_t::null;
22581                assert_invariant();
22582                break;
22583            }
22584
22585            case value_t::object:
22586            {
22587                result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
22588                                              last.m_it.object_iterator);
22589                break;
22590            }
22591
22592            case value_t::array:
22593            {
22594                result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
22595                                             last.m_it.array_iterator);
22596                break;
22597            }
22598
22599            case value_t::null:
22600            case value_t::discarded:
22601            default:
22602                JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22603        }
22604
22605        return result;
22606    }
22607
22608  private:
22609    template < typename KeyType, detail::enable_if_t <
22610                   detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22611    size_type erase_internal(KeyType && key)
22612    {
22613        // this erase only works for objects
22614        if (JSON_HEDLEY_UNLIKELY(!is_object()))
22615        {
22616            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22617        }
22618
22619        return m_data.m_value.object->erase(std::forward<KeyType>(key));
22620    }
22621
22622    template < typename KeyType, detail::enable_if_t <
22623                   !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
22624    size_type erase_internal(KeyType && key)
22625    {
22626        // this erase only works for objects
22627        if (JSON_HEDLEY_UNLIKELY(!is_object()))
22628        {
22629            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22630        }
22631
22632        const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
22633        if (it != m_data.m_value.object->end())
22634        {
22635            m_data.m_value.object->erase(it);
22636            return 1;
22637        }
22638        return 0;
22639    }
22640
22641  public:
22642
22643    /// @brief remove element from a JSON object given a key
22644    /// @sa https://json.nlohmann.me/api/basic_json/erase/
22645    size_type erase(const typename object_t::key_type& key)
22646    {
22647        // the indirection via erase_internal() is added to avoid making this
22648        // function a template and thus de-rank it during overload resolution
22649        return erase_internal(key);
22650    }
22651
22652    /// @brief remove element from a JSON object given a key
22653    /// @sa https://json.nlohmann.me/api/basic_json/erase/
22654    template<class KeyType, detail::enable_if_t<
22655                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22656    size_type erase(KeyType && key)
22657    {
22658        return erase_internal(std::forward<KeyType>(key));
22659    }
22660
22661    /// @brief remove element from a JSON array given an index
22662    /// @sa https://json.nlohmann.me/api/basic_json/erase/
22663    void erase(const size_type idx)
22664    {
22665        // this erase only works for arrays
22666        if (JSON_HEDLEY_LIKELY(is_array()))
22667        {
22668            if (JSON_HEDLEY_UNLIKELY(idx >= size()))
22669            {
22670                JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
22671            }
22672
22673            m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
22674        }
22675        else
22676        {
22677            JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
22678        }
22679    }
22680
22681    /// @}
22682
22683    ////////////
22684    // lookup //
22685    ////////////
22686
22687    /// @name lookup
22688    /// @{
22689
22690    /// @brief find an element in a JSON object
22691    /// @sa https://json.nlohmann.me/api/basic_json/find/
22692    iterator find(const typename object_t::key_type& key)
22693    {
22694        auto result = end();
22695
22696        if (is_object())
22697        {
22698            result.m_it.object_iterator = m_data.m_value.object->find(key);
22699        }
22700
22701        return result;
22702    }
22703
22704    /// @brief find an element in a JSON object
22705    /// @sa https://json.nlohmann.me/api/basic_json/find/
22706    const_iterator find(const typename object_t::key_type& key) const
22707    {
22708        auto result = cend();
22709
22710        if (is_object())
22711        {
22712            result.m_it.object_iterator = m_data.m_value.object->find(key);
22713        }
22714
22715        return result;
22716    }
22717
22718    /// @brief find an element in a JSON object
22719    /// @sa https://json.nlohmann.me/api/basic_json/find/
22720    template<class KeyType, detail::enable_if_t<
22721                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22722    iterator find(KeyType && key)
22723    {
22724        auto result = end();
22725
22726        if (is_object())
22727        {
22728            result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22729        }
22730
22731        return result;
22732    }
22733
22734    /// @brief find an element in a JSON object
22735    /// @sa https://json.nlohmann.me/api/basic_json/find/
22736    template<class KeyType, detail::enable_if_t<
22737                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22738    const_iterator find(KeyType && key) const
22739    {
22740        auto result = cend();
22741
22742        if (is_object())
22743        {
22744            result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
22745        }
22746
22747        return result;
22748    }
22749
22750    /// @brief returns the number of occurrences of a key in a JSON object
22751    /// @sa https://json.nlohmann.me/api/basic_json/count/
22752    size_type count(const typename object_t::key_type& key) const
22753    {
22754        // return 0 for all nonobject types
22755        return is_object() ? m_data.m_value.object->count(key) : 0;
22756    }
22757
22758    /// @brief returns the number of occurrences of a key in a JSON object
22759    /// @sa https://json.nlohmann.me/api/basic_json/count/
22760    template<class KeyType, detail::enable_if_t<
22761                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22762    size_type count(KeyType && key) const
22763    {
22764        // return 0 for all nonobject types
22765        return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
22766    }
22767
22768    /// @brief check the existence of an element in a JSON object
22769    /// @sa https://json.nlohmann.me/api/basic_json/contains/
22770    bool contains(const typename object_t::key_type& key) const
22771    {
22772        return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
22773    }
22774
22775    /// @brief check the existence of an element in a JSON object
22776    /// @sa https://json.nlohmann.me/api/basic_json/contains/
22777    template<class KeyType, detail::enable_if_t<
22778                 detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
22779    bool contains(KeyType && key) const
22780    {
22781        return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
22782    }
22783
22784    /// @brief check the existence of an element in a JSON object given a JSON pointer
22785    /// @sa https://json.nlohmann.me/api/basic_json/contains/
22786    bool contains(const json_pointer& ptr) const
22787    {
22788        return ptr.contains(this);
22789    }
22790
22791    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
22792    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
22793    bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
22794    {
22795        return ptr.contains(this);
22796    }
22797
22798    /// @}
22799
22800    ///////////////
22801    // iterators //
22802    ///////////////
22803
22804    /// @name iterators
22805    /// @{
22806
22807    /// @brief returns an iterator to the first element
22808    /// @sa https://json.nlohmann.me/api/basic_json/begin/
22809    iterator begin() noexcept
22810    {
22811        iterator result(this);
22812        result.set_begin();
22813        return result;
22814    }
22815
22816    /// @brief returns an iterator to the first element
22817    /// @sa https://json.nlohmann.me/api/basic_json/begin/
22818    const_iterator begin() const noexcept
22819    {
22820        return cbegin();
22821    }
22822
22823    /// @brief returns a const iterator to the first element
22824    /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
22825    const_iterator cbegin() const noexcept
22826    {
22827        const_iterator result(this);
22828        result.set_begin();
22829        return result;
22830    }
22831
22832    /// @brief returns an iterator to one past the last element
22833    /// @sa https://json.nlohmann.me/api/basic_json/end/
22834    iterator end() noexcept
22835    {
22836        iterator result(this);
22837        result.set_end();
22838        return result;
22839    }
22840
22841    /// @brief returns an iterator to one past the last element
22842    /// @sa https://json.nlohmann.me/api/basic_json/end/
22843    const_iterator end() const noexcept
22844    {
22845        return cend();
22846    }
22847
22848    /// @brief returns an iterator to one past the last element
22849    /// @sa https://json.nlohmann.me/api/basic_json/cend/
22850    const_iterator cend() const noexcept
22851    {
22852        const_iterator result(this);
22853        result.set_end();
22854        return result;
22855    }
22856
22857    /// @brief returns an iterator to the reverse-beginning
22858    /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22859    reverse_iterator rbegin() noexcept
22860    {
22861        return reverse_iterator(end());
22862    }
22863
22864    /// @brief returns an iterator to the reverse-beginning
22865    /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
22866    const_reverse_iterator rbegin() const noexcept
22867    {
22868        return crbegin();
22869    }
22870
22871    /// @brief returns an iterator to the reverse-end
22872    /// @sa https://json.nlohmann.me/api/basic_json/rend/
22873    reverse_iterator rend() noexcept
22874    {
22875        return reverse_iterator(begin());
22876    }
22877
22878    /// @brief returns an iterator to the reverse-end
22879    /// @sa https://json.nlohmann.me/api/basic_json/rend/
22880    const_reverse_iterator rend() const noexcept
22881    {
22882        return crend();
22883    }
22884
22885    /// @brief returns a const reverse iterator to the last element
22886    /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
22887    const_reverse_iterator crbegin() const noexcept
22888    {
22889        return const_reverse_iterator(cend());
22890    }
22891
22892    /// @brief returns a const reverse iterator to one before the first
22893    /// @sa https://json.nlohmann.me/api/basic_json/crend/
22894    const_reverse_iterator crend() const noexcept
22895    {
22896        return const_reverse_iterator(cbegin());
22897    }
22898
22899  public:
22900    /// @brief wrapper to access iterator member functions in range-based for
22901    /// @sa https://json.nlohmann.me/api/basic_json/items/
22902    /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22903    ///             version 4.0.0 of the library. Please use @ref items() instead;
22904    ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22905    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22906    static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
22907    {
22908        return ref.items();
22909    }
22910
22911    /// @brief wrapper to access iterator member functions in range-based for
22912    /// @sa https://json.nlohmann.me/api/basic_json/items/
22913    /// @deprecated This function is deprecated since 3.1.0 and will be removed in
22914    ///         version 4.0.0 of the library. Please use @ref items() instead;
22915    ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
22916    JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
22917    static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
22918    {
22919        return ref.items();
22920    }
22921
22922    /// @brief helper to access iterator member functions in range-based for
22923    /// @sa https://json.nlohmann.me/api/basic_json/items/
22924    iteration_proxy<iterator> items() noexcept
22925    {
22926        return iteration_proxy<iterator>(*this);
22927    }
22928
22929    /// @brief helper to access iterator member functions in range-based for
22930    /// @sa https://json.nlohmann.me/api/basic_json/items/
22931    iteration_proxy<const_iterator> items() const noexcept
22932    {
22933        return iteration_proxy<const_iterator>(*this);
22934    }
22935
22936    /// @}
22937
22938    //////////////
22939    // capacity //
22940    //////////////
22941
22942    /// @name capacity
22943    /// @{
22944
22945    /// @brief checks whether the container is empty.
22946    /// @sa https://json.nlohmann.me/api/basic_json/empty/
22947    bool empty() const noexcept
22948    {
22949        switch (m_data.m_type)
22950        {
22951            case value_t::null:
22952            {
22953                // null values are empty
22954                return true;
22955            }
22956
22957            case value_t::array:
22958            {
22959                // delegate call to array_t::empty()
22960                return m_data.m_value.array->empty();
22961            }
22962
22963            case value_t::object:
22964            {
22965                // delegate call to object_t::empty()
22966                return m_data.m_value.object->empty();
22967            }
22968
22969            case value_t::string:
22970            case value_t::boolean:
22971            case value_t::number_integer:
22972            case value_t::number_unsigned:
22973            case value_t::number_float:
22974            case value_t::binary:
22975            case value_t::discarded:
22976            default:
22977            {
22978                // all other types are nonempty
22979                return false;
22980            }
22981        }
22982    }
22983
22984    /// @brief returns the number of elements
22985    /// @sa https://json.nlohmann.me/api/basic_json/size/
22986    size_type size() const noexcept
22987    {
22988        switch (m_data.m_type)
22989        {
22990            case value_t::null:
22991            {
22992                // null values are empty
22993                return 0;
22994            }
22995
22996            case value_t::array:
22997            {
22998                // delegate call to array_t::size()
22999                return m_data.m_value.array->size();
23000            }
23001
23002            case value_t::object:
23003            {
23004                // delegate call to object_t::size()
23005                return m_data.m_value.object->size();
23006            }
23007
23008            case value_t::string:
23009            case value_t::boolean:
23010            case value_t::number_integer:
23011            case value_t::number_unsigned:
23012            case value_t::number_float:
23013            case value_t::binary:
23014            case value_t::discarded:
23015            default:
23016            {
23017                // all other types have size 1
23018                return 1;
23019            }
23020        }
23021    }
23022
23023    /// @brief returns the maximum possible number of elements
23024    /// @sa https://json.nlohmann.me/api/basic_json/max_size/
23025    size_type max_size() const noexcept
23026    {
23027        switch (m_data.m_type)
23028        {
23029            case value_t::array:
23030            {
23031                // delegate call to array_t::max_size()
23032                return m_data.m_value.array->max_size();
23033            }
23034
23035            case value_t::object:
23036            {
23037                // delegate call to object_t::max_size()
23038                return m_data.m_value.object->max_size();
23039            }
23040
23041            case value_t::null:
23042            case value_t::string:
23043            case value_t::boolean:
23044            case value_t::number_integer:
23045            case value_t::number_unsigned:
23046            case value_t::number_float:
23047            case value_t::binary:
23048            case value_t::discarded:
23049            default:
23050            {
23051                // all other types have max_size() == size()
23052                return size();
23053            }
23054        }
23055    }
23056
23057    /// @}
23058
23059    ///////////////
23060    // modifiers //
23061    ///////////////
23062
23063    /// @name modifiers
23064    /// @{
23065
23066    /// @brief clears the contents
23067    /// @sa https://json.nlohmann.me/api/basic_json/clear/
23068    void clear() noexcept
23069    {
23070        switch (m_data.m_type)
23071        {
23072            case value_t::number_integer:
23073            {
23074                m_data.m_value.number_integer = 0;
23075                break;
23076            }
23077
23078            case value_t::number_unsigned:
23079            {
23080                m_data.m_value.number_unsigned = 0;
23081                break;
23082            }
23083
23084            case value_t::number_float:
23085            {
23086                m_data.m_value.number_float = 0.0;
23087                break;
23088            }
23089
23090            case value_t::boolean:
23091            {
23092                m_data.m_value.boolean = false;
23093                break;
23094            }
23095
23096            case value_t::string:
23097            {
23098                m_data.m_value.string->clear();
23099                break;
23100            }
23101
23102            case value_t::binary:
23103            {
23104                m_data.m_value.binary->clear();
23105                break;
23106            }
23107
23108            case value_t::array:
23109            {
23110                m_data.m_value.array->clear();
23111                break;
23112            }
23113
23114            case value_t::object:
23115            {
23116                m_data.m_value.object->clear();
23117                break;
23118            }
23119
23120            case value_t::null:
23121            case value_t::discarded:
23122            default:
23123                break;
23124        }
23125    }
23126
23127    /// @brief add an object to an array
23128    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23129    void push_back(basic_json&& val)
23130    {
23131        // push_back only works for null objects or arrays
23132        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23133        {
23134            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23135        }
23136
23137        // transform null object into an array
23138        if (is_null())
23139        {
23140            m_data.m_type = value_t::array;
23141            m_data.m_value = value_t::array;
23142            assert_invariant();
23143        }
23144
23145        // add element to array (move semantics)
23146        const auto old_capacity = m_data.m_value.array->capacity();
23147        m_data.m_value.array->push_back(std::move(val));
23148        set_parent(m_data.m_value.array->back(), old_capacity);
23149        // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
23150    }
23151
23152    /// @brief add an object to an array
23153    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23154    reference operator+=(basic_json&& val)
23155    {
23156        push_back(std::move(val));
23157        return *this;
23158    }
23159
23160    /// @brief add an object to an array
23161    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23162    void push_back(const basic_json& val)
23163    {
23164        // push_back only works for null objects or arrays
23165        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23166        {
23167            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23168        }
23169
23170        // transform null object into an array
23171        if (is_null())
23172        {
23173            m_data.m_type = value_t::array;
23174            m_data.m_value = value_t::array;
23175            assert_invariant();
23176        }
23177
23178        // add element to array
23179        const auto old_capacity = m_data.m_value.array->capacity();
23180        m_data.m_value.array->push_back(val);
23181        set_parent(m_data.m_value.array->back(), old_capacity);
23182    }
23183
23184    /// @brief add an object to an array
23185    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23186    reference operator+=(const basic_json& val)
23187    {
23188        push_back(val);
23189        return *this;
23190    }
23191
23192    /// @brief add an object to an object
23193    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23194    void push_back(const typename object_t::value_type& val)
23195    {
23196        // push_back only works for null objects or objects
23197        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23198        {
23199            JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
23200        }
23201
23202        // transform null object into an object
23203        if (is_null())
23204        {
23205            m_data.m_type = value_t::object;
23206            m_data.m_value = value_t::object;
23207            assert_invariant();
23208        }
23209
23210        // add element to object
23211        auto res = m_data.m_value.object->insert(val);
23212        set_parent(res.first->second);
23213    }
23214
23215    /// @brief add an object to an object
23216    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23217    reference operator+=(const typename object_t::value_type& val)
23218    {
23219        push_back(val);
23220        return *this;
23221    }
23222
23223    /// @brief add an object to an object
23224    /// @sa https://json.nlohmann.me/api/basic_json/push_back/
23225    void push_back(initializer_list_t init)
23226    {
23227        if (is_object() && init.size() == 2 && (*init.begin())->is_string())
23228        {
23229            basic_json&& key = init.begin()->moved_or_copied();
23230            push_back(typename object_t::value_type(
23231                          std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
23232        }
23233        else
23234        {
23235            push_back(basic_json(init));
23236        }
23237    }
23238
23239    /// @brief add an object to an object
23240    /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
23241    reference operator+=(initializer_list_t init)
23242    {
23243        push_back(init);
23244        return *this;
23245    }
23246
23247    /// @brief add an object to an array
23248    /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
23249    template<class... Args>
23250    reference emplace_back(Args&& ... args)
23251    {
23252        // emplace_back only works for null objects or arrays
23253        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
23254        {
23255            JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
23256        }
23257
23258        // transform null object into an array
23259        if (is_null())
23260        {
23261            m_data.m_type = value_t::array;
23262            m_data.m_value = value_t::array;
23263            assert_invariant();
23264        }
23265
23266        // add element to array (perfect forwarding)
23267        const auto old_capacity = m_data.m_value.array->capacity();
23268        m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
23269        return set_parent(m_data.m_value.array->back(), old_capacity);
23270    }
23271
23272    /// @brief add an object to an object if key does not exist
23273    /// @sa https://json.nlohmann.me/api/basic_json/emplace/
23274    template<class... Args>
23275    std::pair<iterator, bool> emplace(Args&& ... args)
23276    {
23277        // emplace only works for null objects or arrays
23278        if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
23279        {
23280            JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
23281        }
23282
23283        // transform null object into an object
23284        if (is_null())
23285        {
23286            m_data.m_type = value_t::object;
23287            m_data.m_value = value_t::object;
23288            assert_invariant();
23289        }
23290
23291        // add element to array (perfect forwarding)
23292        auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
23293        set_parent(res.first->second);
23294
23295        // create result iterator and set iterator to the result of emplace
23296        auto it = begin();
23297        it.m_it.object_iterator = res.first;
23298
23299        // return pair of iterator and boolean
23300        return {it, res.second};
23301    }
23302
23303    /// Helper for insertion of an iterator
23304    /// @note: This uses std::distance to support GCC 4.8,
23305    ///        see https://github.com/nlohmann/json/pull/1257
23306    template<typename... Args>
23307    iterator insert_iterator(const_iterator pos, Args&& ... args) // NOLINT(performance-unnecessary-value-param)
23308    {
23309        iterator result(this);
23310        JSON_ASSERT(m_data.m_value.array != nullptr);
23311
23312        auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
23313        m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
23314        result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
23315
23316        // This could have been written as:
23317        // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
23318        // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
23319
23320        set_parents();
23321        return result;
23322    }
23323
23324    /// @brief inserts element into array
23325    /// @sa https://json.nlohmann.me/api/basic_json/insert/
23326    iterator insert(const_iterator pos, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23327    {
23328        // insert only works for arrays
23329        if (JSON_HEDLEY_LIKELY(is_array()))
23330        {
23331            // check if iterator pos fits to this JSON value
23332            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23333            {
23334                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23335            }
23336
23337            // insert to array and return iterator
23338            return insert_iterator(pos, val);
23339        }
23340
23341        JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23342    }
23343
23344    /// @brief inserts element into array
23345    /// @sa https://json.nlohmann.me/api/basic_json/insert/
23346    iterator insert(const_iterator pos, basic_json&& val) // NOLINT(performance-unnecessary-value-param)
23347    {
23348        return insert(pos, val);
23349    }
23350
23351    /// @brief inserts copies of element into array
23352    /// @sa https://json.nlohmann.me/api/basic_json/insert/
23353    iterator insert(const_iterator pos, size_type cnt, const basic_json& val) // NOLINT(performance-unnecessary-value-param)
23354    {
23355        // insert only works for arrays
23356        if (JSON_HEDLEY_LIKELY(is_array()))
23357        {
23358            // check if iterator pos fits to this JSON value
23359            if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23360            {
23361                JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23362            }
23363
23364            // insert to array and return iterator
23365            return insert_iterator(pos, cnt, val);
23366        }
23367
23368        JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23369    }
23370
23371    /// @brief inserts range of elements into array
23372    /// @sa https://json.nlohmann.me/api/basic_json/insert/
23373    iterator insert(const_iterator pos, const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23374    {
23375        // insert only works for arrays
23376        if (JSON_HEDLEY_UNLIKELY(!is_array()))
23377        {
23378            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23379        }
23380
23381        // check if iterator pos fits to this JSON value
23382        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23383        {
23384            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23385        }
23386
23387        // check if range iterators belong to the same JSON object
23388        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23389        {
23390            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23391        }
23392
23393        if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
23394        {
23395            JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
23396        }
23397
23398        // insert to array and return iterator
23399        return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
23400    }
23401
23402    /// @brief inserts elements from initializer list into array
23403    /// @sa https://json.nlohmann.me/api/basic_json/insert/
23404    iterator insert(const_iterator pos, initializer_list_t ilist) // NOLINT(performance-unnecessary-value-param)
23405    {
23406        // insert only works for arrays
23407        if (JSON_HEDLEY_UNLIKELY(!is_array()))
23408        {
23409            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23410        }
23411
23412        // check if iterator pos fits to this JSON value
23413        if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
23414        {
23415            JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
23416        }
23417
23418        // insert to array and return iterator
23419        return insert_iterator(pos, ilist.begin(), ilist.end());
23420    }
23421
23422    /// @brief inserts range of elements into object
23423    /// @sa https://json.nlohmann.me/api/basic_json/insert/
23424    void insert(const_iterator first, const_iterator last) // NOLINT(performance-unnecessary-value-param)
23425    {
23426        // insert only works for objects
23427        if (JSON_HEDLEY_UNLIKELY(!is_object()))
23428        {
23429            JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
23430        }
23431
23432        // check if range iterators belong to the same JSON object
23433        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23434        {
23435            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23436        }
23437
23438        // passed iterators must belong to objects
23439        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23440        {
23441            JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
23442        }
23443
23444        m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
23445        set_parents();
23446    }
23447
23448    /// @brief updates a JSON object from another object, overwriting existing keys
23449    /// @sa https://json.nlohmann.me/api/basic_json/update/
23450    void update(const_reference j, bool merge_objects = false)
23451    {
23452        update(j.begin(), j.end(), merge_objects);
23453    }
23454
23455    /// @brief updates a JSON object from another object, overwriting existing keys
23456    /// @sa https://json.nlohmann.me/api/basic_json/update/
23457    void update(const_iterator first, const_iterator last, bool merge_objects = false) // NOLINT(performance-unnecessary-value-param)
23458    {
23459        // implicitly convert null value to an empty object
23460        if (is_null())
23461        {
23462            m_data.m_type = value_t::object;
23463            m_data.m_value.object = create<object_t>();
23464            assert_invariant();
23465        }
23466
23467        if (JSON_HEDLEY_UNLIKELY(!is_object()))
23468        {
23469            JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
23470        }
23471
23472        // check if range iterators belong to the same JSON object
23473        if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
23474        {
23475            JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
23476        }
23477
23478        // passed iterators must belong to objects
23479        if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
23480        {
23481            JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
23482        }
23483
23484        for (auto it = first; it != last; ++it)
23485        {
23486            if (merge_objects && it.value().is_object())
23487            {
23488                auto it2 = m_data.m_value.object->find(it.key());
23489                if (it2 != m_data.m_value.object->end())
23490                {
23491                    it2->second.update(it.value(), true);
23492                    continue;
23493                }
23494            }
23495            m_data.m_value.object->operator[](it.key()) = it.value();
23496#if JSON_DIAGNOSTICS
23497            m_data.m_value.object->operator[](it.key()).m_parent = this;
23498#endif
23499        }
23500    }
23501
23502    /// @brief exchanges the values
23503    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23504    void swap(reference other) noexcept (
23505        std::is_nothrow_move_constructible<value_t>::value&&
23506        std::is_nothrow_move_assignable<value_t>::value&&
23507        std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23508        std::is_nothrow_move_assignable<json_value>::value
23509    )
23510    {
23511        std::swap(m_data.m_type, other.m_data.m_type);
23512        std::swap(m_data.m_value, other.m_data.m_value);
23513
23514        set_parents();
23515        other.set_parents();
23516        assert_invariant();
23517    }
23518
23519    /// @brief exchanges the values
23520    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23521    friend void swap(reference left, reference right) noexcept (
23522        std::is_nothrow_move_constructible<value_t>::value&&
23523        std::is_nothrow_move_assignable<value_t>::value&&
23524        std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23525        std::is_nothrow_move_assignable<json_value>::value
23526    )
23527    {
23528        left.swap(right);
23529    }
23530
23531    /// @brief exchanges the values
23532    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23533    void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23534    {
23535        // swap only works for arrays
23536        if (JSON_HEDLEY_LIKELY(is_array()))
23537        {
23538            using std::swap;
23539            swap(*(m_data.m_value.array), other);
23540        }
23541        else
23542        {
23543            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
23544        }
23545    }
23546
23547    /// @brief exchanges the values
23548    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23549    void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23550    {
23551        // swap only works for objects
23552        if (JSON_HEDLEY_LIKELY(is_object()))
23553        {
23554            using std::swap;
23555            swap(*(m_data.m_value.object), other);
23556        }
23557        else
23558        {
23559            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
23560        }
23561    }
23562
23563    /// @brief exchanges the values
23564    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23565    void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23566    {
23567        // swap only works for strings
23568        if (JSON_HEDLEY_LIKELY(is_string()))
23569        {
23570            using std::swap;
23571            swap(*(m_data.m_value.string), other);
23572        }
23573        else
23574        {
23575            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
23576        }
23577    }
23578
23579    /// @brief exchanges the values
23580    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23581    void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
23582    {
23583        // swap only works for strings
23584        if (JSON_HEDLEY_LIKELY(is_binary()))
23585        {
23586            using std::swap;
23587            swap(*(m_data.m_value.binary), other);
23588        }
23589        else
23590        {
23591            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
23592        }
23593    }
23594
23595    /// @brief exchanges the values
23596    /// @sa https://json.nlohmann.me/api/basic_json/swap/
23597    void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
23598    {
23599        // swap only works for strings
23600        if (JSON_HEDLEY_LIKELY(is_binary()))
23601        {
23602            using std::swap;
23603            swap(*(m_data.m_value.binary), other);
23604        }
23605        else
23606        {
23607            JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
23608        }
23609    }
23610
23611    /// @}
23612
23613    //////////////////////////////////////////
23614    // lexicographical comparison operators //
23615    //////////////////////////////////////////
23616
23617    /// @name lexicographical comparison operators
23618    /// @{
23619
23620    // note parentheses around operands are necessary; see
23621    // https://github.com/nlohmann/json/issues/1530
23622#define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
23623    const auto lhs_type = lhs.type();                                                                    \
23624    const auto rhs_type = rhs.type();                                                                    \
23625    \
23626    if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
23627    {                                                                                                    \
23628        switch (lhs_type)                                                                                \
23629        {                                                                                                \
23630            case value_t::array:                                                                         \
23631                return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array);                                     \
23632                \
23633            case value_t::object:                                                                        \
23634                return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object);                                   \
23635                \
23636            case value_t::null:                                                                          \
23637                return (null_result);                                                                    \
23638                \
23639            case value_t::string:                                                                        \
23640                return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string);                                   \
23641                \
23642            case value_t::boolean:                                                                       \
23643                return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean);                                   \
23644                \
23645            case value_t::number_integer:                                                                \
23646                return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer);                     \
23647                \
23648            case value_t::number_unsigned:                                                               \
23649                return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned);                   \
23650                \
23651            case value_t::number_float:                                                                  \
23652                return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float);                         \
23653                \
23654            case value_t::binary:                                                                        \
23655                return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary);                                   \
23656                \
23657            case value_t::discarded:                                                                     \
23658            default:                                                                                     \
23659                return (unordered_result);                                                               \
23660        }                                                                                                \
23661    }                                                                                                    \
23662    else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
23663    {                                                                                                    \
23664        return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float;      \
23665    }                                                                                                    \
23666    else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
23667    {                                                                                                    \
23668        return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer);      \
23669    }                                                                                                    \
23670    else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
23671    {                                                                                                    \
23672        return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float;     \
23673    }                                                                                                    \
23674    else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
23675    {                                                                                                    \
23676        return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned);     \
23677    }                                                                                                    \
23678    else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
23679    {                                                                                                    \
23680        return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
23681    }                                                                                                    \
23682    else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
23683    {                                                                                                    \
23684        return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
23685    }                                                                                                    \
23686    else if(compares_unordered(lhs, rhs))\
23687    {\
23688        return (unordered_result);\
23689    }\
23690    \
23691    return (default_result);
23692
23693  JSON_PRIVATE_UNLESS_TESTED:
23694    // returns true if:
23695    // - any operand is NaN and the other operand is of number type
23696    // - any operand is discarded
23697    // in legacy mode, discarded values are considered ordered if
23698    // an operation is computed as an odd number of inverses of others
23699    static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
23700    {
23701        if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
23702                || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
23703        {
23704            return true;
23705        }
23706#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23707        return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
23708#else
23709        static_cast<void>(inverse);
23710        return lhs.is_discarded() || rhs.is_discarded();
23711#endif
23712    }
23713
23714  private:
23715    bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
23716    {
23717        return compares_unordered(*this, rhs, inverse);
23718    }
23719
23720  public:
23721#if JSON_HAS_THREE_WAY_COMPARISON
23722    /// @brief comparison: equal
23723    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23724    bool operator==(const_reference rhs) const noexcept
23725    {
23726#ifdef __GNUC__
23727#pragma GCC diagnostic push
23728#pragma GCC diagnostic ignored "-Wfloat-equal"
23729#endif
23730        const_reference lhs = *this;
23731        JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23732#ifdef __GNUC__
23733#pragma GCC diagnostic pop
23734#endif
23735    }
23736
23737    /// @brief comparison: equal
23738    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23739    template<typename ScalarType>
23740    requires std::is_scalar_v<ScalarType>
23741    bool operator==(ScalarType rhs) const noexcept
23742    {
23743        return *this == basic_json(rhs);
23744    }
23745
23746    /// @brief comparison: not equal
23747    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23748    bool operator!=(const_reference rhs) const noexcept
23749    {
23750        if (compares_unordered(rhs, true))
23751        {
23752            return false;
23753        }
23754        return !operator==(rhs);
23755    }
23756
23757    /// @brief comparison: 3-way
23758    /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23759    std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
23760    {
23761        const_reference lhs = *this;
23762        // default_result is used if we cannot compare values. In that case,
23763        // we compare types.
23764        JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
23765                                std::partial_ordering::equivalent,
23766                                std::partial_ordering::unordered,
23767                                lhs_type <=> rhs_type) // *NOPAD*
23768    }
23769
23770    /// @brief comparison: 3-way
23771    /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
23772    template<typename ScalarType>
23773    requires std::is_scalar_v<ScalarType>
23774    std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
23775    {
23776        return *this <=> basic_json(rhs); // *NOPAD*
23777    }
23778
23779#if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
23780    // all operators that are computed as an odd number of inverses of others
23781    // need to be overloaded to emulate the legacy comparison behavior
23782
23783    /// @brief comparison: less than or equal
23784    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23785    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23786    bool operator<=(const_reference rhs) const noexcept
23787    {
23788        if (compares_unordered(rhs, true))
23789        {
23790            return false;
23791        }
23792        return !(rhs < *this);
23793    }
23794
23795    /// @brief comparison: less than or equal
23796    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23797    template<typename ScalarType>
23798    requires std::is_scalar_v<ScalarType>
23799    bool operator<=(ScalarType rhs) const noexcept
23800    {
23801        return *this <= basic_json(rhs);
23802    }
23803
23804    /// @brief comparison: greater than or equal
23805    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23806    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
23807    bool operator>=(const_reference rhs) const noexcept
23808    {
23809        if (compares_unordered(rhs, true))
23810        {
23811            return false;
23812        }
23813        return !(*this < rhs);
23814    }
23815
23816    /// @brief comparison: greater than or equal
23817    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23818    template<typename ScalarType>
23819    requires std::is_scalar_v<ScalarType>
23820    bool operator>=(ScalarType rhs) const noexcept
23821    {
23822        return *this >= basic_json(rhs);
23823    }
23824#endif
23825#else
23826    /// @brief comparison: equal
23827    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23828    friend bool operator==(const_reference lhs, const_reference rhs) noexcept
23829    {
23830#ifdef __GNUC__
23831#pragma GCC diagnostic push
23832#pragma GCC diagnostic ignored "-Wfloat-equal"
23833#endif
23834        JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
23835#ifdef __GNUC__
23836#pragma GCC diagnostic pop
23837#endif
23838    }
23839
23840    /// @brief comparison: equal
23841    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23842    template<typename ScalarType, typename std::enable_if<
23843                 std::is_scalar<ScalarType>::value, int>::type = 0>
23844    friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
23845    {
23846        return lhs == basic_json(rhs);
23847    }
23848
23849    /// @brief comparison: equal
23850    /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
23851    template<typename ScalarType, typename std::enable_if<
23852                 std::is_scalar<ScalarType>::value, int>::type = 0>
23853    friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
23854    {
23855        return basic_json(lhs) == rhs;
23856    }
23857
23858    /// @brief comparison: not equal
23859    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23860    friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
23861    {
23862        if (compares_unordered(lhs, rhs, true))
23863        {
23864            return false;
23865        }
23866        return !(lhs == rhs);
23867    }
23868
23869    /// @brief comparison: not equal
23870    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23871    template<typename ScalarType, typename std::enable_if<
23872                 std::is_scalar<ScalarType>::value, int>::type = 0>
23873    friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
23874    {
23875        return lhs != basic_json(rhs);
23876    }
23877
23878    /// @brief comparison: not equal
23879    /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
23880    template<typename ScalarType, typename std::enable_if<
23881                 std::is_scalar<ScalarType>::value, int>::type = 0>
23882    friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
23883    {
23884        return basic_json(lhs) != rhs;
23885    }
23886
23887    /// @brief comparison: less than
23888    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23889    friend bool operator<(const_reference lhs, const_reference rhs) noexcept
23890    {
23891        // default_result is used if we cannot compare values. In that case,
23892        // we compare types. Note we have to call the operator explicitly,
23893        // because MSVC has problems otherwise.
23894        JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
23895    }
23896
23897    /// @brief comparison: less than
23898    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23899    template<typename ScalarType, typename std::enable_if<
23900                 std::is_scalar<ScalarType>::value, int>::type = 0>
23901    friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
23902    {
23903        return lhs < basic_json(rhs);
23904    }
23905
23906    /// @brief comparison: less than
23907    /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
23908    template<typename ScalarType, typename std::enable_if<
23909                 std::is_scalar<ScalarType>::value, int>::type = 0>
23910    friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
23911    {
23912        return basic_json(lhs) < rhs;
23913    }
23914
23915    /// @brief comparison: less than or equal
23916    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23917    friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
23918    {
23919        if (compares_unordered(lhs, rhs, true))
23920        {
23921            return false;
23922        }
23923        return !(rhs < lhs);
23924    }
23925
23926    /// @brief comparison: less than or equal
23927    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23928    template<typename ScalarType, typename std::enable_if<
23929                 std::is_scalar<ScalarType>::value, int>::type = 0>
23930    friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
23931    {
23932        return lhs <= basic_json(rhs);
23933    }
23934
23935    /// @brief comparison: less than or equal
23936    /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
23937    template<typename ScalarType, typename std::enable_if<
23938                 std::is_scalar<ScalarType>::value, int>::type = 0>
23939    friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
23940    {
23941        return basic_json(lhs) <= rhs;
23942    }
23943
23944    /// @brief comparison: greater than
23945    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23946    friend bool operator>(const_reference lhs, const_reference rhs) noexcept
23947    {
23948        // double inverse
23949        if (compares_unordered(lhs, rhs))
23950        {
23951            return false;
23952        }
23953        return !(lhs <= rhs);
23954    }
23955
23956    /// @brief comparison: greater than
23957    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23958    template<typename ScalarType, typename std::enable_if<
23959                 std::is_scalar<ScalarType>::value, int>::type = 0>
23960    friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
23961    {
23962        return lhs > basic_json(rhs);
23963    }
23964
23965    /// @brief comparison: greater than
23966    /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
23967    template<typename ScalarType, typename std::enable_if<
23968                 std::is_scalar<ScalarType>::value, int>::type = 0>
23969    friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
23970    {
23971        return basic_json(lhs) > rhs;
23972    }
23973
23974    /// @brief comparison: greater than or equal
23975    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23976    friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
23977    {
23978        if (compares_unordered(lhs, rhs, true))
23979        {
23980            return false;
23981        }
23982        return !(lhs < rhs);
23983    }
23984
23985    /// @brief comparison: greater than or equal
23986    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23987    template<typename ScalarType, typename std::enable_if<
23988                 std::is_scalar<ScalarType>::value, int>::type = 0>
23989    friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
23990    {
23991        return lhs >= basic_json(rhs);
23992    }
23993
23994    /// @brief comparison: greater than or equal
23995    /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
23996    template<typename ScalarType, typename std::enable_if<
23997                 std::is_scalar<ScalarType>::value, int>::type = 0>
23998    friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
23999    {
24000        return basic_json(lhs) >= rhs;
24001    }
24002#endif
24003
24004#undef JSON_IMPLEMENT_OPERATOR
24005
24006    /// @}
24007
24008    ///////////////////
24009    // serialization //
24010    ///////////////////
24011
24012    /// @name serialization
24013    /// @{
24014#ifndef JSON_NO_IO
24015    /// @brief serialize to stream
24016    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
24017    friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
24018    {
24019        // read width member and use it as indentation parameter if nonzero
24020        const bool pretty_print = o.width() > 0;
24021        const auto indentation = pretty_print ? o.width() : 0;
24022
24023        // reset width to 0 for subsequent calls to this stream
24024        o.width(0);
24025
24026        // do the actual serialization
24027        serializer s(detail::output_adapter<char>(o), o.fill());
24028        s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
24029        return o;
24030    }
24031
24032    /// @brief serialize to stream
24033    /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
24034    /// @deprecated This function is deprecated since 3.0.0 and will be removed in
24035    ///             version 4.0.0 of the library. Please use
24036    ///             operator<<(std::ostream&, const basic_json&) instead; that is,
24037    ///             replace calls like `j >> o;` with `o << j;`.
24038    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
24039    friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
24040    {
24041        return o << j;
24042    }
24043#endif  // JSON_NO_IO
24044    /// @}
24045
24046    /////////////////////
24047    // deserialization //
24048    /////////////////////
24049
24050    /// @name deserialization
24051    /// @{
24052
24053    /// @brief deserialize from a compatible input
24054    /// @sa https://json.nlohmann.me/api/basic_json/parse/
24055    template<typename InputType>
24056    JSON_HEDLEY_WARN_UNUSED_RESULT
24057    static basic_json parse(InputType&& i,
24058                            parser_callback_t cb = nullptr,
24059                            const bool allow_exceptions = true,
24060                            const bool ignore_comments = false)
24061    {
24062        basic_json result;
24063        parser(detail::input_adapter(std::forward<InputType>(i)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved,accessForwarded]
24064        return result;
24065    }
24066
24067    /// @brief deserialize from a pair of character iterators
24068    /// @sa https://json.nlohmann.me/api/basic_json/parse/
24069    template<typename IteratorType>
24070    JSON_HEDLEY_WARN_UNUSED_RESULT
24071    static basic_json parse(IteratorType first,
24072                            IteratorType last,
24073                            parser_callback_t cb = nullptr,
24074                            const bool allow_exceptions = true,
24075                            const bool ignore_comments = false)
24076    {
24077        basic_json result;
24078        parser(detail::input_adapter(std::move(first), std::move(last)), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24079        return result;
24080    }
24081
24082    JSON_HEDLEY_WARN_UNUSED_RESULT
24083    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
24084    static basic_json parse(detail::span_input_adapter&& i,
24085                            parser_callback_t cb = nullptr,
24086                            const bool allow_exceptions = true,
24087                            const bool ignore_comments = false)
24088    {
24089        basic_json result;
24090        parser(i.get(), std::move(cb), allow_exceptions, ignore_comments).parse(true, result); // cppcheck-suppress[accessMoved]
24091        return result;
24092    }
24093
24094    /// @brief check if the input is valid JSON
24095    /// @sa https://json.nlohmann.me/api/basic_json/accept/
24096    template<typename InputType>
24097    static bool accept(InputType&& i,
24098                       const bool ignore_comments = false)
24099    {
24100        return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
24101    }
24102
24103    /// @brief check if the input is valid JSON
24104    /// @sa https://json.nlohmann.me/api/basic_json/accept/
24105    template<typename IteratorType>
24106    static bool accept(IteratorType first, IteratorType last,
24107                       const bool ignore_comments = false)
24108    {
24109        return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
24110    }
24111
24112    JSON_HEDLEY_WARN_UNUSED_RESULT
24113    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
24114    static bool accept(detail::span_input_adapter&& i,
24115                       const bool ignore_comments = false)
24116    {
24117        return parser(i.get(), nullptr, false, ignore_comments).accept(true);
24118    }
24119
24120    /// @brief generate SAX events
24121    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24122    template <typename InputType, typename SAX>
24123    JSON_HEDLEY_NON_NULL(2)
24124    static bool sax_parse(InputType&& i, SAX* sax,
24125                          input_format_t format = input_format_t::json,
24126                          const bool strict = true,
24127                          const bool ignore_comments = false)
24128    {
24129        auto ia = detail::input_adapter(std::forward<InputType>(i));
24130        return format == input_format_t::json
24131               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24132               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24133    }
24134
24135    /// @brief generate SAX events
24136    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24137    template<class IteratorType, class SAX>
24138    JSON_HEDLEY_NON_NULL(3)
24139    static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
24140                          input_format_t format = input_format_t::json,
24141                          const bool strict = true,
24142                          const bool ignore_comments = false)
24143    {
24144        auto ia = detail::input_adapter(std::move(first), std::move(last));
24145        return format == input_format_t::json
24146               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24147               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24148    }
24149
24150    /// @brief generate SAX events
24151    /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
24152    /// @deprecated This function is deprecated since 3.8.0 and will be removed in
24153    ///             version 4.0.0 of the library. Please use
24154    ///             sax_parse(ptr, ptr + len) instead.
24155    template <typename SAX>
24156    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
24157    JSON_HEDLEY_NON_NULL(2)
24158    static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
24159                          input_format_t format = input_format_t::json,
24160                          const bool strict = true,
24161                          const bool ignore_comments = false)
24162    {
24163        auto ia = i.get();
24164        return format == input_format_t::json
24165               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24166               ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
24167               // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24168               : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
24169    }
24170#ifndef JSON_NO_IO
24171    /// @brief deserialize from stream
24172    /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
24173    /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
24174    ///             version 4.0.0 of the library. Please use
24175    ///             operator>>(std::istream&, basic_json&) instead; that is,
24176    ///             replace calls like `j << i;` with `i >> j;`.
24177    JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
24178    friend std::istream& operator<<(basic_json& j, std::istream& i)
24179    {
24180        return operator>>(i, j);
24181    }
24182
24183    /// @brief deserialize from stream
24184    /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
24185    friend std::istream& operator>>(std::istream& i, basic_json& j)
24186    {
24187        parser(detail::input_adapter(i)).parse(false, j);
24188        return i;
24189    }
24190#endif  // JSON_NO_IO
24191    /// @}
24192
24193    ///////////////////////////
24194    // convenience functions //
24195    ///////////////////////////
24196
24197    /// @brief return the type as string
24198    /// @sa https://json.nlohmann.me/api/basic_json/type_name/
24199    JSON_HEDLEY_RETURNS_NON_NULL
24200    const char* type_name() const noexcept
24201    {
24202        switch (m_data.m_type)
24203        {
24204            case value_t::null:
24205                return "null";
24206            case value_t::object:
24207                return "object";
24208            case value_t::array:
24209                return "array";
24210            case value_t::string:
24211                return "string";
24212            case value_t::boolean:
24213                return "boolean";
24214            case value_t::binary:
24215                return "binary";
24216            case value_t::discarded:
24217                return "discarded";
24218            case value_t::number_integer:
24219            case value_t::number_unsigned:
24220            case value_t::number_float:
24221            default:
24222                return "number";
24223        }
24224    }
24225
24226  JSON_PRIVATE_UNLESS_TESTED:
24227    //////////////////////
24228    // member variables //
24229    //////////////////////
24230
24231    struct data
24232    {
24233        /// the type of the current element
24234        value_t m_type = value_t::null;
24235
24236        /// the value of the current element
24237        json_value m_value = {};
24238
24239        data(const value_t v)
24240            : m_type(v), m_value(v)
24241        {
24242        }
24243
24244        data(size_type cnt, const basic_json& val)
24245            : m_type(value_t::array)
24246        {
24247            m_value.array = create<array_t>(cnt, val);
24248        }
24249
24250        data() noexcept = default;
24251        data(data&&) noexcept = default;
24252        data(const data&) noexcept = delete;
24253        data& operator=(data&&) noexcept = delete;
24254        data& operator=(const data&) noexcept = delete;
24255
24256        ~data() noexcept
24257        {
24258            m_value.destroy(m_type);
24259        }
24260    };
24261
24262    data m_data = {};
24263
24264#if JSON_DIAGNOSTICS
24265    /// a pointer to a parent value (for debugging purposes)
24266    basic_json* m_parent = nullptr;
24267#endif
24268
24269#if JSON_DIAGNOSTIC_POSITIONS
24270    /// the start position of the value
24271    std::size_t start_position = std::string::npos;
24272    /// the end position of the value
24273    std::size_t end_position = std::string::npos;
24274  public:
24275    constexpr std::size_t start_pos() const noexcept
24276    {
24277        return start_position;
24278    }
24279
24280    constexpr std::size_t end_pos() const noexcept
24281    {
24282        return end_position;
24283    }
24284#endif
24285
24286    //////////////////////////////////////////
24287    // binary serialization/deserialization //
24288    //////////////////////////////////////////
24289
24290    /// @name binary serialization/deserialization support
24291    /// @{
24292
24293  public:
24294    /// @brief create a CBOR serialization of a given JSON value
24295    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24296    static std::vector<std::uint8_t> to_cbor(const basic_json& j)
24297    {
24298        std::vector<std::uint8_t> result;
24299        to_cbor(j, result);
24300        return result;
24301    }
24302
24303    /// @brief create a CBOR serialization of a given JSON value
24304    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24305    static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24306    {
24307        binary_writer<std::uint8_t>(o).write_cbor(j);
24308    }
24309
24310    /// @brief create a CBOR serialization of a given JSON value
24311    /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
24312    static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
24313    {
24314        binary_writer<char>(o).write_cbor(j);
24315    }
24316
24317    /// @brief create a MessagePack serialization of a given JSON value
24318    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24319    static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
24320    {
24321        std::vector<std::uint8_t> result;
24322        to_msgpack(j, result);
24323        return result;
24324    }
24325
24326    /// @brief create a MessagePack serialization of a given JSON value
24327    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24328    static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24329    {
24330        binary_writer<std::uint8_t>(o).write_msgpack(j);
24331    }
24332
24333    /// @brief create a MessagePack serialization of a given JSON value
24334    /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
24335    static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
24336    {
24337        binary_writer<char>(o).write_msgpack(j);
24338    }
24339
24340    /// @brief create a UBJSON serialization of a given JSON value
24341    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24342    static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
24343            const bool use_size = false,
24344            const bool use_type = false)
24345    {
24346        std::vector<std::uint8_t> result;
24347        to_ubjson(j, result, use_size, use_type);
24348        return result;
24349    }
24350
24351    /// @brief create a UBJSON serialization of a given JSON value
24352    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24353    static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
24354                          const bool use_size = false, const bool use_type = false)
24355    {
24356        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
24357    }
24358
24359    /// @brief create a UBJSON serialization of a given JSON value
24360    /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
24361    static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
24362                          const bool use_size = false, const bool use_type = false)
24363    {
24364        binary_writer<char>(o).write_ubjson(j, use_size, use_type);
24365    }
24366
24367    /// @brief create a BJData serialization of a given JSON value
24368    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24369    static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
24370            const bool use_size = false,
24371            const bool use_type = false,
24372            const bjdata_version_t version = bjdata_version_t::draft2)
24373    {
24374        std::vector<std::uint8_t> result;
24375        to_bjdata(j, result, use_size, use_type, version);
24376        return result;
24377    }
24378
24379    /// @brief create a BJData serialization of a given JSON value
24380    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24381    static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
24382                          const bool use_size = false, const bool use_type = false,
24383                          const bjdata_version_t version = bjdata_version_t::draft2)
24384    {
24385        binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true, version);
24386    }
24387
24388    /// @brief create a BJData serialization of a given JSON value
24389    /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
24390    static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
24391                          const bool use_size = false, const bool use_type = false,
24392                          const bjdata_version_t version = bjdata_version_t::draft2)
24393    {
24394        binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true, version);
24395    }
24396
24397    /// @brief create a BSON serialization of a given JSON value
24398    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24399    static std::vector<std::uint8_t> to_bson(const basic_json& j)
24400    {
24401        std::vector<std::uint8_t> result;
24402        to_bson(j, result);
24403        return result;
24404    }
24405
24406    /// @brief create a BSON serialization of a given JSON value
24407    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24408    static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
24409    {
24410        binary_writer<std::uint8_t>(o).write_bson(j);
24411    }
24412
24413    /// @brief create a BSON serialization of a given JSON value
24414    /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
24415    static void to_bson(const basic_json& j, detail::output_adapter<char> o)
24416    {
24417        binary_writer<char>(o).write_bson(j);
24418    }
24419
24420    /// @brief create a JSON value from an input in CBOR format
24421    /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
24422    template<typename InputType>
24423    JSON_HEDLEY_WARN_UNUSED_RESULT
24424    static basic_json from_cbor(InputType&& i,
24425                                const bool strict = true,
24426                                const bool allow_exceptions = true,
24427                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24428    {
24429        basic_json result;
24430        auto ia = detail::input_adapter(std::forward<InputType>(i));
24431        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24432        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24433        return res ? result : basic_json(value_t::discarded);
24434    }
24435
24436    /// @brief create a JSON value from an input in CBOR format
24437    /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
24438    template<typename IteratorType>
24439    JSON_HEDLEY_WARN_UNUSED_RESULT
24440    static basic_json from_cbor(IteratorType first, IteratorType last,
24441                                const bool strict = true,
24442                                const bool allow_exceptions = true,
24443                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24444    {
24445        basic_json result;
24446        auto ia = detail::input_adapter(std::move(first), std::move(last));
24447        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24448        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24449        return res ? result : basic_json(value_t::discarded);
24450    }
24451
24452    template<typename T>
24453    JSON_HEDLEY_WARN_UNUSED_RESULT
24454    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24455    static basic_json from_cbor(const T* ptr, std::size_t len,
24456                                const bool strict = true,
24457                                const bool allow_exceptions = true,
24458                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24459    {
24460        return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
24461    }
24462
24463    JSON_HEDLEY_WARN_UNUSED_RESULT
24464    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
24465    static basic_json from_cbor(detail::span_input_adapter&& i,
24466                                const bool strict = true,
24467                                const bool allow_exceptions = true,
24468                                const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
24469    {
24470        basic_json result;
24471        auto ia = i.get();
24472        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24473        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24474        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler); // cppcheck-suppress[accessMoved]
24475        return res ? result : basic_json(value_t::discarded);
24476    }
24477
24478    /// @brief create a JSON value from an input in MessagePack format
24479    /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
24480    template<typename InputType>
24481    JSON_HEDLEY_WARN_UNUSED_RESULT
24482    static basic_json from_msgpack(InputType&& i,
24483                                   const bool strict = true,
24484                                   const bool allow_exceptions = true)
24485    {
24486        basic_json result;
24487        auto ia = detail::input_adapter(std::forward<InputType>(i));
24488        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24489        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24490        return res ? result : basic_json(value_t::discarded);
24491    }
24492
24493    /// @brief create a JSON value from an input in MessagePack format
24494    /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
24495    template<typename IteratorType>
24496    JSON_HEDLEY_WARN_UNUSED_RESULT
24497    static basic_json from_msgpack(IteratorType first, IteratorType last,
24498                                   const bool strict = true,
24499                                   const bool allow_exceptions = true)
24500    {
24501        basic_json result;
24502        auto ia = detail::input_adapter(std::move(first), std::move(last));
24503        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24504        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24505        return res ? result : basic_json(value_t::discarded);
24506    }
24507
24508    template<typename T>
24509    JSON_HEDLEY_WARN_UNUSED_RESULT
24510    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24511    static basic_json from_msgpack(const T* ptr, std::size_t len,
24512                                   const bool strict = true,
24513                                   const bool allow_exceptions = true)
24514    {
24515        return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
24516    }
24517
24518    JSON_HEDLEY_WARN_UNUSED_RESULT
24519    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
24520    static basic_json from_msgpack(detail::span_input_adapter&& i,
24521                                   const bool strict = true,
24522                                   const bool allow_exceptions = true)
24523    {
24524        basic_json result;
24525        auto ia = i.get();
24526        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24527        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24528        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict); // cppcheck-suppress[accessMoved]
24529        return res ? result : basic_json(value_t::discarded);
24530    }
24531
24532    /// @brief create a JSON value from an input in UBJSON format
24533    /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
24534    template<typename InputType>
24535    JSON_HEDLEY_WARN_UNUSED_RESULT
24536    static basic_json from_ubjson(InputType&& i,
24537                                  const bool strict = true,
24538                                  const bool allow_exceptions = true)
24539    {
24540        basic_json result;
24541        auto ia = detail::input_adapter(std::forward<InputType>(i));
24542        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24543        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24544        return res ? result : basic_json(value_t::discarded);
24545    }
24546
24547    /// @brief create a JSON value from an input in UBJSON format
24548    /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
24549    template<typename IteratorType>
24550    JSON_HEDLEY_WARN_UNUSED_RESULT
24551    static basic_json from_ubjson(IteratorType first, IteratorType last,
24552                                  const bool strict = true,
24553                                  const bool allow_exceptions = true)
24554    {
24555        basic_json result;
24556        auto ia = detail::input_adapter(std::move(first), std::move(last));
24557        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24558        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24559        return res ? result : basic_json(value_t::discarded);
24560    }
24561
24562    template<typename T>
24563    JSON_HEDLEY_WARN_UNUSED_RESULT
24564    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24565    static basic_json from_ubjson(const T* ptr, std::size_t len,
24566                                  const bool strict = true,
24567                                  const bool allow_exceptions = true)
24568    {
24569        return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
24570    }
24571
24572    JSON_HEDLEY_WARN_UNUSED_RESULT
24573    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
24574    static basic_json from_ubjson(detail::span_input_adapter&& i,
24575                                  const bool strict = true,
24576                                  const bool allow_exceptions = true)
24577    {
24578        basic_json result;
24579        auto ia = i.get();
24580        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24581        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24582        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict); // cppcheck-suppress[accessMoved]
24583        return res ? result : basic_json(value_t::discarded);
24584    }
24585
24586    /// @brief create a JSON value from an input in BJData format
24587    /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24588    template<typename InputType>
24589    JSON_HEDLEY_WARN_UNUSED_RESULT
24590    static basic_json from_bjdata(InputType&& i,
24591                                  const bool strict = true,
24592                                  const bool allow_exceptions = true)
24593    {
24594        basic_json result;
24595        auto ia = detail::input_adapter(std::forward<InputType>(i));
24596        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24597        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24598        return res ? result : basic_json(value_t::discarded);
24599    }
24600
24601    /// @brief create a JSON value from an input in BJData format
24602    /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
24603    template<typename IteratorType>
24604    JSON_HEDLEY_WARN_UNUSED_RESULT
24605    static basic_json from_bjdata(IteratorType first, IteratorType last,
24606                                  const bool strict = true,
24607                                  const bool allow_exceptions = true)
24608    {
24609        basic_json result;
24610        auto ia = detail::input_adapter(std::move(first), std::move(last));
24611        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24612        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict); // cppcheck-suppress[accessMoved]
24613        return res ? result : basic_json(value_t::discarded);
24614    }
24615
24616    /// @brief create a JSON value from an input in BSON format
24617    /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24618    template<typename InputType>
24619    JSON_HEDLEY_WARN_UNUSED_RESULT
24620    static basic_json from_bson(InputType&& i,
24621                                const bool strict = true,
24622                                const bool allow_exceptions = true)
24623    {
24624        basic_json result;
24625        auto ia = detail::input_adapter(std::forward<InputType>(i));
24626        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24627        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24628        return res ? result : basic_json(value_t::discarded);
24629    }
24630
24631    /// @brief create a JSON value from an input in BSON format
24632    /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
24633    template<typename IteratorType>
24634    JSON_HEDLEY_WARN_UNUSED_RESULT
24635    static basic_json from_bson(IteratorType first, IteratorType last,
24636                                const bool strict = true,
24637                                const bool allow_exceptions = true)
24638    {
24639        basic_json result;
24640        auto ia = detail::input_adapter(std::move(first), std::move(last));
24641        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24642        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24643        return res ? result : basic_json(value_t::discarded);
24644    }
24645
24646    template<typename T>
24647    JSON_HEDLEY_WARN_UNUSED_RESULT
24648    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24649    static basic_json from_bson(const T* ptr, std::size_t len,
24650                                const bool strict = true,
24651                                const bool allow_exceptions = true)
24652    {
24653        return from_bson(ptr, ptr + len, strict, allow_exceptions);
24654    }
24655
24656    JSON_HEDLEY_WARN_UNUSED_RESULT
24657    JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
24658    static basic_json from_bson(detail::span_input_adapter&& i,
24659                                const bool strict = true,
24660                                const bool allow_exceptions = true)
24661    {
24662        basic_json result;
24663        auto ia = i.get();
24664        detail::json_sax_dom_parser<basic_json, decltype(ia)> sdp(result, allow_exceptions);
24665        // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
24666        const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict); // cppcheck-suppress[accessMoved]
24667        return res ? result : basic_json(value_t::discarded);
24668    }
24669    /// @}
24670
24671    //////////////////////////
24672    // JSON Pointer support //
24673    //////////////////////////
24674
24675    /// @name JSON Pointer functions
24676    /// @{
24677
24678    /// @brief access specified element via JSON Pointer
24679    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24680    reference operator[](const json_pointer& ptr)
24681    {
24682        return ptr.get_unchecked(this);
24683    }
24684
24685    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24686    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24687    reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24688    {
24689        return ptr.get_unchecked(this);
24690    }
24691
24692    /// @brief access specified element via JSON Pointer
24693    /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
24694    const_reference operator[](const json_pointer& ptr) const
24695    {
24696        return ptr.get_unchecked(this);
24697    }
24698
24699    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24700    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24701    const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24702    {
24703        return ptr.get_unchecked(this);
24704    }
24705
24706    /// @brief access specified element via JSON Pointer
24707    /// @sa https://json.nlohmann.me/api/basic_json/at/
24708    reference at(const json_pointer& ptr)
24709    {
24710        return ptr.get_checked(this);
24711    }
24712
24713    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24714    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24715    reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
24716    {
24717        return ptr.get_checked(this);
24718    }
24719
24720    /// @brief access specified element via JSON Pointer
24721    /// @sa https://json.nlohmann.me/api/basic_json/at/
24722    const_reference at(const json_pointer& ptr) const
24723    {
24724        return ptr.get_checked(this);
24725    }
24726
24727    template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
24728    JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
24729    const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
24730    {
24731        return ptr.get_checked(this);
24732    }
24733
24734    /// @brief return flattened JSON value
24735    /// @sa https://json.nlohmann.me/api/basic_json/flatten/
24736    basic_json flatten() const
24737    {
24738        basic_json result(value_t::object);
24739        json_pointer::flatten("", *this, result);
24740        return result;
24741    }
24742
24743    /// @brief unflatten a previously flattened JSON value
24744    /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
24745    basic_json unflatten() const
24746    {
24747        return json_pointer::unflatten(*this);
24748    }
24749
24750    /// @}
24751
24752    //////////////////////////
24753    // JSON Patch functions //
24754    //////////////////////////
24755
24756    /// @name JSON Patch functions
24757    /// @{
24758
24759    /// @brief applies a JSON patch in-place without copying the object
24760    /// @sa https://json.nlohmann.me/api/basic_json/patch/
24761    void patch_inplace(const basic_json& json_patch)
24762    {
24763        basic_json& result = *this;
24764        // the valid JSON Patch operations
24765        enum class patch_operations {add, remove, replace, move, copy, test, invalid};
24766
24767        const auto get_op = [](const string_t& op)
24768        {
24769            if (op == "add")
24770            {
24771                return patch_operations::add;
24772            }
24773            if (op == "remove")
24774            {
24775                return patch_operations::remove;
24776            }
24777            if (op == "replace")
24778            {
24779                return patch_operations::replace;
24780            }
24781            if (op == "move")
24782            {
24783                return patch_operations::move;
24784            }
24785            if (op == "copy")
24786            {
24787                return patch_operations::copy;
24788            }
24789            if (op == "test")
24790            {
24791                return patch_operations::test;
24792            }
24793
24794            return patch_operations::invalid;
24795        };
24796
24797        // wrapper for "add" operation; add value at ptr
24798        const auto operation_add = [&result](json_pointer & ptr, const basic_json & val)
24799        {
24800            // adding to the root of the target document means replacing it
24801            if (ptr.empty())
24802            {
24803                result = val;
24804                return;
24805            }
24806
24807            // make sure the top element of the pointer exists
24808            json_pointer const top_pointer = ptr.top();
24809            if (top_pointer != ptr)
24810            {
24811                result.at(top_pointer);
24812            }
24813
24814            // get reference to parent of JSON pointer ptr
24815            const auto last_path = ptr.back();
24816            ptr.pop_back();
24817            // parent must exist when performing patch add per RFC6902 specs
24818            basic_json& parent = result.at(ptr);
24819
24820            switch (parent.m_data.m_type)
24821            {
24822                case value_t::null:
24823                case value_t::object:
24824                {
24825                    // use operator[] to add value
24826                    parent[last_path] = val;
24827                    break;
24828                }
24829
24830                case value_t::array:
24831                {
24832                    if (last_path == "-")
24833                    {
24834                        // special case: append to back
24835                        parent.push_back(val);
24836                    }
24837                    else
24838                    {
24839                        const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
24840                        if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
24841                        {
24842                            // avoid undefined behavior
24843                            JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
24844                        }
24845
24846                        // default case: insert add offset
24847                        parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
24848                    }
24849                    break;
24850                }
24851
24852                // if there exists a parent it cannot be primitive
24853                case value_t::string: // LCOV_EXCL_LINE
24854                case value_t::boolean: // LCOV_EXCL_LINE
24855                case value_t::number_integer: // LCOV_EXCL_LINE
24856                case value_t::number_unsigned: // LCOV_EXCL_LINE
24857                case value_t::number_float: // LCOV_EXCL_LINE
24858                case value_t::binary: // LCOV_EXCL_LINE
24859                case value_t::discarded: // LCOV_EXCL_LINE
24860                default:            // LCOV_EXCL_LINE
24861                    JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
24862            }
24863        };
24864
24865        // wrapper for "remove" operation; remove value at ptr
24866        const auto operation_remove = [this, & result](json_pointer & ptr)
24867        {
24868            // get reference to parent of JSON pointer ptr
24869            const auto last_path = ptr.back();
24870            ptr.pop_back();
24871            basic_json& parent = result.at(ptr);
24872
24873            // remove child
24874            if (parent.is_object())
24875            {
24876                // perform range check
24877                auto it = parent.find(last_path);
24878                if (JSON_HEDLEY_LIKELY(it != parent.end()))
24879                {
24880                    parent.erase(it);
24881                }
24882                else
24883                {
24884                    JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
24885                }
24886            }
24887            else if (parent.is_array())
24888            {
24889                // note erase performs range check
24890                parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
24891            }
24892        };
24893
24894        // type check: top level value must be an array
24895        if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
24896        {
24897            JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
24898        }
24899
24900        // iterate and apply the operations
24901        for (const auto& val : json_patch)
24902        {
24903            // wrapper to get a value for an operation
24904            const auto get_value = [&val](const string_t& op,
24905                                          const string_t& member,
24906                                          bool string_type) -> basic_json &
24907            {
24908                // find value
24909                auto it = val.m_data.m_value.object->find(member);
24910
24911                // context-sensitive error message
24912                const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\''); // NOLINT(bugprone-unused-local-non-trivial-variable)
24913
24914                // check if desired value is present
24915                if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
24916                {
24917                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24918                    JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
24919                }
24920
24921                // check if result is of type string
24922                if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
24923                {
24924                    // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
24925                    JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
24926                }
24927
24928                // no error: return value
24929                return it->second;
24930            };
24931
24932            // type check: every element of the array must be an object
24933            if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
24934            {
24935                JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
24936            }
24937
24938            // collect mandatory members
24939            const auto op = get_value("op", "op", true).template get<string_t>();
24940            const auto path = get_value(op, "path", true).template get<string_t>();
24941            json_pointer ptr(path);
24942
24943            switch (get_op(op))
24944            {
24945                case patch_operations::add:
24946                {
24947                    operation_add(ptr, get_value("add", "value", false));
24948                    break;
24949                }
24950
24951                case patch_operations::remove:
24952                {
24953                    operation_remove(ptr);
24954                    break;
24955                }
24956
24957                case patch_operations::replace:
24958                {
24959                    // the "path" location must exist - use at()
24960                    result.at(ptr) = get_value("replace", "value", false);
24961                    break;
24962                }
24963
24964                case patch_operations::move:
24965                {
24966                    const auto from_path = get_value("move", "from", true).template get<string_t>();
24967                    json_pointer from_ptr(from_path);
24968
24969                    // the "from" location must exist - use at()
24970                    basic_json const v = result.at(from_ptr);
24971
24972                    // The move operation is functionally identical to a
24973                    // "remove" operation on the "from" location, followed
24974                    // immediately by an "add" operation at the target
24975                    // location with the value that was just removed.
24976                    operation_remove(from_ptr);
24977                    operation_add(ptr, v);
24978                    break;
24979                }
24980
24981                case patch_operations::copy:
24982                {
24983                    const auto from_path = get_value("copy", "from", true).template get<string_t>();
24984                    const json_pointer from_ptr(from_path);
24985
24986                    // the "from" location must exist - use at()
24987                    basic_json const v = result.at(from_ptr);
24988
24989                    // The copy is functionally identical to an "add"
24990                    // operation at the target location using the value
24991                    // specified in the "from" member.
24992                    operation_add(ptr, v);
24993                    break;
24994                }
24995
24996                case patch_operations::test:
24997                {
24998                    bool success = false;
24999                    JSON_TRY
25000                    {
25001                        // check if "value" matches the one at "path"
25002                        // the "path" location must exist - use at()
25003                        success = (result.at(ptr) == get_value("test", "value", false));
25004                    }
25005                    JSON_INTERNAL_CATCH (out_of_range&)
25006                    {
25007                        // ignore out of range errors: success remains false
25008                    }
25009
25010                    // throw an exception if test fails
25011                    if (JSON_HEDLEY_UNLIKELY(!success))
25012                    {
25013                        JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
25014                    }
25015
25016                    break;
25017                }
25018
25019                case patch_operations::invalid:
25020                default:
25021                {
25022                    // op must be "add", "remove", "replace", "move", "copy", or
25023                    // "test"
25024                    JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
25025                }
25026            }
25027        }
25028    }
25029
25030    /// @brief applies a JSON patch to a copy of the current object
25031    /// @sa https://json.nlohmann.me/api/basic_json/patch/
25032    basic_json patch(const basic_json& json_patch) const
25033    {
25034        basic_json result = *this;
25035        result.patch_inplace(json_patch);
25036        return result;
25037    }
25038
25039    /// @brief creates a diff as a JSON patch
25040    /// @sa https://json.nlohmann.me/api/basic_json/diff/
25041    JSON_HEDLEY_WARN_UNUSED_RESULT
25042    static basic_json diff(const basic_json& source, const basic_json& target,
25043                           const string_t& path = "")
25044    {
25045        // the patch
25046        basic_json result(value_t::array);
25047
25048        // if the values are the same, return empty patch
25049        if (source == target)
25050        {
25051            return result;
25052        }
25053
25054        if (source.type() != target.type())
25055        {
25056            // different types: replace value
25057            result.push_back(
25058            {
25059                {"op", "replace"}, {"path", path}, {"value", target}
25060            });
25061            return result;
25062        }
25063
25064        switch (source.type())
25065        {
25066            case value_t::array:
25067            {
25068                // first pass: traverse common elements
25069                std::size_t i = 0;
25070                while (i < source.size() && i < target.size())
25071                {
25072                    // recursive call to compare array values at index i
25073                    auto temp_diff = diff(source[i], target[i], detail::concat<string_t>(path, '/', detail::to_string<string_t>(i)));
25074                    result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25075                    ++i;
25076                }
25077
25078                // We now reached the end of at least one array
25079                // in a second pass, traverse the remaining elements
25080
25081                // remove my remaining elements
25082                const auto end_index = static_cast<difference_type>(result.size());
25083                while (i < source.size())
25084                {
25085                    // add operations in reverse order to avoid invalid
25086                    // indices
25087                    result.insert(result.begin() + end_index, object(
25088                    {
25089                        {"op", "remove"},
25090                        {"path", detail::concat<string_t>(path, '/', detail::to_string<string_t>(i))}
25091                    }));
25092                    ++i;
25093                }
25094
25095                // add other remaining elements
25096                while (i < target.size())
25097                {
25098                    result.push_back(
25099                    {
25100                        {"op", "add"},
25101                        {"path", detail::concat<string_t>(path, "/-")},
25102                        {"value", target[i]}
25103                    });
25104                    ++i;
25105                }
25106
25107                break;
25108            }
25109
25110            case value_t::object:
25111            {
25112                // first pass: traverse this object's elements
25113                for (auto it = source.cbegin(); it != source.cend(); ++it)
25114                {
25115                    // escape the key name to be used in a JSON patch
25116                    const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25117
25118                    if (target.find(it.key()) != target.end())
25119                    {
25120                        // recursive call to compare object values at key it
25121                        auto temp_diff = diff(it.value(), target[it.key()], path_key);
25122                        result.insert(result.end(), temp_diff.begin(), temp_diff.end());
25123                    }
25124                    else
25125                    {
25126                        // found a key that is not in o -> remove it
25127                        result.push_back(object(
25128                        {
25129                            {"op", "remove"}, {"path", path_key}
25130                        }));
25131                    }
25132                }
25133
25134                // second pass: traverse other object's elements
25135                for (auto it = target.cbegin(); it != target.cend(); ++it)
25136                {
25137                    if (source.find(it.key()) == source.end())
25138                    {
25139                        // found a key that is not in this -> add it
25140                        const auto path_key = detail::concat<string_t>(path, '/', detail::escape(it.key()));
25141                        result.push_back(
25142                        {
25143                            {"op", "add"}, {"path", path_key},
25144                            {"value", it.value()}
25145                        });
25146                    }
25147                }
25148
25149                break;
25150            }
25151
25152            case value_t::null:
25153            case value_t::string:
25154            case value_t::boolean:
25155            case value_t::number_integer:
25156            case value_t::number_unsigned:
25157            case value_t::number_float:
25158            case value_t::binary:
25159            case value_t::discarded:
25160            default:
25161            {
25162                // both primitive type: replace value
25163                result.push_back(
25164                {
25165                    {"op", "replace"}, {"path", path}, {"value", target}
25166                });
25167                break;
25168            }
25169        }
25170
25171        return result;
25172    }
25173    /// @}
25174
25175    ////////////////////////////////
25176    // JSON Merge Patch functions //
25177    ////////////////////////////////
25178
25179    /// @name JSON Merge Patch functions
25180    /// @{
25181
25182    /// @brief applies a JSON Merge Patch
25183    /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
25184    void merge_patch(const basic_json& apply_patch)
25185    {
25186        if (apply_patch.is_object())
25187        {
25188            if (!is_object())
25189            {
25190                *this = object();
25191            }
25192            for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
25193            {
25194                if (it.value().is_null())
25195                {
25196                    erase(it.key());
25197                }
25198                else
25199                {
25200                    operator[](it.key()).merge_patch(it.value());
25201                }
25202            }
25203        }
25204        else
25205        {
25206            *this = apply_patch;
25207        }
25208    }
25209
25210    /// @}
25211};
25212
25213/// @brief user-defined to_string function for JSON values
25214/// @sa https://json.nlohmann.me/api/basic_json/to_string/
25215NLOHMANN_BASIC_JSON_TPL_DECLARATION
25216std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
25217{
25218    return j.dump();
25219}
25220
25221inline namespace literals
25222{
25223inline namespace json_literals
25224{
25225
25226/// @brief user-defined string literal for JSON values
25227/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
25228JSON_HEDLEY_NON_NULL(1)
25229#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25230    inline nlohmann::json operator ""_json(const char* s, std::size_t n)
25231#else
25232    inline nlohmann::json operator "" _json(const char* s, std::size_t n)
25233#endif
25234{
25235    return nlohmann::json::parse(s, s + n);
25236}
25237
25238/// @brief user-defined string literal for JSON pointer
25239/// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
25240JSON_HEDLEY_NON_NULL(1)
25241#if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25242    inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
25243#else
25244    inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
25245#endif
25246{
25247    return nlohmann::json::json_pointer(std::string(s, n));
25248}
25249
25250}  // namespace json_literals
25251}  // namespace literals
25252NLOHMANN_JSON_NAMESPACE_END
25253
25254///////////////////////
25255// nonmember support //
25256///////////////////////
25257
25258namespace std // NOLINT(cert-dcl58-cpp)
25259{
25260
25261/// @brief hash value for JSON objects
25262/// @sa https://json.nlohmann.me/api/basic_json/std_hash/
25263NLOHMANN_BASIC_JSON_TPL_DECLARATION
25264struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
25265{
25266    std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
25267    {
25268        return nlohmann::detail::hash(j);
25269    }
25270};
25271
25272// specialization for std::less<value_t>
25273template<>
25274struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
25275{
25276    /*!
25277    @brief compare two value_t enum values
25278    @since version 3.0.0
25279    */
25280    bool operator()(::nlohmann::detail::value_t lhs,
25281                    ::nlohmann::detail::value_t rhs) const noexcept
25282    {
25283#if JSON_HAS_THREE_WAY_COMPARISON
25284        return std::is_lt(lhs <=> rhs); // *NOPAD*
25285#else
25286        return ::nlohmann::detail::operator<(lhs, rhs);
25287#endif
25288    }
25289};
25290
25291// C++20 prohibit function specialization in the std namespace.
25292#ifndef JSON_HAS_CPP_20
25293
25294/// @brief exchanges the values of two JSON objects
25295/// @sa https://json.nlohmann.me/api/basic_json/std_swap/
25296NLOHMANN_BASIC_JSON_TPL_DECLARATION
25297inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
25298    is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
25299    is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
25300{
25301    j1.swap(j2);
25302}
25303
25304#endif
25305
25306}  // namespace std
25307
25308#if JSON_USE_GLOBAL_UDLS
25309    #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
25310        using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25311        using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25312    #else
25313        using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25314        using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
25315    #endif
25316#endif
25317
25318// #include <nlohmann/detail/macro_unscope.hpp>
25319//     __ _____ _____ _____
25320//  __|  |   __|     |   | |  JSON for Modern C++
25321// |  |  |__   |  |  | | | |  version 3.12.0
25322// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
25323//
25324// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25325// SPDX-License-Identifier: MIT
25326
25327
25328
25329// restore clang diagnostic settings
25330#if defined(__clang__)
25331    #pragma clang diagnostic pop
25332#endif
25333
25334// clean up
25335#undef JSON_ASSERT
25336#undef JSON_INTERNAL_CATCH
25337#undef JSON_THROW
25338#undef JSON_PRIVATE_UNLESS_TESTED
25339#undef NLOHMANN_BASIC_JSON_TPL_DECLARATION
25340#undef NLOHMANN_BASIC_JSON_TPL
25341#undef JSON_EXPLICIT
25342#undef NLOHMANN_CAN_CALL_STD_FUNC_IMPL
25343#undef JSON_INLINE_VARIABLE
25344#undef JSON_NO_UNIQUE_ADDRESS
25345#undef JSON_DISABLE_ENUM_SERIALIZATION
25346#undef JSON_USE_GLOBAL_UDLS
25347
25348#ifndef JSON_TEST_KEEP_MACROS
25349    #undef JSON_CATCH
25350    #undef JSON_TRY
25351    #undef JSON_HAS_CPP_11
25352    #undef JSON_HAS_CPP_14
25353    #undef JSON_HAS_CPP_17
25354    #undef JSON_HAS_CPP_20
25355    #undef JSON_HAS_CPP_23
25356    #undef JSON_HAS_FILESYSTEM
25357    #undef JSON_HAS_EXPERIMENTAL_FILESYSTEM
25358    #undef JSON_HAS_THREE_WAY_COMPARISON
25359    #undef JSON_HAS_RANGES
25360    #undef JSON_HAS_STATIC_RTTI
25361    #undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
25362#endif
25363
25364// #include <nlohmann/thirdparty/hedley/hedley_undef.hpp>
25365//     __ _____ _____ _____
25366//  __|  |   __|     |   | |  JSON for Modern C++
25367// |  |  |__   |  |  | | | |  version 3.12.0
25368// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
25369//
25370// SPDX-FileCopyrightText: 2013 - 2025 Niels Lohmann <https://nlohmann.me>
25371// SPDX-License-Identifier: MIT
25372
25373
25374
25375#undef JSON_HEDLEY_ALWAYS_INLINE
25376#undef JSON_HEDLEY_ARM_VERSION
25377#undef JSON_HEDLEY_ARM_VERSION_CHECK
25378#undef JSON_HEDLEY_ARRAY_PARAM
25379#undef JSON_HEDLEY_ASSUME
25380#undef JSON_HEDLEY_BEGIN_C_DECLS
25381#undef JSON_HEDLEY_CLANG_HAS_ATTRIBUTE
25382#undef JSON_HEDLEY_CLANG_HAS_BUILTIN
25383#undef JSON_HEDLEY_CLANG_HAS_CPP_ATTRIBUTE
25384#undef JSON_HEDLEY_CLANG_HAS_DECLSPEC_DECLSPEC_ATTRIBUTE
25385#undef JSON_HEDLEY_CLANG_HAS_EXTENSION
25386#undef JSON_HEDLEY_CLANG_HAS_FEATURE
25387#undef JSON_HEDLEY_CLANG_HAS_WARNING
25388#undef JSON_HEDLEY_COMPCERT_VERSION
25389#undef JSON_HEDLEY_COMPCERT_VERSION_CHECK
25390#undef JSON_HEDLEY_CONCAT
25391#undef JSON_HEDLEY_CONCAT3
25392#undef JSON_HEDLEY_CONCAT3_EX
25393#undef JSON_HEDLEY_CONCAT_EX
25394#undef JSON_HEDLEY_CONST
25395#undef JSON_HEDLEY_CONSTEXPR
25396#undef JSON_HEDLEY_CONST_CAST
25397#undef JSON_HEDLEY_CPP_CAST
25398#undef JSON_HEDLEY_CRAY_VERSION
25399#undef JSON_HEDLEY_CRAY_VERSION_CHECK
25400#undef JSON_HEDLEY_C_DECL
25401#undef JSON_HEDLEY_DEPRECATED
25402#undef JSON_HEDLEY_DEPRECATED_FOR
25403#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CAST_QUAL
25404#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_CPP98_COMPAT_WRAP_
25405#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_DEPRECATED
25406#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_CPP_ATTRIBUTES
25407#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNKNOWN_PRAGMAS
25408#undef JSON_HEDLEY_DIAGNOSTIC_DISABLE_UNUSED_FUNCTION
25409#undef JSON_HEDLEY_DIAGNOSTIC_POP
25410#undef JSON_HEDLEY_DIAGNOSTIC_PUSH
25411#undef JSON_HEDLEY_DMC_VERSION
25412#undef JSON_HEDLEY_DMC_VERSION_CHECK
25413#undef JSON_HEDLEY_EMPTY_BASES
25414#undef JSON_HEDLEY_EMSCRIPTEN_VERSION
25415#undef JSON_HEDLEY_EMSCRIPTEN_VERSION_CHECK
25416#undef JSON_HEDLEY_END_C_DECLS
25417#undef JSON_HEDLEY_FLAGS
25418#undef JSON_HEDLEY_FLAGS_CAST
25419#undef JSON_HEDLEY_GCC_HAS_ATTRIBUTE
25420#undef JSON_HEDLEY_GCC_HAS_BUILTIN
25421#undef JSON_HEDLEY_GCC_HAS_CPP_ATTRIBUTE
25422#undef JSON_HEDLEY_GCC_HAS_DECLSPEC_ATTRIBUTE
25423#undef JSON_HEDLEY_GCC_HAS_EXTENSION
25424#undef JSON_HEDLEY_GCC_HAS_FEATURE
25425#undef JSON_HEDLEY_GCC_HAS_WARNING
25426#undef JSON_HEDLEY_GCC_NOT_CLANG_VERSION_CHECK
25427#undef JSON_HEDLEY_GCC_VERSION
25428#undef JSON_HEDLEY_GCC_VERSION_CHECK
25429#undef JSON_HEDLEY_GNUC_HAS_ATTRIBUTE
25430#undef JSON_HEDLEY_GNUC_HAS_BUILTIN
25431#undef JSON_HEDLEY_GNUC_HAS_CPP_ATTRIBUTE
25432#undef JSON_HEDLEY_GNUC_HAS_DECLSPEC_ATTRIBUTE
25433#undef JSON_HEDLEY_GNUC_HAS_EXTENSION
25434#undef JSON_HEDLEY_GNUC_HAS_FEATURE
25435#undef JSON_HEDLEY_GNUC_HAS_WARNING
25436#undef JSON_HEDLEY_GNUC_VERSION
25437#undef JSON_HEDLEY_GNUC_VERSION_CHECK
25438#undef JSON_HEDLEY_HAS_ATTRIBUTE
25439#undef JSON_HEDLEY_HAS_BUILTIN
25440#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE
25441#undef JSON_HEDLEY_HAS_CPP_ATTRIBUTE_NS
25442#undef JSON_HEDLEY_HAS_DECLSPEC_ATTRIBUTE
25443#undef JSON_HEDLEY_HAS_EXTENSION
25444#undef JSON_HEDLEY_HAS_FEATURE
25445#undef JSON_HEDLEY_HAS_WARNING
25446#undef JSON_HEDLEY_IAR_VERSION
25447#undef JSON_HEDLEY_IAR_VERSION_CHECK
25448#undef JSON_HEDLEY_IBM_VERSION
25449#undef JSON_HEDLEY_IBM_VERSION_CHECK
25450#undef JSON_HEDLEY_IMPORT
25451#undef JSON_HEDLEY_INLINE
25452#undef JSON_HEDLEY_INTEL_CL_VERSION
25453#undef JSON_HEDLEY_INTEL_CL_VERSION_CHECK
25454#undef JSON_HEDLEY_INTEL_VERSION
25455#undef JSON_HEDLEY_INTEL_VERSION_CHECK
25456#undef JSON_HEDLEY_IS_CONSTANT
25457#undef JSON_HEDLEY_IS_CONSTEXPR_
25458#undef JSON_HEDLEY_LIKELY
25459#undef JSON_HEDLEY_MALLOC
25460#undef JSON_HEDLEY_MCST_LCC_VERSION
25461#undef JSON_HEDLEY_MCST_LCC_VERSION_CHECK
25462#undef JSON_HEDLEY_MESSAGE
25463#undef JSON_HEDLEY_MSVC_VERSION
25464#undef JSON_HEDLEY_MSVC_VERSION_CHECK
25465#undef JSON_HEDLEY_NEVER_INLINE
25466#undef JSON_HEDLEY_NON_NULL
25467#undef JSON_HEDLEY_NO_ESCAPE
25468#undef JSON_HEDLEY_NO_RETURN
25469#undef JSON_HEDLEY_NO_THROW
25470#undef JSON_HEDLEY_NULL
25471#undef JSON_HEDLEY_PELLES_VERSION
25472#undef JSON_HEDLEY_PELLES_VERSION_CHECK
25473#undef JSON_HEDLEY_PGI_VERSION
25474#undef JSON_HEDLEY_PGI_VERSION_CHECK
25475#undef JSON_HEDLEY_PREDICT
25476#undef JSON_HEDLEY_PRINTF_FORMAT
25477#undef JSON_HEDLEY_PRIVATE
25478#undef JSON_HEDLEY_PUBLIC
25479#undef JSON_HEDLEY_PURE
25480#undef JSON_HEDLEY_REINTERPRET_CAST
25481#undef JSON_HEDLEY_REQUIRE
25482#undef JSON_HEDLEY_REQUIRE_CONSTEXPR
25483#undef JSON_HEDLEY_REQUIRE_MSG
25484#undef JSON_HEDLEY_RESTRICT
25485#undef JSON_HEDLEY_RETURNS_NON_NULL
25486#undef JSON_HEDLEY_SENTINEL
25487#undef JSON_HEDLEY_STATIC_ASSERT
25488#undef JSON_HEDLEY_STATIC_CAST
25489#undef JSON_HEDLEY_STRINGIFY
25490#undef JSON_HEDLEY_STRINGIFY_EX
25491#undef JSON_HEDLEY_SUNPRO_VERSION
25492#undef JSON_HEDLEY_SUNPRO_VERSION_CHECK
25493#undef JSON_HEDLEY_TINYC_VERSION
25494#undef JSON_HEDLEY_TINYC_VERSION_CHECK
25495#undef JSON_HEDLEY_TI_ARMCL_VERSION
25496#undef JSON_HEDLEY_TI_ARMCL_VERSION_CHECK
25497#undef JSON_HEDLEY_TI_CL2000_VERSION
25498#undef JSON_HEDLEY_TI_CL2000_VERSION_CHECK
25499#undef JSON_HEDLEY_TI_CL430_VERSION
25500#undef JSON_HEDLEY_TI_CL430_VERSION_CHECK
25501#undef JSON_HEDLEY_TI_CL6X_VERSION
25502#undef JSON_HEDLEY_TI_CL6X_VERSION_CHECK
25503#undef JSON_HEDLEY_TI_CL7X_VERSION
25504#undef JSON_HEDLEY_TI_CL7X_VERSION_CHECK
25505#undef JSON_HEDLEY_TI_CLPRU_VERSION
25506#undef JSON_HEDLEY_TI_CLPRU_VERSION_CHECK
25507#undef JSON_HEDLEY_TI_VERSION
25508#undef JSON_HEDLEY_TI_VERSION_CHECK
25509#undef JSON_HEDLEY_UNAVAILABLE
25510#undef JSON_HEDLEY_UNLIKELY
25511#undef JSON_HEDLEY_UNPREDICTABLE
25512#undef JSON_HEDLEY_UNREACHABLE
25513#undef JSON_HEDLEY_UNREACHABLE_RETURN
25514#undef JSON_HEDLEY_VERSION
25515#undef JSON_HEDLEY_VERSION_DECODE_MAJOR
25516#undef JSON_HEDLEY_VERSION_DECODE_MINOR
25517#undef JSON_HEDLEY_VERSION_DECODE_REVISION
25518#undef JSON_HEDLEY_VERSION_ENCODE
25519#undef JSON_HEDLEY_WARNING
25520#undef JSON_HEDLEY_WARN_UNUSED_RESULT
25521#undef JSON_HEDLEY_WARN_UNUSED_RESULT_MSG
25522#undef JSON_HEDLEY_FALL_THROUGH
25523
25524
25525
25526#endif  // INCLUDE_NLOHMANN_JSON_HPP_