Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-12-15 10:19:03

0001 //     __ _____ _____ _____
0002 //  __|  |   __|     |   | |  JSON for Modern C++
0003 // |  |  |__   |  |  | | | |  version 3.11.3
0004 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
0005 //
0006 // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
0007 // SPDX-License-Identifier: MIT
0008 
0009 /****************************************************************************\
0010  * Note on documentation: The source files contain links to the online      *
0011  * documentation of the public API at https://json.nlohmann.me. This URL    *
0012  * contains the most recent documentation and should also be applicable to  *
0013  * previous versions; documentation for deprecated functions is not         *
0014  * removed, but marked deprecated. See "Generate documentation" section in  *
0015  * file docs/README.md.                                                     *
0016 \****************************************************************************/
0017 
0018 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
0019 #define INCLUDE_NLOHMANN_JSON_HPP_
0020 
0021 #include <algorithm> // all_of, find, for_each
0022 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
0023 #include <functional> // hash, less
0024 #include <initializer_list> // initializer_list
0025 #ifndef JSON_NO_IO
0026     #include <iosfwd> // istream, ostream
0027 #endif  // JSON_NO_IO
0028 #include <iterator> // random_access_iterator_tag
0029 #include <memory> // unique_ptr
0030 #include <string> // string, stoi, to_string
0031 #include <utility> // declval, forward, move, pair, swap
0032 #include <vector> // vector
0033 
0034 #include <nlohmann/adl_serializer.hpp>
0035 #include <nlohmann/byte_container_with_subtype.hpp>
0036 #include <nlohmann/detail/conversions/from_json.hpp>
0037 #include <nlohmann/detail/conversions/to_json.hpp>
0038 #include <nlohmann/detail/exceptions.hpp>
0039 #include <nlohmann/detail/hash.hpp>
0040 #include <nlohmann/detail/input/binary_reader.hpp>
0041 #include <nlohmann/detail/input/input_adapters.hpp>
0042 #include <nlohmann/detail/input/lexer.hpp>
0043 #include <nlohmann/detail/input/parser.hpp>
0044 #include <nlohmann/detail/iterators/internal_iterator.hpp>
0045 #include <nlohmann/detail/iterators/iter_impl.hpp>
0046 #include <nlohmann/detail/iterators/iteration_proxy.hpp>
0047 #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
0048 #include <nlohmann/detail/iterators/primitive_iterator.hpp>
0049 #include <nlohmann/detail/json_custom_base_class.hpp>
0050 #include <nlohmann/detail/json_pointer.hpp>
0051 #include <nlohmann/detail/json_ref.hpp>
0052 #include <nlohmann/detail/macro_scope.hpp>
0053 #include <nlohmann/detail/string_concat.hpp>
0054 #include <nlohmann/detail/string_escape.hpp>
0055 #include <nlohmann/detail/meta/cpp_future.hpp>
0056 #include <nlohmann/detail/meta/type_traits.hpp>
0057 #include <nlohmann/detail/output/binary_writer.hpp>
0058 #include <nlohmann/detail/output/output_adapters.hpp>
0059 #include <nlohmann/detail/output/serializer.hpp>
0060 #include <nlohmann/detail/value_t.hpp>
0061 #include <nlohmann/json_fwd.hpp>
0062 #include <nlohmann/ordered_map.hpp>
0063 
0064 #if defined(JSON_HAS_CPP_17)
0065     #if JSON_HAS_STATIC_RTTI
0066         #include <any>
0067     #endif
0068     #include <string_view>
0069 #endif
0070 
0071 /*!
0072 @brief namespace for Niels Lohmann
0073 @see https://github.com/nlohmann
0074 @since version 1.0.0
0075 */
0076 NLOHMANN_JSON_NAMESPACE_BEGIN
0077 
0078 /*!
0079 @brief a class to store JSON values
0080 
0081 @internal
0082 @invariant The member variables @a m_value and @a m_type have the following
0083 relationship:
0084 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
0085 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
0086 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
0087 The invariants are checked by member function assert_invariant().
0088 
0089 @note ObjectType trick from https://stackoverflow.com/a/9860911
0090 @endinternal
0091 
0092 @since version 1.0.0
0093 
0094 @nosubgrouping
0095 */
0096 NLOHMANN_BASIC_JSON_TPL_DECLARATION
0097 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
0098     : public ::nlohmann::detail::json_base_class<CustomBaseClass>
0099 {
0100   private:
0101     template<detail::value_t> friend struct detail::external_constructor;
0102 
0103     template<typename>
0104     friend class ::nlohmann::json_pointer;
0105     // can be restored when json_pointer backwards compatibility is removed
0106     // friend ::nlohmann::json_pointer<StringType>;
0107 
0108     template<typename BasicJsonType, typename InputType>
0109     friend class ::nlohmann::detail::parser;
0110     friend ::nlohmann::detail::serializer<basic_json>;
0111     template<typename BasicJsonType>
0112     friend class ::nlohmann::detail::iter_impl;
0113     template<typename BasicJsonType, typename CharType>
0114     friend class ::nlohmann::detail::binary_writer;
0115     template<typename BasicJsonType, typename InputType, typename SAX>
0116     friend class ::nlohmann::detail::binary_reader;
0117     template<typename BasicJsonType>
0118     friend class ::nlohmann::detail::json_sax_dom_parser;
0119     template<typename BasicJsonType>
0120     friend class ::nlohmann::detail::json_sax_dom_callback_parser;
0121     friend class ::nlohmann::detail::exception;
0122 
0123     /// workaround type for MSVC
0124     using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
0125     using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
0126 
0127   JSON_PRIVATE_UNLESS_TESTED:
0128     // convenience aliases for types residing in namespace detail;
0129     using lexer = ::nlohmann::detail::lexer_base<basic_json>;
0130 
0131     template<typename InputAdapterType>
0132     static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
0133         InputAdapterType adapter,
0134         detail::parser_callback_t<basic_json>cb = nullptr,
0135         const bool allow_exceptions = true,
0136         const bool ignore_comments = false
0137     )
0138     {
0139         return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
0140                 std::move(cb), allow_exceptions, ignore_comments);
0141     }
0142 
0143   private:
0144     using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
0145     template<typename BasicJsonType>
0146     using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
0147     template<typename BasicJsonType>
0148     using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
0149     template<typename Iterator>
0150     using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
0151     template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
0152 
0153     template<typename CharType>
0154     using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
0155 
0156     template<typename InputType>
0157     using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
0158     template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
0159 
0160   JSON_PRIVATE_UNLESS_TESTED:
0161     using serializer = ::nlohmann::detail::serializer<basic_json>;
0162 
0163   public:
0164     using value_t = detail::value_t;
0165     /// JSON Pointer, see @ref nlohmann::json_pointer
0166     using json_pointer = ::nlohmann::json_pointer<StringType>;
0167     template<typename T, typename SFINAE>
0168     using json_serializer = JSONSerializer<T, SFINAE>;
0169     /// how to treat decoding errors
0170     using error_handler_t = detail::error_handler_t;
0171     /// how to treat CBOR tags
0172     using cbor_tag_handler_t = detail::cbor_tag_handler_t;
0173     /// helper type for initializer lists of basic_json values
0174     using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
0175 
0176     using input_format_t = detail::input_format_t;
0177     /// SAX interface type, see @ref nlohmann::json_sax
0178     using json_sax_t = json_sax<basic_json>;
0179 
0180     ////////////////
0181     // exceptions //
0182     ////////////////
0183 
0184     /// @name exceptions
0185     /// Classes to implement user-defined exceptions.
0186     /// @{
0187 
0188     using exception = detail::exception;
0189     using parse_error = detail::parse_error;
0190     using invalid_iterator = detail::invalid_iterator;
0191     using type_error = detail::type_error;
0192     using out_of_range = detail::out_of_range;
0193     using other_error = detail::other_error;
0194 
0195     /// @}
0196 
0197     /////////////////////
0198     // container types //
0199     /////////////////////
0200 
0201     /// @name container types
0202     /// The canonic container types to use @ref basic_json like any other STL
0203     /// container.
0204     /// @{
0205 
0206     /// the type of elements in a basic_json container
0207     using value_type = basic_json;
0208 
0209     /// the type of an element reference
0210     using reference = value_type&;
0211     /// the type of an element const reference
0212     using const_reference = const value_type&;
0213 
0214     /// a type to represent differences between iterators
0215     using difference_type = std::ptrdiff_t;
0216     /// a type to represent container sizes
0217     using size_type = std::size_t;
0218 
0219     /// the allocator type
0220     using allocator_type = AllocatorType<basic_json>;
0221 
0222     /// the type of an element pointer
0223     using pointer = typename std::allocator_traits<allocator_type>::pointer;
0224     /// the type of an element const pointer
0225     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
0226 
0227     /// an iterator for a basic_json container
0228     using iterator = iter_impl<basic_json>;
0229     /// a const iterator for a basic_json container
0230     using const_iterator = iter_impl<const basic_json>;
0231     /// a reverse iterator for a basic_json container
0232     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
0233     /// a const reverse iterator for a basic_json container
0234     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
0235 
0236     /// @}
0237 
0238     /// @brief returns the allocator associated with the container
0239     /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
0240     static allocator_type get_allocator()
0241     {
0242         return allocator_type();
0243     }
0244 
0245     /// @brief returns version information on the library
0246     /// @sa https://json.nlohmann.me/api/basic_json/meta/
0247     JSON_HEDLEY_WARN_UNUSED_RESULT
0248     static basic_json meta()
0249     {
0250         basic_json result;
0251 
0252         result["copyright"] = "(C) 2013-2023 Niels Lohmann";
0253         result["name"] = "JSON for Modern C++";
0254         result["url"] = "https://github.com/nlohmann/json";
0255         result["version"]["string"] =
0256             detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
0257                            std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
0258                            std::to_string(NLOHMANN_JSON_VERSION_PATCH));
0259         result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
0260         result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
0261         result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
0262 
0263 #ifdef _WIN32
0264         result["platform"] = "win32";
0265 #elif defined __linux__
0266         result["platform"] = "linux";
0267 #elif defined __APPLE__
0268         result["platform"] = "apple";
0269 #elif defined __unix__
0270         result["platform"] = "unix";
0271 #else
0272         result["platform"] = "unknown";
0273 #endif
0274 
0275 #if defined(__ICC) || defined(__INTEL_COMPILER)
0276         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
0277 #elif defined(__clang__)
0278         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
0279 #elif defined(__GNUC__) || defined(__GNUG__)
0280         result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
0281                     std::to_string(__GNUC__), '.',
0282                     std::to_string(__GNUC_MINOR__), '.',
0283                     std::to_string(__GNUC_PATCHLEVEL__))
0284             }
0285         };
0286 #elif defined(__HP_cc) || defined(__HP_aCC)
0287         result["compiler"] = "hp"
0288 #elif defined(__IBMCPP__)
0289         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
0290 #elif defined(_MSC_VER)
0291         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
0292 #elif defined(__PGI)
0293         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
0294 #elif defined(__SUNPRO_CC)
0295         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
0296 #else
0297         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
0298 #endif
0299 
0300 #if defined(_MSVC_LANG)
0301         result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
0302 #elif defined(__cplusplus)
0303         result["compiler"]["c++"] = std::to_string(__cplusplus);
0304 #else
0305         result["compiler"]["c++"] = "unknown";
0306 #endif
0307         return result;
0308     }
0309 
0310     ///////////////////////////
0311     // JSON value data types //
0312     ///////////////////////////
0313 
0314     /// @name JSON value data types
0315     /// The data types to store a JSON value. These types are derived from
0316     /// the template arguments passed to class @ref basic_json.
0317     /// @{
0318 
0319     /// @brief default object key comparator type
0320     /// The actual object key comparator type (@ref object_comparator_t) may be
0321     /// different.
0322     /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
0323 #if defined(JSON_HAS_CPP_14)
0324     // use of transparent comparator avoids unnecessary repeated construction of temporaries
0325     // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
0326     using default_object_comparator_t = std::less<>;
0327 #else
0328     using default_object_comparator_t = std::less<StringType>;
0329 #endif
0330 
0331     /// @brief a type for an object
0332     /// @sa https://json.nlohmann.me/api/basic_json/object_t/
0333     using object_t = ObjectType<StringType,
0334           basic_json,
0335           default_object_comparator_t,
0336           AllocatorType<std::pair<const StringType,
0337           basic_json>>>;
0338 
0339     /// @brief a type for an array
0340     /// @sa https://json.nlohmann.me/api/basic_json/array_t/
0341     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
0342 
0343     /// @brief a type for a string
0344     /// @sa https://json.nlohmann.me/api/basic_json/string_t/
0345     using string_t = StringType;
0346 
0347     /// @brief a type for a boolean
0348     /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
0349     using boolean_t = BooleanType;
0350 
0351     /// @brief a type for a number (integer)
0352     /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
0353     using number_integer_t = NumberIntegerType;
0354 
0355     /// @brief a type for a number (unsigned)
0356     /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
0357     using number_unsigned_t = NumberUnsignedType;
0358 
0359     /// @brief a type for a number (floating-point)
0360     /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
0361     using number_float_t = NumberFloatType;
0362 
0363     /// @brief a type for a packed binary type
0364     /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
0365     using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
0366 
0367     /// @brief object key comparator type
0368     /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
0369     using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
0370 
0371     /// @}
0372 
0373   private:
0374 
0375     /// helper for exception-safe object creation
0376     template<typename T, typename... Args>
0377     JSON_HEDLEY_RETURNS_NON_NULL
0378     static T* create(Args&& ... args)
0379     {
0380         AllocatorType<T> alloc;
0381         using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
0382 
0383         auto deleter = [&](T * obj)
0384         {
0385             AllocatorTraits::deallocate(alloc, obj, 1);
0386         };
0387         std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
0388         AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
0389         JSON_ASSERT(obj != nullptr);
0390         return obj.release();
0391     }
0392 
0393     ////////////////////////
0394     // JSON value storage //
0395     ////////////////////////
0396 
0397   JSON_PRIVATE_UNLESS_TESTED:
0398     /*!
0399     @brief a JSON value
0400 
0401     The actual storage for a JSON value of the @ref basic_json class. This
0402     union combines the different storage types for the JSON value types
0403     defined in @ref value_t.
0404 
0405     JSON type | value_t type    | used type
0406     --------- | --------------- | ------------------------
0407     object    | object          | pointer to @ref object_t
0408     array     | array           | pointer to @ref array_t
0409     string    | string          | pointer to @ref string_t
0410     boolean   | boolean         | @ref boolean_t
0411     number    | number_integer  | @ref number_integer_t
0412     number    | number_unsigned | @ref number_unsigned_t
0413     number    | number_float    | @ref number_float_t
0414     binary    | binary          | pointer to @ref binary_t
0415     null      | null            | *no value is stored*
0416 
0417     @note Variable-length types (objects, arrays, and strings) are stored as
0418     pointers. The size of the union should not exceed 64 bits if the default
0419     value types are used.
0420 
0421     @since version 1.0.0
0422     */
0423     union json_value
0424     {
0425         /// object (stored with pointer to save storage)
0426         object_t* object;
0427         /// array (stored with pointer to save storage)
0428         array_t* array;
0429         /// string (stored with pointer to save storage)
0430         string_t* string;
0431         /// binary (stored with pointer to save storage)
0432         binary_t* binary;
0433         /// boolean
0434         boolean_t boolean;
0435         /// number (integer)
0436         number_integer_t number_integer;
0437         /// number (unsigned integer)
0438         number_unsigned_t number_unsigned;
0439         /// number (floating-point)
0440         number_float_t number_float;
0441 
0442         /// default constructor (for null values)
0443         json_value() = default;
0444         /// constructor for booleans
0445         json_value(boolean_t v) noexcept : boolean(v) {}
0446         /// constructor for numbers (integer)
0447         json_value(number_integer_t v) noexcept : number_integer(v) {}
0448         /// constructor for numbers (unsigned)
0449         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
0450         /// constructor for numbers (floating-point)
0451         json_value(number_float_t v) noexcept : number_float(v) {}
0452         /// constructor for empty values of a given type
0453         json_value(value_t t)
0454         {
0455             switch (t)
0456             {
0457                 case value_t::object:
0458                 {
0459                     object = create<object_t>();
0460                     break;
0461                 }
0462 
0463                 case value_t::array:
0464                 {
0465                     array = create<array_t>();
0466                     break;
0467                 }
0468 
0469                 case value_t::string:
0470                 {
0471                     string = create<string_t>("");
0472                     break;
0473                 }
0474 
0475                 case value_t::binary:
0476                 {
0477                     binary = create<binary_t>();
0478                     break;
0479                 }
0480 
0481                 case value_t::boolean:
0482                 {
0483                     boolean = static_cast<boolean_t>(false);
0484                     break;
0485                 }
0486 
0487                 case value_t::number_integer:
0488                 {
0489                     number_integer = static_cast<number_integer_t>(0);
0490                     break;
0491                 }
0492 
0493                 case value_t::number_unsigned:
0494                 {
0495                     number_unsigned = static_cast<number_unsigned_t>(0);
0496                     break;
0497                 }
0498 
0499                 case value_t::number_float:
0500                 {
0501                     number_float = static_cast<number_float_t>(0.0);
0502                     break;
0503                 }
0504 
0505                 case value_t::null:
0506                 {
0507                     object = nullptr;  // silence warning, see #821
0508                     break;
0509                 }
0510 
0511                 case value_t::discarded:
0512                 default:
0513                 {
0514                     object = nullptr;  // silence warning, see #821
0515                     if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
0516                     {
0517                         JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
0518                     }
0519                     break;
0520                 }
0521             }
0522         }
0523 
0524         /// constructor for strings
0525         json_value(const string_t& value) : string(create<string_t>(value)) {}
0526 
0527         /// constructor for rvalue strings
0528         json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
0529 
0530         /// constructor for objects
0531         json_value(const object_t& value) : object(create<object_t>(value)) {}
0532 
0533         /// constructor for rvalue objects
0534         json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
0535 
0536         /// constructor for arrays
0537         json_value(const array_t& value) : array(create<array_t>(value)) {}
0538 
0539         /// constructor for rvalue arrays
0540         json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
0541 
0542         /// constructor for binary arrays
0543         json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
0544 
0545         /// constructor for rvalue binary arrays
0546         json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
0547 
0548         /// constructor for binary arrays (internal type)
0549         json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
0550 
0551         /// constructor for rvalue binary arrays (internal type)
0552         json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
0553 
0554         void destroy(value_t t)
0555         {
0556             if (
0557                 (t == value_t::object && object == nullptr) ||
0558                 (t == value_t::array && array == nullptr) ||
0559                 (t == value_t::string && string == nullptr) ||
0560                 (t == value_t::binary && binary == nullptr)
0561             )
0562             {
0563                 //not initialized (e.g. due to exception in the ctor)
0564                 return;
0565             }
0566             if (t == value_t::array || t == value_t::object)
0567             {
0568                 // flatten the current json_value to a heap-allocated stack
0569                 std::vector<basic_json> stack;
0570 
0571                 // move the top-level items to stack
0572                 if (t == value_t::array)
0573                 {
0574                     stack.reserve(array->size());
0575                     std::move(array->begin(), array->end(), std::back_inserter(stack));
0576                 }
0577                 else
0578                 {
0579                     stack.reserve(object->size());
0580                     for (auto&& it : *object)
0581                     {
0582                         stack.push_back(std::move(it.second));
0583                     }
0584                 }
0585 
0586                 while (!stack.empty())
0587                 {
0588                     // move the last item to local variable to be processed
0589                     basic_json current_item(std::move(stack.back()));
0590                     stack.pop_back();
0591 
0592                     // if current_item is array/object, move
0593                     // its children to the stack to be processed later
0594                     if (current_item.is_array())
0595                     {
0596                         std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
0597 
0598                         current_item.m_data.m_value.array->clear();
0599                     }
0600                     else if (current_item.is_object())
0601                     {
0602                         for (auto&& it : *current_item.m_data.m_value.object)
0603                         {
0604                             stack.push_back(std::move(it.second));
0605                         }
0606 
0607                         current_item.m_data.m_value.object->clear();
0608                     }
0609 
0610                     // it's now safe that current_item get destructed
0611                     // since it doesn't have any children
0612                 }
0613             }
0614 
0615             switch (t)
0616             {
0617                 case value_t::object:
0618                 {
0619                     AllocatorType<object_t> alloc;
0620                     std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
0621                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
0622                     break;
0623                 }
0624 
0625                 case value_t::array:
0626                 {
0627                     AllocatorType<array_t> alloc;
0628                     std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
0629                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
0630                     break;
0631                 }
0632 
0633                 case value_t::string:
0634                 {
0635                     AllocatorType<string_t> alloc;
0636                     std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
0637                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
0638                     break;
0639                 }
0640 
0641                 case value_t::binary:
0642                 {
0643                     AllocatorType<binary_t> alloc;
0644                     std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
0645                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
0646                     break;
0647                 }
0648 
0649                 case value_t::null:
0650                 case value_t::boolean:
0651                 case value_t::number_integer:
0652                 case value_t::number_unsigned:
0653                 case value_t::number_float:
0654                 case value_t::discarded:
0655                 default:
0656                 {
0657                     break;
0658                 }
0659             }
0660         }
0661     };
0662 
0663   private:
0664     /*!
0665     @brief checks the class invariants
0666 
0667     This function asserts the class invariants. It needs to be called at the
0668     end of every constructor to make sure that created objects respect the
0669     invariant. Furthermore, it has to be called each time the type of a JSON
0670     value is changed, because the invariant expresses a relationship between
0671     @a m_type and @a m_value.
0672 
0673     Furthermore, the parent relation is checked for arrays and objects: If
0674     @a check_parents true and the value is an array or object, then the
0675     container's elements must have the current value as parent.
0676 
0677     @param[in] check_parents  whether the parent relation should be checked.
0678                The value is true by default and should only be set to false
0679                during destruction of objects when the invariant does not
0680                need to hold.
0681     */
0682     void assert_invariant(bool check_parents = true) const noexcept
0683     {
0684         JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
0685         JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
0686         JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
0687         JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
0688 
0689 #if JSON_DIAGNOSTICS
0690         JSON_TRY
0691         {
0692             // cppcheck-suppress assertWithSideEffect
0693             JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
0694             {
0695                 return j.m_parent == this;
0696             }));
0697         }
0698         JSON_CATCH(...) {} // LCOV_EXCL_LINE
0699 #endif
0700         static_cast<void>(check_parents);
0701     }
0702 
0703     void set_parents()
0704     {
0705 #if JSON_DIAGNOSTICS
0706         switch (m_data.m_type)
0707         {
0708             case value_t::array:
0709             {
0710                 for (auto& element : *m_data.m_value.array)
0711                 {
0712                     element.m_parent = this;
0713                 }
0714                 break;
0715             }
0716 
0717             case value_t::object:
0718             {
0719                 for (auto& element : *m_data.m_value.object)
0720                 {
0721                     element.second.m_parent = this;
0722                 }
0723                 break;
0724             }
0725 
0726             case value_t::null:
0727             case value_t::string:
0728             case value_t::boolean:
0729             case value_t::number_integer:
0730             case value_t::number_unsigned:
0731             case value_t::number_float:
0732             case value_t::binary:
0733             case value_t::discarded:
0734             default:
0735                 break;
0736         }
0737 #endif
0738     }
0739 
0740     iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
0741     {
0742 #if JSON_DIAGNOSTICS
0743         for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
0744         {
0745             (it + i)->m_parent = this;
0746         }
0747 #else
0748         static_cast<void>(count_set_parents);
0749 #endif
0750         return it;
0751     }
0752 
0753     reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
0754     {
0755 #if JSON_DIAGNOSTICS
0756         if (old_capacity != static_cast<std::size_t>(-1))
0757         {
0758             // see https://github.com/nlohmann/json/issues/2838
0759             JSON_ASSERT(type() == value_t::array);
0760             if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
0761             {
0762                 // capacity has changed: update all parents
0763                 set_parents();
0764                 return j;
0765             }
0766         }
0767 
0768         // ordered_json uses a vector internally, so pointers could have
0769         // been invalidated; see https://github.com/nlohmann/json/issues/2962
0770 #ifdef JSON_HEDLEY_MSVC_VERSION
0771 #pragma warning(push )
0772 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
0773 #endif
0774         if (detail::is_ordered_map<object_t>::value)
0775         {
0776             set_parents();
0777             return j;
0778         }
0779 #ifdef JSON_HEDLEY_MSVC_VERSION
0780 #pragma warning( pop )
0781 #endif
0782 
0783         j.m_parent = this;
0784 #else
0785         static_cast<void>(j);
0786         static_cast<void>(old_capacity);
0787 #endif
0788         return j;
0789     }
0790 
0791   public:
0792     //////////////////////////
0793     // JSON parser callback //
0794     //////////////////////////
0795 
0796     /// @brief parser event types
0797     /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
0798     using parse_event_t = detail::parse_event_t;
0799 
0800     /// @brief per-element parser callback type
0801     /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
0802     using parser_callback_t = detail::parser_callback_t<basic_json>;
0803 
0804     //////////////////
0805     // constructors //
0806     //////////////////
0807 
0808     /// @name constructors and destructors
0809     /// Constructors of class @ref basic_json, copy/move constructor, copy
0810     /// assignment, static functions creating objects, and the destructor.
0811     /// @{
0812 
0813     /// @brief create an empty value with a given type
0814     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
0815     basic_json(const value_t v)
0816         : m_data(v)
0817     {
0818         assert_invariant();
0819     }
0820 
0821     /// @brief create a null object
0822     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
0823     basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
0824         : basic_json(value_t::null)
0825     {
0826         assert_invariant();
0827     }
0828 
0829     /// @brief create a JSON value from compatible types
0830     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
0831     template < typename CompatibleType,
0832                typename U = detail::uncvref_t<CompatibleType>,
0833                detail::enable_if_t <
0834                    !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
0835     basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
0836                 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
0837                                            std::forward<CompatibleType>(val))))
0838     {
0839         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
0840         set_parents();
0841         assert_invariant();
0842     }
0843 
0844     /// @brief create a JSON value from an existing one
0845     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
0846     template < typename BasicJsonType,
0847                detail::enable_if_t <
0848                    detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
0849     basic_json(const BasicJsonType& val)
0850     {
0851         using other_boolean_t = typename BasicJsonType::boolean_t;
0852         using other_number_float_t = typename BasicJsonType::number_float_t;
0853         using other_number_integer_t = typename BasicJsonType::number_integer_t;
0854         using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
0855         using other_string_t = typename BasicJsonType::string_t;
0856         using other_object_t = typename BasicJsonType::object_t;
0857         using other_array_t = typename BasicJsonType::array_t;
0858         using other_binary_t = typename BasicJsonType::binary_t;
0859 
0860         switch (val.type())
0861         {
0862             case value_t::boolean:
0863                 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
0864                 break;
0865             case value_t::number_float:
0866                 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
0867                 break;
0868             case value_t::number_integer:
0869                 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
0870                 break;
0871             case value_t::number_unsigned:
0872                 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
0873                 break;
0874             case value_t::string:
0875                 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
0876                 break;
0877             case value_t::object:
0878                 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
0879                 break;
0880             case value_t::array:
0881                 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
0882                 break;
0883             case value_t::binary:
0884                 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
0885                 break;
0886             case value_t::null:
0887                 *this = nullptr;
0888                 break;
0889             case value_t::discarded:
0890                 m_data.m_type = value_t::discarded;
0891                 break;
0892             default:            // LCOV_EXCL_LINE
0893                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
0894         }
0895         JSON_ASSERT(m_data.m_type == val.type());
0896         set_parents();
0897         assert_invariant();
0898     }
0899 
0900     /// @brief create a container (array or object) from an initializer list
0901     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
0902     basic_json(initializer_list_t init,
0903                bool type_deduction = true,
0904                value_t manual_type = value_t::array)
0905     {
0906         // check if each element is an array with two elements whose first
0907         // element is a string
0908         bool is_an_object = std::all_of(init.begin(), init.end(),
0909                                         [](const detail::json_ref<basic_json>& element_ref)
0910         {
0911             // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
0912             // (many string types can be constructed from 0 via its null-pointer guise, so we get a
0913             // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
0914             return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
0915         });
0916 
0917         // adjust type if type deduction is not wanted
0918         if (!type_deduction)
0919         {
0920             // if array is wanted, do not create an object though possible
0921             if (manual_type == value_t::array)
0922             {
0923                 is_an_object = false;
0924             }
0925 
0926             // if object is wanted but impossible, throw an exception
0927             if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
0928             {
0929                 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
0930             }
0931         }
0932 
0933         if (is_an_object)
0934         {
0935             // the initializer list is a list of pairs -> create object
0936             m_data.m_type = value_t::object;
0937             m_data.m_value = value_t::object;
0938 
0939             for (auto& element_ref : init)
0940             {
0941                 auto element = element_ref.moved_or_copied();
0942                 m_data.m_value.object->emplace(
0943                     std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
0944                     std::move((*element.m_data.m_value.array)[1]));
0945             }
0946         }
0947         else
0948         {
0949             // the initializer list describes an array -> create array
0950             m_data.m_type = value_t::array;
0951             m_data.m_value.array = create<array_t>(init.begin(), init.end());
0952         }
0953 
0954         set_parents();
0955         assert_invariant();
0956     }
0957 
0958     /// @brief explicitly create a binary array (without subtype)
0959     /// @sa https://json.nlohmann.me/api/basic_json/binary/
0960     JSON_HEDLEY_WARN_UNUSED_RESULT
0961     static basic_json binary(const typename binary_t::container_type& init)
0962     {
0963         auto res = basic_json();
0964         res.m_data.m_type = value_t::binary;
0965         res.m_data.m_value = init;
0966         return res;
0967     }
0968 
0969     /// @brief explicitly create a binary array (with subtype)
0970     /// @sa https://json.nlohmann.me/api/basic_json/binary/
0971     JSON_HEDLEY_WARN_UNUSED_RESULT
0972     static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
0973     {
0974         auto res = basic_json();
0975         res.m_data.m_type = value_t::binary;
0976         res.m_data.m_value = binary_t(init, subtype);
0977         return res;
0978     }
0979 
0980     /// @brief explicitly create a binary array
0981     /// @sa https://json.nlohmann.me/api/basic_json/binary/
0982     JSON_HEDLEY_WARN_UNUSED_RESULT
0983     static basic_json binary(typename binary_t::container_type&& init)
0984     {
0985         auto res = basic_json();
0986         res.m_data.m_type = value_t::binary;
0987         res.m_data.m_value = std::move(init);
0988         return res;
0989     }
0990 
0991     /// @brief explicitly create a binary array (with subtype)
0992     /// @sa https://json.nlohmann.me/api/basic_json/binary/
0993     JSON_HEDLEY_WARN_UNUSED_RESULT
0994     static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
0995     {
0996         auto res = basic_json();
0997         res.m_data.m_type = value_t::binary;
0998         res.m_data.m_value = binary_t(std::move(init), subtype);
0999         return res;
1000     }
1001 
1002     /// @brief explicitly create an array from an initializer list
1003     /// @sa https://json.nlohmann.me/api/basic_json/array/
1004     JSON_HEDLEY_WARN_UNUSED_RESULT
1005     static basic_json array(initializer_list_t init = {})
1006     {
1007         return basic_json(init, false, value_t::array);
1008     }
1009 
1010     /// @brief explicitly create an object from an initializer list
1011     /// @sa https://json.nlohmann.me/api/basic_json/object/
1012     JSON_HEDLEY_WARN_UNUSED_RESULT
1013     static basic_json object(initializer_list_t init = {})
1014     {
1015         return basic_json(init, false, value_t::object);
1016     }
1017 
1018     /// @brief construct an array with count copies of given value
1019     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1020     basic_json(size_type cnt, const basic_json& val):
1021         m_data{cnt, val}
1022     {
1023         set_parents();
1024         assert_invariant();
1025     }
1026 
1027     /// @brief construct a JSON container given an iterator range
1028     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1029     template < class InputIT, typename std::enable_if <
1030                    std::is_same<InputIT, typename basic_json_t::iterator>::value ||
1031                    std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
1032     basic_json(InputIT first, InputIT last)
1033     {
1034         JSON_ASSERT(first.m_object != nullptr);
1035         JSON_ASSERT(last.m_object != nullptr);
1036 
1037         // make sure iterator fits the current value
1038         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1039         {
1040             JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
1041         }
1042 
1043         // copy type from first iterator
1044         m_data.m_type = first.m_object->m_data.m_type;
1045 
1046         // check if iterator range is complete for primitive values
1047         switch (m_data.m_type)
1048         {
1049             case value_t::boolean:
1050             case value_t::number_float:
1051             case value_t::number_integer:
1052             case value_t::number_unsigned:
1053             case value_t::string:
1054             {
1055                 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
1056                                          || !last.m_it.primitive_iterator.is_end()))
1057                 {
1058                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
1059                 }
1060                 break;
1061             }
1062 
1063             case value_t::null:
1064             case value_t::object:
1065             case value_t::array:
1066             case value_t::binary:
1067             case value_t::discarded:
1068             default:
1069                 break;
1070         }
1071 
1072         switch (m_data.m_type)
1073         {
1074             case value_t::number_integer:
1075             {
1076                 m_data.m_value.number_integer = first.m_object->m_data.m_value.number_integer;
1077                 break;
1078             }
1079 
1080             case value_t::number_unsigned:
1081             {
1082                 m_data.m_value.number_unsigned = first.m_object->m_data.m_value.number_unsigned;
1083                 break;
1084             }
1085 
1086             case value_t::number_float:
1087             {
1088                 m_data.m_value.number_float = first.m_object->m_data.m_value.number_float;
1089                 break;
1090             }
1091 
1092             case value_t::boolean:
1093             {
1094                 m_data.m_value.boolean = first.m_object->m_data.m_value.boolean;
1095                 break;
1096             }
1097 
1098             case value_t::string:
1099             {
1100                 m_data.m_value = *first.m_object->m_data.m_value.string;
1101                 break;
1102             }
1103 
1104             case value_t::object:
1105             {
1106                 m_data.m_value.object = create<object_t>(first.m_it.object_iterator,
1107                                         last.m_it.object_iterator);
1108                 break;
1109             }
1110 
1111             case value_t::array:
1112             {
1113                 m_data.m_value.array = create<array_t>(first.m_it.array_iterator,
1114                                                        last.m_it.array_iterator);
1115                 break;
1116             }
1117 
1118             case value_t::binary:
1119             {
1120                 m_data.m_value = *first.m_object->m_data.m_value.binary;
1121                 break;
1122             }
1123 
1124             case value_t::null:
1125             case value_t::discarded:
1126             default:
1127                 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
1128         }
1129 
1130         set_parents();
1131         assert_invariant();
1132     }
1133 
1134     ///////////////////////////////////////
1135     // other constructors and destructor //
1136     ///////////////////////////////////////
1137 
1138     template<typename JsonRef,
1139              detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
1140                                  std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
1141     basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
1142 
1143     /// @brief copy constructor
1144     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1145     basic_json(const basic_json& other)
1146         : json_base_class_t(other)
1147     {
1148         m_data.m_type = other.m_data.m_type;
1149         // check of passed value is valid
1150         other.assert_invariant();
1151 
1152         switch (m_data.m_type)
1153         {
1154             case value_t::object:
1155             {
1156                 m_data.m_value = *other.m_data.m_value.object;
1157                 break;
1158             }
1159 
1160             case value_t::array:
1161             {
1162                 m_data.m_value = *other.m_data.m_value.array;
1163                 break;
1164             }
1165 
1166             case value_t::string:
1167             {
1168                 m_data.m_value = *other.m_data.m_value.string;
1169                 break;
1170             }
1171 
1172             case value_t::boolean:
1173             {
1174                 m_data.m_value = other.m_data.m_value.boolean;
1175                 break;
1176             }
1177 
1178             case value_t::number_integer:
1179             {
1180                 m_data.m_value = other.m_data.m_value.number_integer;
1181                 break;
1182             }
1183 
1184             case value_t::number_unsigned:
1185             {
1186                 m_data.m_value = other.m_data.m_value.number_unsigned;
1187                 break;
1188             }
1189 
1190             case value_t::number_float:
1191             {
1192                 m_data.m_value = other.m_data.m_value.number_float;
1193                 break;
1194             }
1195 
1196             case value_t::binary:
1197             {
1198                 m_data.m_value = *other.m_data.m_value.binary;
1199                 break;
1200             }
1201 
1202             case value_t::null:
1203             case value_t::discarded:
1204             default:
1205                 break;
1206         }
1207 
1208         set_parents();
1209         assert_invariant();
1210     }
1211 
1212     /// @brief move constructor
1213     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1214     basic_json(basic_json&& other) noexcept
1215         : json_base_class_t(std::forward<json_base_class_t>(other)),
1216           m_data(std::move(other.m_data))
1217     {
1218         // check that passed value is valid
1219         other.assert_invariant(false);
1220 
1221         // invalidate payload
1222         other.m_data.m_type = value_t::null;
1223         other.m_data.m_value = {};
1224 
1225         set_parents();
1226         assert_invariant();
1227     }
1228 
1229     /// @brief copy assignment
1230     /// @sa https://json.nlohmann.me/api/basic_json/operator=/
1231     basic_json& operator=(basic_json other) noexcept (
1232         std::is_nothrow_move_constructible<value_t>::value&&
1233         std::is_nothrow_move_assignable<value_t>::value&&
1234         std::is_nothrow_move_constructible<json_value>::value&&
1235         std::is_nothrow_move_assignable<json_value>::value&&
1236         std::is_nothrow_move_assignable<json_base_class_t>::value
1237     )
1238     {
1239         // check that passed value is valid
1240         other.assert_invariant();
1241 
1242         using std::swap;
1243         swap(m_data.m_type, other.m_data.m_type);
1244         swap(m_data.m_value, other.m_data.m_value);
1245         json_base_class_t::operator=(std::move(other));
1246 
1247         set_parents();
1248         assert_invariant();
1249         return *this;
1250     }
1251 
1252     /// @brief destructor
1253     /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
1254     ~basic_json() noexcept
1255     {
1256         assert_invariant(false);
1257     }
1258 
1259     /// @}
1260 
1261   public:
1262     ///////////////////////
1263     // object inspection //
1264     ///////////////////////
1265 
1266     /// @name object inspection
1267     /// Functions to inspect the type of a JSON value.
1268     /// @{
1269 
1270     /// @brief serialization
1271     /// @sa https://json.nlohmann.me/api/basic_json/dump/
1272     string_t dump(const int indent = -1,
1273                   const char indent_char = ' ',
1274                   const bool ensure_ascii = false,
1275                   const error_handler_t error_handler = error_handler_t::strict) const
1276     {
1277         string_t result;
1278         serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
1279 
1280         if (indent >= 0)
1281         {
1282             s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
1283         }
1284         else
1285         {
1286             s.dump(*this, false, ensure_ascii, 0);
1287         }
1288 
1289         return result;
1290     }
1291 
1292     /// @brief return the type of the JSON value (explicit)
1293     /// @sa https://json.nlohmann.me/api/basic_json/type/
1294     constexpr value_t type() const noexcept
1295     {
1296         return m_data.m_type;
1297     }
1298 
1299     /// @brief return whether type is primitive
1300     /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
1301     constexpr bool is_primitive() const noexcept
1302     {
1303         return is_null() || is_string() || is_boolean() || is_number() || is_binary();
1304     }
1305 
1306     /// @brief return whether type is structured
1307     /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
1308     constexpr bool is_structured() const noexcept
1309     {
1310         return is_array() || is_object();
1311     }
1312 
1313     /// @brief return whether value is null
1314     /// @sa https://json.nlohmann.me/api/basic_json/is_null/
1315     constexpr bool is_null() const noexcept
1316     {
1317         return m_data.m_type == value_t::null;
1318     }
1319 
1320     /// @brief return whether value is a boolean
1321     /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
1322     constexpr bool is_boolean() const noexcept
1323     {
1324         return m_data.m_type == value_t::boolean;
1325     }
1326 
1327     /// @brief return whether value is a number
1328     /// @sa https://json.nlohmann.me/api/basic_json/is_number/
1329     constexpr bool is_number() const noexcept
1330     {
1331         return is_number_integer() || is_number_float();
1332     }
1333 
1334     /// @brief return whether value is an integer number
1335     /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
1336     constexpr bool is_number_integer() const noexcept
1337     {
1338         return m_data.m_type == value_t::number_integer || m_data.m_type == value_t::number_unsigned;
1339     }
1340 
1341     /// @brief return whether value is an unsigned integer number
1342     /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
1343     constexpr bool is_number_unsigned() const noexcept
1344     {
1345         return m_data.m_type == value_t::number_unsigned;
1346     }
1347 
1348     /// @brief return whether value is a floating-point number
1349     /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
1350     constexpr bool is_number_float() const noexcept
1351     {
1352         return m_data.m_type == value_t::number_float;
1353     }
1354 
1355     /// @brief return whether value is an object
1356     /// @sa https://json.nlohmann.me/api/basic_json/is_object/
1357     constexpr bool is_object() const noexcept
1358     {
1359         return m_data.m_type == value_t::object;
1360     }
1361 
1362     /// @brief return whether value is an array
1363     /// @sa https://json.nlohmann.me/api/basic_json/is_array/
1364     constexpr bool is_array() const noexcept
1365     {
1366         return m_data.m_type == value_t::array;
1367     }
1368 
1369     /// @brief return whether value is a string
1370     /// @sa https://json.nlohmann.me/api/basic_json/is_string/
1371     constexpr bool is_string() const noexcept
1372     {
1373         return m_data.m_type == value_t::string;
1374     }
1375 
1376     /// @brief return whether value is a binary array
1377     /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
1378     constexpr bool is_binary() const noexcept
1379     {
1380         return m_data.m_type == value_t::binary;
1381     }
1382 
1383     /// @brief return whether value is discarded
1384     /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
1385     constexpr bool is_discarded() const noexcept
1386     {
1387         return m_data.m_type == value_t::discarded;
1388     }
1389 
1390     /// @brief return the type of the JSON value (implicit)
1391     /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
1392     constexpr operator value_t() const noexcept
1393     {
1394         return m_data.m_type;
1395     }
1396 
1397     /// @}
1398 
1399   private:
1400     //////////////////
1401     // value access //
1402     //////////////////
1403 
1404     /// get a boolean (explicit)
1405     boolean_t get_impl(boolean_t* /*unused*/) const
1406     {
1407         if (JSON_HEDLEY_LIKELY(is_boolean()))
1408         {
1409             return m_data.m_value.boolean;
1410         }
1411 
1412         JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
1413     }
1414 
1415     /// get a pointer to the value (object)
1416     object_t* get_impl_ptr(object_t* /*unused*/) noexcept
1417     {
1418         return is_object() ? m_data.m_value.object : nullptr;
1419     }
1420 
1421     /// get a pointer to the value (object)
1422     constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
1423     {
1424         return is_object() ? m_data.m_value.object : nullptr;
1425     }
1426 
1427     /// get a pointer to the value (array)
1428     array_t* get_impl_ptr(array_t* /*unused*/) noexcept
1429     {
1430         return is_array() ? m_data.m_value.array : nullptr;
1431     }
1432 
1433     /// get a pointer to the value (array)
1434     constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
1435     {
1436         return is_array() ? m_data.m_value.array : nullptr;
1437     }
1438 
1439     /// get a pointer to the value (string)
1440     string_t* get_impl_ptr(string_t* /*unused*/) noexcept
1441     {
1442         return is_string() ? m_data.m_value.string : nullptr;
1443     }
1444 
1445     /// get a pointer to the value (string)
1446     constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
1447     {
1448         return is_string() ? m_data.m_value.string : nullptr;
1449     }
1450 
1451     /// get a pointer to the value (boolean)
1452     boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
1453     {
1454         return is_boolean() ? &m_data.m_value.boolean : nullptr;
1455     }
1456 
1457     /// get a pointer to the value (boolean)
1458     constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
1459     {
1460         return is_boolean() ? &m_data.m_value.boolean : nullptr;
1461     }
1462 
1463     /// get a pointer to the value (integer number)
1464     number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
1465     {
1466         return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
1467     }
1468 
1469     /// get a pointer to the value (integer number)
1470     constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
1471     {
1472         return is_number_integer() ? &m_data.m_value.number_integer : nullptr;
1473     }
1474 
1475     /// get a pointer to the value (unsigned number)
1476     number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
1477     {
1478         return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
1479     }
1480 
1481     /// get a pointer to the value (unsigned number)
1482     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
1483     {
1484         return is_number_unsigned() ? &m_data.m_value.number_unsigned : nullptr;
1485     }
1486 
1487     /// get a pointer to the value (floating-point number)
1488     number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
1489     {
1490         return is_number_float() ? &m_data.m_value.number_float : nullptr;
1491     }
1492 
1493     /// get a pointer to the value (floating-point number)
1494     constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
1495     {
1496         return is_number_float() ? &m_data.m_value.number_float : nullptr;
1497     }
1498 
1499     /// get a pointer to the value (binary)
1500     binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
1501     {
1502         return is_binary() ? m_data.m_value.binary : nullptr;
1503     }
1504 
1505     /// get a pointer to the value (binary)
1506     constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
1507     {
1508         return is_binary() ? m_data.m_value.binary : nullptr;
1509     }
1510 
1511     /*!
1512     @brief helper function to implement get_ref()
1513 
1514     This function helps to implement get_ref() without code duplication for
1515     const and non-const overloads
1516 
1517     @tparam ThisType will be deduced as `basic_json` or `const basic_json`
1518 
1519     @throw type_error.303 if ReferenceType does not match underlying value
1520     type of the current JSON
1521     */
1522     template<typename ReferenceType, typename ThisType>
1523     static ReferenceType get_ref_impl(ThisType& obj)
1524     {
1525         // delegate the call to get_ptr<>()
1526         auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
1527 
1528         if (JSON_HEDLEY_LIKELY(ptr != nullptr))
1529         {
1530             return *ptr;
1531         }
1532 
1533         JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
1534     }
1535 
1536   public:
1537     /// @name value access
1538     /// Direct access to the stored value of a JSON value.
1539     /// @{
1540 
1541     /// @brief get a pointer value (implicit)
1542     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
1543     template<typename PointerType, typename std::enable_if<
1544                  std::is_pointer<PointerType>::value, int>::type = 0>
1545     auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
1546     {
1547         // delegate the call to get_impl_ptr<>()
1548         return get_impl_ptr(static_cast<PointerType>(nullptr));
1549     }
1550 
1551     /// @brief get a pointer value (implicit)
1552     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
1553     template < typename PointerType, typename std::enable_if <
1554                    std::is_pointer<PointerType>::value&&
1555                    std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
1556     constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
1557     {
1558         // delegate the call to get_impl_ptr<>() const
1559         return get_impl_ptr(static_cast<PointerType>(nullptr));
1560     }
1561 
1562   private:
1563     /*!
1564     @brief get a value (explicit)
1565 
1566     Explicit type conversion between the JSON value and a compatible value
1567     which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
1568     and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1569     The value is converted by calling the @ref json_serializer<ValueType>
1570     `from_json()` method.
1571 
1572     The function is equivalent to executing
1573     @code {.cpp}
1574     ValueType ret;
1575     JSONSerializer<ValueType>::from_json(*this, ret);
1576     return ret;
1577     @endcode
1578 
1579     This overloads is chosen if:
1580     - @a ValueType is not @ref basic_json,
1581     - @ref json_serializer<ValueType> has a `from_json()` method of the form
1582       `void from_json(const basic_json&, ValueType&)`, and
1583     - @ref json_serializer<ValueType> does not have a `from_json()` method of
1584       the form `ValueType from_json(const basic_json&)`
1585 
1586     @tparam ValueType the returned value type
1587 
1588     @return copy of the JSON value, converted to @a ValueType
1589 
1590     @throw what @ref json_serializer<ValueType> `from_json()` method throws
1591 
1592     @liveexample{The example below shows several conversions from JSON values
1593     to other types. There a few things to note: (1) Floating-point numbers can
1594     be converted to integers\, (2) A JSON array can be converted to a standard
1595     `std::vector<short>`\, (3) A JSON object can be converted to C++
1596     associative containers such as `std::unordered_map<std::string\,
1597     json>`.,get__ValueType_const}
1598 
1599     @since version 2.1.0
1600     */
1601     template < typename ValueType,
1602                detail::enable_if_t <
1603                    detail::is_default_constructible<ValueType>::value&&
1604                    detail::has_from_json<basic_json_t, ValueType>::value,
1605                    int > = 0 >
1606     ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
1607                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
1608     {
1609         auto ret = ValueType();
1610         JSONSerializer<ValueType>::from_json(*this, ret);
1611         return ret;
1612     }
1613 
1614     /*!
1615     @brief get a value (explicit); special case
1616 
1617     Explicit type conversion between the JSON value and a compatible value
1618     which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
1619     and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1620     The value is converted by calling the @ref json_serializer<ValueType>
1621     `from_json()` method.
1622 
1623     The function is equivalent to executing
1624     @code {.cpp}
1625     return JSONSerializer<ValueType>::from_json(*this);
1626     @endcode
1627 
1628     This overloads is chosen if:
1629     - @a ValueType is not @ref basic_json and
1630     - @ref json_serializer<ValueType> has a `from_json()` method of the form
1631       `ValueType from_json(const basic_json&)`
1632 
1633     @note If @ref json_serializer<ValueType> has both overloads of
1634     `from_json()`, this one is chosen.
1635 
1636     @tparam ValueType the returned value type
1637 
1638     @return copy of the JSON value, converted to @a ValueType
1639 
1640     @throw what @ref json_serializer<ValueType> `from_json()` method throws
1641 
1642     @since version 2.1.0
1643     */
1644     template < typename ValueType,
1645                detail::enable_if_t <
1646                    detail::has_non_default_from_json<basic_json_t, ValueType>::value,
1647                    int > = 0 >
1648     ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
1649                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
1650     {
1651         return JSONSerializer<ValueType>::from_json(*this);
1652     }
1653 
1654     /*!
1655     @brief get special-case overload
1656 
1657     This overloads converts the current @ref basic_json in a different
1658     @ref basic_json type
1659 
1660     @tparam BasicJsonType == @ref basic_json
1661 
1662     @return a copy of *this, converted into @a BasicJsonType
1663 
1664     @complexity Depending on the implementation of the called `from_json()`
1665                 method.
1666 
1667     @since version 3.2.0
1668     */
1669     template < typename BasicJsonType,
1670                detail::enable_if_t <
1671                    detail::is_basic_json<BasicJsonType>::value,
1672                    int > = 0 >
1673     BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
1674     {
1675         return *this;
1676     }
1677 
1678     /*!
1679     @brief get special-case overload
1680 
1681     This overloads avoids a lot of template boilerplate, it can be seen as the
1682     identity method
1683 
1684     @tparam BasicJsonType == @ref basic_json
1685 
1686     @return a copy of *this
1687 
1688     @complexity Constant.
1689 
1690     @since version 2.1.0
1691     */
1692     template<typename BasicJsonType,
1693              detail::enable_if_t<
1694                  std::is_same<BasicJsonType, basic_json_t>::value,
1695                  int> = 0>
1696     basic_json get_impl(detail::priority_tag<3> /*unused*/) const
1697     {
1698         return *this;
1699     }
1700 
1701     /*!
1702     @brief get a pointer value (explicit)
1703     @copydoc get()
1704     */
1705     template<typename PointerType,
1706              detail::enable_if_t<
1707                  std::is_pointer<PointerType>::value,
1708                  int> = 0>
1709     constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
1710     -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
1711     {
1712         // delegate the call to get_ptr
1713         return get_ptr<PointerType>();
1714     }
1715 
1716   public:
1717     /*!
1718     @brief get a (pointer) value (explicit)
1719 
1720     Performs explicit type conversion between the JSON value and a compatible value if required.
1721 
1722     - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
1723     No copies are made.
1724 
1725     - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
1726     from the current @ref basic_json.
1727 
1728     - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
1729     method.
1730 
1731     @tparam ValueTypeCV the provided value type
1732     @tparam ValueType the returned value type
1733 
1734     @return copy of the JSON value, converted to @tparam ValueType if necessary
1735 
1736     @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
1737 
1738     @since version 2.1.0
1739     */
1740     template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
1741 #if defined(JSON_HAS_CPP_14)
1742     constexpr
1743 #endif
1744     auto get() const noexcept(
1745     noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
1746     -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
1747     {
1748         // we cannot static_assert on ValueTypeCV being non-const, because
1749         // there is support for get<const basic_json_t>(), which is why we
1750         // still need the uncvref
1751         static_assert(!std::is_reference<ValueTypeCV>::value,
1752                       "get() cannot be used with reference types, you might want to use get_ref()");
1753         return get_impl<ValueType>(detail::priority_tag<4> {});
1754     }
1755 
1756     /*!
1757     @brief get a pointer value (explicit)
1758 
1759     Explicit pointer access to the internally stored JSON value. No copies are
1760     made.
1761 
1762     @warning The pointer becomes invalid if the underlying JSON object
1763     changes.
1764 
1765     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
1766     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
1767     @ref number_unsigned_t, or @ref number_float_t.
1768 
1769     @return pointer to the internally stored JSON value if the requested
1770     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
1771 
1772     @complexity Constant.
1773 
1774     @liveexample{The example below shows how pointers to internal values of a
1775     JSON value can be requested. Note that no type conversions are made and a
1776     `nullptr` is returned if the value and the requested pointer type does not
1777     match.,get__PointerType}
1778 
1779     @sa see @ref get_ptr() for explicit pointer-member access
1780 
1781     @since version 1.0.0
1782     */
1783     template<typename PointerType, typename std::enable_if<
1784                  std::is_pointer<PointerType>::value, int>::type = 0>
1785     auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
1786     {
1787         // delegate the call to get_ptr
1788         return get_ptr<PointerType>();
1789     }
1790 
1791     /// @brief get a value (explicit)
1792     /// @sa https://json.nlohmann.me/api/basic_json/get_to/
1793     template < typename ValueType,
1794                detail::enable_if_t <
1795                    !detail::is_basic_json<ValueType>::value&&
1796                    detail::has_from_json<basic_json_t, ValueType>::value,
1797                    int > = 0 >
1798     ValueType & get_to(ValueType& v) const noexcept(noexcept(
1799                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
1800     {
1801         JSONSerializer<ValueType>::from_json(*this, v);
1802         return v;
1803     }
1804 
1805     // specialization to allow calling get_to with a basic_json value
1806     // see https://github.com/nlohmann/json/issues/2175
1807     template<typename ValueType,
1808              detail::enable_if_t <
1809                  detail::is_basic_json<ValueType>::value,
1810                  int> = 0>
1811     ValueType & get_to(ValueType& v) const
1812     {
1813         v = *this;
1814         return v;
1815     }
1816 
1817     template <
1818         typename T, std::size_t N,
1819         typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
1820         detail::enable_if_t <
1821             detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
1822     Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
1823     noexcept(noexcept(JSONSerializer<Array>::from_json(
1824                           std::declval<const basic_json_t&>(), v)))
1825     {
1826         JSONSerializer<Array>::from_json(*this, v);
1827         return v;
1828     }
1829 
1830     /// @brief get a reference value (implicit)
1831     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
1832     template<typename ReferenceType, typename std::enable_if<
1833                  std::is_reference<ReferenceType>::value, int>::type = 0>
1834     ReferenceType get_ref()
1835     {
1836         // delegate call to get_ref_impl
1837         return get_ref_impl<ReferenceType>(*this);
1838     }
1839 
1840     /// @brief get a reference value (implicit)
1841     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
1842     template < typename ReferenceType, typename std::enable_if <
1843                    std::is_reference<ReferenceType>::value&&
1844                    std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
1845     ReferenceType get_ref() const
1846     {
1847         // delegate call to get_ref_impl
1848         return get_ref_impl<ReferenceType>(*this);
1849     }
1850 
1851     /*!
1852     @brief get a value (implicit)
1853 
1854     Implicit type conversion between the JSON value and a compatible value.
1855     The call is realized by calling @ref get() const.
1856 
1857     @tparam ValueType non-pointer type compatible to the JSON value, for
1858     instance `int` for JSON integer numbers, `bool` for JSON booleans, or
1859     `std::vector` types for JSON arrays. The character type of @ref string_t
1860     as well as an initializer list of this type is excluded to avoid
1861     ambiguities as these types implicitly convert to `std::string`.
1862 
1863     @return copy of the JSON value, converted to type @a ValueType
1864 
1865     @throw type_error.302 in case passed type @a ValueType is incompatible
1866     to the JSON value type (e.g., the JSON value is of type boolean, but a
1867     string is requested); see example below
1868 
1869     @complexity Linear in the size of the JSON value.
1870 
1871     @liveexample{The example below shows several conversions from JSON values
1872     to other types. There a few things to note: (1) Floating-point numbers can
1873     be converted to integers\, (2) A JSON array can be converted to a standard
1874     `std::vector<short>`\, (3) A JSON object can be converted to C++
1875     associative containers such as `std::unordered_map<std::string\,
1876     json>`.,operator__ValueType}
1877 
1878     @since version 1.0.0
1879     */
1880     template < typename ValueType, typename std::enable_if <
1881                    detail::conjunction <
1882                        detail::negation<std::is_pointer<ValueType>>,
1883                        detail::negation<std::is_same<ValueType, std::nullptr_t>>,
1884                        detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
1885                                         detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
1886                                         detail::negation<detail::is_basic_json<ValueType>>,
1887                                         detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
1888 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
1889                                                 detail::negation<std::is_same<ValueType, std::string_view>>,
1890 #endif
1891 #if defined(JSON_HAS_CPP_17) && JSON_HAS_STATIC_RTTI
1892                                                 detail::negation<std::is_same<ValueType, std::any>>,
1893 #endif
1894                                                 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
1895                                                 >::value, int >::type = 0 >
1896                                         JSON_EXPLICIT operator ValueType() const
1897     {
1898         // delegate the call to get<>() const
1899         return get<ValueType>();
1900     }
1901 
1902     /// @brief get a binary value
1903     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
1904     binary_t& get_binary()
1905     {
1906         if (!is_binary())
1907         {
1908             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
1909         }
1910 
1911         return *get_ptr<binary_t*>();
1912     }
1913 
1914     /// @brief get a binary value
1915     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
1916     const binary_t& get_binary() const
1917     {
1918         if (!is_binary())
1919         {
1920             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
1921         }
1922 
1923         return *get_ptr<const binary_t*>();
1924     }
1925 
1926     /// @}
1927 
1928     ////////////////////
1929     // element access //
1930     ////////////////////
1931 
1932     /// @name element access
1933     /// Access to the JSON value.
1934     /// @{
1935 
1936     /// @brief access specified array element with bounds checking
1937     /// @sa https://json.nlohmann.me/api/basic_json/at/
1938     reference at(size_type idx)
1939     {
1940         // at only works for arrays
1941         if (JSON_HEDLEY_LIKELY(is_array()))
1942         {
1943             JSON_TRY
1944             {
1945                 return set_parent(m_data.m_value.array->at(idx));
1946             }
1947             JSON_CATCH (std::out_of_range&)
1948             {
1949                 // create better exception explanation
1950                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
1951             }
1952         }
1953         else
1954         {
1955             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1956         }
1957     }
1958 
1959     /// @brief access specified array element with bounds checking
1960     /// @sa https://json.nlohmann.me/api/basic_json/at/
1961     const_reference at(size_type idx) const
1962     {
1963         // at only works for arrays
1964         if (JSON_HEDLEY_LIKELY(is_array()))
1965         {
1966             JSON_TRY
1967             {
1968                 return m_data.m_value.array->at(idx);
1969             }
1970             JSON_CATCH (std::out_of_range&)
1971             {
1972                 // create better exception explanation
1973                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
1974             }
1975         }
1976         else
1977         {
1978             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1979         }
1980     }
1981 
1982     /// @brief access specified object element with bounds checking
1983     /// @sa https://json.nlohmann.me/api/basic_json/at/
1984     reference at(const typename object_t::key_type& key)
1985     {
1986         // at only works for objects
1987         if (JSON_HEDLEY_UNLIKELY(!is_object()))
1988         {
1989             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1990         }
1991 
1992         auto it = m_data.m_value.object->find(key);
1993         if (it == m_data.m_value.object->end())
1994         {
1995             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
1996         }
1997         return set_parent(it->second);
1998     }
1999 
2000     /// @brief access specified object element with bounds checking
2001     /// @sa https://json.nlohmann.me/api/basic_json/at/
2002     template<class KeyType, detail::enable_if_t<
2003                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2004     reference at(KeyType && key)
2005     {
2006         // at only works for objects
2007         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2008         {
2009             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2010         }
2011 
2012         auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2013         if (it == m_data.m_value.object->end())
2014         {
2015             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
2016         }
2017         return set_parent(it->second);
2018     }
2019 
2020     /// @brief access specified object element with bounds checking
2021     /// @sa https://json.nlohmann.me/api/basic_json/at/
2022     const_reference at(const typename object_t::key_type& key) const
2023     {
2024         // at only works for objects
2025         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2026         {
2027             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2028         }
2029 
2030         auto it = m_data.m_value.object->find(key);
2031         if (it == m_data.m_value.object->end())
2032         {
2033             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
2034         }
2035         return it->second;
2036     }
2037 
2038     /// @brief access specified object element with bounds checking
2039     /// @sa https://json.nlohmann.me/api/basic_json/at/
2040     template<class KeyType, detail::enable_if_t<
2041                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2042     const_reference at(KeyType && key) const
2043     {
2044         // at only works for objects
2045         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2046         {
2047             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2048         }
2049 
2050         auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2051         if (it == m_data.m_value.object->end())
2052         {
2053             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
2054         }
2055         return it->second;
2056     }
2057 
2058     /// @brief access specified array element
2059     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2060     reference operator[](size_type idx)
2061     {
2062         // implicitly convert null value to an empty array
2063         if (is_null())
2064         {
2065             m_data.m_type = value_t::array;
2066             m_data.m_value.array = create<array_t>();
2067             assert_invariant();
2068         }
2069 
2070         // operator[] only works for arrays
2071         if (JSON_HEDLEY_LIKELY(is_array()))
2072         {
2073             // fill up array with null values if given idx is outside range
2074             if (idx >= m_data.m_value.array->size())
2075             {
2076 #if JSON_DIAGNOSTICS
2077                 // remember array size & capacity before resizing
2078                 const auto old_size = m_data.m_value.array->size();
2079                 const auto old_capacity = m_data.m_value.array->capacity();
2080 #endif
2081                 m_data.m_value.array->resize(idx + 1);
2082 
2083 #if JSON_DIAGNOSTICS
2084                 if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
2085                 {
2086                     // capacity has changed: update all parents
2087                     set_parents();
2088                 }
2089                 else
2090                 {
2091                     // set parent for values added above
2092                     set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
2093                 }
2094 #endif
2095                 assert_invariant();
2096             }
2097 
2098             return m_data.m_value.array->operator[](idx);
2099         }
2100 
2101         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
2102     }
2103 
2104     /// @brief access specified array element
2105     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2106     const_reference operator[](size_type idx) const
2107     {
2108         // const operator[] only works for arrays
2109         if (JSON_HEDLEY_LIKELY(is_array()))
2110         {
2111             return m_data.m_value.array->operator[](idx);
2112         }
2113 
2114         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
2115     }
2116 
2117     /// @brief access specified object element
2118     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2119     reference operator[](typename object_t::key_type key)
2120     {
2121         // implicitly convert null value to an empty object
2122         if (is_null())
2123         {
2124             m_data.m_type = value_t::object;
2125             m_data.m_value.object = create<object_t>();
2126             assert_invariant();
2127         }
2128 
2129         // operator[] only works for objects
2130         if (JSON_HEDLEY_LIKELY(is_object()))
2131         {
2132             auto result = m_data.m_value.object->emplace(std::move(key), nullptr);
2133             return set_parent(result.first->second);
2134         }
2135 
2136         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2137     }
2138 
2139     /// @brief access specified object element
2140     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2141     const_reference operator[](const typename object_t::key_type& key) const
2142     {
2143         // const operator[] only works for objects
2144         if (JSON_HEDLEY_LIKELY(is_object()))
2145         {
2146             auto it = m_data.m_value.object->find(key);
2147             JSON_ASSERT(it != m_data.m_value.object->end());
2148             return it->second;
2149         }
2150 
2151         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2152     }
2153 
2154     // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
2155     // (they seemingly cannot be constrained to resolve the ambiguity)
2156     template<typename T>
2157     reference operator[](T* key)
2158     {
2159         return operator[](typename object_t::key_type(key));
2160     }
2161 
2162     template<typename T>
2163     const_reference operator[](T* key) const
2164     {
2165         return operator[](typename object_t::key_type(key));
2166     }
2167 
2168     /// @brief access specified object element
2169     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2170     template<class KeyType, detail::enable_if_t<
2171                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
2172     reference operator[](KeyType && key)
2173     {
2174         // implicitly convert null value to an empty object
2175         if (is_null())
2176         {
2177             m_data.m_type = value_t::object;
2178             m_data.m_value.object = create<object_t>();
2179             assert_invariant();
2180         }
2181 
2182         // operator[] only works for objects
2183         if (JSON_HEDLEY_LIKELY(is_object()))
2184         {
2185             auto result = m_data.m_value.object->emplace(std::forward<KeyType>(key), nullptr);
2186             return set_parent(result.first->second);
2187         }
2188 
2189         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2190     }
2191 
2192     /// @brief access specified object element
2193     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2194     template<class KeyType, detail::enable_if_t<
2195                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
2196     const_reference operator[](KeyType && key) const
2197     {
2198         // const operator[] only works for objects
2199         if (JSON_HEDLEY_LIKELY(is_object()))
2200         {
2201             auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2202             JSON_ASSERT(it != m_data.m_value.object->end());
2203             return it->second;
2204         }
2205 
2206         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2207     }
2208 
2209   private:
2210     template<typename KeyType>
2211     using is_comparable_with_object_key = detail::is_comparable <
2212         object_comparator_t, const typename object_t::key_type&, KeyType >;
2213 
2214     template<typename ValueType>
2215     using value_return_type = std::conditional <
2216         detail::is_c_string_uncvref<ValueType>::value,
2217         string_t, typename std::decay<ValueType>::type >;
2218 
2219   public:
2220     /// @brief access specified object element with default value
2221     /// @sa https://json.nlohmann.me/api/basic_json/value/
2222     template < class ValueType, detail::enable_if_t <
2223                    !detail::is_transparent<object_comparator_t>::value
2224                    && detail::is_getable<basic_json_t, ValueType>::value
2225                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2226     ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
2227     {
2228         // value only works for objects
2229         if (JSON_HEDLEY_LIKELY(is_object()))
2230         {
2231             // if key is found, return value and given default value otherwise
2232             const auto it = find(key);
2233             if (it != end())
2234             {
2235                 return it->template get<ValueType>();
2236             }
2237 
2238             return default_value;
2239         }
2240 
2241         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2242     }
2243 
2244     /// @brief access specified object element with default value
2245     /// @sa https://json.nlohmann.me/api/basic_json/value/
2246     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
2247                detail::enable_if_t <
2248                    !detail::is_transparent<object_comparator_t>::value
2249                    && detail::is_getable<basic_json_t, ReturnType>::value
2250                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2251     ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
2252     {
2253         // value only works for objects
2254         if (JSON_HEDLEY_LIKELY(is_object()))
2255         {
2256             // if key is found, return value and given default value otherwise
2257             const auto it = find(key);
2258             if (it != end())
2259             {
2260                 return it->template get<ReturnType>();
2261             }
2262 
2263             return std::forward<ValueType>(default_value);
2264         }
2265 
2266         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2267     }
2268 
2269     /// @brief access specified object element with default value
2270     /// @sa https://json.nlohmann.me/api/basic_json/value/
2271     template < class ValueType, class KeyType, detail::enable_if_t <
2272                    detail::is_transparent<object_comparator_t>::value
2273                    && !detail::is_json_pointer<KeyType>::value
2274                    && is_comparable_with_object_key<KeyType>::value
2275                    && detail::is_getable<basic_json_t, ValueType>::value
2276                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2277     ValueType value(KeyType && key, const ValueType& default_value) const
2278     {
2279         // value only works for objects
2280         if (JSON_HEDLEY_LIKELY(is_object()))
2281         {
2282             // if key is found, return value and given default value otherwise
2283             const auto it = find(std::forward<KeyType>(key));
2284             if (it != end())
2285             {
2286                 return it->template get<ValueType>();
2287             }
2288 
2289             return default_value;
2290         }
2291 
2292         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2293     }
2294 
2295     /// @brief access specified object element via JSON Pointer with default value
2296     /// @sa https://json.nlohmann.me/api/basic_json/value/
2297     template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
2298                detail::enable_if_t <
2299                    detail::is_transparent<object_comparator_t>::value
2300                    && !detail::is_json_pointer<KeyType>::value
2301                    && is_comparable_with_object_key<KeyType>::value
2302                    && detail::is_getable<basic_json_t, ReturnType>::value
2303                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2304     ReturnType value(KeyType && key, ValueType && default_value) const
2305     {
2306         // value only works for objects
2307         if (JSON_HEDLEY_LIKELY(is_object()))
2308         {
2309             // if key is found, return value and given default value otherwise
2310             const auto it = find(std::forward<KeyType>(key));
2311             if (it != end())
2312             {
2313                 return it->template get<ReturnType>();
2314             }
2315 
2316             return std::forward<ValueType>(default_value);
2317         }
2318 
2319         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2320     }
2321 
2322     /// @brief access specified object element via JSON Pointer with default value
2323     /// @sa https://json.nlohmann.me/api/basic_json/value/
2324     template < class ValueType, detail::enable_if_t <
2325                    detail::is_getable<basic_json_t, ValueType>::value
2326                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2327     ValueType value(const json_pointer& ptr, const ValueType& default_value) const
2328     {
2329         // value only works for objects
2330         if (JSON_HEDLEY_LIKELY(is_object()))
2331         {
2332             // if pointer resolves a value, return it or use default value
2333             JSON_TRY
2334             {
2335                 return ptr.get_checked(this).template get<ValueType>();
2336             }
2337             JSON_INTERNAL_CATCH (out_of_range&)
2338             {
2339                 return default_value;
2340             }
2341         }
2342 
2343         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2344     }
2345 
2346     /// @brief access specified object element via JSON Pointer with default value
2347     /// @sa https://json.nlohmann.me/api/basic_json/value/
2348     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
2349                detail::enable_if_t <
2350                    detail::is_getable<basic_json_t, ReturnType>::value
2351                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2352     ReturnType value(const json_pointer& ptr, ValueType && default_value) const
2353     {
2354         // value only works for objects
2355         if (JSON_HEDLEY_LIKELY(is_object()))
2356         {
2357             // if pointer resolves a value, return it or use default value
2358             JSON_TRY
2359             {
2360                 return ptr.get_checked(this).template get<ReturnType>();
2361             }
2362             JSON_INTERNAL_CATCH (out_of_range&)
2363             {
2364                 return std::forward<ValueType>(default_value);
2365             }
2366         }
2367 
2368         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2369     }
2370 
2371     template < class ValueType, class BasicJsonType, detail::enable_if_t <
2372                    detail::is_basic_json<BasicJsonType>::value
2373                    && detail::is_getable<basic_json_t, ValueType>::value
2374                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2375     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
2376     ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
2377     {
2378         return value(ptr.convert(), default_value);
2379     }
2380 
2381     template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
2382                detail::enable_if_t <
2383                    detail::is_basic_json<BasicJsonType>::value
2384                    && detail::is_getable<basic_json_t, ReturnType>::value
2385                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2386     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
2387     ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
2388     {
2389         return value(ptr.convert(), std::forward<ValueType>(default_value));
2390     }
2391 
2392     /// @brief access the first element
2393     /// @sa https://json.nlohmann.me/api/basic_json/front/
2394     reference front()
2395     {
2396         return *begin();
2397     }
2398 
2399     /// @brief access the first element
2400     /// @sa https://json.nlohmann.me/api/basic_json/front/
2401     const_reference front() const
2402     {
2403         return *cbegin();
2404     }
2405 
2406     /// @brief access the last element
2407     /// @sa https://json.nlohmann.me/api/basic_json/back/
2408     reference back()
2409     {
2410         auto tmp = end();
2411         --tmp;
2412         return *tmp;
2413     }
2414 
2415     /// @brief access the last element
2416     /// @sa https://json.nlohmann.me/api/basic_json/back/
2417     const_reference back() const
2418     {
2419         auto tmp = cend();
2420         --tmp;
2421         return *tmp;
2422     }
2423 
2424     /// @brief remove element given an iterator
2425     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2426     template < class IteratorType, detail::enable_if_t <
2427                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
2428                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
2429     IteratorType erase(IteratorType pos)
2430     {
2431         // make sure iterator fits the current value
2432         if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
2433         {
2434             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
2435         }
2436 
2437         IteratorType result = end();
2438 
2439         switch (m_data.m_type)
2440         {
2441             case value_t::boolean:
2442             case value_t::number_float:
2443             case value_t::number_integer:
2444             case value_t::number_unsigned:
2445             case value_t::string:
2446             case value_t::binary:
2447             {
2448                 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
2449                 {
2450                     JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
2451                 }
2452 
2453                 if (is_string())
2454                 {
2455                     AllocatorType<string_t> alloc;
2456                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
2457                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
2458                     m_data.m_value.string = nullptr;
2459                 }
2460                 else if (is_binary())
2461                 {
2462                     AllocatorType<binary_t> alloc;
2463                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
2464                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
2465                     m_data.m_value.binary = nullptr;
2466                 }
2467 
2468                 m_data.m_type = value_t::null;
2469                 assert_invariant();
2470                 break;
2471             }
2472 
2473             case value_t::object:
2474             {
2475                 result.m_it.object_iterator = m_data.m_value.object->erase(pos.m_it.object_iterator);
2476                 break;
2477             }
2478 
2479             case value_t::array:
2480             {
2481                 result.m_it.array_iterator = m_data.m_value.array->erase(pos.m_it.array_iterator);
2482                 break;
2483             }
2484 
2485             case value_t::null:
2486             case value_t::discarded:
2487             default:
2488                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2489         }
2490 
2491         return result;
2492     }
2493 
2494     /// @brief remove elements given an iterator range
2495     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2496     template < class IteratorType, detail::enable_if_t <
2497                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
2498                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
2499     IteratorType erase(IteratorType first, IteratorType last)
2500     {
2501         // make sure iterator fits the current value
2502         if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
2503         {
2504             JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
2505         }
2506 
2507         IteratorType result = end();
2508 
2509         switch (m_data.m_type)
2510         {
2511             case value_t::boolean:
2512             case value_t::number_float:
2513             case value_t::number_integer:
2514             case value_t::number_unsigned:
2515             case value_t::string:
2516             case value_t::binary:
2517             {
2518                 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
2519                                        || !last.m_it.primitive_iterator.is_end()))
2520                 {
2521                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
2522                 }
2523 
2524                 if (is_string())
2525                 {
2526                     AllocatorType<string_t> alloc;
2527                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.string);
2528                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.string, 1);
2529                     m_data.m_value.string = nullptr;
2530                 }
2531                 else if (is_binary())
2532                 {
2533                     AllocatorType<binary_t> alloc;
2534                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_data.m_value.binary);
2535                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_data.m_value.binary, 1);
2536                     m_data.m_value.binary = nullptr;
2537                 }
2538 
2539                 m_data.m_type = value_t::null;
2540                 assert_invariant();
2541                 break;
2542             }
2543 
2544             case value_t::object:
2545             {
2546                 result.m_it.object_iterator = m_data.m_value.object->erase(first.m_it.object_iterator,
2547                                               last.m_it.object_iterator);
2548                 break;
2549             }
2550 
2551             case value_t::array:
2552             {
2553                 result.m_it.array_iterator = m_data.m_value.array->erase(first.m_it.array_iterator,
2554                                              last.m_it.array_iterator);
2555                 break;
2556             }
2557 
2558             case value_t::null:
2559             case value_t::discarded:
2560             default:
2561                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2562         }
2563 
2564         return result;
2565     }
2566 
2567   private:
2568     template < typename KeyType, detail::enable_if_t <
2569                    detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
2570     size_type erase_internal(KeyType && key)
2571     {
2572         // this erase only works for objects
2573         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2574         {
2575             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2576         }
2577 
2578         return m_data.m_value.object->erase(std::forward<KeyType>(key));
2579     }
2580 
2581     template < typename KeyType, detail::enable_if_t <
2582                    !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
2583     size_type erase_internal(KeyType && key)
2584     {
2585         // this erase only works for objects
2586         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2587         {
2588             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2589         }
2590 
2591         const auto it = m_data.m_value.object->find(std::forward<KeyType>(key));
2592         if (it != m_data.m_value.object->end())
2593         {
2594             m_data.m_value.object->erase(it);
2595             return 1;
2596         }
2597         return 0;
2598     }
2599 
2600   public:
2601 
2602     /// @brief remove element from a JSON object given a key
2603     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2604     size_type erase(const typename object_t::key_type& key)
2605     {
2606         // the indirection via erase_internal() is added to avoid making this
2607         // function a template and thus de-rank it during overload resolution
2608         return erase_internal(key);
2609     }
2610 
2611     /// @brief remove element from a JSON object given a key
2612     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2613     template<class KeyType, detail::enable_if_t<
2614                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2615     size_type erase(KeyType && key)
2616     {
2617         return erase_internal(std::forward<KeyType>(key));
2618     }
2619 
2620     /// @brief remove element from a JSON array given an index
2621     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2622     void erase(const size_type idx)
2623     {
2624         // this erase only works for arrays
2625         if (JSON_HEDLEY_LIKELY(is_array()))
2626         {
2627             if (JSON_HEDLEY_UNLIKELY(idx >= size()))
2628             {
2629                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
2630             }
2631 
2632             m_data.m_value.array->erase(m_data.m_value.array->begin() + static_cast<difference_type>(idx));
2633         }
2634         else
2635         {
2636             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2637         }
2638     }
2639 
2640     /// @}
2641 
2642     ////////////
2643     // lookup //
2644     ////////////
2645 
2646     /// @name lookup
2647     /// @{
2648 
2649     /// @brief find an element in a JSON object
2650     /// @sa https://json.nlohmann.me/api/basic_json/find/
2651     iterator find(const typename object_t::key_type& key)
2652     {
2653         auto result = end();
2654 
2655         if (is_object())
2656         {
2657             result.m_it.object_iterator = m_data.m_value.object->find(key);
2658         }
2659 
2660         return result;
2661     }
2662 
2663     /// @brief find an element in a JSON object
2664     /// @sa https://json.nlohmann.me/api/basic_json/find/
2665     const_iterator find(const typename object_t::key_type& key) const
2666     {
2667         auto result = cend();
2668 
2669         if (is_object())
2670         {
2671             result.m_it.object_iterator = m_data.m_value.object->find(key);
2672         }
2673 
2674         return result;
2675     }
2676 
2677     /// @brief find an element in a JSON object
2678     /// @sa https://json.nlohmann.me/api/basic_json/find/
2679     template<class KeyType, detail::enable_if_t<
2680                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2681     iterator find(KeyType && key)
2682     {
2683         auto result = end();
2684 
2685         if (is_object())
2686         {
2687             result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
2688         }
2689 
2690         return result;
2691     }
2692 
2693     /// @brief find an element in a JSON object
2694     /// @sa https://json.nlohmann.me/api/basic_json/find/
2695     template<class KeyType, detail::enable_if_t<
2696                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2697     const_iterator find(KeyType && key) const
2698     {
2699         auto result = cend();
2700 
2701         if (is_object())
2702         {
2703             result.m_it.object_iterator = m_data.m_value.object->find(std::forward<KeyType>(key));
2704         }
2705 
2706         return result;
2707     }
2708 
2709     /// @brief returns the number of occurrences of a key in a JSON object
2710     /// @sa https://json.nlohmann.me/api/basic_json/count/
2711     size_type count(const typename object_t::key_type& key) const
2712     {
2713         // return 0 for all nonobject types
2714         return is_object() ? m_data.m_value.object->count(key) : 0;
2715     }
2716 
2717     /// @brief returns the number of occurrences of a key in a JSON object
2718     /// @sa https://json.nlohmann.me/api/basic_json/count/
2719     template<class KeyType, detail::enable_if_t<
2720                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2721     size_type count(KeyType && key) const
2722     {
2723         // return 0 for all nonobject types
2724         return is_object() ? m_data.m_value.object->count(std::forward<KeyType>(key)) : 0;
2725     }
2726 
2727     /// @brief check the existence of an element in a JSON object
2728     /// @sa https://json.nlohmann.me/api/basic_json/contains/
2729     bool contains(const typename object_t::key_type& key) const
2730     {
2731         return is_object() && m_data.m_value.object->find(key) != m_data.m_value.object->end();
2732     }
2733 
2734     /// @brief check the existence of an element in a JSON object
2735     /// @sa https://json.nlohmann.me/api/basic_json/contains/
2736     template<class KeyType, detail::enable_if_t<
2737                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
2738     bool contains(KeyType && key) const
2739     {
2740         return is_object() && m_data.m_value.object->find(std::forward<KeyType>(key)) != m_data.m_value.object->end();
2741     }
2742 
2743     /// @brief check the existence of an element in a JSON object given a JSON pointer
2744     /// @sa https://json.nlohmann.me/api/basic_json/contains/
2745     bool contains(const json_pointer& ptr) const
2746     {
2747         return ptr.contains(this);
2748     }
2749 
2750     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
2751     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
2752     bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
2753     {
2754         return ptr.contains(this);
2755     }
2756 
2757     /// @}
2758 
2759     ///////////////
2760     // iterators //
2761     ///////////////
2762 
2763     /// @name iterators
2764     /// @{
2765 
2766     /// @brief returns an iterator to the first element
2767     /// @sa https://json.nlohmann.me/api/basic_json/begin/
2768     iterator begin() noexcept
2769     {
2770         iterator result(this);
2771         result.set_begin();
2772         return result;
2773     }
2774 
2775     /// @brief returns an iterator to the first element
2776     /// @sa https://json.nlohmann.me/api/basic_json/begin/
2777     const_iterator begin() const noexcept
2778     {
2779         return cbegin();
2780     }
2781 
2782     /// @brief returns a const iterator to the first element
2783     /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
2784     const_iterator cbegin() const noexcept
2785     {
2786         const_iterator result(this);
2787         result.set_begin();
2788         return result;
2789     }
2790 
2791     /// @brief returns an iterator to one past the last element
2792     /// @sa https://json.nlohmann.me/api/basic_json/end/
2793     iterator end() noexcept
2794     {
2795         iterator result(this);
2796         result.set_end();
2797         return result;
2798     }
2799 
2800     /// @brief returns an iterator to one past the last element
2801     /// @sa https://json.nlohmann.me/api/basic_json/end/
2802     const_iterator end() const noexcept
2803     {
2804         return cend();
2805     }
2806 
2807     /// @brief returns an iterator to one past the last element
2808     /// @sa https://json.nlohmann.me/api/basic_json/cend/
2809     const_iterator cend() const noexcept
2810     {
2811         const_iterator result(this);
2812         result.set_end();
2813         return result;
2814     }
2815 
2816     /// @brief returns an iterator to the reverse-beginning
2817     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
2818     reverse_iterator rbegin() noexcept
2819     {
2820         return reverse_iterator(end());
2821     }
2822 
2823     /// @brief returns an iterator to the reverse-beginning
2824     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
2825     const_reverse_iterator rbegin() const noexcept
2826     {
2827         return crbegin();
2828     }
2829 
2830     /// @brief returns an iterator to the reverse-end
2831     /// @sa https://json.nlohmann.me/api/basic_json/rend/
2832     reverse_iterator rend() noexcept
2833     {
2834         return reverse_iterator(begin());
2835     }
2836 
2837     /// @brief returns an iterator to the reverse-end
2838     /// @sa https://json.nlohmann.me/api/basic_json/rend/
2839     const_reverse_iterator rend() const noexcept
2840     {
2841         return crend();
2842     }
2843 
2844     /// @brief returns a const reverse iterator to the last element
2845     /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
2846     const_reverse_iterator crbegin() const noexcept
2847     {
2848         return const_reverse_iterator(cend());
2849     }
2850 
2851     /// @brief returns a const reverse iterator to one before the first
2852     /// @sa https://json.nlohmann.me/api/basic_json/crend/
2853     const_reverse_iterator crend() const noexcept
2854     {
2855         return const_reverse_iterator(cbegin());
2856     }
2857 
2858   public:
2859     /// @brief wrapper to access iterator member functions in range-based for
2860     /// @sa https://json.nlohmann.me/api/basic_json/items/
2861     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
2862     ///             version 4.0.0 of the library. Please use @ref items() instead;
2863     ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
2864     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
2865     static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
2866     {
2867         return ref.items();
2868     }
2869 
2870     /// @brief wrapper to access iterator member functions in range-based for
2871     /// @sa https://json.nlohmann.me/api/basic_json/items/
2872     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
2873     ///         version 4.0.0 of the library. Please use @ref items() instead;
2874     ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
2875     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
2876     static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
2877     {
2878         return ref.items();
2879     }
2880 
2881     /// @brief helper to access iterator member functions in range-based for
2882     /// @sa https://json.nlohmann.me/api/basic_json/items/
2883     iteration_proxy<iterator> items() noexcept
2884     {
2885         return iteration_proxy<iterator>(*this);
2886     }
2887 
2888     /// @brief helper to access iterator member functions in range-based for
2889     /// @sa https://json.nlohmann.me/api/basic_json/items/
2890     iteration_proxy<const_iterator> items() const noexcept
2891     {
2892         return iteration_proxy<const_iterator>(*this);
2893     }
2894 
2895     /// @}
2896 
2897     //////////////
2898     // capacity //
2899     //////////////
2900 
2901     /// @name capacity
2902     /// @{
2903 
2904     /// @brief checks whether the container is empty.
2905     /// @sa https://json.nlohmann.me/api/basic_json/empty/
2906     bool empty() const noexcept
2907     {
2908         switch (m_data.m_type)
2909         {
2910             case value_t::null:
2911             {
2912                 // null values are empty
2913                 return true;
2914             }
2915 
2916             case value_t::array:
2917             {
2918                 // delegate call to array_t::empty()
2919                 return m_data.m_value.array->empty();
2920             }
2921 
2922             case value_t::object:
2923             {
2924                 // delegate call to object_t::empty()
2925                 return m_data.m_value.object->empty();
2926             }
2927 
2928             case value_t::string:
2929             case value_t::boolean:
2930             case value_t::number_integer:
2931             case value_t::number_unsigned:
2932             case value_t::number_float:
2933             case value_t::binary:
2934             case value_t::discarded:
2935             default:
2936             {
2937                 // all other types are nonempty
2938                 return false;
2939             }
2940         }
2941     }
2942 
2943     /// @brief returns the number of elements
2944     /// @sa https://json.nlohmann.me/api/basic_json/size/
2945     size_type size() const noexcept
2946     {
2947         switch (m_data.m_type)
2948         {
2949             case value_t::null:
2950             {
2951                 // null values are empty
2952                 return 0;
2953             }
2954 
2955             case value_t::array:
2956             {
2957                 // delegate call to array_t::size()
2958                 return m_data.m_value.array->size();
2959             }
2960 
2961             case value_t::object:
2962             {
2963                 // delegate call to object_t::size()
2964                 return m_data.m_value.object->size();
2965             }
2966 
2967             case value_t::string:
2968             case value_t::boolean:
2969             case value_t::number_integer:
2970             case value_t::number_unsigned:
2971             case value_t::number_float:
2972             case value_t::binary:
2973             case value_t::discarded:
2974             default:
2975             {
2976                 // all other types have size 1
2977                 return 1;
2978             }
2979         }
2980     }
2981 
2982     /// @brief returns the maximum possible number of elements
2983     /// @sa https://json.nlohmann.me/api/basic_json/max_size/
2984     size_type max_size() const noexcept
2985     {
2986         switch (m_data.m_type)
2987         {
2988             case value_t::array:
2989             {
2990                 // delegate call to array_t::max_size()
2991                 return m_data.m_value.array->max_size();
2992             }
2993 
2994             case value_t::object:
2995             {
2996                 // delegate call to object_t::max_size()
2997                 return m_data.m_value.object->max_size();
2998             }
2999 
3000             case value_t::null:
3001             case value_t::string:
3002             case value_t::boolean:
3003             case value_t::number_integer:
3004             case value_t::number_unsigned:
3005             case value_t::number_float:
3006             case value_t::binary:
3007             case value_t::discarded:
3008             default:
3009             {
3010                 // all other types have max_size() == size()
3011                 return size();
3012             }
3013         }
3014     }
3015 
3016     /// @}
3017 
3018     ///////////////
3019     // modifiers //
3020     ///////////////
3021 
3022     /// @name modifiers
3023     /// @{
3024 
3025     /// @brief clears the contents
3026     /// @sa https://json.nlohmann.me/api/basic_json/clear/
3027     void clear() noexcept
3028     {
3029         switch (m_data.m_type)
3030         {
3031             case value_t::number_integer:
3032             {
3033                 m_data.m_value.number_integer = 0;
3034                 break;
3035             }
3036 
3037             case value_t::number_unsigned:
3038             {
3039                 m_data.m_value.number_unsigned = 0;
3040                 break;
3041             }
3042 
3043             case value_t::number_float:
3044             {
3045                 m_data.m_value.number_float = 0.0;
3046                 break;
3047             }
3048 
3049             case value_t::boolean:
3050             {
3051                 m_data.m_value.boolean = false;
3052                 break;
3053             }
3054 
3055             case value_t::string:
3056             {
3057                 m_data.m_value.string->clear();
3058                 break;
3059             }
3060 
3061             case value_t::binary:
3062             {
3063                 m_data.m_value.binary->clear();
3064                 break;
3065             }
3066 
3067             case value_t::array:
3068             {
3069                 m_data.m_value.array->clear();
3070                 break;
3071             }
3072 
3073             case value_t::object:
3074             {
3075                 m_data.m_value.object->clear();
3076                 break;
3077             }
3078 
3079             case value_t::null:
3080             case value_t::discarded:
3081             default:
3082                 break;
3083         }
3084     }
3085 
3086     /// @brief add an object to an array
3087     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3088     void push_back(basic_json&& val)
3089     {
3090         // push_back only works for null objects or arrays
3091         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3092         {
3093             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3094         }
3095 
3096         // transform null object into an array
3097         if (is_null())
3098         {
3099             m_data.m_type = value_t::array;
3100             m_data.m_value = value_t::array;
3101             assert_invariant();
3102         }
3103 
3104         // add element to array (move semantics)
3105         const auto old_capacity = m_data.m_value.array->capacity();
3106         m_data.m_value.array->push_back(std::move(val));
3107         set_parent(m_data.m_value.array->back(), old_capacity);
3108         // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
3109     }
3110 
3111     /// @brief add an object to an array
3112     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3113     reference operator+=(basic_json&& val)
3114     {
3115         push_back(std::move(val));
3116         return *this;
3117     }
3118 
3119     /// @brief add an object to an array
3120     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3121     void push_back(const basic_json& val)
3122     {
3123         // push_back only works for null objects or arrays
3124         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3125         {
3126             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3127         }
3128 
3129         // transform null object into an array
3130         if (is_null())
3131         {
3132             m_data.m_type = value_t::array;
3133             m_data.m_value = value_t::array;
3134             assert_invariant();
3135         }
3136 
3137         // add element to array
3138         const auto old_capacity = m_data.m_value.array->capacity();
3139         m_data.m_value.array->push_back(val);
3140         set_parent(m_data.m_value.array->back(), old_capacity);
3141     }
3142 
3143     /// @brief add an object to an array
3144     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3145     reference operator+=(const basic_json& val)
3146     {
3147         push_back(val);
3148         return *this;
3149     }
3150 
3151     /// @brief add an object to an object
3152     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3153     void push_back(const typename object_t::value_type& val)
3154     {
3155         // push_back only works for null objects or objects
3156         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
3157         {
3158             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3159         }
3160 
3161         // transform null object into an object
3162         if (is_null())
3163         {
3164             m_data.m_type = value_t::object;
3165             m_data.m_value = value_t::object;
3166             assert_invariant();
3167         }
3168 
3169         // add element to object
3170         auto res = m_data.m_value.object->insert(val);
3171         set_parent(res.first->second);
3172     }
3173 
3174     /// @brief add an object to an object
3175     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3176     reference operator+=(const typename object_t::value_type& val)
3177     {
3178         push_back(val);
3179         return *this;
3180     }
3181 
3182     /// @brief add an object to an object
3183     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
3184     void push_back(initializer_list_t init)
3185     {
3186         if (is_object() && init.size() == 2 && (*init.begin())->is_string())
3187         {
3188             basic_json&& key = init.begin()->moved_or_copied();
3189             push_back(typename object_t::value_type(
3190                           std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
3191         }
3192         else
3193         {
3194             push_back(basic_json(init));
3195         }
3196     }
3197 
3198     /// @brief add an object to an object
3199     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
3200     reference operator+=(initializer_list_t init)
3201     {
3202         push_back(init);
3203         return *this;
3204     }
3205 
3206     /// @brief add an object to an array
3207     /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
3208     template<class... Args>
3209     reference emplace_back(Args&& ... args)
3210     {
3211         // emplace_back only works for null objects or arrays
3212         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3213         {
3214             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
3215         }
3216 
3217         // transform null object into an array
3218         if (is_null())
3219         {
3220             m_data.m_type = value_t::array;
3221             m_data.m_value = value_t::array;
3222             assert_invariant();
3223         }
3224 
3225         // add element to array (perfect forwarding)
3226         const auto old_capacity = m_data.m_value.array->capacity();
3227         m_data.m_value.array->emplace_back(std::forward<Args>(args)...);
3228         return set_parent(m_data.m_value.array->back(), old_capacity);
3229     }
3230 
3231     /// @brief add an object to an object if key does not exist
3232     /// @sa https://json.nlohmann.me/api/basic_json/emplace/
3233     template<class... Args>
3234     std::pair<iterator, bool> emplace(Args&& ... args)
3235     {
3236         // emplace only works for null objects or arrays
3237         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
3238         {
3239             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
3240         }
3241 
3242         // transform null object into an object
3243         if (is_null())
3244         {
3245             m_data.m_type = value_t::object;
3246             m_data.m_value = value_t::object;
3247             assert_invariant();
3248         }
3249 
3250         // add element to array (perfect forwarding)
3251         auto res = m_data.m_value.object->emplace(std::forward<Args>(args)...);
3252         set_parent(res.first->second);
3253 
3254         // create result iterator and set iterator to the result of emplace
3255         auto it = begin();
3256         it.m_it.object_iterator = res.first;
3257 
3258         // return pair of iterator and boolean
3259         return {it, res.second};
3260     }
3261 
3262     /// Helper for insertion of an iterator
3263     /// @note: This uses std::distance to support GCC 4.8,
3264     ///        see https://github.com/nlohmann/json/pull/1257
3265     template<typename... Args>
3266     iterator insert_iterator(const_iterator pos, Args&& ... args)
3267     {
3268         iterator result(this);
3269         JSON_ASSERT(m_data.m_value.array != nullptr);
3270 
3271         auto insert_pos = std::distance(m_data.m_value.array->begin(), pos.m_it.array_iterator);
3272         m_data.m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
3273         result.m_it.array_iterator = m_data.m_value.array->begin() + insert_pos;
3274 
3275         // This could have been written as:
3276         // result.m_it.array_iterator = m_data.m_value.array->insert(pos.m_it.array_iterator, cnt, val);
3277         // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
3278 
3279         set_parents();
3280         return result;
3281     }
3282 
3283     /// @brief inserts element into array
3284     /// @sa https://json.nlohmann.me/api/basic_json/insert/
3285     iterator insert(const_iterator pos, const basic_json& val)
3286     {
3287         // insert only works for arrays
3288         if (JSON_HEDLEY_LIKELY(is_array()))
3289         {
3290             // check if iterator pos fits to this JSON value
3291             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3292             {
3293                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3294             }
3295 
3296             // insert to array and return iterator
3297             return insert_iterator(pos, val);
3298         }
3299 
3300         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3301     }
3302 
3303     /// @brief inserts element into array
3304     /// @sa https://json.nlohmann.me/api/basic_json/insert/
3305     iterator insert(const_iterator pos, basic_json&& val)
3306     {
3307         return insert(pos, val);
3308     }
3309 
3310     /// @brief inserts copies of element into array
3311     /// @sa https://json.nlohmann.me/api/basic_json/insert/
3312     iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
3313     {
3314         // insert only works for arrays
3315         if (JSON_HEDLEY_LIKELY(is_array()))
3316         {
3317             // check if iterator pos fits to this JSON value
3318             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3319             {
3320                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3321             }
3322 
3323             // insert to array and return iterator
3324             return insert_iterator(pos, cnt, val);
3325         }
3326 
3327         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3328     }
3329 
3330     /// @brief inserts range of elements into array
3331     /// @sa https://json.nlohmann.me/api/basic_json/insert/
3332     iterator insert(const_iterator pos, const_iterator first, const_iterator last)
3333     {
3334         // insert only works for arrays
3335         if (JSON_HEDLEY_UNLIKELY(!is_array()))
3336         {
3337             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3338         }
3339 
3340         // check if iterator pos fits to this JSON value
3341         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3342         {
3343             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3344         }
3345 
3346         // check if range iterators belong to the same JSON object
3347         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3348         {
3349             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3350         }
3351 
3352         if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
3353         {
3354             JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
3355         }
3356 
3357         // insert to array and return iterator
3358         return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
3359     }
3360 
3361     /// @brief inserts elements from initializer list into array
3362     /// @sa https://json.nlohmann.me/api/basic_json/insert/
3363     iterator insert(const_iterator pos, initializer_list_t ilist)
3364     {
3365         // insert only works for arrays
3366         if (JSON_HEDLEY_UNLIKELY(!is_array()))
3367         {
3368             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3369         }
3370 
3371         // check if iterator pos fits to this JSON value
3372         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3373         {
3374             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3375         }
3376 
3377         // insert to array and return iterator
3378         return insert_iterator(pos, ilist.begin(), ilist.end());
3379     }
3380 
3381     /// @brief inserts range of elements into object
3382     /// @sa https://json.nlohmann.me/api/basic_json/insert/
3383     void insert(const_iterator first, const_iterator last)
3384     {
3385         // insert only works for objects
3386         if (JSON_HEDLEY_UNLIKELY(!is_object()))
3387         {
3388             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3389         }
3390 
3391         // check if range iterators belong to the same JSON object
3392         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3393         {
3394             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3395         }
3396 
3397         // passed iterators must belong to objects
3398         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
3399         {
3400             JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
3401         }
3402 
3403         m_data.m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
3404     }
3405 
3406     /// @brief updates a JSON object from another object, overwriting existing keys
3407     /// @sa https://json.nlohmann.me/api/basic_json/update/
3408     void update(const_reference j, bool merge_objects = false)
3409     {
3410         update(j.begin(), j.end(), merge_objects);
3411     }
3412 
3413     /// @brief updates a JSON object from another object, overwriting existing keys
3414     /// @sa https://json.nlohmann.me/api/basic_json/update/
3415     void update(const_iterator first, const_iterator last, bool merge_objects = false)
3416     {
3417         // implicitly convert null value to an empty object
3418         if (is_null())
3419         {
3420             m_data.m_type = value_t::object;
3421             m_data.m_value.object = create<object_t>();
3422             assert_invariant();
3423         }
3424 
3425         if (JSON_HEDLEY_UNLIKELY(!is_object()))
3426         {
3427             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
3428         }
3429 
3430         // check if range iterators belong to the same JSON object
3431         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3432         {
3433             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3434         }
3435 
3436         // passed iterators must belong to objects
3437         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
3438         {
3439             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
3440         }
3441 
3442         for (auto it = first; it != last; ++it)
3443         {
3444             if (merge_objects && it.value().is_object())
3445             {
3446                 auto it2 = m_data.m_value.object->find(it.key());
3447                 if (it2 != m_data.m_value.object->end())
3448                 {
3449                     it2->second.update(it.value(), true);
3450                     continue;
3451                 }
3452             }
3453             m_data.m_value.object->operator[](it.key()) = it.value();
3454 #if JSON_DIAGNOSTICS
3455             m_data.m_value.object->operator[](it.key()).m_parent = this;
3456 #endif
3457         }
3458     }
3459 
3460     /// @brief exchanges the values
3461     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3462     void swap(reference other) noexcept (
3463         std::is_nothrow_move_constructible<value_t>::value&&
3464         std::is_nothrow_move_assignable<value_t>::value&&
3465         std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3466         std::is_nothrow_move_assignable<json_value>::value
3467     )
3468     {
3469         std::swap(m_data.m_type, other.m_data.m_type);
3470         std::swap(m_data.m_value, other.m_data.m_value);
3471 
3472         set_parents();
3473         other.set_parents();
3474         assert_invariant();
3475     }
3476 
3477     /// @brief exchanges the values
3478     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3479     friend void swap(reference left, reference right) noexcept (
3480         std::is_nothrow_move_constructible<value_t>::value&&
3481         std::is_nothrow_move_assignable<value_t>::value&&
3482         std::is_nothrow_move_constructible<json_value>::value&& // NOLINT(cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3483         std::is_nothrow_move_assignable<json_value>::value
3484     )
3485     {
3486         left.swap(right);
3487     }
3488 
3489     /// @brief exchanges the values
3490     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3491     void swap(array_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3492     {
3493         // swap only works for arrays
3494         if (JSON_HEDLEY_LIKELY(is_array()))
3495         {
3496             using std::swap;
3497             swap(*(m_data.m_value.array), other);
3498         }
3499         else
3500         {
3501             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
3502         }
3503     }
3504 
3505     /// @brief exchanges the values
3506     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3507     void swap(object_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3508     {
3509         // swap only works for objects
3510         if (JSON_HEDLEY_LIKELY(is_object()))
3511         {
3512             using std::swap;
3513             swap(*(m_data.m_value.object), other);
3514         }
3515         else
3516         {
3517             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
3518         }
3519     }
3520 
3521     /// @brief exchanges the values
3522     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3523     void swap(string_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3524     {
3525         // swap only works for strings
3526         if (JSON_HEDLEY_LIKELY(is_string()))
3527         {
3528             using std::swap;
3529             swap(*(m_data.m_value.string), other);
3530         }
3531         else
3532         {
3533             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
3534         }
3535     }
3536 
3537     /// @brief exchanges the values
3538     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3539     void swap(binary_t& other) // NOLINT(bugprone-exception-escape,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
3540     {
3541         // swap only works for strings
3542         if (JSON_HEDLEY_LIKELY(is_binary()))
3543         {
3544             using std::swap;
3545             swap(*(m_data.m_value.binary), other);
3546         }
3547         else
3548         {
3549             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
3550         }
3551     }
3552 
3553     /// @brief exchanges the values
3554     /// @sa https://json.nlohmann.me/api/basic_json/swap/
3555     void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
3556     {
3557         // swap only works for strings
3558         if (JSON_HEDLEY_LIKELY(is_binary()))
3559         {
3560             using std::swap;
3561             swap(*(m_data.m_value.binary), other);
3562         }
3563         else
3564         {
3565             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
3566         }
3567     }
3568 
3569     /// @}
3570 
3571     //////////////////////////////////////////
3572     // lexicographical comparison operators //
3573     //////////////////////////////////////////
3574 
3575     /// @name lexicographical comparison operators
3576     /// @{
3577 
3578     // note parentheses around operands are necessary; see
3579     // https://github.com/nlohmann/json/issues/1530
3580 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
3581     const auto lhs_type = lhs.type();                                                                    \
3582     const auto rhs_type = rhs.type();                                                                    \
3583     \
3584     if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
3585     {                                                                                                    \
3586         switch (lhs_type)                                                                                \
3587         {                                                                                                \
3588             case value_t::array:                                                                         \
3589                 return (*lhs.m_data.m_value.array) op (*rhs.m_data.m_value.array);                                     \
3590                 \
3591             case value_t::object:                                                                        \
3592                 return (*lhs.m_data.m_value.object) op (*rhs.m_data.m_value.object);                                   \
3593                 \
3594             case value_t::null:                                                                          \
3595                 return (null_result);                                                                    \
3596                 \
3597             case value_t::string:                                                                        \
3598                 return (*lhs.m_data.m_value.string) op (*rhs.m_data.m_value.string);                                   \
3599                 \
3600             case value_t::boolean:                                                                       \
3601                 return (lhs.m_data.m_value.boolean) op (rhs.m_data.m_value.boolean);                                   \
3602                 \
3603             case value_t::number_integer:                                                                \
3604                 return (lhs.m_data.m_value.number_integer) op (rhs.m_data.m_value.number_integer);                     \
3605                 \
3606             case value_t::number_unsigned:                                                               \
3607                 return (lhs.m_data.m_value.number_unsigned) op (rhs.m_data.m_value.number_unsigned);                   \
3608                 \
3609             case value_t::number_float:                                                                  \
3610                 return (lhs.m_data.m_value.number_float) op (rhs.m_data.m_value.number_float);                         \
3611                 \
3612             case value_t::binary:                                                                        \
3613                 return (*lhs.m_data.m_value.binary) op (*rhs.m_data.m_value.binary);                                   \
3614                 \
3615             case value_t::discarded:                                                                     \
3616             default:                                                                                     \
3617                 return (unordered_result);                                                               \
3618         }                                                                                                \
3619     }                                                                                                    \
3620     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
3621     {                                                                                                    \
3622         return static_cast<number_float_t>(lhs.m_data.m_value.number_integer) op rhs.m_data.m_value.number_float;      \
3623     }                                                                                                    \
3624     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
3625     {                                                                                                    \
3626         return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_integer);      \
3627     }                                                                                                    \
3628     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
3629     {                                                                                                    \
3630         return static_cast<number_float_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_float;     \
3631     }                                                                                                    \
3632     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
3633     {                                                                                                    \
3634         return lhs.m_data.m_value.number_float op static_cast<number_float_t>(rhs.m_data.m_value.number_unsigned);     \
3635     }                                                                                                    \
3636     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
3637     {                                                                                                    \
3638         return static_cast<number_integer_t>(lhs.m_data.m_value.number_unsigned) op rhs.m_data.m_value.number_integer; \
3639     }                                                                                                    \
3640     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
3641     {                                                                                                    \
3642         return lhs.m_data.m_value.number_integer op static_cast<number_integer_t>(rhs.m_data.m_value.number_unsigned); \
3643     }                                                                                                    \
3644     else if(compares_unordered(lhs, rhs))\
3645     {\
3646         return (unordered_result);\
3647     }\
3648     \
3649     return (default_result);
3650 
3651   JSON_PRIVATE_UNLESS_TESTED:
3652     // returns true if:
3653     // - any operand is NaN and the other operand is of number type
3654     // - any operand is discarded
3655     // in legacy mode, discarded values are considered ordered if
3656     // an operation is computed as an odd number of inverses of others
3657     static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
3658     {
3659         if ((lhs.is_number_float() && std::isnan(lhs.m_data.m_value.number_float) && rhs.is_number())
3660                 || (rhs.is_number_float() && std::isnan(rhs.m_data.m_value.number_float) && lhs.is_number()))
3661         {
3662             return true;
3663         }
3664 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
3665         return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
3666 #else
3667         static_cast<void>(inverse);
3668         return lhs.is_discarded() || rhs.is_discarded();
3669 #endif
3670     }
3671 
3672   private:
3673     bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
3674     {
3675         return compares_unordered(*this, rhs, inverse);
3676     }
3677 
3678   public:
3679 #if JSON_HAS_THREE_WAY_COMPARISON
3680     /// @brief comparison: equal
3681     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3682     bool operator==(const_reference rhs) const noexcept
3683     {
3684 #ifdef __GNUC__
3685 #pragma GCC diagnostic push
3686 #pragma GCC diagnostic ignored "-Wfloat-equal"
3687 #endif
3688         const_reference lhs = *this;
3689         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
3690 #ifdef __GNUC__
3691 #pragma GCC diagnostic pop
3692 #endif
3693     }
3694 
3695     /// @brief comparison: equal
3696     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3697     template<typename ScalarType>
3698     requires std::is_scalar_v<ScalarType>
3699     bool operator==(ScalarType rhs) const noexcept
3700     {
3701         return *this == basic_json(rhs);
3702     }
3703 
3704     /// @brief comparison: not equal
3705     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3706     bool operator!=(const_reference rhs) const noexcept
3707     {
3708         if (compares_unordered(rhs, true))
3709         {
3710             return false;
3711         }
3712         return !operator==(rhs);
3713     }
3714 
3715     /// @brief comparison: 3-way
3716     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
3717     std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
3718     {
3719         const_reference lhs = *this;
3720         // default_result is used if we cannot compare values. In that case,
3721         // we compare types.
3722         JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
3723                                 std::partial_ordering::equivalent,
3724                                 std::partial_ordering::unordered,
3725                                 lhs_type <=> rhs_type) // *NOPAD*
3726     }
3727 
3728     /// @brief comparison: 3-way
3729     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
3730     template<typename ScalarType>
3731     requires std::is_scalar_v<ScalarType>
3732     std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
3733     {
3734         return *this <=> basic_json(rhs); // *NOPAD*
3735     }
3736 
3737 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
3738     // all operators that are computed as an odd number of inverses of others
3739     // need to be overloaded to emulate the legacy comparison behavior
3740 
3741     /// @brief comparison: less than or equal
3742     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3743     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
3744     bool operator<=(const_reference rhs) const noexcept
3745     {
3746         if (compares_unordered(rhs, true))
3747         {
3748             return false;
3749         }
3750         return !(rhs < *this);
3751     }
3752 
3753     /// @brief comparison: less than or equal
3754     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3755     template<typename ScalarType>
3756     requires std::is_scalar_v<ScalarType>
3757     bool operator<=(ScalarType rhs) const noexcept
3758     {
3759         return *this <= basic_json(rhs);
3760     }
3761 
3762     /// @brief comparison: greater than or equal
3763     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3764     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
3765     bool operator>=(const_reference rhs) const noexcept
3766     {
3767         if (compares_unordered(rhs, true))
3768         {
3769             return false;
3770         }
3771         return !(*this < rhs);
3772     }
3773 
3774     /// @brief comparison: greater than or equal
3775     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3776     template<typename ScalarType>
3777     requires std::is_scalar_v<ScalarType>
3778     bool operator>=(ScalarType rhs) const noexcept
3779     {
3780         return *this >= basic_json(rhs);
3781     }
3782 #endif
3783 #else
3784     /// @brief comparison: equal
3785     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3786     friend bool operator==(const_reference lhs, const_reference rhs) noexcept
3787     {
3788 #ifdef __GNUC__
3789 #pragma GCC diagnostic push
3790 #pragma GCC diagnostic ignored "-Wfloat-equal"
3791 #endif
3792         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
3793 #ifdef __GNUC__
3794 #pragma GCC diagnostic pop
3795 #endif
3796     }
3797 
3798     /// @brief comparison: equal
3799     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3800     template<typename ScalarType, typename std::enable_if<
3801                  std::is_scalar<ScalarType>::value, int>::type = 0>
3802     friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
3803     {
3804         return lhs == basic_json(rhs);
3805     }
3806 
3807     /// @brief comparison: equal
3808     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3809     template<typename ScalarType, typename std::enable_if<
3810                  std::is_scalar<ScalarType>::value, int>::type = 0>
3811     friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
3812     {
3813         return basic_json(lhs) == rhs;
3814     }
3815 
3816     /// @brief comparison: not equal
3817     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3818     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
3819     {
3820         if (compares_unordered(lhs, rhs, true))
3821         {
3822             return false;
3823         }
3824         return !(lhs == rhs);
3825     }
3826 
3827     /// @brief comparison: not equal
3828     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3829     template<typename ScalarType, typename std::enable_if<
3830                  std::is_scalar<ScalarType>::value, int>::type = 0>
3831     friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
3832     {
3833         return lhs != basic_json(rhs);
3834     }
3835 
3836     /// @brief comparison: not equal
3837     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3838     template<typename ScalarType, typename std::enable_if<
3839                  std::is_scalar<ScalarType>::value, int>::type = 0>
3840     friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
3841     {
3842         return basic_json(lhs) != rhs;
3843     }
3844 
3845     /// @brief comparison: less than
3846     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3847     friend bool operator<(const_reference lhs, const_reference rhs) noexcept
3848     {
3849         // default_result is used if we cannot compare values. In that case,
3850         // we compare types. Note we have to call the operator explicitly,
3851         // because MSVC has problems otherwise.
3852         JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
3853     }
3854 
3855     /// @brief comparison: less than
3856     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3857     template<typename ScalarType, typename std::enable_if<
3858                  std::is_scalar<ScalarType>::value, int>::type = 0>
3859     friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
3860     {
3861         return lhs < basic_json(rhs);
3862     }
3863 
3864     /// @brief comparison: less than
3865     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3866     template<typename ScalarType, typename std::enable_if<
3867                  std::is_scalar<ScalarType>::value, int>::type = 0>
3868     friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
3869     {
3870         return basic_json(lhs) < rhs;
3871     }
3872 
3873     /// @brief comparison: less than or equal
3874     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3875     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
3876     {
3877         if (compares_unordered(lhs, rhs, true))
3878         {
3879             return false;
3880         }
3881         return !(rhs < lhs);
3882     }
3883 
3884     /// @brief comparison: less than or equal
3885     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3886     template<typename ScalarType, typename std::enable_if<
3887                  std::is_scalar<ScalarType>::value, int>::type = 0>
3888     friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
3889     {
3890         return lhs <= basic_json(rhs);
3891     }
3892 
3893     /// @brief comparison: less than or equal
3894     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3895     template<typename ScalarType, typename std::enable_if<
3896                  std::is_scalar<ScalarType>::value, int>::type = 0>
3897     friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
3898     {
3899         return basic_json(lhs) <= rhs;
3900     }
3901 
3902     /// @brief comparison: greater than
3903     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3904     friend bool operator>(const_reference lhs, const_reference rhs) noexcept
3905     {
3906         // double inverse
3907         if (compares_unordered(lhs, rhs))
3908         {
3909             return false;
3910         }
3911         return !(lhs <= rhs);
3912     }
3913 
3914     /// @brief comparison: greater than
3915     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3916     template<typename ScalarType, typename std::enable_if<
3917                  std::is_scalar<ScalarType>::value, int>::type = 0>
3918     friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
3919     {
3920         return lhs > basic_json(rhs);
3921     }
3922 
3923     /// @brief comparison: greater than
3924     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3925     template<typename ScalarType, typename std::enable_if<
3926                  std::is_scalar<ScalarType>::value, int>::type = 0>
3927     friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
3928     {
3929         return basic_json(lhs) > rhs;
3930     }
3931 
3932     /// @brief comparison: greater than or equal
3933     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3934     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
3935     {
3936         if (compares_unordered(lhs, rhs, true))
3937         {
3938             return false;
3939         }
3940         return !(lhs < rhs);
3941     }
3942 
3943     /// @brief comparison: greater than or equal
3944     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3945     template<typename ScalarType, typename std::enable_if<
3946                  std::is_scalar<ScalarType>::value, int>::type = 0>
3947     friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
3948     {
3949         return lhs >= basic_json(rhs);
3950     }
3951 
3952     /// @brief comparison: greater than or equal
3953     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3954     template<typename ScalarType, typename std::enable_if<
3955                  std::is_scalar<ScalarType>::value, int>::type = 0>
3956     friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
3957     {
3958         return basic_json(lhs) >= rhs;
3959     }
3960 #endif
3961 
3962 #undef JSON_IMPLEMENT_OPERATOR
3963 
3964     /// @}
3965 
3966     ///////////////////
3967     // serialization //
3968     ///////////////////
3969 
3970     /// @name serialization
3971     /// @{
3972 #ifndef JSON_NO_IO
3973     /// @brief serialize to stream
3974     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
3975     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
3976     {
3977         // read width member and use it as indentation parameter if nonzero
3978         const bool pretty_print = o.width() > 0;
3979         const auto indentation = pretty_print ? o.width() : 0;
3980 
3981         // reset width to 0 for subsequent calls to this stream
3982         o.width(0);
3983 
3984         // do the actual serialization
3985         serializer s(detail::output_adapter<char>(o), o.fill());
3986         s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
3987         return o;
3988     }
3989 
3990     /// @brief serialize to stream
3991     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
3992     /// @deprecated This function is deprecated since 3.0.0 and will be removed in
3993     ///             version 4.0.0 of the library. Please use
3994     ///             operator<<(std::ostream&, const basic_json&) instead; that is,
3995     ///             replace calls like `j >> o;` with `o << j;`.
3996     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
3997     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
3998     {
3999         return o << j;
4000     }
4001 #endif  // JSON_NO_IO
4002     /// @}
4003 
4004     /////////////////////
4005     // deserialization //
4006     /////////////////////
4007 
4008     /// @name deserialization
4009     /// @{
4010 
4011     /// @brief deserialize from a compatible input
4012     /// @sa https://json.nlohmann.me/api/basic_json/parse/
4013     template<typename InputType>
4014     JSON_HEDLEY_WARN_UNUSED_RESULT
4015     static basic_json parse(InputType&& i,
4016                             const parser_callback_t cb = nullptr,
4017                             const bool allow_exceptions = true,
4018                             const bool ignore_comments = false)
4019     {
4020         basic_json result;
4021         parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
4022         return result;
4023     }
4024 
4025     /// @brief deserialize from a pair of character iterators
4026     /// @sa https://json.nlohmann.me/api/basic_json/parse/
4027     template<typename IteratorType>
4028     JSON_HEDLEY_WARN_UNUSED_RESULT
4029     static basic_json parse(IteratorType first,
4030                             IteratorType last,
4031                             const parser_callback_t cb = nullptr,
4032                             const bool allow_exceptions = true,
4033                             const bool ignore_comments = false)
4034     {
4035         basic_json result;
4036         parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
4037         return result;
4038     }
4039 
4040     JSON_HEDLEY_WARN_UNUSED_RESULT
4041     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
4042     static basic_json parse(detail::span_input_adapter&& i,
4043                             const parser_callback_t cb = nullptr,
4044                             const bool allow_exceptions = true,
4045                             const bool ignore_comments = false)
4046     {
4047         basic_json result;
4048         parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
4049         return result;
4050     }
4051 
4052     /// @brief check if the input is valid JSON
4053     /// @sa https://json.nlohmann.me/api/basic_json/accept/
4054     template<typename InputType>
4055     static bool accept(InputType&& i,
4056                        const bool ignore_comments = false)
4057     {
4058         return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
4059     }
4060 
4061     /// @brief check if the input is valid JSON
4062     /// @sa https://json.nlohmann.me/api/basic_json/accept/
4063     template<typename IteratorType>
4064     static bool accept(IteratorType first, IteratorType last,
4065                        const bool ignore_comments = false)
4066     {
4067         return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
4068     }
4069 
4070     JSON_HEDLEY_WARN_UNUSED_RESULT
4071     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
4072     static bool accept(detail::span_input_adapter&& i,
4073                        const bool ignore_comments = false)
4074     {
4075         return parser(i.get(), nullptr, false, ignore_comments).accept(true);
4076     }
4077 
4078     /// @brief generate SAX events
4079     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4080     template <typename InputType, typename SAX>
4081     JSON_HEDLEY_NON_NULL(2)
4082     static bool sax_parse(InputType&& i, SAX* sax,
4083                           input_format_t format = input_format_t::json,
4084                           const bool strict = true,
4085                           const bool ignore_comments = false)
4086     {
4087         auto ia = detail::input_adapter(std::forward<InputType>(i));
4088         return format == input_format_t::json
4089                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
4090                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4091     }
4092 
4093     /// @brief generate SAX events
4094     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4095     template<class IteratorType, class SAX>
4096     JSON_HEDLEY_NON_NULL(3)
4097     static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
4098                           input_format_t format = input_format_t::json,
4099                           const bool strict = true,
4100                           const bool ignore_comments = false)
4101     {
4102         auto ia = detail::input_adapter(std::move(first), std::move(last));
4103         return format == input_format_t::json
4104                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
4105                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4106     }
4107 
4108     /// @brief generate SAX events
4109     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4110     /// @deprecated This function is deprecated since 3.8.0 and will be removed in
4111     ///             version 4.0.0 of the library. Please use
4112     ///             sax_parse(ptr, ptr + len) instead.
4113     template <typename SAX>
4114     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
4115     JSON_HEDLEY_NON_NULL(2)
4116     static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
4117                           input_format_t format = input_format_t::json,
4118                           const bool strict = true,
4119                           const bool ignore_comments = false)
4120     {
4121         auto ia = i.get();
4122         return format == input_format_t::json
4123                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4124                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
4125                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4126                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4127     }
4128 #ifndef JSON_NO_IO
4129     /// @brief deserialize from stream
4130     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
4131     /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
4132     ///             version 4.0.0 of the library. Please use
4133     ///             operator>>(std::istream&, basic_json&) instead; that is,
4134     ///             replace calls like `j << i;` with `i >> j;`.
4135     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
4136     friend std::istream& operator<<(basic_json& j, std::istream& i)
4137     {
4138         return operator>>(i, j);
4139     }
4140 
4141     /// @brief deserialize from stream
4142     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
4143     friend std::istream& operator>>(std::istream& i, basic_json& j)
4144     {
4145         parser(detail::input_adapter(i)).parse(false, j);
4146         return i;
4147     }
4148 #endif  // JSON_NO_IO
4149     /// @}
4150 
4151     ///////////////////////////
4152     // convenience functions //
4153     ///////////////////////////
4154 
4155     /// @brief return the type as string
4156     /// @sa https://json.nlohmann.me/api/basic_json/type_name/
4157     JSON_HEDLEY_RETURNS_NON_NULL
4158     const char* type_name() const noexcept
4159     {
4160         switch (m_data.m_type)
4161         {
4162             case value_t::null:
4163                 return "null";
4164             case value_t::object:
4165                 return "object";
4166             case value_t::array:
4167                 return "array";
4168             case value_t::string:
4169                 return "string";
4170             case value_t::boolean:
4171                 return "boolean";
4172             case value_t::binary:
4173                 return "binary";
4174             case value_t::discarded:
4175                 return "discarded";
4176             case value_t::number_integer:
4177             case value_t::number_unsigned:
4178             case value_t::number_float:
4179             default:
4180                 return "number";
4181         }
4182     }
4183 
4184   JSON_PRIVATE_UNLESS_TESTED:
4185     //////////////////////
4186     // member variables //
4187     //////////////////////
4188 
4189     struct data
4190     {
4191         /// the type of the current element
4192         value_t m_type = value_t::null;
4193 
4194         /// the value of the current element
4195         json_value m_value = {};
4196 
4197         data(const value_t v)
4198             : m_type(v), m_value(v)
4199         {
4200         }
4201 
4202         data(size_type cnt, const basic_json& val)
4203             : m_type(value_t::array)
4204         {
4205             m_value.array = create<array_t>(cnt, val);
4206         }
4207 
4208         data() noexcept = default;
4209         data(data&&) noexcept = default;
4210         data(const data&) noexcept = delete;
4211         data& operator=(data&&) noexcept = delete;
4212         data& operator=(const data&) noexcept = delete;
4213 
4214         ~data() noexcept
4215         {
4216             m_value.destroy(m_type);
4217         }
4218     };
4219 
4220     data m_data = {};
4221 
4222 #if JSON_DIAGNOSTICS
4223     /// a pointer to a parent value (for debugging purposes)
4224     basic_json* m_parent = nullptr;
4225 #endif
4226 
4227     //////////////////////////////////////////
4228     // binary serialization/deserialization //
4229     //////////////////////////////////////////
4230 
4231     /// @name binary serialization/deserialization support
4232     /// @{
4233 
4234   public:
4235     /// @brief create a CBOR serialization of a given JSON value
4236     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4237     static std::vector<std::uint8_t> to_cbor(const basic_json& j)
4238     {
4239         std::vector<std::uint8_t> result;
4240         to_cbor(j, result);
4241         return result;
4242     }
4243 
4244     /// @brief create a CBOR serialization of a given JSON value
4245     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4246     static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
4247     {
4248         binary_writer<std::uint8_t>(o).write_cbor(j);
4249     }
4250 
4251     /// @brief create a CBOR serialization of a given JSON value
4252     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4253     static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
4254     {
4255         binary_writer<char>(o).write_cbor(j);
4256     }
4257 
4258     /// @brief create a MessagePack serialization of a given JSON value
4259     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4260     static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
4261     {
4262         std::vector<std::uint8_t> result;
4263         to_msgpack(j, result);
4264         return result;
4265     }
4266 
4267     /// @brief create a MessagePack serialization of a given JSON value
4268     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4269     static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
4270     {
4271         binary_writer<std::uint8_t>(o).write_msgpack(j);
4272     }
4273 
4274     /// @brief create a MessagePack serialization of a given JSON value
4275     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4276     static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
4277     {
4278         binary_writer<char>(o).write_msgpack(j);
4279     }
4280 
4281     /// @brief create a UBJSON serialization of a given JSON value
4282     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4283     static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
4284             const bool use_size = false,
4285             const bool use_type = false)
4286     {
4287         std::vector<std::uint8_t> result;
4288         to_ubjson(j, result, use_size, use_type);
4289         return result;
4290     }
4291 
4292     /// @brief create a UBJSON serialization of a given JSON value
4293     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4294     static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
4295                           const bool use_size = false, const bool use_type = false)
4296     {
4297         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
4298     }
4299 
4300     /// @brief create a UBJSON serialization of a given JSON value
4301     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4302     static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
4303                           const bool use_size = false, const bool use_type = false)
4304     {
4305         binary_writer<char>(o).write_ubjson(j, use_size, use_type);
4306     }
4307 
4308     /// @brief create a BJData serialization of a given JSON value
4309     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4310     static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
4311             const bool use_size = false,
4312             const bool use_type = false)
4313     {
4314         std::vector<std::uint8_t> result;
4315         to_bjdata(j, result, use_size, use_type);
4316         return result;
4317     }
4318 
4319     /// @brief create a BJData serialization of a given JSON value
4320     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4321     static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
4322                           const bool use_size = false, const bool use_type = false)
4323     {
4324         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
4325     }
4326 
4327     /// @brief create a BJData serialization of a given JSON value
4328     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4329     static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
4330                           const bool use_size = false, const bool use_type = false)
4331     {
4332         binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
4333     }
4334 
4335     /// @brief create a BSON serialization of a given JSON value
4336     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4337     static std::vector<std::uint8_t> to_bson(const basic_json& j)
4338     {
4339         std::vector<std::uint8_t> result;
4340         to_bson(j, result);
4341         return result;
4342     }
4343 
4344     /// @brief create a BSON serialization of a given JSON value
4345     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4346     static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
4347     {
4348         binary_writer<std::uint8_t>(o).write_bson(j);
4349     }
4350 
4351     /// @brief create a BSON serialization of a given JSON value
4352     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4353     static void to_bson(const basic_json& j, detail::output_adapter<char> o)
4354     {
4355         binary_writer<char>(o).write_bson(j);
4356     }
4357 
4358     /// @brief create a JSON value from an input in CBOR format
4359     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
4360     template<typename InputType>
4361     JSON_HEDLEY_WARN_UNUSED_RESULT
4362     static basic_json from_cbor(InputType&& i,
4363                                 const bool strict = true,
4364                                 const bool allow_exceptions = true,
4365                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4366     {
4367         basic_json result;
4368         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4369         auto ia = detail::input_adapter(std::forward<InputType>(i));
4370         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
4371         return res ? result : basic_json(value_t::discarded);
4372     }
4373 
4374     /// @brief create a JSON value from an input in CBOR format
4375     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
4376     template<typename IteratorType>
4377     JSON_HEDLEY_WARN_UNUSED_RESULT
4378     static basic_json from_cbor(IteratorType first, IteratorType last,
4379                                 const bool strict = true,
4380                                 const bool allow_exceptions = true,
4381                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4382     {
4383         basic_json result;
4384         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4385         auto ia = detail::input_adapter(std::move(first), std::move(last));
4386         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
4387         return res ? result : basic_json(value_t::discarded);
4388     }
4389 
4390     template<typename T>
4391     JSON_HEDLEY_WARN_UNUSED_RESULT
4392     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
4393     static basic_json from_cbor(const T* ptr, std::size_t len,
4394                                 const bool strict = true,
4395                                 const bool allow_exceptions = true,
4396                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4397     {
4398         return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
4399     }
4400 
4401     JSON_HEDLEY_WARN_UNUSED_RESULT
4402     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
4403     static basic_json from_cbor(detail::span_input_adapter&& i,
4404                                 const bool strict = true,
4405                                 const bool allow_exceptions = true,
4406                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4407     {
4408         basic_json result;
4409         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4410         auto ia = i.get();
4411         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4412         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
4413         return res ? result : basic_json(value_t::discarded);
4414     }
4415 
4416     /// @brief create a JSON value from an input in MessagePack format
4417     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
4418     template<typename InputType>
4419     JSON_HEDLEY_WARN_UNUSED_RESULT
4420     static basic_json from_msgpack(InputType&& i,
4421                                    const bool strict = true,
4422                                    const bool allow_exceptions = true)
4423     {
4424         basic_json result;
4425         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4426         auto ia = detail::input_adapter(std::forward<InputType>(i));
4427         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
4428         return res ? result : basic_json(value_t::discarded);
4429     }
4430 
4431     /// @brief create a JSON value from an input in MessagePack format
4432     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
4433     template<typename IteratorType>
4434     JSON_HEDLEY_WARN_UNUSED_RESULT
4435     static basic_json from_msgpack(IteratorType first, IteratorType last,
4436                                    const bool strict = true,
4437                                    const bool allow_exceptions = true)
4438     {
4439         basic_json result;
4440         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4441         auto ia = detail::input_adapter(std::move(first), std::move(last));
4442         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
4443         return res ? result : basic_json(value_t::discarded);
4444     }
4445 
4446     template<typename T>
4447     JSON_HEDLEY_WARN_UNUSED_RESULT
4448     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
4449     static basic_json from_msgpack(const T* ptr, std::size_t len,
4450                                    const bool strict = true,
4451                                    const bool allow_exceptions = true)
4452     {
4453         return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
4454     }
4455 
4456     JSON_HEDLEY_WARN_UNUSED_RESULT
4457     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
4458     static basic_json from_msgpack(detail::span_input_adapter&& i,
4459                                    const bool strict = true,
4460                                    const bool allow_exceptions = true)
4461     {
4462         basic_json result;
4463         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4464         auto ia = i.get();
4465         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4466         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
4467         return res ? result : basic_json(value_t::discarded);
4468     }
4469 
4470     /// @brief create a JSON value from an input in UBJSON format
4471     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
4472     template<typename InputType>
4473     JSON_HEDLEY_WARN_UNUSED_RESULT
4474     static basic_json from_ubjson(InputType&& i,
4475                                   const bool strict = true,
4476                                   const bool allow_exceptions = true)
4477     {
4478         basic_json result;
4479         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4480         auto ia = detail::input_adapter(std::forward<InputType>(i));
4481         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
4482         return res ? result : basic_json(value_t::discarded);
4483     }
4484 
4485     /// @brief create a JSON value from an input in UBJSON format
4486     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
4487     template<typename IteratorType>
4488     JSON_HEDLEY_WARN_UNUSED_RESULT
4489     static basic_json from_ubjson(IteratorType first, IteratorType last,
4490                                   const bool strict = true,
4491                                   const bool allow_exceptions = true)
4492     {
4493         basic_json result;
4494         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4495         auto ia = detail::input_adapter(std::move(first), std::move(last));
4496         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
4497         return res ? result : basic_json(value_t::discarded);
4498     }
4499 
4500     template<typename T>
4501     JSON_HEDLEY_WARN_UNUSED_RESULT
4502     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
4503     static basic_json from_ubjson(const T* ptr, std::size_t len,
4504                                   const bool strict = true,
4505                                   const bool allow_exceptions = true)
4506     {
4507         return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
4508     }
4509 
4510     JSON_HEDLEY_WARN_UNUSED_RESULT
4511     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
4512     static basic_json from_ubjson(detail::span_input_adapter&& i,
4513                                   const bool strict = true,
4514                                   const bool allow_exceptions = true)
4515     {
4516         basic_json result;
4517         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4518         auto ia = i.get();
4519         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4520         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
4521         return res ? result : basic_json(value_t::discarded);
4522     }
4523 
4524     /// @brief create a JSON value from an input in BJData format
4525     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
4526     template<typename InputType>
4527     JSON_HEDLEY_WARN_UNUSED_RESULT
4528     static basic_json from_bjdata(InputType&& i,
4529                                   const bool strict = true,
4530                                   const bool allow_exceptions = true)
4531     {
4532         basic_json result;
4533         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4534         auto ia = detail::input_adapter(std::forward<InputType>(i));
4535         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
4536         return res ? result : basic_json(value_t::discarded);
4537     }
4538 
4539     /// @brief create a JSON value from an input in BJData format
4540     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
4541     template<typename IteratorType>
4542     JSON_HEDLEY_WARN_UNUSED_RESULT
4543     static basic_json from_bjdata(IteratorType first, IteratorType last,
4544                                   const bool strict = true,
4545                                   const bool allow_exceptions = true)
4546     {
4547         basic_json result;
4548         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4549         auto ia = detail::input_adapter(std::move(first), std::move(last));
4550         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
4551         return res ? result : basic_json(value_t::discarded);
4552     }
4553 
4554     /// @brief create a JSON value from an input in BSON format
4555     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
4556     template<typename InputType>
4557     JSON_HEDLEY_WARN_UNUSED_RESULT
4558     static basic_json from_bson(InputType&& i,
4559                                 const bool strict = true,
4560                                 const bool allow_exceptions = true)
4561     {
4562         basic_json result;
4563         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4564         auto ia = detail::input_adapter(std::forward<InputType>(i));
4565         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
4566         return res ? result : basic_json(value_t::discarded);
4567     }
4568 
4569     /// @brief create a JSON value from an input in BSON format
4570     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
4571     template<typename IteratorType>
4572     JSON_HEDLEY_WARN_UNUSED_RESULT
4573     static basic_json from_bson(IteratorType first, IteratorType last,
4574                                 const bool strict = true,
4575                                 const bool allow_exceptions = true)
4576     {
4577         basic_json result;
4578         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4579         auto ia = detail::input_adapter(std::move(first), std::move(last));
4580         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
4581         return res ? result : basic_json(value_t::discarded);
4582     }
4583 
4584     template<typename T>
4585     JSON_HEDLEY_WARN_UNUSED_RESULT
4586     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
4587     static basic_json from_bson(const T* ptr, std::size_t len,
4588                                 const bool strict = true,
4589                                 const bool allow_exceptions = true)
4590     {
4591         return from_bson(ptr, ptr + len, strict, allow_exceptions);
4592     }
4593 
4594     JSON_HEDLEY_WARN_UNUSED_RESULT
4595     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
4596     static basic_json from_bson(detail::span_input_adapter&& i,
4597                                 const bool strict = true,
4598                                 const bool allow_exceptions = true)
4599     {
4600         basic_json result;
4601         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4602         auto ia = i.get();
4603         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4604         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
4605         return res ? result : basic_json(value_t::discarded);
4606     }
4607     /// @}
4608 
4609     //////////////////////////
4610     // JSON Pointer support //
4611     //////////////////////////
4612 
4613     /// @name JSON Pointer functions
4614     /// @{
4615 
4616     /// @brief access specified element via JSON Pointer
4617     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
4618     reference operator[](const json_pointer& ptr)
4619     {
4620         return ptr.get_unchecked(this);
4621     }
4622 
4623     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4624     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4625     reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
4626     {
4627         return ptr.get_unchecked(this);
4628     }
4629 
4630     /// @brief access specified element via JSON Pointer
4631     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
4632     const_reference operator[](const json_pointer& ptr) const
4633     {
4634         return ptr.get_unchecked(this);
4635     }
4636 
4637     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4638     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4639     const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
4640     {
4641         return ptr.get_unchecked(this);
4642     }
4643 
4644     /// @brief access specified element via JSON Pointer
4645     /// @sa https://json.nlohmann.me/api/basic_json/at/
4646     reference at(const json_pointer& ptr)
4647     {
4648         return ptr.get_checked(this);
4649     }
4650 
4651     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4652     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4653     reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
4654     {
4655         return ptr.get_checked(this);
4656     }
4657 
4658     /// @brief access specified element via JSON Pointer
4659     /// @sa https://json.nlohmann.me/api/basic_json/at/
4660     const_reference at(const json_pointer& ptr) const
4661     {
4662         return ptr.get_checked(this);
4663     }
4664 
4665     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4666     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4667     const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
4668     {
4669         return ptr.get_checked(this);
4670     }
4671 
4672     /// @brief return flattened JSON value
4673     /// @sa https://json.nlohmann.me/api/basic_json/flatten/
4674     basic_json flatten() const
4675     {
4676         basic_json result(value_t::object);
4677         json_pointer::flatten("", *this, result);
4678         return result;
4679     }
4680 
4681     /// @brief unflatten a previously flattened JSON value
4682     /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
4683     basic_json unflatten() const
4684     {
4685         return json_pointer::unflatten(*this);
4686     }
4687 
4688     /// @}
4689 
4690     //////////////////////////
4691     // JSON Patch functions //
4692     //////////////////////////
4693 
4694     /// @name JSON Patch functions
4695     /// @{
4696 
4697     /// @brief applies a JSON patch in-place without copying the object
4698     /// @sa https://json.nlohmann.me/api/basic_json/patch/
4699     void patch_inplace(const basic_json& json_patch)
4700     {
4701         basic_json& result = *this;
4702         // the valid JSON Patch operations
4703         enum class patch_operations {add, remove, replace, move, copy, test, invalid};
4704 
4705         const auto get_op = [](const std::string & op)
4706         {
4707             if (op == "add")
4708             {
4709                 return patch_operations::add;
4710             }
4711             if (op == "remove")
4712             {
4713                 return patch_operations::remove;
4714             }
4715             if (op == "replace")
4716             {
4717                 return patch_operations::replace;
4718             }
4719             if (op == "move")
4720             {
4721                 return patch_operations::move;
4722             }
4723             if (op == "copy")
4724             {
4725                 return patch_operations::copy;
4726             }
4727             if (op == "test")
4728             {
4729                 return patch_operations::test;
4730             }
4731 
4732             return patch_operations::invalid;
4733         };
4734 
4735         // wrapper for "add" operation; add value at ptr
4736         const auto operation_add = [&result](json_pointer & ptr, basic_json val)
4737         {
4738             // adding to the root of the target document means replacing it
4739             if (ptr.empty())
4740             {
4741                 result = val;
4742                 return;
4743             }
4744 
4745             // make sure the top element of the pointer exists
4746             json_pointer const top_pointer = ptr.top();
4747             if (top_pointer != ptr)
4748             {
4749                 result.at(top_pointer);
4750             }
4751 
4752             // get reference to parent of JSON pointer ptr
4753             const auto last_path = ptr.back();
4754             ptr.pop_back();
4755             // parent must exist when performing patch add per RFC6902 specs
4756             basic_json& parent = result.at(ptr);
4757 
4758             switch (parent.m_data.m_type)
4759             {
4760                 case value_t::null:
4761                 case value_t::object:
4762                 {
4763                     // use operator[] to add value
4764                     parent[last_path] = val;
4765                     break;
4766                 }
4767 
4768                 case value_t::array:
4769                 {
4770                     if (last_path == "-")
4771                     {
4772                         // special case: append to back
4773                         parent.push_back(val);
4774                     }
4775                     else
4776                     {
4777                         const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
4778                         if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
4779                         {
4780                             // avoid undefined behavior
4781                             JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
4782                         }
4783 
4784                         // default case: insert add offset
4785                         parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
4786                     }
4787                     break;
4788                 }
4789 
4790                 // if there exists a parent it cannot be primitive
4791                 case value_t::string: // LCOV_EXCL_LINE
4792                 case value_t::boolean: // LCOV_EXCL_LINE
4793                 case value_t::number_integer: // LCOV_EXCL_LINE
4794                 case value_t::number_unsigned: // LCOV_EXCL_LINE
4795                 case value_t::number_float: // LCOV_EXCL_LINE
4796                 case value_t::binary: // LCOV_EXCL_LINE
4797                 case value_t::discarded: // LCOV_EXCL_LINE
4798                 default:            // LCOV_EXCL_LINE
4799                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
4800             }
4801         };
4802 
4803         // wrapper for "remove" operation; remove value at ptr
4804         const auto operation_remove = [this, & result](json_pointer & ptr)
4805         {
4806             // get reference to parent of JSON pointer ptr
4807             const auto last_path = ptr.back();
4808             ptr.pop_back();
4809             basic_json& parent = result.at(ptr);
4810 
4811             // remove child
4812             if (parent.is_object())
4813             {
4814                 // perform range check
4815                 auto it = parent.find(last_path);
4816                 if (JSON_HEDLEY_LIKELY(it != parent.end()))
4817                 {
4818                     parent.erase(it);
4819                 }
4820                 else
4821                 {
4822                     JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
4823                 }
4824             }
4825             else if (parent.is_array())
4826             {
4827                 // note erase performs range check
4828                 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
4829             }
4830         };
4831 
4832         // type check: top level value must be an array
4833         if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
4834         {
4835             JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
4836         }
4837 
4838         // iterate and apply the operations
4839         for (const auto& val : json_patch)
4840         {
4841             // wrapper to get a value for an operation
4842             const auto get_value = [&val](const std::string & op,
4843                                           const std::string & member,
4844                                           bool string_type) -> basic_json &
4845             {
4846                 // find value
4847                 auto it = val.m_data.m_value.object->find(member);
4848 
4849                 // context-sensitive error message
4850                 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
4851 
4852                 // check if desired value is present
4853                 if (JSON_HEDLEY_UNLIKELY(it == val.m_data.m_value.object->end()))
4854                 {
4855                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
4856                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
4857                 }
4858 
4859                 // check if result is of type string
4860                 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
4861                 {
4862                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
4863                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
4864                 }
4865 
4866                 // no error: return value
4867                 return it->second;
4868             };
4869 
4870             // type check: every element of the array must be an object
4871             if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
4872             {
4873                 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
4874             }
4875 
4876             // collect mandatory members
4877             const auto op = get_value("op", "op", true).template get<std::string>();
4878             const auto path = get_value(op, "path", true).template get<std::string>();
4879             json_pointer ptr(path);
4880 
4881             switch (get_op(op))
4882             {
4883                 case patch_operations::add:
4884                 {
4885                     operation_add(ptr, get_value("add", "value", false));
4886                     break;
4887                 }
4888 
4889                 case patch_operations::remove:
4890                 {
4891                     operation_remove(ptr);
4892                     break;
4893                 }
4894 
4895                 case patch_operations::replace:
4896                 {
4897                     // the "path" location must exist - use at()
4898                     result.at(ptr) = get_value("replace", "value", false);
4899                     break;
4900                 }
4901 
4902                 case patch_operations::move:
4903                 {
4904                     const auto from_path = get_value("move", "from", true).template get<std::string>();
4905                     json_pointer from_ptr(from_path);
4906 
4907                     // the "from" location must exist - use at()
4908                     basic_json const v = result.at(from_ptr);
4909 
4910                     // The move operation is functionally identical to a
4911                     // "remove" operation on the "from" location, followed
4912                     // immediately by an "add" operation at the target
4913                     // location with the value that was just removed.
4914                     operation_remove(from_ptr);
4915                     operation_add(ptr, v);
4916                     break;
4917                 }
4918 
4919                 case patch_operations::copy:
4920                 {
4921                     const auto from_path = get_value("copy", "from", true).template get<std::string>();
4922                     const json_pointer from_ptr(from_path);
4923 
4924                     // the "from" location must exist - use at()
4925                     basic_json const v = result.at(from_ptr);
4926 
4927                     // The copy is functionally identical to an "add"
4928                     // operation at the target location using the value
4929                     // specified in the "from" member.
4930                     operation_add(ptr, v);
4931                     break;
4932                 }
4933 
4934                 case patch_operations::test:
4935                 {
4936                     bool success = false;
4937                     JSON_TRY
4938                     {
4939                         // check if "value" matches the one at "path"
4940                         // the "path" location must exist - use at()
4941                         success = (result.at(ptr) == get_value("test", "value", false));
4942                     }
4943                     JSON_INTERNAL_CATCH (out_of_range&)
4944                     {
4945                         // ignore out of range errors: success remains false
4946                     }
4947 
4948                     // throw an exception if test fails
4949                     if (JSON_HEDLEY_UNLIKELY(!success))
4950                     {
4951                         JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
4952                     }
4953 
4954                     break;
4955                 }
4956 
4957                 case patch_operations::invalid:
4958                 default:
4959                 {
4960                     // op must be "add", "remove", "replace", "move", "copy", or
4961                     // "test"
4962                     JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
4963                 }
4964             }
4965         }
4966     }
4967 
4968     /// @brief applies a JSON patch to a copy of the current object
4969     /// @sa https://json.nlohmann.me/api/basic_json/patch/
4970     basic_json patch(const basic_json& json_patch) const
4971     {
4972         basic_json result = *this;
4973         result.patch_inplace(json_patch);
4974         return result;
4975     }
4976 
4977     /// @brief creates a diff as a JSON patch
4978     /// @sa https://json.nlohmann.me/api/basic_json/diff/
4979     JSON_HEDLEY_WARN_UNUSED_RESULT
4980     static basic_json diff(const basic_json& source, const basic_json& target,
4981                            const std::string& path = "")
4982     {
4983         // the patch
4984         basic_json result(value_t::array);
4985 
4986         // if the values are the same, return empty patch
4987         if (source == target)
4988         {
4989             return result;
4990         }
4991 
4992         if (source.type() != target.type())
4993         {
4994             // different types: replace value
4995             result.push_back(
4996             {
4997                 {"op", "replace"}, {"path", path}, {"value", target}
4998             });
4999             return result;
5000         }
5001 
5002         switch (source.type())
5003         {
5004             case value_t::array:
5005             {
5006                 // first pass: traverse common elements
5007                 std::size_t i = 0;
5008                 while (i < source.size() && i < target.size())
5009                 {
5010                     // recursive call to compare array values at index i
5011                     auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
5012                     result.insert(result.end(), temp_diff.begin(), temp_diff.end());
5013                     ++i;
5014                 }
5015 
5016                 // We now reached the end of at least one array
5017                 // in a second pass, traverse the remaining elements
5018 
5019                 // remove my remaining elements
5020                 const auto end_index = static_cast<difference_type>(result.size());
5021                 while (i < source.size())
5022                 {
5023                     // add operations in reverse order to avoid invalid
5024                     // indices
5025                     result.insert(result.begin() + end_index, object(
5026                     {
5027                         {"op", "remove"},
5028                         {"path", detail::concat(path, '/', std::to_string(i))}
5029                     }));
5030                     ++i;
5031                 }
5032 
5033                 // add other remaining elements
5034                 while (i < target.size())
5035                 {
5036                     result.push_back(
5037                     {
5038                         {"op", "add"},
5039                         {"path", detail::concat(path, "/-")},
5040                         {"value", target[i]}
5041                     });
5042                     ++i;
5043                 }
5044 
5045                 break;
5046             }
5047 
5048             case value_t::object:
5049             {
5050                 // first pass: traverse this object's elements
5051                 for (auto it = source.cbegin(); it != source.cend(); ++it)
5052                 {
5053                     // escape the key name to be used in a JSON patch
5054                     const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
5055 
5056                     if (target.find(it.key()) != target.end())
5057                     {
5058                         // recursive call to compare object values at key it
5059                         auto temp_diff = diff(it.value(), target[it.key()], path_key);
5060                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());
5061                     }
5062                     else
5063                     {
5064                         // found a key that is not in o -> remove it
5065                         result.push_back(object(
5066                         {
5067                             {"op", "remove"}, {"path", path_key}
5068                         }));
5069                     }
5070                 }
5071 
5072                 // second pass: traverse other object's elements
5073                 for (auto it = target.cbegin(); it != target.cend(); ++it)
5074                 {
5075                     if (source.find(it.key()) == source.end())
5076                     {
5077                         // found a key that is not in this -> add it
5078                         const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
5079                         result.push_back(
5080                         {
5081                             {"op", "add"}, {"path", path_key},
5082                             {"value", it.value()}
5083                         });
5084                     }
5085                 }
5086 
5087                 break;
5088             }
5089 
5090             case value_t::null:
5091             case value_t::string:
5092             case value_t::boolean:
5093             case value_t::number_integer:
5094             case value_t::number_unsigned:
5095             case value_t::number_float:
5096             case value_t::binary:
5097             case value_t::discarded:
5098             default:
5099             {
5100                 // both primitive type: replace value
5101                 result.push_back(
5102                 {
5103                     {"op", "replace"}, {"path", path}, {"value", target}
5104                 });
5105                 break;
5106             }
5107         }
5108 
5109         return result;
5110     }
5111     /// @}
5112 
5113     ////////////////////////////////
5114     // JSON Merge Patch functions //
5115     ////////////////////////////////
5116 
5117     /// @name JSON Merge Patch functions
5118     /// @{
5119 
5120     /// @brief applies a JSON Merge Patch
5121     /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
5122     void merge_patch(const basic_json& apply_patch)
5123     {
5124         if (apply_patch.is_object())
5125         {
5126             if (!is_object())
5127             {
5128                 *this = object();
5129             }
5130             for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
5131             {
5132                 if (it.value().is_null())
5133                 {
5134                     erase(it.key());
5135                 }
5136                 else
5137                 {
5138                     operator[](it.key()).merge_patch(it.value());
5139                 }
5140             }
5141         }
5142         else
5143         {
5144             *this = apply_patch;
5145         }
5146     }
5147 
5148     /// @}
5149 };
5150 
5151 /// @brief user-defined to_string function for JSON values
5152 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
5153 NLOHMANN_BASIC_JSON_TPL_DECLARATION
5154 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
5155 {
5156     return j.dump();
5157 }
5158 
5159 inline namespace literals
5160 {
5161 inline namespace json_literals
5162 {
5163 
5164 /// @brief user-defined string literal for JSON values
5165 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
5166 JSON_HEDLEY_NON_NULL(1)
5167 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
5168     inline nlohmann::json operator ""_json(const char* s, std::size_t n)
5169 #else
5170     inline nlohmann::json operator "" _json(const char* s, std::size_t n)
5171 #endif
5172 {
5173     return nlohmann::json::parse(s, s + n);
5174 }
5175 
5176 /// @brief user-defined string literal for JSON pointer
5177 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
5178 JSON_HEDLEY_NON_NULL(1)
5179 #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
5180     inline nlohmann::json::json_pointer operator ""_json_pointer(const char* s, std::size_t n)
5181 #else
5182     inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
5183 #endif
5184 {
5185     return nlohmann::json::json_pointer(std::string(s, n));
5186 }
5187 
5188 }  // namespace json_literals
5189 }  // namespace literals
5190 NLOHMANN_JSON_NAMESPACE_END
5191 
5192 ///////////////////////
5193 // nonmember support //
5194 ///////////////////////
5195 
5196 namespace std // NOLINT(cert-dcl58-cpp)
5197 {
5198 
5199 /// @brief hash value for JSON objects
5200 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
5201 NLOHMANN_BASIC_JSON_TPL_DECLARATION
5202 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL> // NOLINT(cert-dcl58-cpp)
5203 {
5204     std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
5205     {
5206         return nlohmann::detail::hash(j);
5207     }
5208 };
5209 
5210 // specialization for std::less<value_t>
5211 template<>
5212 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
5213 {
5214     /*!
5215     @brief compare two value_t enum values
5216     @since version 3.0.0
5217     */
5218     bool operator()(::nlohmann::detail::value_t lhs,
5219                     ::nlohmann::detail::value_t rhs) const noexcept
5220     {
5221 #if JSON_HAS_THREE_WAY_COMPARISON
5222         return std::is_lt(lhs <=> rhs); // *NOPAD*
5223 #else
5224         return ::nlohmann::detail::operator<(lhs, rhs);
5225 #endif
5226     }
5227 };
5228 
5229 // C++20 prohibit function specialization in the std namespace.
5230 #ifndef JSON_HAS_CPP_20
5231 
5232 /// @brief exchanges the values of two JSON objects
5233 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
5234 NLOHMANN_BASIC_JSON_TPL_DECLARATION
5235 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name, cert-dcl58-cpp)
5236     is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression,cppcoreguidelines-noexcept-swap,performance-noexcept-swap)
5237     is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
5238 {
5239     j1.swap(j2);
5240 }
5241 
5242 #endif
5243 
5244 }  // namespace std
5245 
5246 #if JSON_USE_GLOBAL_UDLS
5247     #if !defined(JSON_HEDLEY_GCC_VERSION) || JSON_HEDLEY_GCC_VERSION_CHECK(4,9,0)
5248         using nlohmann::literals::json_literals::operator ""_json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5249         using nlohmann::literals::json_literals::operator ""_json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5250     #else
5251         using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5252         using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5253     #endif
5254 #endif
5255 
5256 #include <nlohmann/detail/macro_unscope.hpp>
5257 
5258 #endif  // INCLUDE_NLOHMANN_JSON_HPP_