#
tokens: 63257/50000 1/161 files (page 21/21)
lines: on (toggle) GitHub
raw markdown copy reset
This is page 21 of 21. Use http://codebase.md/wasdubya/x64dbgmcp?lines=true&page={x} to view the full context.

# Directory Structure

```
├── build
│   ├── MCPx64dbg.dp32
│   └── MCPx64dbg.dp64
├── CMakeLists.txt
├── deps
│   ├── pluginsdk
│   │   ├── _dbgfunctions.h
│   │   ├── _plugin_types.h
│   │   ├── _plugins.h
│   │   ├── _scriptapi_argument.h
│   │   ├── _scriptapi_assembler.h
│   │   ├── _scriptapi_bookmark.h
│   │   ├── _scriptapi_comment.h
│   │   ├── _scriptapi_debug.h
│   │   ├── _scriptapi_flag.h
│   │   ├── _scriptapi_function.h
│   │   ├── _scriptapi_gui.h
│   │   ├── _scriptapi_label.h
│   │   ├── _scriptapi_memory.h
│   │   ├── _scriptapi_misc.h
│   │   ├── _scriptapi_module.h
│   │   ├── _scriptapi_pattern.h
│   │   ├── _scriptapi_register.h
│   │   ├── _scriptapi_stack.h
│   │   ├── _scriptapi_symbol.h
│   │   ├── _scriptapi.h
│   │   ├── bridgegraph.h
│   │   ├── bridgelist.h
│   │   ├── bridgemain.h
│   │   ├── dbghelp
│   │   │   ├── dbghelp_x64.a
│   │   │   ├── dbghelp_x64.lib
│   │   │   ├── dbghelp_x86.a
│   │   │   ├── dbghelp_x86.lib
│   │   │   └── dbghelp.h
│   │   ├── DeviceNameResolver
│   │   │   ├── DeviceNameResolver_x64.a
│   │   │   ├── DeviceNameResolver_x64.lib
│   │   │   ├── DeviceNameResolver_x86.a
│   │   │   ├── DeviceNameResolver_x86.lib
│   │   │   └── DeviceNameResolver.h
│   │   ├── jansson
│   │   │   ├── jansson_config.h
│   │   │   ├── jansson_x64.a
│   │   │   ├── jansson_x64.lib
│   │   │   ├── jansson_x64dbg.h
│   │   │   ├── jansson_x86.a
│   │   │   ├── jansson_x86.lib
│   │   │   └── jansson.h
│   │   ├── lz4
│   │   │   ├── lz4_x64.a
│   │   │   ├── lz4_x64.lib
│   │   │   ├── lz4_x86.a
│   │   │   ├── lz4_x86.lib
│   │   │   ├── lz4.h
│   │   │   ├── lz4file.h
│   │   │   └── lz4hc.h
│   │   ├── nlohmann
│   │   │   ├── adl_serializer.hpp
│   │   │   ├── byte_container_with_subtype.hpp
│   │   │   ├── detail
│   │   │   │   ├── abi_macros.hpp
│   │   │   │   ├── conversions
│   │   │   │   │   ├── from_json.hpp
│   │   │   │   │   ├── to_chars.hpp
│   │   │   │   │   └── to_json.hpp
│   │   │   │   ├── exceptions.hpp
│   │   │   │   ├── hash.hpp
│   │   │   │   ├── input
│   │   │   │   │   ├── binary_reader.hpp
│   │   │   │   │   ├── input_adapters.hpp
│   │   │   │   │   ├── json_sax.hpp
│   │   │   │   │   ├── lexer.hpp
│   │   │   │   │   ├── parser.hpp
│   │   │   │   │   └── position_t.hpp
│   │   │   │   ├── iterators
│   │   │   │   │   ├── internal_iterator.hpp
│   │   │   │   │   ├── iter_impl.hpp
│   │   │   │   │   ├── iteration_proxy.hpp
│   │   │   │   │   ├── iterator_traits.hpp
│   │   │   │   │   ├── json_reverse_iterator.hpp
│   │   │   │   │   └── primitive_iterator.hpp
│   │   │   │   ├── json_custom_base_class.hpp
│   │   │   │   ├── json_pointer.hpp
│   │   │   │   ├── json_ref.hpp
│   │   │   │   ├── macro_scope.hpp
│   │   │   │   ├── macro_unscope.hpp
│   │   │   │   ├── meta
│   │   │   │   │   ├── call_std
│   │   │   │   │   │   ├── begin.hpp
│   │   │   │   │   │   └── end.hpp
│   │   │   │   │   ├── cpp_future.hpp
│   │   │   │   │   ├── detected.hpp
│   │   │   │   │   ├── identity_tag.hpp
│   │   │   │   │   ├── is_sax.hpp
│   │   │   │   │   ├── std_fs.hpp
│   │   │   │   │   ├── type_traits.hpp
│   │   │   │   │   └── void_t.hpp
│   │   │   │   ├── output
│   │   │   │   │   ├── binary_writer.hpp
│   │   │   │   │   ├── output_adapters.hpp
│   │   │   │   │   └── serializer.hpp
│   │   │   │   ├── string_concat.hpp
│   │   │   │   ├── string_escape.hpp
│   │   │   │   └── value_t.hpp
│   │   │   ├── json_fwd.hpp
│   │   │   ├── json.hpp
│   │   │   ├── ordered_map.hpp
│   │   │   └── thirdparty
│   │   │       └── hedley
│   │   │           ├── hedley_undef.hpp
│   │   │           └── hedley.hpp
│   │   ├── TitanEngine
│   │   │   ├── TitanEngine_x64.a
│   │   │   ├── TitanEngine_x64.lib
│   │   │   ├── TitanEngine_x86.a
│   │   │   ├── TitanEngine_x86.lib
│   │   │   └── TitanEngine.h
│   │   ├── x32bridge.lib
│   │   ├── x32dbg.lib
│   │   ├── x64bridge.lib
│   │   ├── x64dbg.lib
│   │   └── XEDParse
│   │       ├── XEDParse_x64.a
│   │       ├── XEDParse_x64.lib
│   │       ├── XEDParse_x86.a
│   │       ├── XEDParse_x86.lib
│   │       └── XEDParse.h
│   └── x64dbg_sdk
│       └── pluginsdk
│           ├── _dbgfunctions.h
│           ├── _plugin_types.h
│           ├── _plugins.h
│           ├── _scriptapi_argument.h
│           ├── _scriptapi_assembler.h
│           ├── _scriptapi_bookmark.h
│           ├── _scriptapi_comment.h
│           ├── _scriptapi_debug.h
│           ├── _scriptapi_flag.h
│           ├── _scriptapi_function.h
│           ├── _scriptapi_gui.h
│           ├── _scriptapi_label.h
│           ├── _scriptapi_memory.h
│           ├── _scriptapi_misc.h
│           ├── _scriptapi_module.h
│           ├── _scriptapi_pattern.h
│           ├── _scriptapi_register.h
│           ├── _scriptapi_stack.h
│           ├── _scriptapi_symbol.h
│           ├── _scriptapi.h
│           ├── bridgegraph.h
│           ├── bridgelist.h
│           ├── bridgemain.h
│           ├── dbghelp
│           │   ├── dbghelp_x64.a
│           │   ├── dbghelp_x64.lib
│           │   ├── dbghelp_x86.a
│           │   ├── dbghelp_x86.lib
│           │   └── dbghelp.h
│           ├── DeviceNameResolver
│           │   ├── DeviceNameResolver_x64.a
│           │   ├── DeviceNameResolver_x64.lib
│           │   ├── DeviceNameResolver_x86.a
│           │   ├── DeviceNameResolver_x86.lib
│           │   └── DeviceNameResolver.h
│           ├── jansson
│           │   ├── jansson_config.h
│           │   ├── jansson_x64.a
│           │   ├── jansson_x64.lib
│           │   ├── jansson_x64dbg.h
│           │   ├── jansson_x86.a
│           │   ├── jansson_x86.lib
│           │   └── jansson.h
│           ├── lz4
│           │   ├── lz4_x64.a
│           │   ├── lz4_x64.lib
│           │   ├── lz4_x86.a
│           │   ├── lz4_x86.lib
│           │   ├── lz4.h
│           │   ├── lz4file.h
│           │   └── lz4hc.h
│           ├── TitanEngine
│           │   ├── TitanEngine_x64.a
│           │   ├── TitanEngine_x64.lib
│           │   ├── TitanEngine_x86.a
│           │   ├── TitanEngine_x86.lib
│           │   └── TitanEngine.h
│           ├── TitanEngine_x64.a
│           ├── TitanEngine_x64.lib
│           ├── TitanEngine_x86.a
│           ├── TitanEngine_x86.lib
│           ├── TitanEngine.h
│           ├── x32bridge.lib
│           ├── x32dbg.lib
│           ├── x64bridge.lib
│           ├── x64dbg.lib
│           └── XEDParse
│               ├── XEDParse_x64.a
│               ├── XEDParse_x64.lib
│               ├── XEDParse_x86.a
│               ├── XEDParse_x86.lib
│               └── XEDParse.h
├── include
│   └── nlohmann
│       ├── adl_serializer.hpp
│       ├── byte_container_with_subtype.hpp
│       ├── detail
│       │   ├── abi_macros.hpp
│       │   ├── conversions
│       │   │   ├── from_json.hpp
│       │   │   ├── to_chars.hpp
│       │   │   └── to_json.hpp
│       │   ├── exceptions.hpp
│       │   ├── hash.hpp
│       │   ├── input
│       │   │   ├── binary_reader.hpp
│       │   │   ├── input_adapters.hpp
│       │   │   ├── json_sax.hpp
│       │   │   ├── lexer.hpp
│       │   │   ├── parser.hpp
│       │   │   └── position_t.hpp
│       │   ├── iterators
│       │   │   ├── internal_iterator.hpp
│       │   │   ├── iter_impl.hpp
│       │   │   ├── iteration_proxy.hpp
│       │   │   ├── iterator_traits.hpp
│       │   │   ├── json_reverse_iterator.hpp
│       │   │   └── primitive_iterator.hpp
│       │   ├── json_custom_base_class.hpp
│       │   ├── json_pointer.hpp
│       │   ├── json_ref.hpp
│       │   ├── macro_scope.hpp
│       │   ├── macro_unscope.hpp
│       │   ├── meta
│       │   │   ├── call_std
│       │   │   │   ├── begin.hpp
│       │   │   │   └── end.hpp
│       │   │   ├── cpp_future.hpp
│       │   │   ├── detected.hpp
│       │   │   ├── identity_tag.hpp
│       │   │   ├── is_sax.hpp
│       │   │   ├── std_fs.hpp
│       │   │   ├── type_traits.hpp
│       │   │   └── void_t.hpp
│       │   ├── output
│       │   │   ├── binary_writer.hpp
│       │   │   ├── output_adapters.hpp
│       │   │   └── serializer.hpp
│       │   ├── string_concat.hpp
│       │   ├── string_escape.hpp
│       │   └── value_t.hpp
│       ├── json_fwd.hpp
│       ├── json.hpp
│       ├── ordered_map.hpp
│       └── thirdparty
│           └── hedley
│               ├── hedley_undef.hpp
│               └── hedley.hpp
├── README.md
├── Showcase.gif
├── side profile of a voxel spider walking.jpg
└── src
    ├── MCPx64dbg.cpp
    └── x64dbg.py
```

# Files

--------------------------------------------------------------------------------
/include/nlohmann/json.hpp:
--------------------------------------------------------------------------------

```
   1 | //     __ _____ _____ _____
   2 | //  __|  |   __|     |   | |  JSON for Modern C++
   3 | // |  |  |__   |  |  | | | |  version 3.11.3
   4 | // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
   5 | //
   6 | // SPDX-FileCopyrightText: 2013-2023 Niels Lohmann <https://nlohmann.me>
   7 | // SPDX-License-Identifier: MIT
   8 | 
   9 | /****************************************************************************\
  10 |  * Note on documentation: The source files contain links to the online      *
  11 |  * documentation of the public API at https://json.nlohmann.me. This URL    *
  12 |  * contains the most recent documentation and should also be applicable to  *
  13 |  * previous versions; documentation for deprecated functions is not         *
  14 |  * removed, but marked deprecated. See "Generate documentation" section in  *
  15 |  * file docs/README.md.                                                     *
  16 | \****************************************************************************/
  17 | 
  18 | #ifndef INCLUDE_NLOHMANN_JSON_HPP_
  19 | #define INCLUDE_NLOHMANN_JSON_HPP_
  20 | 
  21 | #include <algorithm> // all_of, find, for_each
  22 | #include <cstddef> // nullptr_t, ptrdiff_t, size_t
  23 | #include <functional> // hash, less
  24 | #include <initializer_list> // initializer_list
  25 | #ifndef JSON_NO_IO
  26 |     #include <iosfwd> // istream, ostream
  27 | #endif  // JSON_NO_IO
  28 | #include <iterator> // random_access_iterator_tag
  29 | #include <memory> // unique_ptr
  30 | #include <string> // string, stoi, to_string
  31 | #include <utility> // declval, forward, move, pair, swap
  32 | #include <vector> // vector
  33 | 
  34 | #include <nlohmann/adl_serializer.hpp>
  35 | #include <nlohmann/byte_container_with_subtype.hpp>
  36 | #include <nlohmann/detail/conversions/from_json.hpp>
  37 | #include <nlohmann/detail/conversions/to_json.hpp>
  38 | #include <nlohmann/detail/exceptions.hpp>
  39 | #include <nlohmann/detail/hash.hpp>
  40 | #include <nlohmann/detail/input/binary_reader.hpp>
  41 | #include <nlohmann/detail/input/input_adapters.hpp>
  42 | #include <nlohmann/detail/input/lexer.hpp>
  43 | #include <nlohmann/detail/input/parser.hpp>
  44 | #include <nlohmann/detail/iterators/internal_iterator.hpp>
  45 | #include <nlohmann/detail/iterators/iter_impl.hpp>
  46 | #include <nlohmann/detail/iterators/iteration_proxy.hpp>
  47 | #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
  48 | #include <nlohmann/detail/iterators/primitive_iterator.hpp>
  49 | #include <nlohmann/detail/json_custom_base_class.hpp>
  50 | #include <nlohmann/detail/json_pointer.hpp>
  51 | #include <nlohmann/detail/json_ref.hpp>
  52 | #include <nlohmann/detail/macro_scope.hpp>
  53 | #include <nlohmann/detail/string_concat.hpp>
  54 | #include <nlohmann/detail/string_escape.hpp>
  55 | #include <nlohmann/detail/meta/cpp_future.hpp>
  56 | #include <nlohmann/detail/meta/type_traits.hpp>
  57 | #include <nlohmann/detail/output/binary_writer.hpp>
  58 | #include <nlohmann/detail/output/output_adapters.hpp>
  59 | #include <nlohmann/detail/output/serializer.hpp>
  60 | #include <nlohmann/detail/value_t.hpp>
  61 | #include <nlohmann/json_fwd.hpp>
  62 | #include <nlohmann/ordered_map.hpp>
  63 | 
  64 | #if defined(JSON_HAS_CPP_17)
  65 |     #if JSON_HAS_STATIC_RTTI
  66 |         #include <any>
  67 |     #endif
  68 |     #include <string_view>
  69 | #endif
  70 | 
  71 | /*!
  72 | @brief namespace for Niels Lohmann
  73 | @see https://github.com/nlohmann
  74 | @since version 1.0.0
  75 | */
  76 | NLOHMANN_JSON_NAMESPACE_BEGIN
  77 | 
  78 | /*!
  79 | @brief a class to store JSON values
  80 | 
  81 | @internal
  82 | @invariant The member variables @a m_value and @a m_type have the following
  83 | relationship:
  84 | - If `m_type == value_t::object`, then `m_value.object != nullptr`.
  85 | - If `m_type == value_t::array`, then `m_value.array != nullptr`.
  86 | - If `m_type == value_t::string`, then `m_value.string != nullptr`.
  87 | The invariants are checked by member function assert_invariant().
  88 | 
  89 | @note ObjectType trick from https://stackoverflow.com/a/9860911
  90 | @endinternal
  91 | 
  92 | @since version 1.0.0
  93 | 
  94 | @nosubgrouping
  95 | */
  96 | NLOHMANN_BASIC_JSON_TPL_DECLARATION
  97 | class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
  98 |     : public ::nlohmann::detail::json_base_class<CustomBaseClass>
  99 | {
 100 |   private:
 101 |     template<detail::value_t> friend struct detail::external_constructor;
 102 | 
 103 |     template<typename>
 104 |     friend class ::nlohmann::json_pointer;
 105 |     // can be restored when json_pointer backwards compatibility is removed
 106 |     // friend ::nlohmann::json_pointer<StringType>;
 107 | 
 108 |     template<typename BasicJsonType, typename InputType>
 109 |     friend class ::nlohmann::detail::parser;
 110 |     friend ::nlohmann::detail::serializer<basic_json>;
 111 |     template<typename BasicJsonType>
 112 |     friend class ::nlohmann::detail::iter_impl;
 113 |     template<typename BasicJsonType, typename CharType>
 114 |     friend class ::nlohmann::detail::binary_writer;
 115 |     template<typename BasicJsonType, typename InputType, typename SAX>
 116 |     friend class ::nlohmann::detail::binary_reader;
 117 |     template<typename BasicJsonType>
 118 |     friend class ::nlohmann::detail::json_sax_dom_parser;
 119 |     template<typename BasicJsonType>
 120 |     friend class ::nlohmann::detail::json_sax_dom_callback_parser;
 121 |     friend class ::nlohmann::detail::exception;
 122 | 
 123 |     /// workaround type for MSVC
 124 |     using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
 125 |     using json_base_class_t = ::nlohmann::detail::json_base_class<CustomBaseClass>;
 126 | 
 127 |   JSON_PRIVATE_UNLESS_TESTED:
 128 |     // convenience aliases for types residing in namespace detail;
 129 |     using lexer = ::nlohmann::detail::lexer_base<basic_json>;
 130 | 
 131 |     template<typename InputAdapterType>
 132 |     static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
 133 |         InputAdapterType adapter,
 134 |         detail::parser_callback_t<basic_json>cb = nullptr,
 135 |         const bool allow_exceptions = true,
 136 |         const bool ignore_comments = false
 137 |     )
 138 |     {
 139 |         return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
 140 |                 std::move(cb), allow_exceptions, ignore_comments);
 141 |     }
 142 | 
 143 |   private:
 144 |     using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
 145 |     template<typename BasicJsonType>
 146 |     using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
 147 |     template<typename BasicJsonType>
 148 |     using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
 149 |     template<typename Iterator>
 150 |     using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
 151 |     template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
 152 | 
 153 |     template<typename CharType>
 154 |     using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
 155 | 
 156 |     template<typename InputType>
 157 |     using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
 158 |     template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
 159 | 
 160 |   JSON_PRIVATE_UNLESS_TESTED:
 161 |     using serializer = ::nlohmann::detail::serializer<basic_json>;
 162 | 
 163 |   public:
 164 |     using value_t = detail::value_t;
 165 |     /// JSON Pointer, see @ref nlohmann::json_pointer
 166 |     using json_pointer = ::nlohmann::json_pointer<StringType>;
 167 |     template<typename T, typename SFINAE>
 168 |     using json_serializer = JSONSerializer<T, SFINAE>;
 169 |     /// how to treat decoding errors
 170 |     using error_handler_t = detail::error_handler_t;
 171 |     /// how to treat CBOR tags
 172 |     using cbor_tag_handler_t = detail::cbor_tag_handler_t;
 173 |     /// helper type for initializer lists of basic_json values
 174 |     using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
 175 | 
 176 |     using input_format_t = detail::input_format_t;
 177 |     /// SAX interface type, see @ref nlohmann::json_sax
 178 |     using json_sax_t = json_sax<basic_json>;
 179 | 
 180 |     ////////////////
 181 |     // exceptions //
 182 |     ////////////////
 183 | 
 184 |     /// @name exceptions
 185 |     /// Classes to implement user-defined exceptions.
 186 |     /// @{
 187 | 
 188 |     using exception = detail::exception;
 189 |     using parse_error = detail::parse_error;
 190 |     using invalid_iterator = detail::invalid_iterator;
 191 |     using type_error = detail::type_error;
 192 |     using out_of_range = detail::out_of_range;
 193 |     using other_error = detail::other_error;
 194 | 
 195 |     /// @}
 196 | 
 197 |     /////////////////////
 198 |     // container types //
 199 |     /////////////////////
 200 | 
 201 |     /// @name container types
 202 |     /// The canonic container types to use @ref basic_json like any other STL
 203 |     /// container.
 204 |     /// @{
 205 | 
 206 |     /// the type of elements in a basic_json container
 207 |     using value_type = basic_json;
 208 | 
 209 |     /// the type of an element reference
 210 |     using reference = value_type&;
 211 |     /// the type of an element const reference
 212 |     using const_reference = const value_type&;
 213 | 
 214 |     /// a type to represent differences between iterators
 215 |     using difference_type = std::ptrdiff_t;
 216 |     /// a type to represent container sizes
 217 |     using size_type = std::size_t;
 218 | 
 219 |     /// the allocator type
 220 |     using allocator_type = AllocatorType<basic_json>;
 221 | 
 222 |     /// the type of an element pointer
 223 |     using pointer = typename std::allocator_traits<allocator_type>::pointer;
 224 |     /// the type of an element const pointer
 225 |     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
 226 | 
 227 |     /// an iterator for a basic_json container
 228 |     using iterator = iter_impl<basic_json>;
 229 |     /// a const iterator for a basic_json container
 230 |     using const_iterator = iter_impl<const basic_json>;
 231 |     /// a reverse iterator for a basic_json container
 232 |     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
 233 |     /// a const reverse iterator for a basic_json container
 234 |     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
 235 | 
 236 |     /// @}
 237 | 
 238 |     /// @brief returns the allocator associated with the container
 239 |     /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
 240 |     static allocator_type get_allocator()
 241 |     {
 242 |         return allocator_type();
 243 |     }
 244 | 
 245 |     /// @brief returns version information on the library
 246 |     /// @sa https://json.nlohmann.me/api/basic_json/meta/
 247 |     JSON_HEDLEY_WARN_UNUSED_RESULT
 248 |     static basic_json meta()
 249 |     {
 250 |         basic_json result;
 251 | 
 252 |         result["copyright"] = "(C) 2013-2023 Niels Lohmann";
 253 |         result["name"] = "JSON for Modern C++";
 254 |         result["url"] = "https://github.com/nlohmann/json";
 255 |         result["version"]["string"] =
 256 |             detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
 257 |                            std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
 258 |                            std::to_string(NLOHMANN_JSON_VERSION_PATCH));
 259 |         result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
 260 |         result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
 261 |         result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
 262 | 
 263 | #ifdef _WIN32
 264 |         result["platform"] = "win32";
 265 | #elif defined __linux__
 266 |         result["platform"] = "linux";
 267 | #elif defined __APPLE__
 268 |         result["platform"] = "apple";
 269 | #elif defined __unix__
 270 |         result["platform"] = "unix";
 271 | #else
 272 |         result["platform"] = "unknown";
 273 | #endif
 274 | 
 275 | #if defined(__ICC) || defined(__INTEL_COMPILER)
 276 |         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
 277 | #elif defined(__clang__)
 278 |         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
 279 | #elif defined(__GNUC__) || defined(__GNUG__)
 280 |         result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
 281 |                     std::to_string(__GNUC__), '.',
 282 |                     std::to_string(__GNUC_MINOR__), '.',
 283 |                     std::to_string(__GNUC_PATCHLEVEL__))
 284 |             }
 285 |         };
 286 | #elif defined(__HP_cc) || defined(__HP_aCC)
 287 |         result["compiler"] = "hp"
 288 | #elif defined(__IBMCPP__)
 289 |         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
 290 | #elif defined(_MSC_VER)
 291 |         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
 292 | #elif defined(__PGI)
 293 |         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
 294 | #elif defined(__SUNPRO_CC)
 295 |         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
 296 | #else
 297 |         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
 298 | #endif
 299 | 
 300 | #if defined(_MSVC_LANG)
 301 |         result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
 302 | #elif defined(__cplusplus)
 303 |         result["compiler"]["c++"] = std::to_string(__cplusplus);
 304 | #else
 305 |         result["compiler"]["c++"] = "unknown";
 306 | #endif
 307 |         return result;
 308 |     }
 309 | 
 310 |     ///////////////////////////
 311 |     // JSON value data types //
 312 |     ///////////////////////////
 313 | 
 314 |     /// @name JSON value data types
 315 |     /// The data types to store a JSON value. These types are derived from
 316 |     /// the template arguments passed to class @ref basic_json.
 317 |     /// @{
 318 | 
 319 |     /// @brief default object key comparator type
 320 |     /// The actual object key comparator type (@ref object_comparator_t) may be
 321 |     /// different.
 322 |     /// @sa https://json.nlohmann.me/api/basic_json/default_object_comparator_t/
 323 | #if defined(JSON_HAS_CPP_14)
 324 |     // use of transparent comparator avoids unnecessary repeated construction of temporaries
 325 |     // in functions involving lookup by key with types other than object_t::key_type (aka. StringType)
 326 |     using default_object_comparator_t = std::less<>;
 327 | #else
 328 |     using default_object_comparator_t = std::less<StringType>;
 329 | #endif
 330 | 
 331 |     /// @brief a type for an object
 332 |     /// @sa https://json.nlohmann.me/api/basic_json/object_t/
 333 |     using object_t = ObjectType<StringType,
 334 |           basic_json,
 335 |           default_object_comparator_t,
 336 |           AllocatorType<std::pair<const StringType,
 337 |           basic_json>>>;
 338 | 
 339 |     /// @brief a type for an array
 340 |     /// @sa https://json.nlohmann.me/api/basic_json/array_t/
 341 |     using array_t = ArrayType<basic_json, AllocatorType<basic_json>>;
 342 | 
 343 |     /// @brief a type for a string
 344 |     /// @sa https://json.nlohmann.me/api/basic_json/string_t/
 345 |     using string_t = StringType;
 346 | 
 347 |     /// @brief a type for a boolean
 348 |     /// @sa https://json.nlohmann.me/api/basic_json/boolean_t/
 349 |     using boolean_t = BooleanType;
 350 | 
 351 |     /// @brief a type for a number (integer)
 352 |     /// @sa https://json.nlohmann.me/api/basic_json/number_integer_t/
 353 |     using number_integer_t = NumberIntegerType;
 354 | 
 355 |     /// @brief a type for a number (unsigned)
 356 |     /// @sa https://json.nlohmann.me/api/basic_json/number_unsigned_t/
 357 |     using number_unsigned_t = NumberUnsignedType;
 358 | 
 359 |     /// @brief a type for a number (floating-point)
 360 |     /// @sa https://json.nlohmann.me/api/basic_json/number_float_t/
 361 |     using number_float_t = NumberFloatType;
 362 | 
 363 |     /// @brief a type for a packed binary type
 364 |     /// @sa https://json.nlohmann.me/api/basic_json/binary_t/
 365 |     using binary_t = nlohmann::byte_container_with_subtype<BinaryType>;
 366 | 
 367 |     /// @brief object key comparator type
 368 |     /// @sa https://json.nlohmann.me/api/basic_json/object_comparator_t/
 369 |     using object_comparator_t = detail::actual_object_comparator_t<basic_json>;
 370 | 
 371 |     /// @}
 372 | 
 373 |   private:
 374 | 
 375 |     /// helper for exception-safe object creation
 376 |     template<typename T, typename... Args>
 377 |     JSON_HEDLEY_RETURNS_NON_NULL
 378 |     static T* create(Args&& ... args)
 379 |     {
 380 |         AllocatorType<T> alloc;
 381 |         using AllocatorTraits = std::allocator_traits<AllocatorType<T>>;
 382 | 
 383 |         auto deleter = [&](T * obj)
 384 |         {
 385 |             AllocatorTraits::deallocate(alloc, obj, 1);
 386 |         };
 387 |         std::unique_ptr<T, decltype(deleter)> obj(AllocatorTraits::allocate(alloc, 1), deleter);
 388 |         AllocatorTraits::construct(alloc, obj.get(), std::forward<Args>(args)...);
 389 |         JSON_ASSERT(obj != nullptr);
 390 |         return obj.release();
 391 |     }
 392 | 
 393 |     ////////////////////////
 394 |     // JSON value storage //
 395 |     ////////////////////////
 396 | 
 397 |   JSON_PRIVATE_UNLESS_TESTED:
 398 |     /*!
 399 |     @brief a JSON value
 400 | 
 401 |     The actual storage for a JSON value of the @ref basic_json class. This
 402 |     union combines the different storage types for the JSON value types
 403 |     defined in @ref value_t.
 404 | 
 405 |     JSON type | value_t type    | used type
 406 |     --------- | --------------- | ------------------------
 407 |     object    | object          | pointer to @ref object_t
 408 |     array     | array           | pointer to @ref array_t
 409 |     string    | string          | pointer to @ref string_t
 410 |     boolean   | boolean         | @ref boolean_t
 411 |     number    | number_integer  | @ref number_integer_t
 412 |     number    | number_unsigned | @ref number_unsigned_t
 413 |     number    | number_float    | @ref number_float_t
 414 |     binary    | binary          | pointer to @ref binary_t
 415 |     null      | null            | *no value is stored*
 416 | 
 417 |     @note Variable-length types (objects, arrays, and strings) are stored as
 418 |     pointers. The size of the union should not exceed 64 bits if the default
 419 |     value types are used.
 420 | 
 421 |     @since version 1.0.0
 422 |     */
 423 |     union json_value
 424 |     {
 425 |         /// object (stored with pointer to save storage)
 426 |         object_t* object;
 427 |         /// array (stored with pointer to save storage)
 428 |         array_t* array;
 429 |         /// string (stored with pointer to save storage)
 430 |         string_t* string;
 431 |         /// binary (stored with pointer to save storage)
 432 |         binary_t* binary;
 433 |         /// boolean
 434 |         boolean_t boolean;
 435 |         /// number (integer)
 436 |         number_integer_t number_integer;
 437 |         /// number (unsigned integer)
 438 |         number_unsigned_t number_unsigned;
 439 |         /// number (floating-point)
 440 |         number_float_t number_float;
 441 | 
 442 |         /// default constructor (for null values)
 443 |         json_value() = default;
 444 |         /// constructor for booleans
 445 |         json_value(boolean_t v) noexcept : boolean(v) {}
 446 |         /// constructor for numbers (integer)
 447 |         json_value(number_integer_t v) noexcept : number_integer(v) {}
 448 |         /// constructor for numbers (unsigned)
 449 |         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
 450 |         /// constructor for numbers (floating-point)
 451 |         json_value(number_float_t v) noexcept : number_float(v) {}
 452 |         /// constructor for empty values of a given type
 453 |         json_value(value_t t)
 454 |         {
 455 |             switch (t)
 456 |             {
 457 |                 case value_t::object:
 458 |                 {
 459 |                     object = create<object_t>();
 460 |                     break;
 461 |                 }
 462 | 
 463 |                 case value_t::array:
 464 |                 {
 465 |                     array = create<array_t>();
 466 |                     break;
 467 |                 }
 468 | 
 469 |                 case value_t::string:
 470 |                 {
 471 |                     string = create<string_t>("");
 472 |                     break;
 473 |                 }
 474 | 
 475 |                 case value_t::binary:
 476 |                 {
 477 |                     binary = create<binary_t>();
 478 |                     break;
 479 |                 }
 480 | 
 481 |                 case value_t::boolean:
 482 |                 {
 483 |                     boolean = static_cast<boolean_t>(false);
 484 |                     break;
 485 |                 }
 486 | 
 487 |                 case value_t::number_integer:
 488 |                 {
 489 |                     number_integer = static_cast<number_integer_t>(0);
 490 |                     break;
 491 |                 }
 492 | 
 493 |                 case value_t::number_unsigned:
 494 |                 {
 495 |                     number_unsigned = static_cast<number_unsigned_t>(0);
 496 |                     break;
 497 |                 }
 498 | 
 499 |                 case value_t::number_float:
 500 |                 {
 501 |                     number_float = static_cast<number_float_t>(0.0);
 502 |                     break;
 503 |                 }
 504 | 
 505 |                 case value_t::null:
 506 |                 {
 507 |                     object = nullptr;  // silence warning, see #821
 508 |                     break;
 509 |                 }
 510 | 
 511 |                 case value_t::discarded:
 512 |                 default:
 513 |                 {
 514 |                     object = nullptr;  // silence warning, see #821
 515 |                     if (JSON_HEDLEY_UNLIKELY(t == value_t::null))
 516 |                     {
 517 |                         JSON_THROW(other_error::create(500, "961c151d2e87f2686a955a9be24d316f1362bf21 3.11.3", nullptr)); // LCOV_EXCL_LINE
 518 |                     }
 519 |                     break;
 520 |                 }
 521 |             }
 522 |         }
 523 | 
 524 |         /// constructor for strings
 525 |         json_value(const string_t& value) : string(create<string_t>(value)) {}
 526 | 
 527 |         /// constructor for rvalue strings
 528 |         json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
 529 | 
 530 |         /// constructor for objects
 531 |         json_value(const object_t& value) : object(create<object_t>(value)) {}
 532 | 
 533 |         /// constructor for rvalue objects
 534 |         json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
 535 | 
 536 |         /// constructor for arrays
 537 |         json_value(const array_t& value) : array(create<array_t>(value)) {}
 538 | 
 539 |         /// constructor for rvalue arrays
 540 |         json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
 541 | 
 542 |         /// constructor for binary arrays
 543 |         json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
 544 | 
 545 |         /// constructor for rvalue binary arrays
 546 |         json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
 547 | 
 548 |         /// constructor for binary arrays (internal type)
 549 |         json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
 550 | 
 551 |         /// constructor for rvalue binary arrays (internal type)
 552 |         json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
 553 | 
 554 |         void destroy(value_t t)
 555 |         {
 556 |             if (
 557 |                 (t == value_t::object && object == nullptr) ||
 558 |                 (t == value_t::array && array == nullptr) ||
 559 |                 (t == value_t::string && string == nullptr) ||
 560 |                 (t == value_t::binary && binary == nullptr)
 561 |             )
 562 |             {
 563 |                 //not initialized (e.g. due to exception in the ctor)
 564 |                 return;
 565 |             }
 566 |             if (t == value_t::array || t == value_t::object)
 567 |             {
 568 |                 // flatten the current json_value to a heap-allocated stack
 569 |                 std::vector<basic_json> stack;
 570 | 
 571 |                 // move the top-level items to stack
 572 |                 if (t == value_t::array)
 573 |                 {
 574 |                     stack.reserve(array->size());
 575 |                     std::move(array->begin(), array->end(), std::back_inserter(stack));
 576 |                 }
 577 |                 else
 578 |                 {
 579 |                     stack.reserve(object->size());
 580 |                     for (auto&& it : *object)
 581 |                     {
 582 |                         stack.push_back(std::move(it.second));
 583 |                     }
 584 |                 }
 585 | 
 586 |                 while (!stack.empty())
 587 |                 {
 588 |                     // move the last item to local variable to be processed
 589 |                     basic_json current_item(std::move(stack.back()));
 590 |                     stack.pop_back();
 591 | 
 592 |                     // if current_item is array/object, move
 593 |                     // its children to the stack to be processed later
 594 |                     if (current_item.is_array())
 595 |                     {
 596 |                         std::move(current_item.m_data.m_value.array->begin(), current_item.m_data.m_value.array->end(), std::back_inserter(stack));
 597 | 
 598 |                         current_item.m_data.m_value.array->clear();
 599 |                     }
 600 |                     else if (current_item.is_object())
 601 |                     {
 602 |                         for (auto&& it : *current_item.m_data.m_value.object)
 603 |                         {
 604 |                             stack.push_back(std::move(it.second));
 605 |                         }
 606 | 
 607 |                         current_item.m_data.m_value.object->clear();
 608 |                     }
 609 | 
 610 |                     // it's now safe that current_item get destructed
 611 |                     // since it doesn't have any children
 612 |                 }
 613 |             }
 614 | 
 615 |             switch (t)
 616 |             {
 617 |                 case value_t::object:
 618 |                 {
 619 |                     AllocatorType<object_t> alloc;
 620 |                     std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
 621 |                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
 622 |                     break;
 623 |                 }
 624 | 
 625 |                 case value_t::array:
 626 |                 {
 627 |                     AllocatorType<array_t> alloc;
 628 |                     std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
 629 |                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
 630 |                     break;
 631 |                 }
 632 | 
 633 |                 case value_t::string:
 634 |                 {
 635 |                     AllocatorType<string_t> alloc;
 636 |                     std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
 637 |                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
 638 |                     break;
 639 |                 }
 640 | 
 641 |                 case value_t::binary:
 642 |                 {
 643 |                     AllocatorType<binary_t> alloc;
 644 |                     std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
 645 |                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
 646 |                     break;
 647 |                 }
 648 | 
 649 |                 case value_t::null:
 650 |                 case value_t::boolean:
 651 |                 case value_t::number_integer:
 652 |                 case value_t::number_unsigned:
 653 |                 case value_t::number_float:
 654 |                 case value_t::discarded:
 655 |                 default:
 656 |                 {
 657 |                     break;
 658 |                 }
 659 |             }
 660 |         }
 661 |     };
 662 | 
 663 |   private:
 664 |     /*!
 665 |     @brief checks the class invariants
 666 | 
 667 |     This function asserts the class invariants. It needs to be called at the
 668 |     end of every constructor to make sure that created objects respect the
 669 |     invariant. Furthermore, it has to be called each time the type of a JSON
 670 |     value is changed, because the invariant expresses a relationship between
 671 |     @a m_type and @a m_value.
 672 | 
 673 |     Furthermore, the parent relation is checked for arrays and objects: If
 674 |     @a check_parents true and the value is an array or object, then the
 675 |     container's elements must have the current value as parent.
 676 | 
 677 |     @param[in] check_parents  whether the parent relation should be checked.
 678 |                The value is true by default and should only be set to false
 679 |                during destruction of objects when the invariant does not
 680 |                need to hold.
 681 |     */
 682 |     void assert_invariant(bool check_parents = true) const noexcept
 683 |     {
 684 |         JSON_ASSERT(m_data.m_type != value_t::object || m_data.m_value.object != nullptr);
 685 |         JSON_ASSERT(m_data.m_type != value_t::array || m_data.m_value.array != nullptr);
 686 |         JSON_ASSERT(m_data.m_type != value_t::string || m_data.m_value.string != nullptr);
 687 |         JSON_ASSERT(m_data.m_type != value_t::binary || m_data.m_value.binary != nullptr);
 688 | 
 689 | #if JSON_DIAGNOSTICS
 690 |         JSON_TRY
 691 |         {
 692 |             // cppcheck-suppress assertWithSideEffect
 693 |             JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
 694 |             {
 695 |                 return j.m_parent == this;
 696 |             }));
 697 |         }
 698 |         JSON_CATCH(...) {} // LCOV_EXCL_LINE
 699 | #endif
 700 |         static_cast<void>(check_parents);
 701 |     }
 702 | 
 703 |     void set_parents()
 704 |     {
 705 | #if JSON_DIAGNOSTICS
 706 |         switch (m_data.m_type)
 707 |         {
 708 |             case value_t::array:
 709 |             {
 710 |                 for (auto& element : *m_data.m_value.array)
 711 |                 {
 712 |                     element.m_parent = this;
 713 |                 }
 714 |                 break;
 715 |             }
 716 | 
 717 |             case value_t::object:
 718 |             {
 719 |                 for (auto& element : *m_data.m_value.object)
 720 |                 {
 721 |                     element.second.m_parent = this;
 722 |                 }
 723 |                 break;
 724 |             }
 725 | 
 726 |             case value_t::null:
 727 |             case value_t::string:
 728 |             case value_t::boolean:
 729 |             case value_t::number_integer:
 730 |             case value_t::number_unsigned:
 731 |             case value_t::number_float:
 732 |             case value_t::binary:
 733 |             case value_t::discarded:
 734 |             default:
 735 |                 break;
 736 |         }
 737 | #endif
 738 |     }
 739 | 
 740 |     iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
 741 |     {
 742 | #if JSON_DIAGNOSTICS
 743 |         for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
 744 |         {
 745 |             (it + i)->m_parent = this;
 746 |         }
 747 | #else
 748 |         static_cast<void>(count_set_parents);
 749 | #endif
 750 |         return it;
 751 |     }
 752 | 
 753 |     reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
 754 |     {
 755 | #if JSON_DIAGNOSTICS
 756 |         if (old_capacity != static_cast<std::size_t>(-1))
 757 |         {
 758 |             // see https://github.com/nlohmann/json/issues/2838
 759 |             JSON_ASSERT(type() == value_t::array);
 760 |             if (JSON_HEDLEY_UNLIKELY(m_data.m_value.array->capacity() != old_capacity))
 761 |             {
 762 |                 // capacity has changed: update all parents
 763 |                 set_parents();
 764 |                 return j;
 765 |             }
 766 |         }
 767 | 
 768 |         // ordered_json uses a vector internally, so pointers could have
 769 |         // been invalidated; see https://github.com/nlohmann/json/issues/2962
 770 | #ifdef JSON_HEDLEY_MSVC_VERSION
 771 | #pragma warning(push )
 772 | #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
 773 | #endif
 774 |         if (detail::is_ordered_map<object_t>::value)
 775 |         {
 776 |             set_parents();
 777 |             return j;
 778 |         }
 779 | #ifdef JSON_HEDLEY_MSVC_VERSION
 780 | #pragma warning( pop )
 781 | #endif
 782 | 
 783 |         j.m_parent = this;
 784 | #else
 785 |         static_cast<void>(j);
 786 |         static_cast<void>(old_capacity);
 787 | #endif
 788 |         return j;
 789 |     }
 790 | 
 791 |   public:
 792 |     //////////////////////////
 793 |     // JSON parser callback //
 794 |     //////////////////////////
 795 | 
 796 |     /// @brief parser event types
 797 |     /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
 798 |     using parse_event_t = detail::parse_event_t;
 799 | 
 800 |     /// @brief per-element parser callback type
 801 |     /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
 802 |     using parser_callback_t = detail::parser_callback_t<basic_json>;
 803 | 
 804 |     //////////////////
 805 |     // constructors //
 806 |     //////////////////
 807 | 
 808 |     /// @name constructors and destructors
 809 |     /// Constructors of class @ref basic_json, copy/move constructor, copy
 810 |     /// assignment, static functions creating objects, and the destructor.
 811 |     /// @{
 812 | 
 813 |     /// @brief create an empty value with a given type
 814 |     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
 815 |     basic_json(const value_t v)
 816 |         : m_data(v)
 817 |     {
 818 |         assert_invariant();
 819 |     }
 820 | 
 821 |     /// @brief create a null object
 822 |     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
 823 |     basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
 824 |         : basic_json(value_t::null)
 825 |     {
 826 |         assert_invariant();
 827 |     }
 828 | 
 829 |     /// @brief create a JSON value from compatible types
 830 |     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
 831 |     template < typename CompatibleType,
 832 |                typename U = detail::uncvref_t<CompatibleType>,
 833 |                detail::enable_if_t <
 834 |                    !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
 835 |     basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
 836 |                 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
 837 |                                            std::forward<CompatibleType>(val))))
 838 |     {
 839 |         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
 840 |         set_parents();
 841 |         assert_invariant();
 842 |     }
 843 | 
 844 |     /// @brief create a JSON value from an existing one
 845 |     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
 846 |     template < typename BasicJsonType,
 847 |                detail::enable_if_t <
 848 |                    detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
 849 |     basic_json(const BasicJsonType& val)
 850 |     {
 851 |         using other_boolean_t = typename BasicJsonType::boolean_t;
 852 |         using other_number_float_t = typename BasicJsonType::number_float_t;
 853 |         using other_number_integer_t = typename BasicJsonType::number_integer_t;
 854 |         using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
 855 |         using other_string_t = typename BasicJsonType::string_t;
 856 |         using other_object_t = typename BasicJsonType::object_t;
 857 |         using other_array_t = typename BasicJsonType::array_t;
 858 |         using other_binary_t = typename BasicJsonType::binary_t;
 859 | 
 860 |         switch (val.type())
 861 |         {
 862 |             case value_t::boolean:
 863 |                 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
 864 |                 break;
 865 |             case value_t::number_float:
 866 |                 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
 867 |                 break;
 868 |             case value_t::number_integer:
 869 |                 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
 870 |                 break;
 871 |             case value_t::number_unsigned:
 872 |                 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
 873 |                 break;
 874 |             case value_t::string:
 875 |                 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
 876 |                 break;
 877 |             case value_t::object:
 878 |                 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
 879 |                 break;
 880 |             case value_t::array:
 881 |                 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
 882 |                 break;
 883 |             case value_t::binary:
 884 |                 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
 885 |                 break;
 886 |             case value_t::null:
 887 |                 *this = nullptr;
 888 |                 break;
 889 |             case value_t::discarded:
 890 |                 m_data.m_type = value_t::discarded;
 891 |                 break;
 892 |             default:            // LCOV_EXCL_LINE
 893 |                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
 894 |         }
 895 |         JSON_ASSERT(m_data.m_type == val.type());
 896 |         set_parents();
 897 |         assert_invariant();
 898 |     }
 899 | 
 900 |     /// @brief create a container (array or object) from an initializer list
 901 |     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
 902 |     basic_json(initializer_list_t init,
 903 |                bool type_deduction = true,
 904 |                value_t manual_type = value_t::array)
 905 |     {
 906 |         // check if each element is an array with two elements whose first
 907 |         // element is a string
 908 |         bool is_an_object = std::all_of(init.begin(), init.end(),
 909 |                                         [](const detail::json_ref<basic_json>& element_ref)
 910 |         {
 911 |             // The cast is to ensure op[size_type] is called, bearing in mind size_type may not be int;
 912 |             // (many string types can be constructed from 0 via its null-pointer guise, so we get a
 913 |             // broken call to op[key_type], the wrong semantics and a 4804 warning on Windows)
 914 |             return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[static_cast<size_type>(0)].is_string();
 915 |         });
 916 | 
 917 |         // adjust type if type deduction is not wanted
 918 |         if (!type_deduction)
 919 |         {
 920 |             // if array is wanted, do not create an object though possible
 921 |             if (manual_type == value_t::array)
 922 |             {
 923 |                 is_an_object = false;
 924 |             }
 925 | 
 926 |             // if object is wanted but impossible, throw an exception
 927 |             if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
 928 |             {
 929 |                 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
 930 |             }
 931 |         }
 932 | 
 933 |         if (is_an_object)
 934 |         {
 935 |             // the initializer list is a list of pairs -> create object
 936 |             m_data.m_type = value_t::object;
 937 |             m_data.m_value = value_t::object;
 938 | 
 939 |             for (auto& element_ref : init)
 940 |             {
 941 |                 auto element = element_ref.moved_or_copied();
 942 |                 m_data.m_value.object->emplace(
 943 |                     std::move(*((*element.m_data.m_value.array)[0].m_data.m_value.string)),
 944 |                     std::move((*element.m_data.m_value.array)[1]));
 945 |             }
 946 |         }
 947 |         else
 948 |         {
 949 |             // the initializer list describes an array -> create array
 950 |             m_data.m_type = value_t::array;
 951 |             m_data.m_value.array = create<array_t>(init.begin(), init.end());
 952 |         }
 953 | 
 954 |         set_parents();
 955 |         assert_invariant();
 956 |     }
 957 | 
 958 |     /// @brief explicitly create a binary array (without subtype)
 959 |     /// @sa https://json.nlohmann.me/api/basic_json/binary/
 960 |     JSON_HEDLEY_WARN_UNUSED_RESULT
 961 |     static basic_json binary(const typename binary_t::container_type& init)
 962 |     {
 963 |         auto res = basic_json();
 964 |         res.m_data.m_type = value_t::binary;
 965 |         res.m_data.m_value = init;
 966 |         return res;
 967 |     }
 968 | 
 969 |     /// @brief explicitly create a binary array (with subtype)
 970 |     /// @sa https://json.nlohmann.me/api/basic_json/binary/
 971 |     JSON_HEDLEY_WARN_UNUSED_RESULT
 972 |     static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
 973 |     {
 974 |         auto res = basic_json();
 975 |         res.m_data.m_type = value_t::binary;
 976 |         res.m_data.m_value = binary_t(init, subtype);
 977 |         return res;
 978 |     }
 979 | 
 980 |     /// @brief explicitly create a binary array
 981 |     /// @sa https://json.nlohmann.me/api/basic_json/binary/
 982 |     JSON_HEDLEY_WARN_UNUSED_RESULT
 983 |     static basic_json binary(typename binary_t::container_type&& init)
 984 |     {
 985 |         auto res = basic_json();
 986 |         res.m_data.m_type = value_t::binary;
 987 |         res.m_data.m_value = std::move(init);
 988 |         return res;
 989 |     }
 990 | 
 991 |     /// @brief explicitly create a binary array (with subtype)
 992 |     /// @sa https://json.nlohmann.me/api/basic_json/binary/
 993 |     JSON_HEDLEY_WARN_UNUSED_RESULT
 994 |     static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
 995 |     {
 996 |         auto res = basic_json();
 997 |         res.m_data.m_type = value_t::binary;
 998 |         res.m_data.m_value = binary_t(std::move(init), subtype);
 999 |         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_
5259 | 
```
Page 21/21FirstPrevNextLast