1 //     __ _____ _____ _____
2 //  __|  |   __|     |   | |  JSON for Modern C++
3 // |  |  |__   |  |  | | | |  version 3.11.2
4 // |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5 //
6 // SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7 // SPDX-License-Identifier: MIT
8 
9 /****************************************************************************\
10  * Note on documentation: The source files contain links to the online      *
11  * documentation of the public API at https://json.nlohmann.me. This URL    *
12  * contains the most recent documentation and should also be applicable to  *
13  * previous versions; documentation for deprecated functions is not         *
14  * removed, but marked deprecated. See "Generate documentation" section in  *
15  * file docs/README.md.                                                     *
16 \****************************************************************************/
17 
18 #ifndef INCLUDE_NLOHMANN_JSON_HPP_
19 #define INCLUDE_NLOHMANN_JSON_HPP_
20 
21 #include <algorithm> // all_of, find, for_each
22 #include <cstddef> // nullptr_t, ptrdiff_t, size_t
23 #include <functional> // hash, less
24 #include <initializer_list> // initializer_list
25 #ifndef JSON_NO_IO
26     #include <iosfwd> // istream, ostream
27 #endif  // JSON_NO_IO
28 #include <iterator> // random_access_iterator_tag
29 #include <memory> // unique_ptr
30 #include <numeric> // accumulate
31 #include <string> // string, stoi, to_string
32 #include <utility> // declval, forward, move, pair, swap
33 #include <vector> // vector
34 
35 #include <nlohmann/adl_serializer.hpp>
36 #include <nlohmann/byte_container_with_subtype.hpp>
37 #include <nlohmann/detail/conversions/from_json.hpp>
38 #include <nlohmann/detail/conversions/to_json.hpp>
39 #include <nlohmann/detail/exceptions.hpp>
40 #include <nlohmann/detail/hash.hpp>
41 #include <nlohmann/detail/input/binary_reader.hpp>
42 #include <nlohmann/detail/input/input_adapters.hpp>
43 #include <nlohmann/detail/input/lexer.hpp>
44 #include <nlohmann/detail/input/parser.hpp>
45 #include <nlohmann/detail/iterators/internal_iterator.hpp>
46 #include <nlohmann/detail/iterators/iter_impl.hpp>
47 #include <nlohmann/detail/iterators/iteration_proxy.hpp>
48 #include <nlohmann/detail/iterators/json_reverse_iterator.hpp>
49 #include <nlohmann/detail/iterators/primitive_iterator.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     #include <any>
66     #include <string_view>
67 #endif
68 
69 /*!
70 @brief namespace for Niels Lohmann
71 @see https://github.com/nlohmann
72 @since version 1.0.0
73 */
74 NLOHMANN_JSON_NAMESPACE_BEGIN
75 
76 /*!
77 @brief a class to store JSON values
78 
79 @internal
80 @invariant The member variables @a m_value and @a m_type have the following
81 relationship:
82 - If `m_type == value_t::object`, then `m_value.object != nullptr`.
83 - If `m_type == value_t::array`, then `m_value.array != nullptr`.
84 - If `m_type == value_t::string`, then `m_value.string != nullptr`.
85 The invariants are checked by member function assert_invariant().
86 
87 @note ObjectType trick from https://stackoverflow.com/a/9860911
88 @endinternal
89 
90 @since version 1.0.0
91 
92 @nosubgrouping
93 */
94 NLOHMANN_BASIC_JSON_TPL_DECLARATION
95 class basic_json // NOLINT(cppcoreguidelines-special-member-functions,hicpp-special-member-functions)
96 {
97   private:
98     template<detail::value_t> friend struct detail::external_constructor;
99 
100     template<typename>
101     friend class ::nlohmann::json_pointer;
102     // can be restored when json_pointer backwards compatibility is removed
103     // friend ::nlohmann::json_pointer<StringType>;
104 
105     template<typename BasicJsonType, typename InputType>
106     friend class ::nlohmann::detail::parser;
107     friend ::nlohmann::detail::serializer<basic_json>;
108     template<typename BasicJsonType>
109     friend class ::nlohmann::detail::iter_impl;
110     template<typename BasicJsonType, typename CharType>
111     friend class ::nlohmann::detail::binary_writer;
112     template<typename BasicJsonType, typename InputType, typename SAX>
113     friend class ::nlohmann::detail::binary_reader;
114     template<typename BasicJsonType>
115     friend class ::nlohmann::detail::json_sax_dom_parser;
116     template<typename BasicJsonType>
117     friend class ::nlohmann::detail::json_sax_dom_callback_parser;
118     friend class ::nlohmann::detail::exception;
119 
120     /// workaround type for MSVC
121     using basic_json_t = NLOHMANN_BASIC_JSON_TPL;
122 
123   JSON_PRIVATE_UNLESS_TESTED:
124     // convenience aliases for types residing in namespace detail;
125     using lexer = ::nlohmann::detail::lexer_base<basic_json>;
126 
127     template<typename InputAdapterType>
parser( InputAdapterType adapter, detail::parser_callback_t<basic_json>cb = nullptr, const bool allow_exceptions = true, const bool ignore_comments = false )128     static ::nlohmann::detail::parser<basic_json, InputAdapterType> parser(
129         InputAdapterType adapter,
130         detail::parser_callback_t<basic_json>cb = nullptr,
131         const bool allow_exceptions = true,
132         const bool ignore_comments = false
133     )
134     {
135         return ::nlohmann::detail::parser<basic_json, InputAdapterType>(std::move(adapter),
136                 std::move(cb), allow_exceptions, ignore_comments);
137     }
138 
139   private:
140     using primitive_iterator_t = ::nlohmann::detail::primitive_iterator_t;
141     template<typename BasicJsonType>
142     using internal_iterator = ::nlohmann::detail::internal_iterator<BasicJsonType>;
143     template<typename BasicJsonType>
144     using iter_impl = ::nlohmann::detail::iter_impl<BasicJsonType>;
145     template<typename Iterator>
146     using iteration_proxy = ::nlohmann::detail::iteration_proxy<Iterator>;
147     template<typename Base> using json_reverse_iterator = ::nlohmann::detail::json_reverse_iterator<Base>;
148 
149     template<typename CharType>
150     using output_adapter_t = ::nlohmann::detail::output_adapter_t<CharType>;
151 
152     template<typename InputType>
153     using binary_reader = ::nlohmann::detail::binary_reader<basic_json, InputType>;
154     template<typename CharType> using binary_writer = ::nlohmann::detail::binary_writer<basic_json, CharType>;
155 
156   JSON_PRIVATE_UNLESS_TESTED:
157     using serializer = ::nlohmann::detail::serializer<basic_json>;
158 
159   public:
160     using value_t = detail::value_t;
161     /// JSON Pointer, see @ref nlohmann::json_pointer
162     using json_pointer = ::nlohmann::json_pointer<StringType>;
163     template<typename T, typename SFINAE>
164     using json_serializer = JSONSerializer<T, SFINAE>;
165     /// how to treat decoding errors
166     using error_handler_t = detail::error_handler_t;
167     /// how to treat CBOR tags
168     using cbor_tag_handler_t = detail::cbor_tag_handler_t;
169     /// helper type for initializer lists of basic_json values
170     using initializer_list_t = std::initializer_list<detail::json_ref<basic_json>>;
171 
172     using input_format_t = detail::input_format_t;
173     /// SAX interface type, see @ref nlohmann::json_sax
174     using json_sax_t = json_sax<basic_json>;
175 
176     ////////////////
177     // exceptions //
178     ////////////////
179 
180     /// @name exceptions
181     /// Classes to implement user-defined exceptions.
182     /// @{
183 
184     using exception = detail::exception;
185     using parse_error = detail::parse_error;
186     using invalid_iterator = detail::invalid_iterator;
187     using type_error = detail::type_error;
188     using out_of_range = detail::out_of_range;
189     using other_error = detail::other_error;
190 
191     /// @}
192 
193 
194     /////////////////////
195     // container types //
196     /////////////////////
197 
198     /// @name container types
199     /// The canonic container types to use @ref basic_json like any other STL
200     /// container.
201     /// @{
202 
203     /// the type of elements in a basic_json container
204     using value_type = basic_json;
205 
206     /// the type of an element reference
207     using reference = value_type&;
208     /// the type of an element const reference
209     using const_reference = const value_type&;
210 
211     /// a type to represent differences between iterators
212     using difference_type = std::ptrdiff_t;
213     /// a type to represent container sizes
214     using size_type = std::size_t;
215 
216     /// the allocator type
217     using allocator_type = AllocatorType<basic_json>;
218 
219     /// the type of an element pointer
220     using pointer = typename std::allocator_traits<allocator_type>::pointer;
221     /// the type of an element const pointer
222     using const_pointer = typename std::allocator_traits<allocator_type>::const_pointer;
223 
224     /// an iterator for a basic_json container
225     using iterator = iter_impl<basic_json>;
226     /// a const iterator for a basic_json container
227     using const_iterator = iter_impl<const basic_json>;
228     /// a reverse iterator for a basic_json container
229     using reverse_iterator = json_reverse_iterator<typename basic_json::iterator>;
230     /// a const reverse iterator for a basic_json container
231     using const_reverse_iterator = json_reverse_iterator<typename basic_json::const_iterator>;
232 
233     /// @}
234 
235 
236     /// @brief returns the allocator associated with the container
237     /// @sa https://json.nlohmann.me/api/basic_json/get_allocator/
get_allocator()238     static allocator_type get_allocator()
239     {
240         return allocator_type();
241     }
242 
243     /// @brief returns version information on the library
244     /// @sa https://json.nlohmann.me/api/basic_json/meta/
245     JSON_HEDLEY_WARN_UNUSED_RESULT
meta()246     static basic_json meta()
247     {
248         basic_json result;
249 
250         result["copyright"] = "(C) 2013-2022 Niels Lohmann";
251         result["name"] = "JSON for Modern C++";
252         result["url"] = "https://github.com/nlohmann/json";
253         result["version"]["string"] =
254             detail::concat(std::to_string(NLOHMANN_JSON_VERSION_MAJOR), '.',
255                            std::to_string(NLOHMANN_JSON_VERSION_MINOR), '.',
256                            std::to_string(NLOHMANN_JSON_VERSION_PATCH));
257         result["version"]["major"] = NLOHMANN_JSON_VERSION_MAJOR;
258         result["version"]["minor"] = NLOHMANN_JSON_VERSION_MINOR;
259         result["version"]["patch"] = NLOHMANN_JSON_VERSION_PATCH;
260 
261 #ifdef _WIN32
262         result["platform"] = "win32";
263 #elif defined __linux__
264         result["platform"] = "linux";
265 #elif defined __APPLE__
266         result["platform"] = "apple";
267 #elif defined __unix__
268         result["platform"] = "unix";
269 #else
270         result["platform"] = "unknown";
271 #endif
272 
273 #if defined(__ICC) || defined(__INTEL_COMPILER)
274         result["compiler"] = {{"family", "icc"}, {"version", __INTEL_COMPILER}};
275 #elif defined(__clang__)
276         result["compiler"] = {{"family", "clang"}, {"version", __clang_version__}};
277 #elif defined(__GNUC__) || defined(__GNUG__)
278         result["compiler"] = {{"family", "gcc"}, {"version", detail::concat(
279                     std::to_string(__GNUC__), '.',
280                     std::to_string(__GNUC_MINOR__), '.',
281                     std::to_string(__GNUC_PATCHLEVEL__))
282             }
283         };
284 #elif defined(__HP_cc) || defined(__HP_aCC)
285         result["compiler"] = "hp"
286 #elif defined(__IBMCPP__)
287         result["compiler"] = {{"family", "ilecpp"}, {"version", __IBMCPP__}};
288 #elif defined(_MSC_VER)
289         result["compiler"] = {{"family", "msvc"}, {"version", _MSC_VER}};
290 #elif defined(__PGI)
291         result["compiler"] = {{"family", "pgcpp"}, {"version", __PGI}};
292 #elif defined(__SUNPRO_CC)
293         result["compiler"] = {{"family", "sunpro"}, {"version", __SUNPRO_CC}};
294 #else
295         result["compiler"] = {{"family", "unknown"}, {"version", "unknown"}};
296 #endif
297 
298 
299 #if defined(_MSVC_LANG)
300         result["compiler"]["c++"] = std::to_string(_MSVC_LANG);
301 #elif defined(__cplusplus)
302         result["compiler"]["c++"] = std::to_string(__cplusplus);
303 #else
304         result["compiler"]["c++"] = "unknown";
305 #endif
306         return result;
307     }
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
create(Args&& .... args)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
boolean(v)445         json_value(boolean_t v) noexcept : boolean(v) {}
446         /// constructor for numbers (integer)
number_integer(v)447         json_value(number_integer_t v) noexcept : number_integer(v) {}
448         /// constructor for numbers (unsigned)
number_unsigned(v)449         json_value(number_unsigned_t v) noexcept : number_unsigned(v) {}
450         /// constructor for numbers (floating-point)
number_float(v)451         json_value(number_float_t v) noexcept : number_float(v) {}
452         /// constructor for empty values of a given type
json_value(value_t t)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.2", nullptr)); // LCOV_EXCL_LINE
518                     }
519                     break;
520                 }
521             }
522         }
523 
524         /// constructor for strings
json_value(const string_t& value)525         json_value(const string_t& value) : string(create<string_t>(value)) {}
526 
527         /// constructor for rvalue strings
json_value(string_t&& value)528         json_value(string_t&& value) : string(create<string_t>(std::move(value))) {}
529 
530         /// constructor for objects
json_value(const object_t& value)531         json_value(const object_t& value) : object(create<object_t>(value)) {}
532 
533         /// constructor for rvalue objects
json_value(object_t&& value)534         json_value(object_t&& value) : object(create<object_t>(std::move(value))) {}
535 
536         /// constructor for arrays
json_value(const array_t& value)537         json_value(const array_t& value) : array(create<array_t>(value)) {}
538 
539         /// constructor for rvalue arrays
json_value(array_t&& value)540         json_value(array_t&& value) : array(create<array_t>(std::move(value))) {}
541 
542         /// constructor for binary arrays
json_value(const typename binary_t::container_type& value)543         json_value(const typename binary_t::container_type& value) : binary(create<binary_t>(value)) {}
544 
545         /// constructor for rvalue binary arrays
json_value(typename binary_t::container_type&& value)546         json_value(typename binary_t::container_type&& value) : binary(create<binary_t>(std::move(value))) {}
547 
548         /// constructor for binary arrays (internal type)
json_value(const binary_t& value)549         json_value(const binary_t& value) : binary(create<binary_t>(value)) {}
550 
551         /// constructor for rvalue binary arrays (internal type)
json_value(binary_t&& value)552         json_value(binary_t&& value) : binary(create<binary_t>(std::move(value))) {}
553 
destroy(value_t t)554         void destroy(value_t t)
555         {
556             if (t == value_t::array || t == value_t::object)
557             {
558                 // flatten the current json_value to a heap-allocated stack
559                 std::vector<basic_json> stack;
560 
561                 // move the top-level items to stack
562                 if (t == value_t::array)
563                 {
564                     stack.reserve(array->size());
565                     std::move(array->begin(), array->end(), std::back_inserter(stack));
566                 }
567                 else
568                 {
569                     stack.reserve(object->size());
570                     for (auto&& it : *object)
571                     {
572                         stack.push_back(std::move(it.second));
573                     }
574                 }
575 
576                 while (!stack.empty())
577                 {
578                     // move the last item to local variable to be processed
579                     basic_json current_item(std::move(stack.back()));
580                     stack.pop_back();
581 
582                     // if current_item is array/object, move
583                     // its children to the stack to be processed later
584                     if (current_item.is_array())
585                     {
586                         std::move(current_item.m_value.array->begin(), current_item.m_value.array->end(), std::back_inserter(stack));
587 
588                         current_item.m_value.array->clear();
589                     }
590                     else if (current_item.is_object())
591                     {
592                         for (auto&& it : *current_item.m_value.object)
593                         {
594                             stack.push_back(std::move(it.second));
595                         }
596 
597                         current_item.m_value.object->clear();
598                     }
599 
600                     // it's now safe that current_item get destructed
601                     // since it doesn't have any children
602                 }
603             }
604 
605             switch (t)
606             {
607                 case value_t::object:
608                 {
609                     AllocatorType<object_t> alloc;
610                     std::allocator_traits<decltype(alloc)>::destroy(alloc, object);
611                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, object, 1);
612                     break;
613                 }
614 
615                 case value_t::array:
616                 {
617                     AllocatorType<array_t> alloc;
618                     std::allocator_traits<decltype(alloc)>::destroy(alloc, array);
619                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, array, 1);
620                     break;
621                 }
622 
623                 case value_t::string:
624                 {
625                     AllocatorType<string_t> alloc;
626                     std::allocator_traits<decltype(alloc)>::destroy(alloc, string);
627                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, string, 1);
628                     break;
629                 }
630 
631                 case value_t::binary:
632                 {
633                     AllocatorType<binary_t> alloc;
634                     std::allocator_traits<decltype(alloc)>::destroy(alloc, binary);
635                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, binary, 1);
636                     break;
637                 }
638 
639                 case value_t::null:
640                 case value_t::boolean:
641                 case value_t::number_integer:
642                 case value_t::number_unsigned:
643                 case value_t::number_float:
644                 case value_t::discarded:
645                 default:
646                 {
647                     break;
648                 }
649             }
650         }
651     };
652 
653   private:
654     /*!
655     @brief checks the class invariants
656 
657     This function asserts the class invariants. It needs to be called at the
658     end of every constructor to make sure that created objects respect the
659     invariant. Furthermore, it has to be called each time the type of a JSON
660     value is changed, because the invariant expresses a relationship between
661     @a m_type and @a m_value.
662 
663     Furthermore, the parent relation is checked for arrays and objects: If
664     @a check_parents true and the value is an array or object, then the
665     container's elements must have the current value as parent.
666 
667     @param[in] check_parents  whether the parent relation should be checked.
668                The value is true by default and should only be set to false
669                during destruction of objects when the invariant does not
670                need to hold.
671     */
672     void assert_invariant(bool check_parents = true) const noexcept
673     {
674         JSON_ASSERT(m_type != value_t::object || m_value.object != nullptr);
675         JSON_ASSERT(m_type != value_t::array || m_value.array != nullptr);
676         JSON_ASSERT(m_type != value_t::string || m_value.string != nullptr);
677         JSON_ASSERT(m_type != value_t::binary || m_value.binary != nullptr);
678 
679 #if JSON_DIAGNOSTICS
680         JSON_TRY
681         {
682             // cppcheck-suppress assertWithSideEffect
683             JSON_ASSERT(!check_parents || !is_structured() || std::all_of(begin(), end(), [this](const basic_json & j)
684             {
685                 return j.m_parent == this;
686             }));
687         }
JSON_CATCH(....)688         JSON_CATCH(...) {} // LCOV_EXCL_LINE
689 #endif
690         static_cast<void>(check_parents);
691     }
692 
set_parents()693     void set_parents()
694     {
695 #if JSON_DIAGNOSTICS
696         switch (m_type)
697         {
698             case value_t::array:
699             {
700                 for (auto& element : *m_value.array)
701                 {
702                     element.m_parent = this;
703                 }
704                 break;
705             }
706 
707             case value_t::object:
708             {
709                 for (auto& element : *m_value.object)
710                 {
711                     element.second.m_parent = this;
712                 }
713                 break;
714             }
715 
716             case value_t::null:
717             case value_t::string:
718             case value_t::boolean:
719             case value_t::number_integer:
720             case value_t::number_unsigned:
721             case value_t::number_float:
722             case value_t::binary:
723             case value_t::discarded:
724             default:
725                 break;
726         }
727 #endif
728     }
729 
set_parents(iterator it, typename iterator::difference_type count_set_parents)730     iterator set_parents(iterator it, typename iterator::difference_type count_set_parents)
731     {
732 #if JSON_DIAGNOSTICS
733         for (typename iterator::difference_type i = 0; i < count_set_parents; ++i)
734         {
735             (it + i)->m_parent = this;
736         }
737 #else
738         static_cast<void>(count_set_parents);
739 #endif
740         return it;
741     }
742 
set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))743     reference set_parent(reference j, std::size_t old_capacity = static_cast<std::size_t>(-1))
744     {
745 #if JSON_DIAGNOSTICS
746         if (old_capacity != static_cast<std::size_t>(-1))
747         {
748             // see https://github.com/nlohmann/json/issues/2838
749             JSON_ASSERT(type() == value_t::array);
750             if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
751             {
752                 // capacity has changed: update all parents
753                 set_parents();
754                 return j;
755             }
756         }
757 
758         // ordered_json uses a vector internally, so pointers could have
759         // been invalidated; see https://github.com/nlohmann/json/issues/2962
760 #ifdef JSON_HEDLEY_MSVC_VERSION
761 #pragma warning(push )
762 #pragma warning(disable : 4127) // ignore warning to replace if with if constexpr
763 #endif
764         if (detail::is_ordered_map<object_t>::value)
765         {
766             set_parents();
767             return j;
768         }
769 #ifdef JSON_HEDLEY_MSVC_VERSION
770 #pragma warning( pop )
771 #endif
772 
773         j.m_parent = this;
774 #else
775         static_cast<void>(j);
776         static_cast<void>(old_capacity);
777 #endif
778         return j;
779     }
780 
781   public:
782     //////////////////////////
783     // JSON parser callback //
784     //////////////////////////
785 
786     /// @brief parser event types
787     /// @sa https://json.nlohmann.me/api/basic_json/parse_event_t/
788     using parse_event_t = detail::parse_event_t;
789 
790     /// @brief per-element parser callback type
791     /// @sa https://json.nlohmann.me/api/basic_json/parser_callback_t/
792     using parser_callback_t = detail::parser_callback_t<basic_json>;
793 
794     //////////////////
795     // constructors //
796     //////////////////
797 
798     /// @name constructors and destructors
799     /// Constructors of class @ref basic_json, copy/move constructor, copy
800     /// assignment, static functions creating objects, and the destructor.
801     /// @{
802 
803     /// @brief create an empty value with a given type
804     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(const value_t v)805     basic_json(const value_t v)
806         : m_type(v), m_value(v)
807     {
808         assert_invariant();
809     }
810 
811     /// @brief create a null object
812     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
813     basic_json(std::nullptr_t = nullptr) noexcept // NOLINT(bugprone-exception-escape)
basic_json(value_t::null)814         : basic_json(value_t::null)
815     {
816         assert_invariant();
817     }
818 
819     /// @brief create a JSON value from compatible types
820     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
821     template < typename CompatibleType,
822                typename U = detail::uncvref_t<CompatibleType>,
823                detail::enable_if_t <
824                    !detail::is_basic_json<U>::value && detail::is_compatible_type<basic_json_t, U>::value, int > = 0 >
noexcept(JSONSerializer<U>::to_json(825     basic_json(CompatibleType && val) noexcept(noexcept( // NOLINT(bugprone-forwarding-reference-overload,bugprone-exception-escape)
826                 JSONSerializer<U>::to_json(std::declval<basic_json_t&>(),
827                                            std::forward<CompatibleType>(val))))
828     {
829         JSONSerializer<U>::to_json(*this, std::forward<CompatibleType>(val));
830         set_parents();
831         assert_invariant();
832     }
833 
834     /// @brief create a JSON value from an existing one
835     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
836     template < typename BasicJsonType,
837                detail::enable_if_t <
838                    detail::is_basic_json<BasicJsonType>::value&& !std::is_same<basic_json, BasicJsonType>::value, int > = 0 >
basic_json(const BasicJsonType& val)839     basic_json(const BasicJsonType& val)
840     {
841         using other_boolean_t = typename BasicJsonType::boolean_t;
842         using other_number_float_t = typename BasicJsonType::number_float_t;
843         using other_number_integer_t = typename BasicJsonType::number_integer_t;
844         using other_number_unsigned_t = typename BasicJsonType::number_unsigned_t;
845         using other_string_t = typename BasicJsonType::string_t;
846         using other_object_t = typename BasicJsonType::object_t;
847         using other_array_t = typename BasicJsonType::array_t;
848         using other_binary_t = typename BasicJsonType::binary_t;
849 
850         switch (val.type())
851         {
852             case value_t::boolean:
853                 JSONSerializer<other_boolean_t>::to_json(*this, val.template get<other_boolean_t>());
854                 break;
855             case value_t::number_float:
856                 JSONSerializer<other_number_float_t>::to_json(*this, val.template get<other_number_float_t>());
857                 break;
858             case value_t::number_integer:
859                 JSONSerializer<other_number_integer_t>::to_json(*this, val.template get<other_number_integer_t>());
860                 break;
861             case value_t::number_unsigned:
862                 JSONSerializer<other_number_unsigned_t>::to_json(*this, val.template get<other_number_unsigned_t>());
863                 break;
864             case value_t::string:
865                 JSONSerializer<other_string_t>::to_json(*this, val.template get_ref<const other_string_t&>());
866                 break;
867             case value_t::object:
868                 JSONSerializer<other_object_t>::to_json(*this, val.template get_ref<const other_object_t&>());
869                 break;
870             case value_t::array:
871                 JSONSerializer<other_array_t>::to_json(*this, val.template get_ref<const other_array_t&>());
872                 break;
873             case value_t::binary:
874                 JSONSerializer<other_binary_t>::to_json(*this, val.template get_ref<const other_binary_t&>());
875                 break;
876             case value_t::null:
877                 *this = nullptr;
878                 break;
879             case value_t::discarded:
880                 m_type = value_t::discarded;
881                 break;
882             default:            // LCOV_EXCL_LINE
883                 JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
884         }
885         JSON_ASSERT(m_type == val.type());
886         set_parents();
887         assert_invariant();
888     }
889 
890     /// @brief create a container (array or object) from an initializer list
891     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(initializer_list_t init, bool type_deduction = true, value_t manual_type = value_t::array)892     basic_json(initializer_list_t init,
893                bool type_deduction = true,
894                value_t manual_type = value_t::array)
895     {
896         // check if each element is an array with two elements whose first
897         // element is a string
898         bool is_an_object = std::all_of(init.begin(), init.end(),
899                                         [](const detail::json_ref<basic_json>& element_ref)
900         {
901             return element_ref->is_array() && element_ref->size() == 2 && (*element_ref)[0].is_string();
902         });
903 
904         // adjust type if type deduction is not wanted
905         if (!type_deduction)
906         {
907             // if array is wanted, do not create an object though possible
908             if (manual_type == value_t::array)
909             {
910                 is_an_object = false;
911             }
912 
913             // if object is wanted but impossible, throw an exception
914             if (JSON_HEDLEY_UNLIKELY(manual_type == value_t::object && !is_an_object))
915             {
916                 JSON_THROW(type_error::create(301, "cannot create object from initializer list", nullptr));
917             }
918         }
919 
920         if (is_an_object)
921         {
922             // the initializer list is a list of pairs -> create object
923             m_type = value_t::object;
924             m_value = value_t::object;
925 
926             for (auto& element_ref : init)
927             {
928                 auto element = element_ref.moved_or_copied();
929                 m_value.object->emplace(
930                     std::move(*((*element.m_value.array)[0].m_value.string)),
931                     std::move((*element.m_value.array)[1]));
932             }
933         }
934         else
935         {
936             // the initializer list describes an array -> create array
937             m_type = value_t::array;
938             m_value.array = create<array_t>(init.begin(), init.end());
939         }
940 
941         set_parents();
942         assert_invariant();
943     }
944 
945     /// @brief explicitly create a binary array (without subtype)
946     /// @sa https://json.nlohmann.me/api/basic_json/binary/
947     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(const typename binary_t::container_type& init)948     static basic_json binary(const typename binary_t::container_type& init)
949     {
950         auto res = basic_json();
951         res.m_type = value_t::binary;
952         res.m_value = init;
953         return res;
954     }
955 
956     /// @brief explicitly create a binary array (with subtype)
957     /// @sa https://json.nlohmann.me/api/basic_json/binary/
958     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)959     static basic_json binary(const typename binary_t::container_type& init, typename binary_t::subtype_type subtype)
960     {
961         auto res = basic_json();
962         res.m_type = value_t::binary;
963         res.m_value = binary_t(init, subtype);
964         return res;
965     }
966 
967     /// @brief explicitly create a binary array
968     /// @sa https://json.nlohmann.me/api/basic_json/binary/
969     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(typename binary_t::container_type&& init)970     static basic_json binary(typename binary_t::container_type&& init)
971     {
972         auto res = basic_json();
973         res.m_type = value_t::binary;
974         res.m_value = std::move(init);
975         return res;
976     }
977 
978     /// @brief explicitly create a binary array (with subtype)
979     /// @sa https://json.nlohmann.me/api/basic_json/binary/
980     JSON_HEDLEY_WARN_UNUSED_RESULT
binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)981     static basic_json binary(typename binary_t::container_type&& init, typename binary_t::subtype_type subtype)
982     {
983         auto res = basic_json();
984         res.m_type = value_t::binary;
985         res.m_value = binary_t(std::move(init), subtype);
986         return res;
987     }
988 
989     /// @brief explicitly create an array from an initializer list
990     /// @sa https://json.nlohmann.me/api/basic_json/array/
991     JSON_HEDLEY_WARN_UNUSED_RESULT
array(initializer_list_t init = {})992     static basic_json array(initializer_list_t init = {})
993     {
994         return basic_json(init, false, value_t::array);
995     }
996 
997     /// @brief explicitly create an object from an initializer list
998     /// @sa https://json.nlohmann.me/api/basic_json/object/
999     JSON_HEDLEY_WARN_UNUSED_RESULT
object(initializer_list_t init = {})1000     static basic_json object(initializer_list_t init = {})
1001     {
1002         return basic_json(init, false, value_t::object);
1003     }
1004 
1005     /// @brief construct an array with count copies of given value
1006     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(size_type cnt, const basic_json& val)1007     basic_json(size_type cnt, const basic_json& val)
1008         : m_type(value_t::array)
1009     {
1010         m_value.array = create<array_t>(cnt, val);
1011         set_parents();
1012         assert_invariant();
1013     }
1014 
1015     /// @brief construct a JSON container given an iterator range
1016     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1017     template < class InputIT, typename std::enable_if <
1018                    std::is_same<InputIT, typename basic_json_t::iterator>::value ||
1019                    std::is_same<InputIT, typename basic_json_t::const_iterator>::value, int >::type = 0 >
basic_json(InputIT first, InputIT last)1020     basic_json(InputIT first, InputIT last)
1021     {
1022         JSON_ASSERT(first.m_object != nullptr);
1023         JSON_ASSERT(last.m_object != nullptr);
1024 
1025         // make sure iterator fits the current value
1026         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
1027         {
1028             JSON_THROW(invalid_iterator::create(201, "iterators are not compatible", nullptr));
1029         }
1030 
1031         // copy type from first iterator
1032         m_type = first.m_object->m_type;
1033 
1034         // check if iterator range is complete for primitive values
1035         switch (m_type)
1036         {
1037             case value_t::boolean:
1038             case value_t::number_float:
1039             case value_t::number_integer:
1040             case value_t::number_unsigned:
1041             case value_t::string:
1042             {
1043                 if (JSON_HEDLEY_UNLIKELY(!first.m_it.primitive_iterator.is_begin()
1044                                          || !last.m_it.primitive_iterator.is_end()))
1045                 {
1046                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", first.m_object));
1047                 }
1048                 break;
1049             }
1050 
1051             case value_t::null:
1052             case value_t::object:
1053             case value_t::array:
1054             case value_t::binary:
1055             case value_t::discarded:
1056             default:
1057                 break;
1058         }
1059 
1060         switch (m_type)
1061         {
1062             case value_t::number_integer:
1063             {
1064                 m_value.number_integer = first.m_object->m_value.number_integer;
1065                 break;
1066             }
1067 
1068             case value_t::number_unsigned:
1069             {
1070                 m_value.number_unsigned = first.m_object->m_value.number_unsigned;
1071                 break;
1072             }
1073 
1074             case value_t::number_float:
1075             {
1076                 m_value.number_float = first.m_object->m_value.number_float;
1077                 break;
1078             }
1079 
1080             case value_t::boolean:
1081             {
1082                 m_value.boolean = first.m_object->m_value.boolean;
1083                 break;
1084             }
1085 
1086             case value_t::string:
1087             {
1088                 m_value = *first.m_object->m_value.string;
1089                 break;
1090             }
1091 
1092             case value_t::object:
1093             {
1094                 m_value.object = create<object_t>(first.m_it.object_iterator,
1095                                                   last.m_it.object_iterator);
1096                 break;
1097             }
1098 
1099             case value_t::array:
1100             {
1101                 m_value.array = create<array_t>(first.m_it.array_iterator,
1102                                                 last.m_it.array_iterator);
1103                 break;
1104             }
1105 
1106             case value_t::binary:
1107             {
1108                 m_value = *first.m_object->m_value.binary;
1109                 break;
1110             }
1111 
1112             case value_t::null:
1113             case value_t::discarded:
1114             default:
1115                 JSON_THROW(invalid_iterator::create(206, detail::concat("cannot construct with iterators from ", first.m_object->type_name()), first.m_object));
1116         }
1117 
1118         set_parents();
1119         assert_invariant();
1120     }
1121 
1122 
1123     ///////////////////////////////////////
1124     // other constructors and destructor //
1125     ///////////////////////////////////////
1126 
1127     template<typename JsonRef,
1128              detail::enable_if_t<detail::conjunction<detail::is_json_ref<JsonRef>,
1129                                  std::is_same<typename JsonRef::value_type, basic_json>>::value, int> = 0 >
basic_json(const JsonRef& ref)1130     basic_json(const JsonRef& ref) : basic_json(ref.moved_or_copied()) {}
1131 
1132     /// @brief copy constructor
1133     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
basic_json(const basic_json& other)1134     basic_json(const basic_json& other)
1135         : m_type(other.m_type)
1136     {
1137         // check of passed value is valid
1138         other.assert_invariant();
1139 
1140         switch (m_type)
1141         {
1142             case value_t::object:
1143             {
1144                 m_value = *other.m_value.object;
1145                 break;
1146             }
1147 
1148             case value_t::array:
1149             {
1150                 m_value = *other.m_value.array;
1151                 break;
1152             }
1153 
1154             case value_t::string:
1155             {
1156                 m_value = *other.m_value.string;
1157                 break;
1158             }
1159 
1160             case value_t::boolean:
1161             {
1162                 m_value = other.m_value.boolean;
1163                 break;
1164             }
1165 
1166             case value_t::number_integer:
1167             {
1168                 m_value = other.m_value.number_integer;
1169                 break;
1170             }
1171 
1172             case value_t::number_unsigned:
1173             {
1174                 m_value = other.m_value.number_unsigned;
1175                 break;
1176             }
1177 
1178             case value_t::number_float:
1179             {
1180                 m_value = other.m_value.number_float;
1181                 break;
1182             }
1183 
1184             case value_t::binary:
1185             {
1186                 m_value = *other.m_value.binary;
1187                 break;
1188             }
1189 
1190             case value_t::null:
1191             case value_t::discarded:
1192             default:
1193                 break;
1194         }
1195 
1196         set_parents();
1197         assert_invariant();
1198     }
1199 
1200     /// @brief move constructor
1201     /// @sa https://json.nlohmann.me/api/basic_json/basic_json/
1202     basic_json(basic_json&& other) noexcept
1203         : m_type(std::move(other.m_type)),
move(other.m_value)1204           m_value(std::move(other.m_value))
1205     {
1206         // check that passed value is valid
1207         other.assert_invariant(false);
1208 
1209         // invalidate payload
1210         other.m_type = value_t::null;
1211         other.m_value = {};
1212 
1213         set_parents();
1214         assert_invariant();
1215     }
1216 
1217     /// @brief copy assignment
1218     /// @sa https://json.nlohmann.me/api/basic_json/operator=/
noexcept( std::is_nothrow_move_constructible<value_t>::value&& std::is_nothrow_move_assignable<value_t>::value&& std::is_nothrow_move_constructible<json_value>::value&& std::is_nothrow_move_assignable<json_value>::value )1219     basic_json& operator=(basic_json other) noexcept (
1220         std::is_nothrow_move_constructible<value_t>::value&&
1221         std::is_nothrow_move_assignable<value_t>::value&&
1222         std::is_nothrow_move_constructible<json_value>::value&&
1223         std::is_nothrow_move_assignable<json_value>::value
1224     )
1225     {
1226         // check that passed value is valid
1227         other.assert_invariant();
1228 
1229         using std::swap;
1230         swap(m_type, other.m_type);
1231         swap(m_value, other.m_value);
1232 
1233         set_parents();
1234         assert_invariant();
1235         return *this;
1236     }
1237 
1238     /// @brief destructor
1239     /// @sa https://json.nlohmann.me/api/basic_json/~basic_json/
1240     ~basic_json() noexcept
1241     {
1242         assert_invariant(false);
1243         m_value.destroy(m_type);
1244     }
1245 
1246     /// @}
1247 
1248   public:
1249     ///////////////////////
1250     // object inspection //
1251     ///////////////////////
1252 
1253     /// @name object inspection
1254     /// Functions to inspect the type of a JSON value.
1255     /// @{
1256 
1257     /// @brief serialization
1258     /// @sa https://json.nlohmann.me/api/basic_json/dump/
dump(const int indent = -1, const char indent_char = �, const bool ensure_ascii = false, const error_handler_t error_handler = error_handler_t::strict) const1259     string_t dump(const int indent = -1,
1260                   const char indent_char = ' ',
1261                   const bool ensure_ascii = false,
1262                   const error_handler_t error_handler = error_handler_t::strict) const
1263     {
1264         string_t result;
1265         serializer s(detail::output_adapter<char, string_t>(result), indent_char, error_handler);
1266 
1267         if (indent >= 0)
1268         {
1269             s.dump(*this, true, ensure_ascii, static_cast<unsigned int>(indent));
1270         }
1271         else
1272         {
1273             s.dump(*this, false, ensure_ascii, 0);
1274         }
1275 
1276         return result;
1277     }
1278 
1279     /// @brief return the type of the JSON value (explicit)
1280     /// @sa https://json.nlohmann.me/api/basic_json/type/
1281     constexpr value_t type() const noexcept
1282     {
1283         return m_type;
1284     }
1285 
1286     /// @brief return whether type is primitive
1287     /// @sa https://json.nlohmann.me/api/basic_json/is_primitive/
1288     constexpr bool is_primitive() const noexcept
1289     {
1290         return is_null() || is_string() || is_boolean() || is_number() || is_binary();
1291     }
1292 
1293     /// @brief return whether type is structured
1294     /// @sa https://json.nlohmann.me/api/basic_json/is_structured/
1295     constexpr bool is_structured() const noexcept
1296     {
1297         return is_array() || is_object();
1298     }
1299 
1300     /// @brief return whether value is null
1301     /// @sa https://json.nlohmann.me/api/basic_json/is_null/
1302     constexpr bool is_null() const noexcept
1303     {
1304         return m_type == value_t::null;
1305     }
1306 
1307     /// @brief return whether value is a boolean
1308     /// @sa https://json.nlohmann.me/api/basic_json/is_boolean/
1309     constexpr bool is_boolean() const noexcept
1310     {
1311         return m_type == value_t::boolean;
1312     }
1313 
1314     /// @brief return whether value is a number
1315     /// @sa https://json.nlohmann.me/api/basic_json/is_number/
1316     constexpr bool is_number() const noexcept
1317     {
1318         return is_number_integer() || is_number_float();
1319     }
1320 
1321     /// @brief return whether value is an integer number
1322     /// @sa https://json.nlohmann.me/api/basic_json/is_number_integer/
1323     constexpr bool is_number_integer() const noexcept
1324     {
1325         return m_type == value_t::number_integer || m_type == value_t::number_unsigned;
1326     }
1327 
1328     /// @brief return whether value is an unsigned integer number
1329     /// @sa https://json.nlohmann.me/api/basic_json/is_number_unsigned/
1330     constexpr bool is_number_unsigned() const noexcept
1331     {
1332         return m_type == value_t::number_unsigned;
1333     }
1334 
1335     /// @brief return whether value is a floating-point number
1336     /// @sa https://json.nlohmann.me/api/basic_json/is_number_float/
1337     constexpr bool is_number_float() const noexcept
1338     {
1339         return m_type == value_t::number_float;
1340     }
1341 
1342     /// @brief return whether value is an object
1343     /// @sa https://json.nlohmann.me/api/basic_json/is_object/
1344     constexpr bool is_object() const noexcept
1345     {
1346         return m_type == value_t::object;
1347     }
1348 
1349     /// @brief return whether value is an array
1350     /// @sa https://json.nlohmann.me/api/basic_json/is_array/
1351     constexpr bool is_array() const noexcept
1352     {
1353         return m_type == value_t::array;
1354     }
1355 
1356     /// @brief return whether value is a string
1357     /// @sa https://json.nlohmann.me/api/basic_json/is_string/
1358     constexpr bool is_string() const noexcept
1359     {
1360         return m_type == value_t::string;
1361     }
1362 
1363     /// @brief return whether value is a binary array
1364     /// @sa https://json.nlohmann.me/api/basic_json/is_binary/
1365     constexpr bool is_binary() const noexcept
1366     {
1367         return m_type == value_t::binary;
1368     }
1369 
1370     /// @brief return whether value is discarded
1371     /// @sa https://json.nlohmann.me/api/basic_json/is_discarded/
1372     constexpr bool is_discarded() const noexcept
1373     {
1374         return m_type == value_t::discarded;
1375     }
1376 
1377     /// @brief return the type of the JSON value (implicit)
1378     /// @sa https://json.nlohmann.me/api/basic_json/operator_value_t/
1379     constexpr operator value_t() const noexcept
1380     {
1381         return m_type;
1382     }
1383 
1384     /// @}
1385 
1386   private:
1387     //////////////////
1388     // value access //
1389     //////////////////
1390 
1391     /// get a boolean (explicit)
get_impl(boolean_t* ) const1392     boolean_t get_impl(boolean_t* /*unused*/) const
1393     {
1394         if (JSON_HEDLEY_LIKELY(is_boolean()))
1395         {
1396             return m_value.boolean;
1397         }
1398 
1399         JSON_THROW(type_error::create(302, detail::concat("type must be boolean, but is ", type_name()), this));
1400     }
1401 
1402     /// get a pointer to the value (object)
1403     object_t* get_impl_ptr(object_t* /*unused*/) noexcept
1404     {
1405         return is_object() ? m_value.object : nullptr;
1406     }
1407 
1408     /// get a pointer to the value (object)
1409     constexpr const object_t* get_impl_ptr(const object_t* /*unused*/) const noexcept
1410     {
1411         return is_object() ? m_value.object : nullptr;
1412     }
1413 
1414     /// get a pointer to the value (array)
1415     array_t* get_impl_ptr(array_t* /*unused*/) noexcept
1416     {
1417         return is_array() ? m_value.array : nullptr;
1418     }
1419 
1420     /// get a pointer to the value (array)
1421     constexpr const array_t* get_impl_ptr(const array_t* /*unused*/) const noexcept
1422     {
1423         return is_array() ? m_value.array : nullptr;
1424     }
1425 
1426     /// get a pointer to the value (string)
1427     string_t* get_impl_ptr(string_t* /*unused*/) noexcept
1428     {
1429         return is_string() ? m_value.string : nullptr;
1430     }
1431 
1432     /// get a pointer to the value (string)
1433     constexpr const string_t* get_impl_ptr(const string_t* /*unused*/) const noexcept
1434     {
1435         return is_string() ? m_value.string : nullptr;
1436     }
1437 
1438     /// get a pointer to the value (boolean)
1439     boolean_t* get_impl_ptr(boolean_t* /*unused*/) noexcept
1440     {
1441         return is_boolean() ? &m_value.boolean : nullptr;
1442     }
1443 
1444     /// get a pointer to the value (boolean)
1445     constexpr const boolean_t* get_impl_ptr(const boolean_t* /*unused*/) const noexcept
1446     {
1447         return is_boolean() ? &m_value.boolean : nullptr;
1448     }
1449 
1450     /// get a pointer to the value (integer number)
1451     number_integer_t* get_impl_ptr(number_integer_t* /*unused*/) noexcept
1452     {
1453         return is_number_integer() ? &m_value.number_integer : nullptr;
1454     }
1455 
1456     /// get a pointer to the value (integer number)
1457     constexpr const number_integer_t* get_impl_ptr(const number_integer_t* /*unused*/) const noexcept
1458     {
1459         return is_number_integer() ? &m_value.number_integer : nullptr;
1460     }
1461 
1462     /// get a pointer to the value (unsigned number)
1463     number_unsigned_t* get_impl_ptr(number_unsigned_t* /*unused*/) noexcept
1464     {
1465         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
1466     }
1467 
1468     /// get a pointer to the value (unsigned number)
1469     constexpr const number_unsigned_t* get_impl_ptr(const number_unsigned_t* /*unused*/) const noexcept
1470     {
1471         return is_number_unsigned() ? &m_value.number_unsigned : nullptr;
1472     }
1473 
1474     /// get a pointer to the value (floating-point number)
1475     number_float_t* get_impl_ptr(number_float_t* /*unused*/) noexcept
1476     {
1477         return is_number_float() ? &m_value.number_float : nullptr;
1478     }
1479 
1480     /// get a pointer to the value (floating-point number)
1481     constexpr const number_float_t* get_impl_ptr(const number_float_t* /*unused*/) const noexcept
1482     {
1483         return is_number_float() ? &m_value.number_float : nullptr;
1484     }
1485 
1486     /// get a pointer to the value (binary)
1487     binary_t* get_impl_ptr(binary_t* /*unused*/) noexcept
1488     {
1489         return is_binary() ? m_value.binary : nullptr;
1490     }
1491 
1492     /// get a pointer to the value (binary)
1493     constexpr const binary_t* get_impl_ptr(const binary_t* /*unused*/) const noexcept
1494     {
1495         return is_binary() ? m_value.binary : nullptr;
1496     }
1497 
1498     /*!
1499     @brief helper function to implement get_ref()
1500 
1501     This function helps to implement get_ref() without code duplication for
1502     const and non-const overloads
1503 
1504     @tparam ThisType will be deduced as `basic_json` or `const basic_json`
1505 
1506     @throw type_error.303 if ReferenceType does not match underlying value
1507     type of the current JSON
1508     */
1509     template<typename ReferenceType, typename ThisType>
get_ref_impl(ThisType& obj)1510     static ReferenceType get_ref_impl(ThisType& obj)
1511     {
1512         // delegate the call to get_ptr<>()
1513         auto* ptr = obj.template get_ptr<typename std::add_pointer<ReferenceType>::type>();
1514 
1515         if (JSON_HEDLEY_LIKELY(ptr != nullptr))
1516         {
1517             return *ptr;
1518         }
1519 
1520         JSON_THROW(type_error::create(303, detail::concat("incompatible ReferenceType for get_ref, actual type is ", obj.type_name()), &obj));
1521     }
1522 
1523   public:
1524     /// @name value access
1525     /// Direct access to the stored value of a JSON value.
1526     /// @{
1527 
1528     /// @brief get a pointer value (implicit)
1529     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
1530     template<typename PointerType, typename std::enable_if<
1531                  std::is_pointer<PointerType>::value, int>::type = 0>
declval()1532     auto get_ptr() noexcept -> decltype(std::declval<basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
1533     {
1534         // delegate the call to get_impl_ptr<>()
1535         return get_impl_ptr(static_cast<PointerType>(nullptr));
1536     }
1537 
1538     /// @brief get a pointer value (implicit)
1539     /// @sa https://json.nlohmann.me/api/basic_json/get_ptr/
1540     template < typename PointerType, typename std::enable_if <
1541                    std::is_pointer<PointerType>::value&&
1542                    std::is_const<typename std::remove_pointer<PointerType>::type>::value, int >::type = 0 >
declval()1543     constexpr auto get_ptr() const noexcept -> decltype(std::declval<const basic_json_t&>().get_impl_ptr(std::declval<PointerType>()))
1544     {
1545         // delegate the call to get_impl_ptr<>() const
1546         return get_impl_ptr(static_cast<PointerType>(nullptr));
1547     }
1548 
1549   private:
1550     /*!
1551     @brief get a value (explicit)
1552 
1553     Explicit type conversion between the JSON value and a compatible value
1554     which is [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
1555     and [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1556     The value is converted by calling the @ref json_serializer<ValueType>
1557     `from_json()` method.
1558 
1559     The function is equivalent to executing
1560     @code {.cpp}
1561     ValueType ret;
1562     JSONSerializer<ValueType>::from_json(*this, ret);
1563     return ret;
1564     @endcode
1565 
1566     This overloads is chosen if:
1567     - @a ValueType is not @ref basic_json,
1568     - @ref json_serializer<ValueType> has a `from_json()` method of the form
1569       `void from_json(const basic_json&, ValueType&)`, and
1570     - @ref json_serializer<ValueType> does not have a `from_json()` method of
1571       the form `ValueType from_json(const basic_json&)`
1572 
1573     @tparam ValueType the returned value type
1574 
1575     @return copy of the JSON value, converted to @a ValueType
1576 
1577     @throw what @ref json_serializer<ValueType> `from_json()` method throws
1578 
1579     @liveexample{The example below shows several conversions from JSON values
1580     to other types. There a few things to note: (1) Floating-point numbers can
1581     be converted to integers\, (2) A JSON array can be converted to a standard
1582     `std::vector<short>`\, (3) A JSON object can be converted to C++
1583     associative containers such as `std::unordered_map<std::string\,
1584     json>`.,get__ValueType_const}
1585 
1586     @since version 2.1.0
1587     */
1588     template < typename ValueType,
1589                detail::enable_if_t <
1590                    detail::is_default_constructible<ValueType>::value&&
1591                    detail::has_from_json<basic_json_t, ValueType>::value,
1592                    int > = 0 >
noexcept(JSONSerializer<ValueType>::from_json(1593     ValueType get_impl(detail::priority_tag<0> /*unused*/) const noexcept(noexcept(
1594                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), std::declval<ValueType&>())))
1595     {
1596         auto ret = ValueType();
1597         JSONSerializer<ValueType>::from_json(*this, ret);
1598         return ret;
1599     }
1600 
1601     /*!
1602     @brief get a value (explicit); special case
1603 
1604     Explicit type conversion between the JSON value and a compatible value
1605     which is **not** [CopyConstructible](https://en.cppreference.com/w/cpp/named_req/CopyConstructible)
1606     and **not** [DefaultConstructible](https://en.cppreference.com/w/cpp/named_req/DefaultConstructible).
1607     The value is converted by calling the @ref json_serializer<ValueType>
1608     `from_json()` method.
1609 
1610     The function is equivalent to executing
1611     @code {.cpp}
1612     return JSONSerializer<ValueType>::from_json(*this);
1613     @endcode
1614 
1615     This overloads is chosen if:
1616     - @a ValueType is not @ref basic_json and
1617     - @ref json_serializer<ValueType> has a `from_json()` method of the form
1618       `ValueType from_json(const basic_json&)`
1619 
1620     @note If @ref json_serializer<ValueType> has both overloads of
1621     `from_json()`, this one is chosen.
1622 
1623     @tparam ValueType the returned value type
1624 
1625     @return copy of the JSON value, converted to @a ValueType
1626 
1627     @throw what @ref json_serializer<ValueType> `from_json()` method throws
1628 
1629     @since version 2.1.0
1630     */
1631     template < typename ValueType,
1632                detail::enable_if_t <
1633                    detail::has_non_default_from_json<basic_json_t, ValueType>::value,
1634                    int > = 0 >
noexcept(JSONSerializer<ValueType>::from_json(1635     ValueType get_impl(detail::priority_tag<1> /*unused*/) const noexcept(noexcept(
1636                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>())))
1637     {
1638         return JSONSerializer<ValueType>::from_json(*this);
1639     }
1640 
1641     /*!
1642     @brief get special-case overload
1643 
1644     This overloads converts the current @ref basic_json in a different
1645     @ref basic_json type
1646 
1647     @tparam BasicJsonType == @ref basic_json
1648 
1649     @return a copy of *this, converted into @a BasicJsonType
1650 
1651     @complexity Depending on the implementation of the called `from_json()`
1652                 method.
1653 
1654     @since version 3.2.0
1655     */
1656     template < typename BasicJsonType,
1657                detail::enable_if_t <
1658                    detail::is_basic_json<BasicJsonType>::value,
1659                    int > = 0 >
get_impl(detail::priority_tag<2> ) const1660     BasicJsonType get_impl(detail::priority_tag<2> /*unused*/) const
1661     {
1662         return *this;
1663     }
1664 
1665     /*!
1666     @brief get special-case overload
1667 
1668     This overloads avoids a lot of template boilerplate, it can be seen as the
1669     identity method
1670 
1671     @tparam BasicJsonType == @ref basic_json
1672 
1673     @return a copy of *this
1674 
1675     @complexity Constant.
1676 
1677     @since version 2.1.0
1678     */
1679     template<typename BasicJsonType,
1680              detail::enable_if_t<
1681                  std::is_same<BasicJsonType, basic_json_t>::value,
1682                  int> = 0>
get_impl(detail::priority_tag<3> ) const1683     basic_json get_impl(detail::priority_tag<3> /*unused*/) const
1684     {
1685         return *this;
1686     }
1687 
1688     /*!
1689     @brief get a pointer value (explicit)
1690     @copydoc get()
1691     */
1692     template<typename PointerType,
1693              detail::enable_if_t<
1694                  std::is_pointer<PointerType>::value,
1695                  int> = 0>
1696     constexpr auto get_impl(detail::priority_tag<4> /*unused*/) const noexcept
get_ptr()1697     -> decltype(std::declval<const basic_json_t&>().template get_ptr<PointerType>())
1698     {
1699         // delegate the call to get_ptr
1700         return get_ptr<PointerType>();
1701     }
1702 
1703   public:
1704     /*!
1705     @brief get a (pointer) value (explicit)
1706 
1707     Performs explicit type conversion between the JSON value and a compatible value if required.
1708 
1709     - If the requested type is a pointer to the internally stored JSON value that pointer is returned.
1710     No copies are made.
1711 
1712     - If the requested type is the current @ref basic_json, or a different @ref basic_json convertible
1713     from the current @ref basic_json.
1714 
1715     - Otherwise the value is converted by calling the @ref json_serializer<ValueType> `from_json()`
1716     method.
1717 
1718     @tparam ValueTypeCV the provided value type
1719     @tparam ValueType the returned value type
1720 
1721     @return copy of the JSON value, converted to @tparam ValueType if necessary
1722 
1723     @throw what @ref json_serializer<ValueType> `from_json()` method throws if conversion is required
1724 
1725     @since version 2.1.0
1726     */
1727     template < typename ValueTypeCV, typename ValueType = detail::uncvref_t<ValueTypeCV>>
1728 #if defined(JSON_HAS_CPP_14)
1729     constexpr
1730 #endif
1731     auto get() const noexcept(
1732     noexcept(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {})))
1733     -> decltype(std::declval<const basic_json_t&>().template get_impl<ValueType>(detail::priority_tag<4> {}))
1734     {
1735         // we cannot static_assert on ValueTypeCV being non-const, because
1736         // there is support for get<const basic_json_t>(), which is why we
1737         // still need the uncvref
1738         static_assert(!std::is_reference<ValueTypeCV>::value,
1739                       "get() cannot be used with reference types, you might want to use get_ref()");
1740         return get_impl<ValueType>(detail::priority_tag<4> {});
1741     }
1742 
1743     /*!
1744     @brief get a pointer value (explicit)
1745 
1746     Explicit pointer access to the internally stored JSON value. No copies are
1747     made.
1748 
1749     @warning The pointer becomes invalid if the underlying JSON object
1750     changes.
1751 
1752     @tparam PointerType pointer type; must be a pointer to @ref array_t, @ref
1753     object_t, @ref string_t, @ref boolean_t, @ref number_integer_t,
1754     @ref number_unsigned_t, or @ref number_float_t.
1755 
1756     @return pointer to the internally stored JSON value if the requested
1757     pointer type @a PointerType fits to the JSON value; `nullptr` otherwise
1758 
1759     @complexity Constant.
1760 
1761     @liveexample{The example below shows how pointers to internal values of a
1762     JSON value can be requested. Note that no type conversions are made and a
1763     `nullptr` is returned if the value and the requested pointer type does not
1764     match.,get__PointerType}
1765 
1766     @sa see @ref get_ptr() for explicit pointer-member access
1767 
1768     @since version 1.0.0
1769     */
1770     template<typename PointerType, typename std::enable_if<
1771                  std::is_pointer<PointerType>::value, int>::type = 0>
get_ptr()1772     auto get() noexcept -> decltype(std::declval<basic_json_t&>().template get_ptr<PointerType>())
1773     {
1774         // delegate the call to get_ptr
1775         return get_ptr<PointerType>();
1776     }
1777 
1778     /// @brief get a value (explicit)
1779     /// @sa https://json.nlohmann.me/api/basic_json/get_to/
1780     template < typename ValueType,
1781                detail::enable_if_t <
1782                    !detail::is_basic_json<ValueType>::value&&
1783                    detail::has_from_json<basic_json_t, ValueType>::value,
1784                    int > = 0 >
noexcept(JSONSerializer<ValueType>::from_json(1785     ValueType & get_to(ValueType& v) const noexcept(noexcept(
1786                 JSONSerializer<ValueType>::from_json(std::declval<const basic_json_t&>(), v)))
1787     {
1788         JSONSerializer<ValueType>::from_json(*this, v);
1789         return v;
1790     }
1791 
1792     // specialization to allow calling get_to with a basic_json value
1793     // see https://github.com/nlohmann/json/issues/2175
1794     template<typename ValueType,
1795              detail::enable_if_t <
1796                  detail::is_basic_json<ValueType>::value,
1797                  int> = 0>
get_to(ValueType& v) const1798     ValueType & get_to(ValueType& v) const
1799     {
1800         v = *this;
1801         return v;
1802     }
1803 
1804     template <
1805         typename T, std::size_t N,
1806         typename Array = T (&)[N], // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
1807         detail::enable_if_t <
1808             detail::has_from_json<basic_json_t, Array>::value, int > = 0 >
1809     Array get_to(T (&v)[N]) const // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
noexcept(noexcept(1810     noexcept(noexcept(JSONSerializer<Array>::from_json(
1811                           std::declval<const basic_json_t&>(), v)))
1812     {
1813         JSONSerializer<Array>::from_json(*this, v);
1814         return v;
1815     }
1816 
1817     /// @brief get a reference value (implicit)
1818     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
1819     template<typename ReferenceType, typename std::enable_if<
1820                  std::is_reference<ReferenceType>::value, int>::type = 0>
get_ref()1821     ReferenceType get_ref()
1822     {
1823         // delegate call to get_ref_impl
1824         return get_ref_impl<ReferenceType>(*this);
1825     }
1826 
1827     /// @brief get a reference value (implicit)
1828     /// @sa https://json.nlohmann.me/api/basic_json/get_ref/
1829     template < typename ReferenceType, typename std::enable_if <
1830                    std::is_reference<ReferenceType>::value&&
1831                    std::is_const<typename std::remove_reference<ReferenceType>::type>::value, int >::type = 0 >
get_ref() const1832     ReferenceType get_ref() const
1833     {
1834         // delegate call to get_ref_impl
1835         return get_ref_impl<ReferenceType>(*this);
1836     }
1837 
1838     /*!
1839     @brief get a value (implicit)
1840 
1841     Implicit type conversion between the JSON value and a compatible value.
1842     The call is realized by calling @ref get() const.
1843 
1844     @tparam ValueType non-pointer type compatible to the JSON value, for
1845     instance `int` for JSON integer numbers, `bool` for JSON booleans, or
1846     `std::vector` types for JSON arrays. The character type of @ref string_t
1847     as well as an initializer list of this type is excluded to avoid
1848     ambiguities as these types implicitly convert to `std::string`.
1849 
1850     @return copy of the JSON value, converted to type @a ValueType
1851 
1852     @throw type_error.302 in case passed type @a ValueType is incompatible
1853     to the JSON value type (e.g., the JSON value is of type boolean, but a
1854     string is requested); see example below
1855 
1856     @complexity Linear in the size of the JSON value.
1857 
1858     @liveexample{The example below shows several conversions from JSON values
1859     to other types. There a few things to note: (1) Floating-point numbers can
1860     be converted to integers\, (2) A JSON array can be converted to a standard
1861     `std::vector<short>`\, (3) A JSON object can be converted to C++
1862     associative containers such as `std::unordered_map<std::string\,
1863     json>`.,operator__ValueType}
1864 
1865     @since version 1.0.0
1866     */
1867     template < typename ValueType, typename std::enable_if <
1868                    detail::conjunction <
1869                        detail::negation<std::is_pointer<ValueType>>,
1870                        detail::negation<std::is_same<ValueType, std::nullptr_t>>,
1871                        detail::negation<std::is_same<ValueType, detail::json_ref<basic_json>>>,
1872                                         detail::negation<std::is_same<ValueType, typename string_t::value_type>>,
1873                                         detail::negation<detail::is_basic_json<ValueType>>,
1874                                         detail::negation<std::is_same<ValueType, std::initializer_list<typename string_t::value_type>>>,
1875 #if defined(JSON_HAS_CPP_17) && (defined(__GNUC__) || (defined(_MSC_VER) && _MSC_VER >= 1910 && _MSC_VER <= 1914))
1876                                                 detail::negation<std::is_same<ValueType, std::string_view>>,
1877 #endif
1878 #if defined(JSON_HAS_CPP_17)
1879                                                 detail::negation<std::is_same<ValueType, std::any>>,
1880 #endif
1881                                                 detail::is_detected_lazy<detail::get_template_function, const basic_json_t&, ValueType>
1882                                                 >::value, int >::type = 0 >
operator ValueType() const1883                                         JSON_EXPLICIT operator ValueType() const
1884     {
1885         // delegate the call to get<>() const
1886         return get<ValueType>();
1887     }
1888 
1889     /// @brief get a binary value
1890     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
get_binary()1891     binary_t& get_binary()
1892     {
1893         if (!is_binary())
1894         {
1895             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
1896         }
1897 
1898         return *get_ptr<binary_t*>();
1899     }
1900 
1901     /// @brief get a binary value
1902     /// @sa https://json.nlohmann.me/api/basic_json/get_binary/
get_binary() const1903     const binary_t& get_binary() const
1904     {
1905         if (!is_binary())
1906         {
1907             JSON_THROW(type_error::create(302, detail::concat("type must be binary, but is ", type_name()), this));
1908         }
1909 
1910         return *get_ptr<const binary_t*>();
1911     }
1912 
1913     /// @}
1914 
1915 
1916     ////////////////////
1917     // element access //
1918     ////////////////////
1919 
1920     /// @name element access
1921     /// Access to the JSON value.
1922     /// @{
1923 
1924     /// @brief access specified array element with bounds checking
1925     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(size_type idx)1926     reference at(size_type idx)
1927     {
1928         // at only works for arrays
1929         if (JSON_HEDLEY_LIKELY(is_array()))
1930         {
1931             JSON_TRY
1932             {
1933                 return set_parent(m_value.array->at(idx));
1934             }
1935             JSON_CATCH (std::out_of_range&)
1936             {
1937                 // create better exception explanation
1938                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
1939             }
1940         }
1941         else
1942         {
1943             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1944         }
1945     }
1946 
1947     /// @brief access specified array element with bounds checking
1948     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(size_type idx) const1949     const_reference at(size_type idx) const
1950     {
1951         // at only works for arrays
1952         if (JSON_HEDLEY_LIKELY(is_array()))
1953         {
1954             JSON_TRY
1955             {
1956                 return m_value.array->at(idx);
1957             }
1958             JSON_CATCH (std::out_of_range&)
1959             {
1960                 // create better exception explanation
1961                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
1962             }
1963         }
1964         else
1965         {
1966             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1967         }
1968     }
1969 
1970     /// @brief access specified object element with bounds checking
1971     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(const typename object_t::key_type& key)1972     reference at(const typename object_t::key_type& key)
1973     {
1974         // at only works for objects
1975         if (JSON_HEDLEY_UNLIKELY(!is_object()))
1976         {
1977             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1978         }
1979 
1980         auto it = m_value.object->find(key);
1981         if (it == m_value.object->end())
1982         {
1983             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
1984         }
1985         return set_parent(it->second);
1986     }
1987 
1988     /// @brief access specified object element with bounds checking
1989     /// @sa https://json.nlohmann.me/api/basic_json/at/
1990     template<class KeyType, detail::enable_if_t<
1991                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
at(KeyType && key)1992     reference at(KeyType && key)
1993     {
1994         // at only works for objects
1995         if (JSON_HEDLEY_UNLIKELY(!is_object()))
1996         {
1997             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
1998         }
1999 
2000         auto it = m_value.object->find(std::forward<KeyType>(key));
2001         if (it == m_value.object->end())
2002         {
2003             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
2004         }
2005         return set_parent(it->second);
2006     }
2007 
2008     /// @brief access specified object element with bounds checking
2009     /// @sa https://json.nlohmann.me/api/basic_json/at/
at(const typename object_t::key_type& key) const2010     const_reference at(const typename object_t::key_type& key) const
2011     {
2012         // at only works for objects
2013         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2014         {
2015             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2016         }
2017 
2018         auto it = m_value.object->find(key);
2019         if (it == m_value.object->end())
2020         {
2021             JSON_THROW(out_of_range::create(403, detail::concat("key '", key, "' not found"), this));
2022         }
2023         return it->second;
2024     }
2025 
2026     /// @brief access specified object element with bounds checking
2027     /// @sa https://json.nlohmann.me/api/basic_json/at/
2028     template<class KeyType, detail::enable_if_t<
2029                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
at(KeyType && key) const2030     const_reference at(KeyType && key) const
2031     {
2032         // at only works for objects
2033         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2034         {
2035             JSON_THROW(type_error::create(304, detail::concat("cannot use at() with ", type_name()), this));
2036         }
2037 
2038         auto it = m_value.object->find(std::forward<KeyType>(key));
2039         if (it == m_value.object->end())
2040         {
2041             JSON_THROW(out_of_range::create(403, detail::concat("key '", string_t(std::forward<KeyType>(key)), "' not found"), this));
2042         }
2043         return it->second;
2044     }
2045 
2046     /// @brief access specified array element
2047     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](size_type idx)2048     reference operator[](size_type idx)
2049     {
2050         // implicitly convert null value to an empty array
2051         if (is_null())
2052         {
2053             m_type = value_t::array;
2054             m_value.array = create<array_t>();
2055             assert_invariant();
2056         }
2057 
2058         // operator[] only works for arrays
2059         if (JSON_HEDLEY_LIKELY(is_array()))
2060         {
2061             // fill up array with null values if given idx is outside range
2062             if (idx >= m_value.array->size())
2063             {
2064 #if JSON_DIAGNOSTICS
2065                 // remember array size & capacity before resizing
2066                 const auto old_size = m_value.array->size();
2067                 const auto old_capacity = m_value.array->capacity();
2068 #endif
2069                 m_value.array->resize(idx + 1);
2070 
2071 #if JSON_DIAGNOSTICS
2072                 if (JSON_HEDLEY_UNLIKELY(m_value.array->capacity() != old_capacity))
2073                 {
2074                     // capacity has changed: update all parents
2075                     set_parents();
2076                 }
2077                 else
2078                 {
2079                     // set parent for values added above
2080                     set_parents(begin() + static_cast<typename iterator::difference_type>(old_size), static_cast<typename iterator::difference_type>(idx + 1 - old_size));
2081                 }
2082 #endif
2083                 assert_invariant();
2084             }
2085 
2086             return m_value.array->operator[](idx);
2087         }
2088 
2089         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
2090     }
2091 
2092     /// @brief access specified array element
2093     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](size_type idx) const2094     const_reference operator[](size_type idx) const
2095     {
2096         // const operator[] only works for arrays
2097         if (JSON_HEDLEY_LIKELY(is_array()))
2098         {
2099             return m_value.array->operator[](idx);
2100         }
2101 
2102         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a numeric argument with ", type_name()), this));
2103     }
2104 
2105     /// @brief access specified object element
2106     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](typename object_t::key_type key)2107     reference operator[](typename object_t::key_type key)
2108     {
2109         // implicitly convert null value to an empty object
2110         if (is_null())
2111         {
2112             m_type = value_t::object;
2113             m_value.object = create<object_t>();
2114             assert_invariant();
2115         }
2116 
2117         // operator[] only works for objects
2118         if (JSON_HEDLEY_LIKELY(is_object()))
2119         {
2120             auto result = m_value.object->emplace(std::move(key), nullptr);
2121             return set_parent(result.first->second);
2122         }
2123 
2124         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2125     }
2126 
2127     /// @brief access specified object element
2128     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
operator [](const typename object_t::key_type& key) const2129     const_reference operator[](const typename object_t::key_type& key) const
2130     {
2131         // const operator[] only works for objects
2132         if (JSON_HEDLEY_LIKELY(is_object()))
2133         {
2134             auto it = m_value.object->find(key);
2135             JSON_ASSERT(it != m_value.object->end());
2136             return it->second;
2137         }
2138 
2139         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2140     }
2141 
2142     // these two functions resolve a (const) char * ambiguity affecting Clang and MSVC
2143     // (they seemingly cannot be constrained to resolve the ambiguity)
2144     template<typename T>
operator [](T* key)2145     reference operator[](T* key)
2146     {
2147         return operator[](typename object_t::key_type(key));
2148     }
2149 
2150     template<typename T>
operator [](T* key) const2151     const_reference operator[](T* key) const
2152     {
2153         return operator[](typename object_t::key_type(key));
2154     }
2155 
2156     /// @brief access specified object element
2157     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2158     template<class KeyType, detail::enable_if_t<
2159                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
operator [](KeyType && key)2160     reference operator[](KeyType && key)
2161     {
2162         // implicitly convert null value to an empty object
2163         if (is_null())
2164         {
2165             m_type = value_t::object;
2166             m_value.object = create<object_t>();
2167             assert_invariant();
2168         }
2169 
2170         // operator[] only works for objects
2171         if (JSON_HEDLEY_LIKELY(is_object()))
2172         {
2173             auto result = m_value.object->emplace(std::forward<KeyType>(key), nullptr);
2174             return set_parent(result.first->second);
2175         }
2176 
2177         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2178     }
2179 
2180     /// @brief access specified object element
2181     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
2182     template<class KeyType, detail::enable_if_t<
2183                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int > = 0 >
operator [](KeyType && key) const2184     const_reference operator[](KeyType && key) const
2185     {
2186         // const operator[] only works for objects
2187         if (JSON_HEDLEY_LIKELY(is_object()))
2188         {
2189             auto it = m_value.object->find(std::forward<KeyType>(key));
2190             JSON_ASSERT(it != m_value.object->end());
2191             return it->second;
2192         }
2193 
2194         JSON_THROW(type_error::create(305, detail::concat("cannot use operator[] with a string argument with ", type_name()), this));
2195     }
2196 
2197   private:
2198     template<typename KeyType>
2199     using is_comparable_with_object_key = detail::is_comparable <
2200         object_comparator_t, const typename object_t::key_type&, KeyType >;
2201 
2202     template<typename ValueType>
2203     using value_return_type = std::conditional <
2204         detail::is_c_string_uncvref<ValueType>::value,
2205         string_t, typename std::decay<ValueType>::type >;
2206 
2207   public:
2208     /// @brief access specified object element with default value
2209     /// @sa https://json.nlohmann.me/api/basic_json/value/
2210     template < class ValueType, detail::enable_if_t <
2211                    !detail::is_transparent<object_comparator_t>::value
2212                    && detail::is_getable<basic_json_t, ValueType>::value
2213                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
value(const typename object_t::key_type& key, const ValueType& default_value) const2214     ValueType value(const typename object_t::key_type& key, const ValueType& default_value) const
2215     {
2216         // value only works for objects
2217         if (JSON_HEDLEY_LIKELY(is_object()))
2218         {
2219             // if key is found, return value and given default value otherwise
2220             const auto it = find(key);
2221             if (it != end())
2222             {
2223                 return it->template get<ValueType>();
2224             }
2225 
2226             return default_value;
2227         }
2228 
2229         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2230     }
2231 
2232     /// @brief access specified object element with default value
2233     /// @sa https://json.nlohmann.me/api/basic_json/value/
2234     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
2235                detail::enable_if_t <
2236                    !detail::is_transparent<object_comparator_t>::value
2237                    && detail::is_getable<basic_json_t, ReturnType>::value
2238                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
value(const typename object_t::key_type& key, ValueType && default_value) const2239     ReturnType value(const typename object_t::key_type& key, ValueType && default_value) const
2240     {
2241         // value only works for objects
2242         if (JSON_HEDLEY_LIKELY(is_object()))
2243         {
2244             // if key is found, return value and given default value otherwise
2245             const auto it = find(key);
2246             if (it != end())
2247             {
2248                 return it->template get<ReturnType>();
2249             }
2250 
2251             return std::forward<ValueType>(default_value);
2252         }
2253 
2254         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2255     }
2256 
2257     /// @brief access specified object element with default value
2258     /// @sa https://json.nlohmann.me/api/basic_json/value/
2259     template < class ValueType, class KeyType, detail::enable_if_t <
2260                    detail::is_transparent<object_comparator_t>::value
2261                    && !detail::is_json_pointer<KeyType>::value
2262                    && is_comparable_with_object_key<KeyType>::value
2263                    && detail::is_getable<basic_json_t, ValueType>::value
2264                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
value(KeyType && key, const ValueType& default_value) const2265     ValueType value(KeyType && key, const ValueType& default_value) const
2266     {
2267         // value only works for objects
2268         if (JSON_HEDLEY_LIKELY(is_object()))
2269         {
2270             // if key is found, return value and given default value otherwise
2271             const auto it = find(std::forward<KeyType>(key));
2272             if (it != end())
2273             {
2274                 return it->template get<ValueType>();
2275             }
2276 
2277             return default_value;
2278         }
2279 
2280         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2281     }
2282 
2283     /// @brief access specified object element via JSON Pointer with default value
2284     /// @sa https://json.nlohmann.me/api/basic_json/value/
2285     template < class ValueType, class KeyType, class ReturnType = typename value_return_type<ValueType>::type,
2286                detail::enable_if_t <
2287                    detail::is_transparent<object_comparator_t>::value
2288                    && !detail::is_json_pointer<KeyType>::value
2289                    && is_comparable_with_object_key<KeyType>::value
2290                    && detail::is_getable<basic_json_t, ReturnType>::value
2291                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
value(KeyType && key, ValueType && default_value) const2292     ReturnType value(KeyType && key, ValueType && default_value) const
2293     {
2294         // value only works for objects
2295         if (JSON_HEDLEY_LIKELY(is_object()))
2296         {
2297             // if key is found, return value and given default value otherwise
2298             const auto it = find(std::forward<KeyType>(key));
2299             if (it != end())
2300             {
2301                 return it->template get<ReturnType>();
2302             }
2303 
2304             return std::forward<ValueType>(default_value);
2305         }
2306 
2307         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2308     }
2309 
2310     /// @brief access specified object element via JSON Pointer with default value
2311     /// @sa https://json.nlohmann.me/api/basic_json/value/
2312     template < class ValueType, detail::enable_if_t <
2313                    detail::is_getable<basic_json_t, ValueType>::value
2314                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
value(const json_pointer& ptr, const ValueType& default_value) const2315     ValueType value(const json_pointer& ptr, const ValueType& default_value) const
2316     {
2317         // value only works for objects
2318         if (JSON_HEDLEY_LIKELY(is_object()))
2319         {
2320             // if pointer resolves a value, return it or use default value
2321             JSON_TRY
2322             {
2323                 return ptr.get_checked(this).template get<ValueType>();
2324             }
2325             JSON_INTERNAL_CATCH (out_of_range&)
2326             {
2327                 return default_value;
2328             }
2329         }
2330 
2331         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2332     }
2333 
2334     /// @brief access specified object element via JSON Pointer with default value
2335     /// @sa https://json.nlohmann.me/api/basic_json/value/
2336     template < class ValueType, class ReturnType = typename value_return_type<ValueType>::type,
2337                detail::enable_if_t <
2338                    detail::is_getable<basic_json_t, ReturnType>::value
2339                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
value(const json_pointer& ptr, ValueType && default_value) const2340     ReturnType value(const json_pointer& ptr, ValueType && default_value) const
2341     {
2342         // value only works for objects
2343         if (JSON_HEDLEY_LIKELY(is_object()))
2344         {
2345             // if pointer resolves a value, return it or use default value
2346             JSON_TRY
2347             {
2348                 return ptr.get_checked(this).template get<ReturnType>();
2349             }
2350             JSON_INTERNAL_CATCH (out_of_range&)
2351             {
2352                 return std::forward<ValueType>(default_value);
2353             }
2354         }
2355 
2356         JSON_THROW(type_error::create(306, detail::concat("cannot use value() with ", type_name()), this));
2357     }
2358 
2359     template < class ValueType, class BasicJsonType, detail::enable_if_t <
2360                    detail::is_basic_json<BasicJsonType>::value
2361                    && detail::is_getable<basic_json_t, ValueType>::value
2362                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2363     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const2364     ValueType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, const ValueType& default_value) const
2365     {
2366         return value(ptr.convert(), default_value);
2367     }
2368 
2369     template < class ValueType, class BasicJsonType, class ReturnType = typename value_return_type<ValueType>::type,
2370                detail::enable_if_t <
2371                    detail::is_basic_json<BasicJsonType>::value
2372                    && detail::is_getable<basic_json_t, ReturnType>::value
2373                    && !std::is_same<value_t, detail::uncvref_t<ValueType>>::value, int > = 0 >
2374     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const2375     ReturnType value(const ::nlohmann::json_pointer<BasicJsonType>& ptr, ValueType && default_value) const
2376     {
2377         return value(ptr.convert(), std::forward<ValueType>(default_value));
2378     }
2379 
2380     /// @brief access the first element
2381     /// @sa https://json.nlohmann.me/api/basic_json/front/
front()2382     reference front()
2383     {
2384         return *begin();
2385     }
2386 
2387     /// @brief access the first element
2388     /// @sa https://json.nlohmann.me/api/basic_json/front/
front() const2389     const_reference front() const
2390     {
2391         return *cbegin();
2392     }
2393 
2394     /// @brief access the last element
2395     /// @sa https://json.nlohmann.me/api/basic_json/back/
back()2396     reference back()
2397     {
2398         auto tmp = end();
2399         --tmp;
2400         return *tmp;
2401     }
2402 
2403     /// @brief access the last element
2404     /// @sa https://json.nlohmann.me/api/basic_json/back/
back() const2405     const_reference back() const
2406     {
2407         auto tmp = cend();
2408         --tmp;
2409         return *tmp;
2410     }
2411 
2412     /// @brief remove element given an iterator
2413     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2414     template < class IteratorType, detail::enable_if_t <
2415                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
2416                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
erase(IteratorType pos)2417     IteratorType erase(IteratorType pos)
2418     {
2419         // make sure iterator fits the current value
2420         if (JSON_HEDLEY_UNLIKELY(this != pos.m_object))
2421         {
2422             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
2423         }
2424 
2425         IteratorType result = end();
2426 
2427         switch (m_type)
2428         {
2429             case value_t::boolean:
2430             case value_t::number_float:
2431             case value_t::number_integer:
2432             case value_t::number_unsigned:
2433             case value_t::string:
2434             case value_t::binary:
2435             {
2436                 if (JSON_HEDLEY_UNLIKELY(!pos.m_it.primitive_iterator.is_begin()))
2437                 {
2438                     JSON_THROW(invalid_iterator::create(205, "iterator out of range", this));
2439                 }
2440 
2441                 if (is_string())
2442                 {
2443                     AllocatorType<string_t> alloc;
2444                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
2445                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
2446                     m_value.string = nullptr;
2447                 }
2448                 else if (is_binary())
2449                 {
2450                     AllocatorType<binary_t> alloc;
2451                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
2452                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
2453                     m_value.binary = nullptr;
2454                 }
2455 
2456                 m_type = value_t::null;
2457                 assert_invariant();
2458                 break;
2459             }
2460 
2461             case value_t::object:
2462             {
2463                 result.m_it.object_iterator = m_value.object->erase(pos.m_it.object_iterator);
2464                 break;
2465             }
2466 
2467             case value_t::array:
2468             {
2469                 result.m_it.array_iterator = m_value.array->erase(pos.m_it.array_iterator);
2470                 break;
2471             }
2472 
2473             case value_t::null:
2474             case value_t::discarded:
2475             default:
2476                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2477         }
2478 
2479         return result;
2480     }
2481 
2482     /// @brief remove elements given an iterator range
2483     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2484     template < class IteratorType, detail::enable_if_t <
2485                    std::is_same<IteratorType, typename basic_json_t::iterator>::value ||
2486                    std::is_same<IteratorType, typename basic_json_t::const_iterator>::value, int > = 0 >
erase(IteratorType first, IteratorType last)2487     IteratorType erase(IteratorType first, IteratorType last)
2488     {
2489         // make sure iterator fits the current value
2490         if (JSON_HEDLEY_UNLIKELY(this != first.m_object || this != last.m_object))
2491         {
2492             JSON_THROW(invalid_iterator::create(203, "iterators do not fit current value", this));
2493         }
2494 
2495         IteratorType result = end();
2496 
2497         switch (m_type)
2498         {
2499             case value_t::boolean:
2500             case value_t::number_float:
2501             case value_t::number_integer:
2502             case value_t::number_unsigned:
2503             case value_t::string:
2504             case value_t::binary:
2505             {
2506                 if (JSON_HEDLEY_LIKELY(!first.m_it.primitive_iterator.is_begin()
2507                                        || !last.m_it.primitive_iterator.is_end()))
2508                 {
2509                     JSON_THROW(invalid_iterator::create(204, "iterators out of range", this));
2510                 }
2511 
2512                 if (is_string())
2513                 {
2514                     AllocatorType<string_t> alloc;
2515                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.string);
2516                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.string, 1);
2517                     m_value.string = nullptr;
2518                 }
2519                 else if (is_binary())
2520                 {
2521                     AllocatorType<binary_t> alloc;
2522                     std::allocator_traits<decltype(alloc)>::destroy(alloc, m_value.binary);
2523                     std::allocator_traits<decltype(alloc)>::deallocate(alloc, m_value.binary, 1);
2524                     m_value.binary = nullptr;
2525                 }
2526 
2527                 m_type = value_t::null;
2528                 assert_invariant();
2529                 break;
2530             }
2531 
2532             case value_t::object:
2533             {
2534                 result.m_it.object_iterator = m_value.object->erase(first.m_it.object_iterator,
2535                                               last.m_it.object_iterator);
2536                 break;
2537             }
2538 
2539             case value_t::array:
2540             {
2541                 result.m_it.array_iterator = m_value.array->erase(first.m_it.array_iterator,
2542                                              last.m_it.array_iterator);
2543                 break;
2544             }
2545 
2546             case value_t::null:
2547             case value_t::discarded:
2548             default:
2549                 JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2550         }
2551 
2552         return result;
2553     }
2554 
2555   private:
2556     template < typename KeyType, detail::enable_if_t <
2557                    detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
erase_internal(KeyType && key)2558     size_type erase_internal(KeyType && key)
2559     {
2560         // this erase only works for objects
2561         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2562         {
2563             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2564         }
2565 
2566         return m_value.object->erase(std::forward<KeyType>(key));
2567     }
2568 
2569     template < typename KeyType, detail::enable_if_t <
2570                    !detail::has_erase_with_key_type<basic_json_t, KeyType>::value, int > = 0 >
erase_internal(KeyType && key)2571     size_type erase_internal(KeyType && key)
2572     {
2573         // this erase only works for objects
2574         if (JSON_HEDLEY_UNLIKELY(!is_object()))
2575         {
2576             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2577         }
2578 
2579         const auto it = m_value.object->find(std::forward<KeyType>(key));
2580         if (it != m_value.object->end())
2581         {
2582             m_value.object->erase(it);
2583             return 1;
2584         }
2585         return 0;
2586     }
2587 
2588   public:
2589 
2590     /// @brief remove element from a JSON object given a key
2591     /// @sa https://json.nlohmann.me/api/basic_json/erase/
erase(const typename object_t::key_type& key)2592     size_type erase(const typename object_t::key_type& key)
2593     {
2594         // the indirection via erase_internal() is added to avoid making this
2595         // function a template and thus de-rank it during overload resolution
2596         return erase_internal(key);
2597     }
2598 
2599     /// @brief remove element from a JSON object given a key
2600     /// @sa https://json.nlohmann.me/api/basic_json/erase/
2601     template<class KeyType, detail::enable_if_t<
2602                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
erase(KeyType && key)2603     size_type erase(KeyType && key)
2604     {
2605         return erase_internal(std::forward<KeyType>(key));
2606     }
2607 
2608     /// @brief remove element from a JSON array given an index
2609     /// @sa https://json.nlohmann.me/api/basic_json/erase/
erase(const size_type idx)2610     void erase(const size_type idx)
2611     {
2612         // this erase only works for arrays
2613         if (JSON_HEDLEY_LIKELY(is_array()))
2614         {
2615             if (JSON_HEDLEY_UNLIKELY(idx >= size()))
2616             {
2617                 JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), this));
2618             }
2619 
2620             m_value.array->erase(m_value.array->begin() + static_cast<difference_type>(idx));
2621         }
2622         else
2623         {
2624             JSON_THROW(type_error::create(307, detail::concat("cannot use erase() with ", type_name()), this));
2625         }
2626     }
2627 
2628     /// @}
2629 
2630 
2631     ////////////
2632     // lookup //
2633     ////////////
2634 
2635     /// @name lookup
2636     /// @{
2637 
2638     /// @brief find an element in a JSON object
2639     /// @sa https://json.nlohmann.me/api/basic_json/find/
find(const typename object_t::key_type& key)2640     iterator find(const typename object_t::key_type& key)
2641     {
2642         auto result = end();
2643 
2644         if (is_object())
2645         {
2646             result.m_it.object_iterator = m_value.object->find(key);
2647         }
2648 
2649         return result;
2650     }
2651 
2652     /// @brief find an element in a JSON object
2653     /// @sa https://json.nlohmann.me/api/basic_json/find/
find(const typename object_t::key_type& key) const2654     const_iterator find(const typename object_t::key_type& key) const
2655     {
2656         auto result = cend();
2657 
2658         if (is_object())
2659         {
2660             result.m_it.object_iterator = m_value.object->find(key);
2661         }
2662 
2663         return result;
2664     }
2665 
2666     /// @brief find an element in a JSON object
2667     /// @sa https://json.nlohmann.me/api/basic_json/find/
2668     template<class KeyType, detail::enable_if_t<
2669                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
find(KeyType && key)2670     iterator find(KeyType && key)
2671     {
2672         auto result = end();
2673 
2674         if (is_object())
2675         {
2676             result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
2677         }
2678 
2679         return result;
2680     }
2681 
2682     /// @brief find an element in a JSON object
2683     /// @sa https://json.nlohmann.me/api/basic_json/find/
2684     template<class KeyType, detail::enable_if_t<
2685                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
find(KeyType && key) const2686     const_iterator find(KeyType && key) const
2687     {
2688         auto result = cend();
2689 
2690         if (is_object())
2691         {
2692             result.m_it.object_iterator = m_value.object->find(std::forward<KeyType>(key));
2693         }
2694 
2695         return result;
2696     }
2697 
2698     /// @brief returns the number of occurrences of a key in a JSON object
2699     /// @sa https://json.nlohmann.me/api/basic_json/count/
count(const typename object_t::key_type& key) const2700     size_type count(const typename object_t::key_type& key) const
2701     {
2702         // return 0 for all nonobject types
2703         return is_object() ? m_value.object->count(key) : 0;
2704     }
2705 
2706     /// @brief returns the number of occurrences of a key in a JSON object
2707     /// @sa https://json.nlohmann.me/api/basic_json/count/
2708     template<class KeyType, detail::enable_if_t<
2709                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
count(KeyType && key) const2710     size_type count(KeyType && key) const
2711     {
2712         // return 0 for all nonobject types
2713         return is_object() ? m_value.object->count(std::forward<KeyType>(key)) : 0;
2714     }
2715 
2716     /// @brief check the existence of an element in a JSON object
2717     /// @sa https://json.nlohmann.me/api/basic_json/contains/
contains(const typename object_t::key_type& key) const2718     bool contains(const typename object_t::key_type& key) const
2719     {
2720         return is_object() && m_value.object->find(key) != m_value.object->end();
2721     }
2722 
2723     /// @brief check the existence of an element in a JSON object
2724     /// @sa https://json.nlohmann.me/api/basic_json/contains/
2725     template<class KeyType, detail::enable_if_t<
2726                  detail::is_usable_as_basic_json_key_type<basic_json_t, KeyType>::value, int> = 0>
contains(KeyType && key) const2727     bool contains(KeyType && key) const
2728     {
2729         return is_object() && m_value.object->find(std::forward<KeyType>(key)) != m_value.object->end();
2730     }
2731 
2732     /// @brief check the existence of an element in a JSON object given a JSON pointer
2733     /// @sa https://json.nlohmann.me/api/basic_json/contains/
contains(const json_pointer& ptr) const2734     bool contains(const json_pointer& ptr) const
2735     {
2736         return ptr.contains(this);
2737     }
2738 
2739     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
2740     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const2741     bool contains(const typename ::nlohmann::json_pointer<BasicJsonType>& ptr) const
2742     {
2743         return ptr.contains(this);
2744     }
2745 
2746     /// @}
2747 
2748 
2749     ///////////////
2750     // iterators //
2751     ///////////////
2752 
2753     /// @name iterators
2754     /// @{
2755 
2756     /// @brief returns an iterator to the first element
2757     /// @sa https://json.nlohmann.me/api/basic_json/begin/
2758     iterator begin() noexcept
2759     {
2760         iterator result(this);
2761         result.set_begin();
2762         return result;
2763     }
2764 
2765     /// @brief returns an iterator to the first element
2766     /// @sa https://json.nlohmann.me/api/basic_json/begin/
2767     const_iterator begin() const noexcept
2768     {
2769         return cbegin();
2770     }
2771 
2772     /// @brief returns a const iterator to the first element
2773     /// @sa https://json.nlohmann.me/api/basic_json/cbegin/
2774     const_iterator cbegin() const noexcept
2775     {
2776         const_iterator result(this);
2777         result.set_begin();
2778         return result;
2779     }
2780 
2781     /// @brief returns an iterator to one past the last element
2782     /// @sa https://json.nlohmann.me/api/basic_json/end/
2783     iterator end() noexcept
2784     {
2785         iterator result(this);
2786         result.set_end();
2787         return result;
2788     }
2789 
2790     /// @brief returns an iterator to one past the last element
2791     /// @sa https://json.nlohmann.me/api/basic_json/end/
2792     const_iterator end() const noexcept
2793     {
2794         return cend();
2795     }
2796 
2797     /// @brief returns an iterator to one past the last element
2798     /// @sa https://json.nlohmann.me/api/basic_json/cend/
2799     const_iterator cend() const noexcept
2800     {
2801         const_iterator result(this);
2802         result.set_end();
2803         return result;
2804     }
2805 
2806     /// @brief returns an iterator to the reverse-beginning
2807     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
2808     reverse_iterator rbegin() noexcept
2809     {
2810         return reverse_iterator(end());
2811     }
2812 
2813     /// @brief returns an iterator to the reverse-beginning
2814     /// @sa https://json.nlohmann.me/api/basic_json/rbegin/
2815     const_reverse_iterator rbegin() const noexcept
2816     {
2817         return crbegin();
2818     }
2819 
2820     /// @brief returns an iterator to the reverse-end
2821     /// @sa https://json.nlohmann.me/api/basic_json/rend/
2822     reverse_iterator rend() noexcept
2823     {
2824         return reverse_iterator(begin());
2825     }
2826 
2827     /// @brief returns an iterator to the reverse-end
2828     /// @sa https://json.nlohmann.me/api/basic_json/rend/
2829     const_reverse_iterator rend() const noexcept
2830     {
2831         return crend();
2832     }
2833 
2834     /// @brief returns a const reverse iterator to the last element
2835     /// @sa https://json.nlohmann.me/api/basic_json/crbegin/
2836     const_reverse_iterator crbegin() const noexcept
2837     {
2838         return const_reverse_iterator(cend());
2839     }
2840 
2841     /// @brief returns a const reverse iterator to one before the first
2842     /// @sa https://json.nlohmann.me/api/basic_json/crend/
2843     const_reverse_iterator crend() const noexcept
2844     {
2845         return const_reverse_iterator(cbegin());
2846     }
2847 
2848   public:
2849     /// @brief wrapper to access iterator member functions in range-based for
2850     /// @sa https://json.nlohmann.me/api/basic_json/items/
2851     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
2852     ///             version 4.0.0 of the library. Please use @ref items() instead;
2853     ///             that is, replace `json::iterator_wrapper(j)` with `j.items()`.
2854     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
2855     static iteration_proxy<iterator> iterator_wrapper(reference ref) noexcept
2856     {
2857         return ref.items();
2858     }
2859 
2860     /// @brief wrapper to access iterator member functions in range-based for
2861     /// @sa https://json.nlohmann.me/api/basic_json/items/
2862     /// @deprecated This function is deprecated since 3.1.0 and will be removed in
2863     ///         version 4.0.0 of the library. Please use @ref items() instead;
2864     ///         that is, replace `json::iterator_wrapper(j)` with `j.items()`.
2865     JSON_HEDLEY_DEPRECATED_FOR(3.1.0, items())
2866     static iteration_proxy<const_iterator> iterator_wrapper(const_reference ref) noexcept
2867     {
2868         return ref.items();
2869     }
2870 
2871     /// @brief helper to access iterator member functions in range-based for
2872     /// @sa https://json.nlohmann.me/api/basic_json/items/
2873     iteration_proxy<iterator> items() noexcept
2874     {
2875         return iteration_proxy<iterator>(*this);
2876     }
2877 
2878     /// @brief helper to access iterator member functions in range-based for
2879     /// @sa https://json.nlohmann.me/api/basic_json/items/
2880     iteration_proxy<const_iterator> items() const noexcept
2881     {
2882         return iteration_proxy<const_iterator>(*this);
2883     }
2884 
2885     /// @}
2886 
2887 
2888     //////////////
2889     // capacity //
2890     //////////////
2891 
2892     /// @name capacity
2893     /// @{
2894 
2895     /// @brief checks whether the container is empty.
2896     /// @sa https://json.nlohmann.me/api/basic_json/empty/
2897     bool empty() const noexcept
2898     {
2899         switch (m_type)
2900         {
2901             case value_t::null:
2902             {
2903                 // null values are empty
2904                 return true;
2905             }
2906 
2907             case value_t::array:
2908             {
2909                 // delegate call to array_t::empty()
2910                 return m_value.array->empty();
2911             }
2912 
2913             case value_t::object:
2914             {
2915                 // delegate call to object_t::empty()
2916                 return m_value.object->empty();
2917             }
2918 
2919             case value_t::string:
2920             case value_t::boolean:
2921             case value_t::number_integer:
2922             case value_t::number_unsigned:
2923             case value_t::number_float:
2924             case value_t::binary:
2925             case value_t::discarded:
2926             default:
2927             {
2928                 // all other types are nonempty
2929                 return false;
2930             }
2931         }
2932     }
2933 
2934     /// @brief returns the number of elements
2935     /// @sa https://json.nlohmann.me/api/basic_json/size/
2936     size_type size() const noexcept
2937     {
2938         switch (m_type)
2939         {
2940             case value_t::null:
2941             {
2942                 // null values are empty
2943                 return 0;
2944             }
2945 
2946             case value_t::array:
2947             {
2948                 // delegate call to array_t::size()
2949                 return m_value.array->size();
2950             }
2951 
2952             case value_t::object:
2953             {
2954                 // delegate call to object_t::size()
2955                 return m_value.object->size();
2956             }
2957 
2958             case value_t::string:
2959             case value_t::boolean:
2960             case value_t::number_integer:
2961             case value_t::number_unsigned:
2962             case value_t::number_float:
2963             case value_t::binary:
2964             case value_t::discarded:
2965             default:
2966             {
2967                 // all other types have size 1
2968                 return 1;
2969             }
2970         }
2971     }
2972 
2973     /// @brief returns the maximum possible number of elements
2974     /// @sa https://json.nlohmann.me/api/basic_json/max_size/
2975     size_type max_size() const noexcept
2976     {
2977         switch (m_type)
2978         {
2979             case value_t::array:
2980             {
2981                 // delegate call to array_t::max_size()
2982                 return m_value.array->max_size();
2983             }
2984 
2985             case value_t::object:
2986             {
2987                 // delegate call to object_t::max_size()
2988                 return m_value.object->max_size();
2989             }
2990 
2991             case value_t::null:
2992             case value_t::string:
2993             case value_t::boolean:
2994             case value_t::number_integer:
2995             case value_t::number_unsigned:
2996             case value_t::number_float:
2997             case value_t::binary:
2998             case value_t::discarded:
2999             default:
3000             {
3001                 // all other types have max_size() == size()
3002                 return size();
3003             }
3004         }
3005     }
3006 
3007     /// @}
3008 
3009 
3010     ///////////////
3011     // modifiers //
3012     ///////////////
3013 
3014     /// @name modifiers
3015     /// @{
3016 
3017     /// @brief clears the contents
3018     /// @sa https://json.nlohmann.me/api/basic_json/clear/
3019     void clear() noexcept
3020     {
3021         switch (m_type)
3022         {
3023             case value_t::number_integer:
3024             {
3025                 m_value.number_integer = 0;
3026                 break;
3027             }
3028 
3029             case value_t::number_unsigned:
3030             {
3031                 m_value.number_unsigned = 0;
3032                 break;
3033             }
3034 
3035             case value_t::number_float:
3036             {
3037                 m_value.number_float = 0.0;
3038                 break;
3039             }
3040 
3041             case value_t::boolean:
3042             {
3043                 m_value.boolean = false;
3044                 break;
3045             }
3046 
3047             case value_t::string:
3048             {
3049                 m_value.string->clear();
3050                 break;
3051             }
3052 
3053             case value_t::binary:
3054             {
3055                 m_value.binary->clear();
3056                 break;
3057             }
3058 
3059             case value_t::array:
3060             {
3061                 m_value.array->clear();
3062                 break;
3063             }
3064 
3065             case value_t::object:
3066             {
3067                 m_value.object->clear();
3068                 break;
3069             }
3070 
3071             case value_t::null:
3072             case value_t::discarded:
3073             default:
3074                 break;
3075         }
3076     }
3077 
3078     /// @brief add an object to an array
3079     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(basic_json&& val)3080     void push_back(basic_json&& val)
3081     {
3082         // push_back only works for null objects or arrays
3083         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3084         {
3085             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3086         }
3087 
3088         // transform null object into an array
3089         if (is_null())
3090         {
3091             m_type = value_t::array;
3092             m_value = value_t::array;
3093             assert_invariant();
3094         }
3095 
3096         // add element to array (move semantics)
3097         const auto old_capacity = m_value.array->capacity();
3098         m_value.array->push_back(std::move(val));
3099         set_parent(m_value.array->back(), old_capacity);
3100         // if val is moved from, basic_json move constructor marks it null, so we do not call the destructor
3101     }
3102 
3103     /// @brief add an object to an array
3104     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(basic_json&& val)3105     reference operator+=(basic_json&& val)
3106     {
3107         push_back(std::move(val));
3108         return *this;
3109     }
3110 
3111     /// @brief add an object to an array
3112     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(const basic_json& val)3113     void push_back(const basic_json& val)
3114     {
3115         // push_back only works for null objects or arrays
3116         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3117         {
3118             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3119         }
3120 
3121         // transform null object into an array
3122         if (is_null())
3123         {
3124             m_type = value_t::array;
3125             m_value = value_t::array;
3126             assert_invariant();
3127         }
3128 
3129         // add element to array
3130         const auto old_capacity = m_value.array->capacity();
3131         m_value.array->push_back(val);
3132         set_parent(m_value.array->back(), old_capacity);
3133     }
3134 
3135     /// @brief add an object to an array
3136     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(const basic_json& val)3137     reference operator+=(const basic_json& val)
3138     {
3139         push_back(val);
3140         return *this;
3141     }
3142 
3143     /// @brief add an object to an object
3144     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(const typename object_t::value_type& val)3145     void push_back(const typename object_t::value_type& val)
3146     {
3147         // push_back only works for null objects or objects
3148         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
3149         {
3150             JSON_THROW(type_error::create(308, detail::concat("cannot use push_back() with ", type_name()), this));
3151         }
3152 
3153         // transform null object into an object
3154         if (is_null())
3155         {
3156             m_type = value_t::object;
3157             m_value = value_t::object;
3158             assert_invariant();
3159         }
3160 
3161         // add element to object
3162         auto res = m_value.object->insert(val);
3163         set_parent(res.first->second);
3164     }
3165 
3166     /// @brief add an object to an object
3167     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(const typename object_t::value_type& val)3168     reference operator+=(const typename object_t::value_type& val)
3169     {
3170         push_back(val);
3171         return *this;
3172     }
3173 
3174     /// @brief add an object to an object
3175     /// @sa https://json.nlohmann.me/api/basic_json/push_back/
push_back(initializer_list_t init)3176     void push_back(initializer_list_t init)
3177     {
3178         if (is_object() && init.size() == 2 && (*init.begin())->is_string())
3179         {
3180             basic_json&& key = init.begin()->moved_or_copied();
3181             push_back(typename object_t::value_type(
3182                           std::move(key.get_ref<string_t&>()), (init.begin() + 1)->moved_or_copied()));
3183         }
3184         else
3185         {
3186             push_back(basic_json(init));
3187         }
3188     }
3189 
3190     /// @brief add an object to an object
3191     /// @sa https://json.nlohmann.me/api/basic_json/operator+=/
operator +=(initializer_list_t init)3192     reference operator+=(initializer_list_t init)
3193     {
3194         push_back(init);
3195         return *this;
3196     }
3197 
3198     /// @brief add an object to an array
3199     /// @sa https://json.nlohmann.me/api/basic_json/emplace_back/
3200     template<class... Args>
emplace_back(Args&& .... args)3201     reference emplace_back(Args&& ... args)
3202     {
3203         // emplace_back only works for null objects or arrays
3204         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_array())))
3205         {
3206             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace_back() with ", type_name()), this));
3207         }
3208 
3209         // transform null object into an array
3210         if (is_null())
3211         {
3212             m_type = value_t::array;
3213             m_value = value_t::array;
3214             assert_invariant();
3215         }
3216 
3217         // add element to array (perfect forwarding)
3218         const auto old_capacity = m_value.array->capacity();
3219         m_value.array->emplace_back(std::forward<Args>(args)...);
3220         return set_parent(m_value.array->back(), old_capacity);
3221     }
3222 
3223     /// @brief add an object to an object if key does not exist
3224     /// @sa https://json.nlohmann.me/api/basic_json/emplace/
3225     template<class... Args>
emplace(Args&& .... args)3226     std::pair<iterator, bool> emplace(Args&& ... args)
3227     {
3228         // emplace only works for null objects or arrays
3229         if (JSON_HEDLEY_UNLIKELY(!(is_null() || is_object())))
3230         {
3231             JSON_THROW(type_error::create(311, detail::concat("cannot use emplace() with ", type_name()), this));
3232         }
3233 
3234         // transform null object into an object
3235         if (is_null())
3236         {
3237             m_type = value_t::object;
3238             m_value = value_t::object;
3239             assert_invariant();
3240         }
3241 
3242         // add element to array (perfect forwarding)
3243         auto res = m_value.object->emplace(std::forward<Args>(args)...);
3244         set_parent(res.first->second);
3245 
3246         // create result iterator and set iterator to the result of emplace
3247         auto it = begin();
3248         it.m_it.object_iterator = res.first;
3249 
3250         // return pair of iterator and boolean
3251         return {it, res.second};
3252     }
3253 
3254     /// Helper for insertion of an iterator
3255     /// @note: This uses std::distance to support GCC 4.8,
3256     ///        see https://github.com/nlohmann/json/pull/1257
3257     template<typename... Args>
insert_iterator(const_iterator pos, Args&& ... args)3258     iterator insert_iterator(const_iterator pos, Args&& ... args)
3259     {
3260         iterator result(this);
3261         JSON_ASSERT(m_value.array != nullptr);
3262 
3263         auto insert_pos = std::distance(m_value.array->begin(), pos.m_it.array_iterator);
3264         m_value.array->insert(pos.m_it.array_iterator, std::forward<Args>(args)...);
3265         result.m_it.array_iterator = m_value.array->begin() + insert_pos;
3266 
3267         // This could have been written as:
3268         // result.m_it.array_iterator = m_value.array->insert(pos.m_it.array_iterator, cnt, val);
3269         // but the return value of insert is missing in GCC 4.8, so it is written this way instead.
3270 
3271         set_parents();
3272         return result;
3273     }
3274 
3275     /// @brief inserts element into array
3276     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos, const basic_json& val)3277     iterator insert(const_iterator pos, const basic_json& val)
3278     {
3279         // insert only works for arrays
3280         if (JSON_HEDLEY_LIKELY(is_array()))
3281         {
3282             // check if iterator pos fits to this JSON value
3283             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3284             {
3285                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3286             }
3287 
3288             // insert to array and return iterator
3289             return insert_iterator(pos, val);
3290         }
3291 
3292         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3293     }
3294 
3295     /// @brief inserts element into array
3296     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos, basic_json&& val)3297     iterator insert(const_iterator pos, basic_json&& val)
3298     {
3299         return insert(pos, val);
3300     }
3301 
3302     /// @brief inserts copies of element into array
3303     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos, size_type cnt, const basic_json& val)3304     iterator insert(const_iterator pos, size_type cnt, const basic_json& val)
3305     {
3306         // insert only works for arrays
3307         if (JSON_HEDLEY_LIKELY(is_array()))
3308         {
3309             // check if iterator pos fits to this JSON value
3310             if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3311             {
3312                 JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3313             }
3314 
3315             // insert to array and return iterator
3316             return insert_iterator(pos, cnt, val);
3317         }
3318 
3319         JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3320     }
3321 
3322     /// @brief inserts range of elements into array
3323     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos, const_iterator first, const_iterator last)3324     iterator insert(const_iterator pos, const_iterator first, const_iterator last)
3325     {
3326         // insert only works for arrays
3327         if (JSON_HEDLEY_UNLIKELY(!is_array()))
3328         {
3329             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3330         }
3331 
3332         // check if iterator pos fits to this JSON value
3333         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3334         {
3335             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3336         }
3337 
3338         // check if range iterators belong to the same JSON object
3339         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3340         {
3341             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3342         }
3343 
3344         if (JSON_HEDLEY_UNLIKELY(first.m_object == this))
3345         {
3346             JSON_THROW(invalid_iterator::create(211, "passed iterators may not belong to container", this));
3347         }
3348 
3349         // insert to array and return iterator
3350         return insert_iterator(pos, first.m_it.array_iterator, last.m_it.array_iterator);
3351     }
3352 
3353     /// @brief inserts elements from initializer list into array
3354     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator pos, initializer_list_t ilist)3355     iterator insert(const_iterator pos, initializer_list_t ilist)
3356     {
3357         // insert only works for arrays
3358         if (JSON_HEDLEY_UNLIKELY(!is_array()))
3359         {
3360             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3361         }
3362 
3363         // check if iterator pos fits to this JSON value
3364         if (JSON_HEDLEY_UNLIKELY(pos.m_object != this))
3365         {
3366             JSON_THROW(invalid_iterator::create(202, "iterator does not fit current value", this));
3367         }
3368 
3369         // insert to array and return iterator
3370         return insert_iterator(pos, ilist.begin(), ilist.end());
3371     }
3372 
3373     /// @brief inserts range of elements into object
3374     /// @sa https://json.nlohmann.me/api/basic_json/insert/
insert(const_iterator first, const_iterator last)3375     void insert(const_iterator first, const_iterator last)
3376     {
3377         // insert only works for objects
3378         if (JSON_HEDLEY_UNLIKELY(!is_object()))
3379         {
3380             JSON_THROW(type_error::create(309, detail::concat("cannot use insert() with ", type_name()), this));
3381         }
3382 
3383         // check if range iterators belong to the same JSON object
3384         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3385         {
3386             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3387         }
3388 
3389         // passed iterators must belong to objects
3390         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
3391         {
3392             JSON_THROW(invalid_iterator::create(202, "iterators first and last must point to objects", this));
3393         }
3394 
3395         m_value.object->insert(first.m_it.object_iterator, last.m_it.object_iterator);
3396     }
3397 
3398     /// @brief updates a JSON object from another object, overwriting existing keys
3399     /// @sa https://json.nlohmann.me/api/basic_json/update/
update(const_reference j, bool merge_objects = false)3400     void update(const_reference j, bool merge_objects = false)
3401     {
3402         update(j.begin(), j.end(), merge_objects);
3403     }
3404 
3405     /// @brief updates a JSON object from another object, overwriting existing keys
3406     /// @sa https://json.nlohmann.me/api/basic_json/update/
update(const_iterator first, const_iterator last, bool merge_objects = false)3407     void update(const_iterator first, const_iterator last, bool merge_objects = false)
3408     {
3409         // implicitly convert null value to an empty object
3410         if (is_null())
3411         {
3412             m_type = value_t::object;
3413             m_value.object = create<object_t>();
3414             assert_invariant();
3415         }
3416 
3417         if (JSON_HEDLEY_UNLIKELY(!is_object()))
3418         {
3419             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", type_name()), this));
3420         }
3421 
3422         // check if range iterators belong to the same JSON object
3423         if (JSON_HEDLEY_UNLIKELY(first.m_object != last.m_object))
3424         {
3425             JSON_THROW(invalid_iterator::create(210, "iterators do not fit", this));
3426         }
3427 
3428         // passed iterators must belong to objects
3429         if (JSON_HEDLEY_UNLIKELY(!first.m_object->is_object()))
3430         {
3431             JSON_THROW(type_error::create(312, detail::concat("cannot use update() with ", first.m_object->type_name()), first.m_object));
3432         }
3433 
3434         for (auto it = first; it != last; ++it)
3435         {
3436             if (merge_objects && it.value().is_object())
3437             {
3438                 auto it2 = m_value.object->find(it.key());
3439                 if (it2 != m_value.object->end())
3440                 {
3441                     it2->second.update(it.value(), true);
3442                     continue;
3443                 }
3444             }
3445             m_value.object->operator[](it.key()) = it.value();
3446 #if JSON_DIAGNOSTICS
3447             m_value.object->operator[](it.key()).m_parent = this;
3448 #endif
3449         }
3450     }
3451 
3452     /// @brief exchanges the values
3453     /// @sa https://json.nlohmann.me/api/basic_json/swap/
noexcept( std::is_nothrow_move_constructible<value_t>::value&& std::is_nothrow_move_assignable<value_t>::value&& std::is_nothrow_move_constructible<json_value>::value&& std::is_nothrow_move_assignable<json_value>::value )3454     void swap(reference other) noexcept (
3455         std::is_nothrow_move_constructible<value_t>::value&&
3456         std::is_nothrow_move_assignable<value_t>::value&&
3457         std::is_nothrow_move_constructible<json_value>::value&&
3458         std::is_nothrow_move_assignable<json_value>::value
3459     )
3460     {
3461         std::swap(m_type, other.m_type);
3462         std::swap(m_value, other.m_value);
3463 
3464         set_parents();
3465         other.set_parents();
3466         assert_invariant();
3467     }
3468 
3469     /// @brief exchanges the values
3470     /// @sa https://json.nlohmann.me/api/basic_json/swap/
noexcept( std::is_nothrow_move_constructible<value_t>::value&& std::is_nothrow_move_assignable<value_t>::value&& std::is_nothrow_move_constructible<json_value>::value&& std::is_nothrow_move_assignable<json_value>::value )3471     friend void swap(reference left, reference right) noexcept (
3472         std::is_nothrow_move_constructible<value_t>::value&&
3473         std::is_nothrow_move_assignable<value_t>::value&&
3474         std::is_nothrow_move_constructible<json_value>::value&&
3475         std::is_nothrow_move_assignable<json_value>::value
3476     )
3477     {
3478         left.swap(right);
3479     }
3480 
3481     /// @brief exchanges the values
3482     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(array_t& other)3483     void swap(array_t& other) // NOLINT(bugprone-exception-escape)
3484     {
3485         // swap only works for arrays
3486         if (JSON_HEDLEY_LIKELY(is_array()))
3487         {
3488             using std::swap;
3489             swap(*(m_value.array), other);
3490         }
3491         else
3492         {
3493             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(array_t&) with ", type_name()), this));
3494         }
3495     }
3496 
3497     /// @brief exchanges the values
3498     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(object_t& other)3499     void swap(object_t& other) // NOLINT(bugprone-exception-escape)
3500     {
3501         // swap only works for objects
3502         if (JSON_HEDLEY_LIKELY(is_object()))
3503         {
3504             using std::swap;
3505             swap(*(m_value.object), other);
3506         }
3507         else
3508         {
3509             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(object_t&) with ", type_name()), this));
3510         }
3511     }
3512 
3513     /// @brief exchanges the values
3514     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(string_t& other)3515     void swap(string_t& other) // NOLINT(bugprone-exception-escape)
3516     {
3517         // swap only works for strings
3518         if (JSON_HEDLEY_LIKELY(is_string()))
3519         {
3520             using std::swap;
3521             swap(*(m_value.string), other);
3522         }
3523         else
3524         {
3525             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(string_t&) with ", type_name()), this));
3526         }
3527     }
3528 
3529     /// @brief exchanges the values
3530     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(binary_t& other)3531     void swap(binary_t& other) // NOLINT(bugprone-exception-escape)
3532     {
3533         // swap only works for strings
3534         if (JSON_HEDLEY_LIKELY(is_binary()))
3535         {
3536             using std::swap;
3537             swap(*(m_value.binary), other);
3538         }
3539         else
3540         {
3541             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t&) with ", type_name()), this));
3542         }
3543     }
3544 
3545     /// @brief exchanges the values
3546     /// @sa https://json.nlohmann.me/api/basic_json/swap/
swap(typename binary_t::container_type& other)3547     void swap(typename binary_t::container_type& other) // NOLINT(bugprone-exception-escape)
3548     {
3549         // swap only works for strings
3550         if (JSON_HEDLEY_LIKELY(is_binary()))
3551         {
3552             using std::swap;
3553             swap(*(m_value.binary), other);
3554         }
3555         else
3556         {
3557             JSON_THROW(type_error::create(310, detail::concat("cannot use swap(binary_t::container_type&) with ", type_name()), this));
3558         }
3559     }
3560 
3561     /// @}
3562 
3563     //////////////////////////////////////////
3564     // lexicographical comparison operators //
3565     //////////////////////////////////////////
3566 
3567     /// @name lexicographical comparison operators
3568     /// @{
3569 
3570     // note parentheses around operands are necessary; see
3571     // https://github.com/nlohmann/json/issues/1530
3572 #define JSON_IMPLEMENT_OPERATOR(op, null_result, unordered_result, default_result)                       \
3573     const auto lhs_type = lhs.type();                                                                    \
3574     const auto rhs_type = rhs.type();                                                                    \
3575     \
3576     if (lhs_type == rhs_type) /* NOLINT(readability/braces) */                                           \
3577     {                                                                                                    \
3578         switch (lhs_type)                                                                                \
3579         {                                                                                                \
3580             case value_t::array:                                                                         \
3581                 return (*lhs.m_value.array) op (*rhs.m_value.array);                                     \
3582                 \
3583             case value_t::object:                                                                        \
3584                 return (*lhs.m_value.object) op (*rhs.m_value.object);                                   \
3585                 \
3586             case value_t::null:                                                                          \
3587                 return (null_result);                                                                    \
3588                 \
3589             case value_t::string:                                                                        \
3590                 return (*lhs.m_value.string) op (*rhs.m_value.string);                                   \
3591                 \
3592             case value_t::boolean:                                                                       \
3593                 return (lhs.m_value.boolean) op (rhs.m_value.boolean);                                   \
3594                 \
3595             case value_t::number_integer:                                                                \
3596                 return (lhs.m_value.number_integer) op (rhs.m_value.number_integer);                     \
3597                 \
3598             case value_t::number_unsigned:                                                               \
3599                 return (lhs.m_value.number_unsigned) op (rhs.m_value.number_unsigned);                   \
3600                 \
3601             case value_t::number_float:                                                                  \
3602                 return (lhs.m_value.number_float) op (rhs.m_value.number_float);                         \
3603                 \
3604             case value_t::binary:                                                                        \
3605                 return (*lhs.m_value.binary) op (*rhs.m_value.binary);                                   \
3606                 \
3607             case value_t::discarded:                                                                     \
3608             default:                                                                                     \
3609                 return (unordered_result);                                                               \
3610         }                                                                                                \
3611     }                                                                                                    \
3612     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_float)                   \
3613     {                                                                                                    \
3614         return static_cast<number_float_t>(lhs.m_value.number_integer) op rhs.m_value.number_float;      \
3615     }                                                                                                    \
3616     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_integer)                   \
3617     {                                                                                                    \
3618         return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_integer);      \
3619     }                                                                                                    \
3620     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_float)                  \
3621     {                                                                                                    \
3622         return static_cast<number_float_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_float;     \
3623     }                                                                                                    \
3624     else if (lhs_type == value_t::number_float && rhs_type == value_t::number_unsigned)                  \
3625     {                                                                                                    \
3626         return lhs.m_value.number_float op static_cast<number_float_t>(rhs.m_value.number_unsigned);     \
3627     }                                                                                                    \
3628     else if (lhs_type == value_t::number_unsigned && rhs_type == value_t::number_integer)                \
3629     {                                                                                                    \
3630         return static_cast<number_integer_t>(lhs.m_value.number_unsigned) op rhs.m_value.number_integer; \
3631     }                                                                                                    \
3632     else if (lhs_type == value_t::number_integer && rhs_type == value_t::number_unsigned)                \
3633     {                                                                                                    \
3634         return lhs.m_value.number_integer op static_cast<number_integer_t>(rhs.m_value.number_unsigned); \
3635     }                                                                                                    \
3636     else if(compares_unordered(lhs, rhs))\
3637     {\
3638         return (unordered_result);\
3639     }\
3640     \
3641     return (default_result);
3642 
3643   JSON_PRIVATE_UNLESS_TESTED:
3644     // returns true if:
3645     // - any operand is NaN and the other operand is of number type
3646     // - any operand is discarded
3647     // in legacy mode, discarded values are considered ordered if
3648     // an operation is computed as an odd number of inverses of others
3649     static bool compares_unordered(const_reference lhs, const_reference rhs, bool inverse = false) noexcept
3650     {
3651         if ((lhs.is_number_float() && std::isnan(lhs.m_value.number_float) && rhs.is_number())
3652                 || (rhs.is_number_float() && std::isnan(rhs.m_value.number_float) && lhs.is_number()))
3653         {
3654             return true;
3655         }
3656 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
3657         return (lhs.is_discarded() || rhs.is_discarded()) && !inverse;
3658 #else
3659         static_cast<void>(inverse);
3660         return lhs.is_discarded() || rhs.is_discarded();
3661 #endif
3662     }
3663 
3664   private:
3665     bool compares_unordered(const_reference rhs, bool inverse = false) const noexcept
3666     {
3667         return compares_unordered(*this, rhs, inverse);
3668     }
3669 
3670   public:
3671 #if JSON_HAS_THREE_WAY_COMPARISON
3672     /// @brief comparison: equal
3673     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3674     bool operator==(const_reference rhs) const noexcept
3675     {
3676 #ifdef __GNUC__
3677 #pragma GCC diagnostic push
3678 #pragma GCC diagnostic ignored "-Wfloat-equal"
3679 #endif
3680         const_reference lhs = *this;
3681         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
3682 #ifdef __GNUC__
3683 #pragma GCC diagnostic pop
3684 #endif
3685     }
3686 
3687     /// @brief comparison: equal
3688     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3689     template<typename ScalarType>
3690     requires std::is_scalar_v<ScalarType>
3691     bool operator==(ScalarType rhs) const noexcept
3692     {
3693         return *this == basic_json(rhs);
3694     }
3695 
3696     /// @brief comparison: not equal
3697     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3698     bool operator!=(const_reference rhs) const noexcept
3699     {
3700         if (compares_unordered(rhs, true))
3701         {
3702             return false;
3703         }
3704         return !operator==(rhs);
3705     }
3706 
3707     /// @brief comparison: 3-way
3708     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
3709     std::partial_ordering operator<=>(const_reference rhs) const noexcept // *NOPAD*
3710     {
3711         const_reference lhs = *this;
3712         // default_result is used if we cannot compare values. In that case,
3713         // we compare types.
3714         JSON_IMPLEMENT_OPERATOR(<=>, // *NOPAD*
3715                                 std::partial_ordering::equivalent,
3716                                 std::partial_ordering::unordered,
3717                                 lhs_type <=> rhs_type) // *NOPAD*
3718     }
3719 
3720     /// @brief comparison: 3-way
3721     /// @sa https://json.nlohmann.me/api/basic_json/operator_spaceship/
3722     template<typename ScalarType>
3723     requires std::is_scalar_v<ScalarType>
3724     std::partial_ordering operator<=>(ScalarType rhs) const noexcept // *NOPAD*
3725     {
3726         return *this <=> basic_json(rhs); // *NOPAD*
3727     }
3728 
3729 #if JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON
3730     // all operators that are computed as an odd number of inverses of others
3731     // need to be overloaded to emulate the legacy comparison behavior
3732 
3733     /// @brief comparison: less than or equal
3734     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3735     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
3736     bool operator<=(const_reference rhs) const noexcept
3737     {
3738         if (compares_unordered(rhs, true))
3739         {
3740             return false;
3741         }
3742         return !(rhs < *this);
3743     }
3744 
3745     /// @brief comparison: less than or equal
3746     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3747     template<typename ScalarType>
3748     requires std::is_scalar_v<ScalarType>
3749     bool operator<=(ScalarType rhs) const noexcept
3750     {
3751         return *this <= basic_json(rhs);
3752     }
3753 
3754     /// @brief comparison: greater than or equal
3755     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3756     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, undef JSON_USE_LEGACY_DISCARDED_VALUE_COMPARISON)
3757     bool operator>=(const_reference rhs) const noexcept
3758     {
3759         if (compares_unordered(rhs, true))
3760         {
3761             return false;
3762         }
3763         return !(*this < rhs);
3764     }
3765 
3766     /// @brief comparison: greater than or equal
3767     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3768     template<typename ScalarType>
3769     requires std::is_scalar_v<ScalarType>
3770     bool operator>=(ScalarType rhs) const noexcept
3771     {
3772         return *this >= basic_json(rhs);
3773     }
3774 #endif
3775 #else
3776     /// @brief comparison: equal
3777     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3778     friend bool operator==(const_reference lhs, const_reference rhs) noexcept
3779     {
3780 #ifdef __GNUC__
3781 #pragma GCC diagnostic push
3782 #pragma GCC diagnostic ignored "-Wfloat-equal"
3783 #endif
3784         JSON_IMPLEMENT_OPERATOR( ==, true, false, false)
3785 #ifdef __GNUC__
3786 #pragma GCC diagnostic pop
3787 #endif
3788     }
3789 
3790     /// @brief comparison: equal
3791     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3792     template<typename ScalarType, typename std::enable_if<
3793                  std::is_scalar<ScalarType>::value, int>::type = 0>
3794     friend bool operator==(const_reference lhs, ScalarType rhs) noexcept
3795     {
3796         return lhs == basic_json(rhs);
3797     }
3798 
3799     /// @brief comparison: equal
3800     /// @sa https://json.nlohmann.me/api/basic_json/operator_eq/
3801     template<typename ScalarType, typename std::enable_if<
3802                  std::is_scalar<ScalarType>::value, int>::type = 0>
3803     friend bool operator==(ScalarType lhs, const_reference rhs) noexcept
3804     {
3805         return basic_json(lhs) == rhs;
3806     }
3807 
3808     /// @brief comparison: not equal
3809     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3810     friend bool operator!=(const_reference lhs, const_reference rhs) noexcept
3811     {
3812         if (compares_unordered(lhs, rhs, true))
3813         {
3814             return false;
3815         }
3816         return !(lhs == rhs);
3817     }
3818 
3819     /// @brief comparison: not equal
3820     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3821     template<typename ScalarType, typename std::enable_if<
3822                  std::is_scalar<ScalarType>::value, int>::type = 0>
3823     friend bool operator!=(const_reference lhs, ScalarType rhs) noexcept
3824     {
3825         return lhs != basic_json(rhs);
3826     }
3827 
3828     /// @brief comparison: not equal
3829     /// @sa https://json.nlohmann.me/api/basic_json/operator_ne/
3830     template<typename ScalarType, typename std::enable_if<
3831                  std::is_scalar<ScalarType>::value, int>::type = 0>
3832     friend bool operator!=(ScalarType lhs, const_reference rhs) noexcept
3833     {
3834         return basic_json(lhs) != rhs;
3835     }
3836 
3837     /// @brief comparison: less than
3838     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3839     friend bool operator<(const_reference lhs, const_reference rhs) noexcept
3840     {
3841         // default_result is used if we cannot compare values. In that case,
3842         // we compare types. Note we have to call the operator explicitly,
3843         // because MSVC has problems otherwise.
3844         JSON_IMPLEMENT_OPERATOR( <, false, false, operator<(lhs_type, rhs_type))
3845     }
3846 
3847     /// @brief comparison: less than
3848     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3849     template<typename ScalarType, typename std::enable_if<
3850                  std::is_scalar<ScalarType>::value, int>::type = 0>
3851     friend bool operator<(const_reference lhs, ScalarType rhs) noexcept
3852     {
3853         return lhs < basic_json(rhs);
3854     }
3855 
3856     /// @brief comparison: less than
3857     /// @sa https://json.nlohmann.me/api/basic_json/operator_lt/
3858     template<typename ScalarType, typename std::enable_if<
3859                  std::is_scalar<ScalarType>::value, int>::type = 0>
3860     friend bool operator<(ScalarType lhs, const_reference rhs) noexcept
3861     {
3862         return basic_json(lhs) < rhs;
3863     }
3864 
3865     /// @brief comparison: less than or equal
3866     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3867     friend bool operator<=(const_reference lhs, const_reference rhs) noexcept
3868     {
3869         if (compares_unordered(lhs, rhs, true))
3870         {
3871             return false;
3872         }
3873         return !(rhs < lhs);
3874     }
3875 
3876     /// @brief comparison: less than or equal
3877     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3878     template<typename ScalarType, typename std::enable_if<
3879                  std::is_scalar<ScalarType>::value, int>::type = 0>
3880     friend bool operator<=(const_reference lhs, ScalarType rhs) noexcept
3881     {
3882         return lhs <= basic_json(rhs);
3883     }
3884 
3885     /// @brief comparison: less than or equal
3886     /// @sa https://json.nlohmann.me/api/basic_json/operator_le/
3887     template<typename ScalarType, typename std::enable_if<
3888                  std::is_scalar<ScalarType>::value, int>::type = 0>
3889     friend bool operator<=(ScalarType lhs, const_reference rhs) noexcept
3890     {
3891         return basic_json(lhs) <= rhs;
3892     }
3893 
3894     /// @brief comparison: greater than
3895     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3896     friend bool operator>(const_reference lhs, const_reference rhs) noexcept
3897     {
3898         // double inverse
3899         if (compares_unordered(lhs, rhs))
3900         {
3901             return false;
3902         }
3903         return !(lhs <= rhs);
3904     }
3905 
3906     /// @brief comparison: greater than
3907     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3908     template<typename ScalarType, typename std::enable_if<
3909                  std::is_scalar<ScalarType>::value, int>::type = 0>
3910     friend bool operator>(const_reference lhs, ScalarType rhs) noexcept
3911     {
3912         return lhs > basic_json(rhs);
3913     }
3914 
3915     /// @brief comparison: greater than
3916     /// @sa https://json.nlohmann.me/api/basic_json/operator_gt/
3917     template<typename ScalarType, typename std::enable_if<
3918                  std::is_scalar<ScalarType>::value, int>::type = 0>
3919     friend bool operator>(ScalarType lhs, const_reference rhs) noexcept
3920     {
3921         return basic_json(lhs) > rhs;
3922     }
3923 
3924     /// @brief comparison: greater than or equal
3925     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3926     friend bool operator>=(const_reference lhs, const_reference rhs) noexcept
3927     {
3928         if (compares_unordered(lhs, rhs, true))
3929         {
3930             return false;
3931         }
3932         return !(lhs < rhs);
3933     }
3934 
3935     /// @brief comparison: greater than or equal
3936     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3937     template<typename ScalarType, typename std::enable_if<
3938                  std::is_scalar<ScalarType>::value, int>::type = 0>
3939     friend bool operator>=(const_reference lhs, ScalarType rhs) noexcept
3940     {
3941         return lhs >= basic_json(rhs);
3942     }
3943 
3944     /// @brief comparison: greater than or equal
3945     /// @sa https://json.nlohmann.me/api/basic_json/operator_ge/
3946     template<typename ScalarType, typename std::enable_if<
3947                  std::is_scalar<ScalarType>::value, int>::type = 0>
3948     friend bool operator>=(ScalarType lhs, const_reference rhs) noexcept
3949     {
3950         return basic_json(lhs) >= rhs;
3951     }
3952 #endif
3953 
3954 #undef JSON_IMPLEMENT_OPERATOR
3955 
3956     /// @}
3957 
3958     ///////////////////
3959     // serialization //
3960     ///////////////////
3961 
3962     /// @name serialization
3963     /// @{
3964 #ifndef JSON_NO_IO
3965     /// @brief serialize to stream
3966     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
3967     friend std::ostream& operator<<(std::ostream& o, const basic_json& j)
3968     {
3969         // read width member and use it as indentation parameter if nonzero
3970         const bool pretty_print = o.width() > 0;
3971         const auto indentation = pretty_print ? o.width() : 0;
3972 
3973         // reset width to 0 for subsequent calls to this stream
3974         o.width(0);
3975 
3976         // do the actual serialization
3977         serializer s(detail::output_adapter<char>(o), o.fill());
3978         s.dump(j, pretty_print, false, static_cast<unsigned int>(indentation));
3979         return o;
3980     }
3981 
3982     /// @brief serialize to stream
3983     /// @sa https://json.nlohmann.me/api/basic_json/operator_ltlt/
3984     /// @deprecated This function is deprecated since 3.0.0 and will be removed in
3985     ///             version 4.0.0 of the library. Please use
3986     ///             operator<<(std::ostream&, const basic_json&) instead; that is,
3987     ///             replace calls like `j >> o;` with `o << j;`.
3988     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator<<(std::ostream&, const basic_json&))
3989     friend std::ostream& operator>>(const basic_json& j, std::ostream& o)
3990     {
3991         return o << j;
3992     }
3993 #endif  // JSON_NO_IO
3994     /// @}
3995 
3996 
3997     /////////////////////
3998     // deserialization //
3999     /////////////////////
4000 
4001     /// @name deserialization
4002     /// @{
4003 
4004     /// @brief deserialize from a compatible input
4005     /// @sa https://json.nlohmann.me/api/basic_json/parse/
4006     template<typename InputType>
4007     JSON_HEDLEY_WARN_UNUSED_RESULT
4008     static basic_json parse(InputType&& i,
4009                             const parser_callback_t cb = nullptr,
4010                             const bool allow_exceptions = true,
4011                             const bool ignore_comments = false)
4012     {
4013         basic_json result;
4014         parser(detail::input_adapter(std::forward<InputType>(i)), cb, allow_exceptions, ignore_comments).parse(true, result);
4015         return result;
4016     }
4017 
4018     /// @brief deserialize from a pair of character iterators
4019     /// @sa https://json.nlohmann.me/api/basic_json/parse/
4020     template<typename IteratorType>
4021     JSON_HEDLEY_WARN_UNUSED_RESULT
4022     static basic_json parse(IteratorType first,
4023                             IteratorType last,
4024                             const parser_callback_t cb = nullptr,
4025                             const bool allow_exceptions = true,
4026                             const bool ignore_comments = false)
4027     {
4028         basic_json result;
4029         parser(detail::input_adapter(std::move(first), std::move(last)), cb, allow_exceptions, ignore_comments).parse(true, result);
4030         return result;
4031     }
4032 
4033     JSON_HEDLEY_WARN_UNUSED_RESULT
4034     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, parse(ptr, ptr + len))
4035     static basic_json parse(detail::span_input_adapter&& i,
4036                             const parser_callback_t cb = nullptr,
4037                             const bool allow_exceptions = true,
4038                             const bool ignore_comments = false)
4039     {
4040         basic_json result;
4041         parser(i.get(), cb, allow_exceptions, ignore_comments).parse(true, result);
4042         return result;
4043     }
4044 
4045     /// @brief check if the input is valid JSON
4046     /// @sa https://json.nlohmann.me/api/basic_json/accept/
4047     template<typename InputType>
4048     static bool accept(InputType&& i,
4049                        const bool ignore_comments = false)
4050     {
4051         return parser(detail::input_adapter(std::forward<InputType>(i)), nullptr, false, ignore_comments).accept(true);
4052     }
4053 
4054     /// @brief check if the input is valid JSON
4055     /// @sa https://json.nlohmann.me/api/basic_json/accept/
4056     template<typename IteratorType>
4057     static bool accept(IteratorType first, IteratorType last,
4058                        const bool ignore_comments = false)
4059     {
4060         return parser(detail::input_adapter(std::move(first), std::move(last)), nullptr, false, ignore_comments).accept(true);
4061     }
4062 
4063     JSON_HEDLEY_WARN_UNUSED_RESULT
4064     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, accept(ptr, ptr + len))
4065     static bool accept(detail::span_input_adapter&& i,
4066                        const bool ignore_comments = false)
4067     {
4068         return parser(i.get(), nullptr, false, ignore_comments).accept(true);
4069     }
4070 
4071     /// @brief generate SAX events
4072     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4073     template <typename InputType, typename SAX>
4074     JSON_HEDLEY_NON_NULL(2)
4075     static bool sax_parse(InputType&& i, SAX* sax,
4076                           input_format_t format = input_format_t::json,
4077                           const bool strict = true,
4078                           const bool ignore_comments = false)
4079     {
4080         auto ia = detail::input_adapter(std::forward<InputType>(i));
4081         return format == input_format_t::json
4082                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
4083                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4084     }
4085 
4086     /// @brief generate SAX events
4087     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4088     template<class IteratorType, class SAX>
4089     JSON_HEDLEY_NON_NULL(3)
4090     static bool sax_parse(IteratorType first, IteratorType last, SAX* sax,
4091                           input_format_t format = input_format_t::json,
4092                           const bool strict = true,
4093                           const bool ignore_comments = false)
4094     {
4095         auto ia = detail::input_adapter(std::move(first), std::move(last));
4096         return format == input_format_t::json
4097                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
4098                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4099     }
4100 
4101     /// @brief generate SAX events
4102     /// @sa https://json.nlohmann.me/api/basic_json/sax_parse/
4103     /// @deprecated This function is deprecated since 3.8.0 and will be removed in
4104     ///             version 4.0.0 of the library. Please use
4105     ///             sax_parse(ptr, ptr + len) instead.
4106     template <typename SAX>
4107     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, sax_parse(ptr, ptr + len, ...))
4108     JSON_HEDLEY_NON_NULL(2)
4109     static bool sax_parse(detail::span_input_adapter&& i, SAX* sax,
4110                           input_format_t format = input_format_t::json,
4111                           const bool strict = true,
4112                           const bool ignore_comments = false)
4113     {
4114         auto ia = i.get();
4115         return format == input_format_t::json
4116                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4117                ? parser(std::move(ia), nullptr, true, ignore_comments).sax_parse(sax, strict)
4118                // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4119                : detail::binary_reader<basic_json, decltype(ia), SAX>(std::move(ia), format).sax_parse(format, sax, strict);
4120     }
4121 #ifndef JSON_NO_IO
4122     /// @brief deserialize from stream
4123     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
4124     /// @deprecated This stream operator is deprecated since 3.0.0 and will be removed in
4125     ///             version 4.0.0 of the library. Please use
4126     ///             operator>>(std::istream&, basic_json&) instead; that is,
4127     ///             replace calls like `j << i;` with `i >> j;`.
4128     JSON_HEDLEY_DEPRECATED_FOR(3.0.0, operator>>(std::istream&, basic_json&))
4129     friend std::istream& operator<<(basic_json& j, std::istream& i)
4130     {
4131         return operator>>(i, j);
4132     }
4133 
4134     /// @brief deserialize from stream
4135     /// @sa https://json.nlohmann.me/api/basic_json/operator_gtgt/
4136     friend std::istream& operator>>(std::istream& i, basic_json& j)
4137     {
4138         parser(detail::input_adapter(i)).parse(false, j);
4139         return i;
4140     }
4141 #endif  // JSON_NO_IO
4142     /// @}
4143 
4144     ///////////////////////////
4145     // convenience functions //
4146     ///////////////////////////
4147 
4148     /// @brief return the type as string
4149     /// @sa https://json.nlohmann.me/api/basic_json/type_name/
4150     JSON_HEDLEY_RETURNS_NON_NULL
4151     const char* type_name() const noexcept
4152     {
4153         switch (m_type)
4154         {
4155             case value_t::null:
4156                 return "null";
4157             case value_t::object:
4158                 return "object";
4159             case value_t::array:
4160                 return "array";
4161             case value_t::string:
4162                 return "string";
4163             case value_t::boolean:
4164                 return "boolean";
4165             case value_t::binary:
4166                 return "binary";
4167             case value_t::discarded:
4168                 return "discarded";
4169             case value_t::number_integer:
4170             case value_t::number_unsigned:
4171             case value_t::number_float:
4172             default:
4173                 return "number";
4174         }
4175     }
4176 
4177 
4178   JSON_PRIVATE_UNLESS_TESTED:
4179     //////////////////////
4180     // member variables //
4181     //////////////////////
4182 
4183     /// the type of the current element
4184     value_t m_type = value_t::null;
4185 
4186     /// the value of the current element
4187     json_value m_value = {};
4188 
4189 #if JSON_DIAGNOSTICS
4190     /// a pointer to a parent value (for debugging purposes)
4191     basic_json* m_parent = nullptr;
4192 #endif
4193 
4194     //////////////////////////////////////////
4195     // binary serialization/deserialization //
4196     //////////////////////////////////////////
4197 
4198     /// @name binary serialization/deserialization support
4199     /// @{
4200 
4201   public:
4202     /// @brief create a CBOR serialization of a given JSON value
4203     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4204     static std::vector<std::uint8_t> to_cbor(const basic_json& j)
4205     {
4206         std::vector<std::uint8_t> result;
4207         to_cbor(j, result);
4208         return result;
4209     }
4210 
4211     /// @brief create a CBOR serialization of a given JSON value
4212     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4213     static void to_cbor(const basic_json& j, detail::output_adapter<std::uint8_t> o)
4214     {
4215         binary_writer<std::uint8_t>(o).write_cbor(j);
4216     }
4217 
4218     /// @brief create a CBOR serialization of a given JSON value
4219     /// @sa https://json.nlohmann.me/api/basic_json/to_cbor/
4220     static void to_cbor(const basic_json& j, detail::output_adapter<char> o)
4221     {
4222         binary_writer<char>(o).write_cbor(j);
4223     }
4224 
4225     /// @brief create a MessagePack serialization of a given JSON value
4226     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4227     static std::vector<std::uint8_t> to_msgpack(const basic_json& j)
4228     {
4229         std::vector<std::uint8_t> result;
4230         to_msgpack(j, result);
4231         return result;
4232     }
4233 
4234     /// @brief create a MessagePack serialization of a given JSON value
4235     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4236     static void to_msgpack(const basic_json& j, detail::output_adapter<std::uint8_t> o)
4237     {
4238         binary_writer<std::uint8_t>(o).write_msgpack(j);
4239     }
4240 
4241     /// @brief create a MessagePack serialization of a given JSON value
4242     /// @sa https://json.nlohmann.me/api/basic_json/to_msgpack/
4243     static void to_msgpack(const basic_json& j, detail::output_adapter<char> o)
4244     {
4245         binary_writer<char>(o).write_msgpack(j);
4246     }
4247 
4248     /// @brief create a UBJSON serialization of a given JSON value
4249     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4250     static std::vector<std::uint8_t> to_ubjson(const basic_json& j,
4251             const bool use_size = false,
4252             const bool use_type = false)
4253     {
4254         std::vector<std::uint8_t> result;
4255         to_ubjson(j, result, use_size, use_type);
4256         return result;
4257     }
4258 
4259     /// @brief create a UBJSON serialization of a given JSON value
4260     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4261     static void to_ubjson(const basic_json& j, detail::output_adapter<std::uint8_t> o,
4262                           const bool use_size = false, const bool use_type = false)
4263     {
4264         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type);
4265     }
4266 
4267     /// @brief create a UBJSON serialization of a given JSON value
4268     /// @sa https://json.nlohmann.me/api/basic_json/to_ubjson/
4269     static void to_ubjson(const basic_json& j, detail::output_adapter<char> o,
4270                           const bool use_size = false, const bool use_type = false)
4271     {
4272         binary_writer<char>(o).write_ubjson(j, use_size, use_type);
4273     }
4274 
4275     /// @brief create a BJData serialization of a given JSON value
4276     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4277     static std::vector<std::uint8_t> to_bjdata(const basic_json& j,
4278             const bool use_size = false,
4279             const bool use_type = false)
4280     {
4281         std::vector<std::uint8_t> result;
4282         to_bjdata(j, result, use_size, use_type);
4283         return result;
4284     }
4285 
4286     /// @brief create a BJData serialization of a given JSON value
4287     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4288     static void to_bjdata(const basic_json& j, detail::output_adapter<std::uint8_t> o,
4289                           const bool use_size = false, const bool use_type = false)
4290     {
4291         binary_writer<std::uint8_t>(o).write_ubjson(j, use_size, use_type, true, true);
4292     }
4293 
4294     /// @brief create a BJData serialization of a given JSON value
4295     /// @sa https://json.nlohmann.me/api/basic_json/to_bjdata/
4296     static void to_bjdata(const basic_json& j, detail::output_adapter<char> o,
4297                           const bool use_size = false, const bool use_type = false)
4298     {
4299         binary_writer<char>(o).write_ubjson(j, use_size, use_type, true, true);
4300     }
4301 
4302     /// @brief create a BSON serialization of a given JSON value
4303     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4304     static std::vector<std::uint8_t> to_bson(const basic_json& j)
4305     {
4306         std::vector<std::uint8_t> result;
4307         to_bson(j, result);
4308         return result;
4309     }
4310 
4311     /// @brief create a BSON serialization of a given JSON value
4312     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4313     static void to_bson(const basic_json& j, detail::output_adapter<std::uint8_t> o)
4314     {
4315         binary_writer<std::uint8_t>(o).write_bson(j);
4316     }
4317 
4318     /// @brief create a BSON serialization of a given JSON value
4319     /// @sa https://json.nlohmann.me/api/basic_json/to_bson/
4320     static void to_bson(const basic_json& j, detail::output_adapter<char> o)
4321     {
4322         binary_writer<char>(o).write_bson(j);
4323     }
4324 
4325     /// @brief create a JSON value from an input in CBOR format
4326     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
4327     template<typename InputType>
4328     JSON_HEDLEY_WARN_UNUSED_RESULT
4329     static basic_json from_cbor(InputType&& i,
4330                                 const bool strict = true,
4331                                 const bool allow_exceptions = true,
4332                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4333     {
4334         basic_json result;
4335         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4336         auto ia = detail::input_adapter(std::forward<InputType>(i));
4337         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
4338         return res ? result : basic_json(value_t::discarded);
4339     }
4340 
4341     /// @brief create a JSON value from an input in CBOR format
4342     /// @sa https://json.nlohmann.me/api/basic_json/from_cbor/
4343     template<typename IteratorType>
4344     JSON_HEDLEY_WARN_UNUSED_RESULT
4345     static basic_json from_cbor(IteratorType first, IteratorType last,
4346                                 const bool strict = true,
4347                                 const bool allow_exceptions = true,
4348                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4349     {
4350         basic_json result;
4351         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4352         auto ia = detail::input_adapter(std::move(first), std::move(last));
4353         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
4354         return res ? result : basic_json(value_t::discarded);
4355     }
4356 
4357     template<typename T>
4358     JSON_HEDLEY_WARN_UNUSED_RESULT
4359     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
4360     static basic_json from_cbor(const T* ptr, std::size_t len,
4361                                 const bool strict = true,
4362                                 const bool allow_exceptions = true,
4363                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4364     {
4365         return from_cbor(ptr, ptr + len, strict, allow_exceptions, tag_handler);
4366     }
4367 
4368 
4369     JSON_HEDLEY_WARN_UNUSED_RESULT
4370     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_cbor(ptr, ptr + len))
4371     static basic_json from_cbor(detail::span_input_adapter&& i,
4372                                 const bool strict = true,
4373                                 const bool allow_exceptions = true,
4374                                 const cbor_tag_handler_t tag_handler = cbor_tag_handler_t::error)
4375     {
4376         basic_json result;
4377         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4378         auto ia = i.get();
4379         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4380         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::cbor).sax_parse(input_format_t::cbor, &sdp, strict, tag_handler);
4381         return res ? result : basic_json(value_t::discarded);
4382     }
4383 
4384     /// @brief create a JSON value from an input in MessagePack format
4385     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
4386     template<typename InputType>
4387     JSON_HEDLEY_WARN_UNUSED_RESULT
4388     static basic_json from_msgpack(InputType&& i,
4389                                    const bool strict = true,
4390                                    const bool allow_exceptions = true)
4391     {
4392         basic_json result;
4393         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4394         auto ia = detail::input_adapter(std::forward<InputType>(i));
4395         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
4396         return res ? result : basic_json(value_t::discarded);
4397     }
4398 
4399     /// @brief create a JSON value from an input in MessagePack format
4400     /// @sa https://json.nlohmann.me/api/basic_json/from_msgpack/
4401     template<typename IteratorType>
4402     JSON_HEDLEY_WARN_UNUSED_RESULT
4403     static basic_json from_msgpack(IteratorType first, IteratorType last,
4404                                    const bool strict = true,
4405                                    const bool allow_exceptions = true)
4406     {
4407         basic_json result;
4408         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4409         auto ia = detail::input_adapter(std::move(first), std::move(last));
4410         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
4411         return res ? result : basic_json(value_t::discarded);
4412     }
4413 
4414     template<typename T>
4415     JSON_HEDLEY_WARN_UNUSED_RESULT
4416     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
4417     static basic_json from_msgpack(const T* ptr, std::size_t len,
4418                                    const bool strict = true,
4419                                    const bool allow_exceptions = true)
4420     {
4421         return from_msgpack(ptr, ptr + len, strict, allow_exceptions);
4422     }
4423 
4424     JSON_HEDLEY_WARN_UNUSED_RESULT
4425     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_msgpack(ptr, ptr + len))
4426     static basic_json from_msgpack(detail::span_input_adapter&& i,
4427                                    const bool strict = true,
4428                                    const bool allow_exceptions = true)
4429     {
4430         basic_json result;
4431         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4432         auto ia = i.get();
4433         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4434         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::msgpack).sax_parse(input_format_t::msgpack, &sdp, strict);
4435         return res ? result : basic_json(value_t::discarded);
4436     }
4437 
4438     /// @brief create a JSON value from an input in UBJSON format
4439     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
4440     template<typename InputType>
4441     JSON_HEDLEY_WARN_UNUSED_RESULT
4442     static basic_json from_ubjson(InputType&& i,
4443                                   const bool strict = true,
4444                                   const bool allow_exceptions = true)
4445     {
4446         basic_json result;
4447         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4448         auto ia = detail::input_adapter(std::forward<InputType>(i));
4449         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
4450         return res ? result : basic_json(value_t::discarded);
4451     }
4452 
4453     /// @brief create a JSON value from an input in UBJSON format
4454     /// @sa https://json.nlohmann.me/api/basic_json/from_ubjson/
4455     template<typename IteratorType>
4456     JSON_HEDLEY_WARN_UNUSED_RESULT
4457     static basic_json from_ubjson(IteratorType first, IteratorType last,
4458                                   const bool strict = true,
4459                                   const bool allow_exceptions = true)
4460     {
4461         basic_json result;
4462         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4463         auto ia = detail::input_adapter(std::move(first), std::move(last));
4464         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
4465         return res ? result : basic_json(value_t::discarded);
4466     }
4467 
4468     template<typename T>
4469     JSON_HEDLEY_WARN_UNUSED_RESULT
4470     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
4471     static basic_json from_ubjson(const T* ptr, std::size_t len,
4472                                   const bool strict = true,
4473                                   const bool allow_exceptions = true)
4474     {
4475         return from_ubjson(ptr, ptr + len, strict, allow_exceptions);
4476     }
4477 
4478     JSON_HEDLEY_WARN_UNUSED_RESULT
4479     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_ubjson(ptr, ptr + len))
4480     static basic_json from_ubjson(detail::span_input_adapter&& i,
4481                                   const bool strict = true,
4482                                   const bool allow_exceptions = true)
4483     {
4484         basic_json result;
4485         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4486         auto ia = i.get();
4487         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4488         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::ubjson).sax_parse(input_format_t::ubjson, &sdp, strict);
4489         return res ? result : basic_json(value_t::discarded);
4490     }
4491 
4492 
4493     /// @brief create a JSON value from an input in BJData format
4494     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
4495     template<typename InputType>
4496     JSON_HEDLEY_WARN_UNUSED_RESULT
4497     static basic_json from_bjdata(InputType&& i,
4498                                   const bool strict = true,
4499                                   const bool allow_exceptions = true)
4500     {
4501         basic_json result;
4502         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4503         auto ia = detail::input_adapter(std::forward<InputType>(i));
4504         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
4505         return res ? result : basic_json(value_t::discarded);
4506     }
4507 
4508     /// @brief create a JSON value from an input in BJData format
4509     /// @sa https://json.nlohmann.me/api/basic_json/from_bjdata/
4510     template<typename IteratorType>
4511     JSON_HEDLEY_WARN_UNUSED_RESULT
4512     static basic_json from_bjdata(IteratorType first, IteratorType last,
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 = detail::input_adapter(std::move(first), std::move(last));
4519         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bjdata).sax_parse(input_format_t::bjdata, &sdp, strict);
4520         return res ? result : basic_json(value_t::discarded);
4521     }
4522 
4523     /// @brief create a JSON value from an input in BSON format
4524     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
4525     template<typename InputType>
4526     JSON_HEDLEY_WARN_UNUSED_RESULT
4527     static basic_json from_bson(InputType&& i,
4528                                 const bool strict = true,
4529                                 const bool allow_exceptions = true)
4530     {
4531         basic_json result;
4532         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4533         auto ia = detail::input_adapter(std::forward<InputType>(i));
4534         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
4535         return res ? result : basic_json(value_t::discarded);
4536     }
4537 
4538     /// @brief create a JSON value from an input in BSON format
4539     /// @sa https://json.nlohmann.me/api/basic_json/from_bson/
4540     template<typename IteratorType>
4541     JSON_HEDLEY_WARN_UNUSED_RESULT
4542     static basic_json from_bson(IteratorType first, IteratorType last,
4543                                 const bool strict = true,
4544                                 const bool allow_exceptions = true)
4545     {
4546         basic_json result;
4547         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4548         auto ia = detail::input_adapter(std::move(first), std::move(last));
4549         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
4550         return res ? result : basic_json(value_t::discarded);
4551     }
4552 
4553     template<typename T>
4554     JSON_HEDLEY_WARN_UNUSED_RESULT
4555     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
4556     static basic_json from_bson(const T* ptr, std::size_t len,
4557                                 const bool strict = true,
4558                                 const bool allow_exceptions = true)
4559     {
4560         return from_bson(ptr, ptr + len, strict, allow_exceptions);
4561     }
4562 
4563     JSON_HEDLEY_WARN_UNUSED_RESULT
4564     JSON_HEDLEY_DEPRECATED_FOR(3.8.0, from_bson(ptr, ptr + len))
4565     static basic_json from_bson(detail::span_input_adapter&& i,
4566                                 const bool strict = true,
4567                                 const bool allow_exceptions = true)
4568     {
4569         basic_json result;
4570         detail::json_sax_dom_parser<basic_json> sdp(result, allow_exceptions);
4571         auto ia = i.get();
4572         // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg)
4573         const bool res = binary_reader<decltype(ia)>(std::move(ia), input_format_t::bson).sax_parse(input_format_t::bson, &sdp, strict);
4574         return res ? result : basic_json(value_t::discarded);
4575     }
4576     /// @}
4577 
4578     //////////////////////////
4579     // JSON Pointer support //
4580     //////////////////////////
4581 
4582     /// @name JSON Pointer functions
4583     /// @{
4584 
4585     /// @brief access specified element via JSON Pointer
4586     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
4587     reference operator[](const json_pointer& ptr)
4588     {
4589         return ptr.get_unchecked(this);
4590     }
4591 
4592     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4593     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4594     reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr)
4595     {
4596         return ptr.get_unchecked(this);
4597     }
4598 
4599     /// @brief access specified element via JSON Pointer
4600     /// @sa https://json.nlohmann.me/api/basic_json/operator%5B%5D/
4601     const_reference operator[](const json_pointer& ptr) const
4602     {
4603         return ptr.get_unchecked(this);
4604     }
4605 
4606     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4607     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4608     const_reference operator[](const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
4609     {
4610         return ptr.get_unchecked(this);
4611     }
4612 
4613     /// @brief access specified element via JSON Pointer
4614     /// @sa https://json.nlohmann.me/api/basic_json/at/
4615     reference at(const json_pointer& ptr)
4616     {
4617         return ptr.get_checked(this);
4618     }
4619 
4620     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4621     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4622     reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr)
4623     {
4624         return ptr.get_checked(this);
4625     }
4626 
4627     /// @brief access specified element via JSON Pointer
4628     /// @sa https://json.nlohmann.me/api/basic_json/at/
4629     const_reference at(const json_pointer& ptr) const
4630     {
4631         return ptr.get_checked(this);
4632     }
4633 
4634     template<typename BasicJsonType, detail::enable_if_t<detail::is_basic_json<BasicJsonType>::value, int> = 0>
4635     JSON_HEDLEY_DEPRECATED_FOR(3.11.0, basic_json::json_pointer or nlohmann::json_pointer<basic_json::string_t>) // NOLINT(readability/alt_tokens)
4636     const_reference at(const ::nlohmann::json_pointer<BasicJsonType>& ptr) const
4637     {
4638         return ptr.get_checked(this);
4639     }
4640 
4641     /// @brief return flattened JSON value
4642     /// @sa https://json.nlohmann.me/api/basic_json/flatten/
4643     basic_json flatten() const
4644     {
4645         basic_json result(value_t::object);
4646         json_pointer::flatten("", *this, result);
4647         return result;
4648     }
4649 
4650     /// @brief unflatten a previously flattened JSON value
4651     /// @sa https://json.nlohmann.me/api/basic_json/unflatten/
4652     basic_json unflatten() const
4653     {
4654         return json_pointer::unflatten(*this);
4655     }
4656 
4657     /// @}
4658 
4659     //////////////////////////
4660     // JSON Patch functions //
4661     //////////////////////////
4662 
4663     /// @name JSON Patch functions
4664     /// @{
4665 
4666     /// @brief applies a JSON patch in-place without copying the object
4667     /// @sa https://json.nlohmann.me/api/basic_json/patch/
4668     void patch_inplace(const basic_json& json_patch)
4669     {
4670         basic_json& result = *this;
4671         // the valid JSON Patch operations
4672         enum class patch_operations {add, remove, replace, move, copy, test, invalid};
4673 
4674         const auto get_op = [](const std::string & op)
4675         {
4676             if (op == "add")
4677             {
4678                 return patch_operations::add;
4679             }
4680             if (op == "remove")
4681             {
4682                 return patch_operations::remove;
4683             }
4684             if (op == "replace")
4685             {
4686                 return patch_operations::replace;
4687             }
4688             if (op == "move")
4689             {
4690                 return patch_operations::move;
4691             }
4692             if (op == "copy")
4693             {
4694                 return patch_operations::copy;
4695             }
4696             if (op == "test")
4697             {
4698                 return patch_operations::test;
4699             }
4700 
4701             return patch_operations::invalid;
4702         };
4703 
4704         // wrapper for "add" operation; add value at ptr
4705         const auto operation_add = [&result](json_pointer & ptr, basic_json val)
4706         {
4707             // adding to the root of the target document means replacing it
4708             if (ptr.empty())
4709             {
4710                 result = val;
4711                 return;
4712             }
4713 
4714             // make sure the top element of the pointer exists
4715             json_pointer top_pointer = ptr.top();
4716             if (top_pointer != ptr)
4717             {
4718                 result.at(top_pointer);
4719             }
4720 
4721             // get reference to parent of JSON pointer ptr
4722             const auto last_path = ptr.back();
4723             ptr.pop_back();
4724             // parent must exist when performing patch add per RFC6902 specs
4725             basic_json& parent = result.at(ptr);
4726 
4727             switch (parent.m_type)
4728             {
4729                 case value_t::null:
4730                 case value_t::object:
4731                 {
4732                     // use operator[] to add value
4733                     parent[last_path] = val;
4734                     break;
4735                 }
4736 
4737                 case value_t::array:
4738                 {
4739                     if (last_path == "-")
4740                     {
4741                         // special case: append to back
4742                         parent.push_back(val);
4743                     }
4744                     else
4745                     {
4746                         const auto idx = json_pointer::template array_index<basic_json_t>(last_path);
4747                         if (JSON_HEDLEY_UNLIKELY(idx > parent.size()))
4748                         {
4749                             // avoid undefined behavior
4750                             JSON_THROW(out_of_range::create(401, detail::concat("array index ", std::to_string(idx), " is out of range"), &parent));
4751                         }
4752 
4753                         // default case: insert add offset
4754                         parent.insert(parent.begin() + static_cast<difference_type>(idx), val);
4755                     }
4756                     break;
4757                 }
4758 
4759                 // if there exists a parent it cannot be primitive
4760                 case value_t::string: // LCOV_EXCL_LINE
4761                 case value_t::boolean: // LCOV_EXCL_LINE
4762                 case value_t::number_integer: // LCOV_EXCL_LINE
4763                 case value_t::number_unsigned: // LCOV_EXCL_LINE
4764                 case value_t::number_float: // LCOV_EXCL_LINE
4765                 case value_t::binary: // LCOV_EXCL_LINE
4766                 case value_t::discarded: // LCOV_EXCL_LINE
4767                 default:            // LCOV_EXCL_LINE
4768                     JSON_ASSERT(false); // NOLINT(cert-dcl03-c,hicpp-static-assert,misc-static-assert) LCOV_EXCL_LINE
4769             }
4770         };
4771 
4772         // wrapper for "remove" operation; remove value at ptr
4773         const auto operation_remove = [this, &result](json_pointer & ptr)
4774         {
4775             // get reference to parent of JSON pointer ptr
4776             const auto last_path = ptr.back();
4777             ptr.pop_back();
4778             basic_json& parent = result.at(ptr);
4779 
4780             // remove child
4781             if (parent.is_object())
4782             {
4783                 // perform range check
4784                 auto it = parent.find(last_path);
4785                 if (JSON_HEDLEY_LIKELY(it != parent.end()))
4786                 {
4787                     parent.erase(it);
4788                 }
4789                 else
4790                 {
4791                     JSON_THROW(out_of_range::create(403, detail::concat("key '", last_path, "' not found"), this));
4792                 }
4793             }
4794             else if (parent.is_array())
4795             {
4796                 // note erase performs range check
4797                 parent.erase(json_pointer::template array_index<basic_json_t>(last_path));
4798             }
4799         };
4800 
4801         // type check: top level value must be an array
4802         if (JSON_HEDLEY_UNLIKELY(!json_patch.is_array()))
4803         {
4804             JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &json_patch));
4805         }
4806 
4807         // iterate and apply the operations
4808         for (const auto& val : json_patch)
4809         {
4810             // wrapper to get a value for an operation
4811             const auto get_value = [&val](const std::string & op,
4812                                           const std::string & member,
4813                                           bool string_type) -> basic_json &
4814             {
4815                 // find value
4816                 auto it = val.m_value.object->find(member);
4817 
4818                 // context-sensitive error message
4819                 const auto error_msg = (op == "op") ? "operation" : detail::concat("operation '", op, '\'');
4820 
4821                 // check if desired value is present
4822                 if (JSON_HEDLEY_UNLIKELY(it == val.m_value.object->end()))
4823                 {
4824                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
4825                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have member '", member, "'"), &val));
4826                 }
4827 
4828                 // check if result is of type string
4829                 if (JSON_HEDLEY_UNLIKELY(string_type && !it->second.is_string()))
4830                 {
4831                     // NOLINTNEXTLINE(performance-inefficient-string-concatenation)
4832                     JSON_THROW(parse_error::create(105, 0, detail::concat(error_msg, " must have string member '", member, "'"), &val));
4833                 }
4834 
4835                 // no error: return value
4836                 return it->second;
4837             };
4838 
4839             // type check: every element of the array must be an object
4840             if (JSON_HEDLEY_UNLIKELY(!val.is_object()))
4841             {
4842                 JSON_THROW(parse_error::create(104, 0, "JSON patch must be an array of objects", &val));
4843             }
4844 
4845             // collect mandatory members
4846             const auto op = get_value("op", "op", true).template get<std::string>();
4847             const auto path = get_value(op, "path", true).template get<std::string>();
4848             json_pointer ptr(path);
4849 
4850             switch (get_op(op))
4851             {
4852                 case patch_operations::add:
4853                 {
4854                     operation_add(ptr, get_value("add", "value", false));
4855                     break;
4856                 }
4857 
4858                 case patch_operations::remove:
4859                 {
4860                     operation_remove(ptr);
4861                     break;
4862                 }
4863 
4864                 case patch_operations::replace:
4865                 {
4866                     // the "path" location must exist - use at()
4867                     result.at(ptr) = get_value("replace", "value", false);
4868                     break;
4869                 }
4870 
4871                 case patch_operations::move:
4872                 {
4873                     const auto from_path = get_value("move", "from", true).template get<std::string>();
4874                     json_pointer from_ptr(from_path);
4875 
4876                     // the "from" location must exist - use at()
4877                     basic_json v = result.at(from_ptr);
4878 
4879                     // The move operation is functionally identical to a
4880                     // "remove" operation on the "from" location, followed
4881                     // immediately by an "add" operation at the target
4882                     // location with the value that was just removed.
4883                     operation_remove(from_ptr);
4884                     operation_add(ptr, v);
4885                     break;
4886                 }
4887 
4888                 case patch_operations::copy:
4889                 {
4890                     const auto from_path = get_value("copy", "from", true).template get<std::string>();
4891                     const json_pointer from_ptr(from_path);
4892 
4893                     // the "from" location must exist - use at()
4894                     basic_json v = result.at(from_ptr);
4895 
4896                     // The copy is functionally identical to an "add"
4897                     // operation at the target location using the value
4898                     // specified in the "from" member.
4899                     operation_add(ptr, v);
4900                     break;
4901                 }
4902 
4903                 case patch_operations::test:
4904                 {
4905                     bool success = false;
4906                     JSON_TRY
4907                     {
4908                         // check if "value" matches the one at "path"
4909                         // the "path" location must exist - use at()
4910                         success = (result.at(ptr) == get_value("test", "value", false));
4911                     }
JSON_INTERNAL_CATCH(out_of_range&)4912                     JSON_INTERNAL_CATCH (out_of_range&)
4913                     {
4914                         // ignore out of range errors: success remains false
4915                     }
4916 
4917                     // throw an exception if test fails
4918                     if (JSON_HEDLEY_UNLIKELY(!success))
4919                     {
4920                         JSON_THROW(other_error::create(501, detail::concat("unsuccessful: ", val.dump()), &val));
4921                     }
4922 
4923                     break;
4924                 }
4925 
4926                 case patch_operations::invalid:
4927                 default:
4928                 {
4929                     // op must be "add", "remove", "replace", "move", "copy", or
4930                     // "test"
4931                     JSON_THROW(parse_error::create(105, 0, detail::concat("operation value '", op, "' is invalid"), &val));
4932                 }
4933             }
4934         }
4935     }
4936 
4937     /// @brief applies a JSON patch to a copy of the current object
4938     /// @sa https://json.nlohmann.me/api/basic_json/patch/
4939     basic_json patch(const basic_json& json_patch) const
4940     {
4941         basic_json result = *this;
4942         result.patch_inplace(json_patch);
4943         return result;
4944     }
4945 
4946     /// @brief creates a diff as a JSON patch
4947     /// @sa https://json.nlohmann.me/api/basic_json/diff/
4948     JSON_HEDLEY_WARN_UNUSED_RESULT
4949     static basic_json diff(const basic_json& source, const basic_json& target,
4950                            const std::string& path = "")
4951     {
4952         // the patch
4953         basic_json result(value_t::array);
4954 
4955         // if the values are the same, return empty patch
4956         if (source == target)
4957         {
4958             return result;
4959         }
4960 
4961         if (source.type() != target.type())
4962         {
4963             // different types: replace value
4964             result.push_back(
4965             {
4966                 {"op", "replace"}, {"path", path}, {"value", target}
4967             });
4968             return result;
4969         }
4970 
4971         switch (source.type())
4972         {
4973             case value_t::array:
4974             {
4975                 // first pass: traverse common elements
4976                 std::size_t i = 0;
4977                 while (i < source.size() && i < target.size())
4978                 {
4979                     // recursive call to compare array values at index i
4980                     auto temp_diff = diff(source[i], target[i], detail::concat(path, '/', std::to_string(i)));
4981                     result.insert(result.end(), temp_diff.begin(), temp_diff.end());
4982                     ++i;
4983                 }
4984 
4985                 // We now reached the end of at least one array
4986                 // in a second pass, traverse the remaining elements
4987 
4988                 // remove my remaining elements
4989                 const auto end_index = static_cast<difference_type>(result.size());
4990                 while (i < source.size())
4991                 {
4992                     // add operations in reverse order to avoid invalid
4993                     // indices
4994                     result.insert(result.begin() + end_index, object(
4995                     {
4996                         {"op", "remove"},
4997                         {"path", detail::concat(path, '/', std::to_string(i))}
4998                     }));
4999                     ++i;
5000                 }
5001 
5002                 // add other remaining elements
5003                 while (i < target.size())
5004                 {
5005                     result.push_back(
5006                     {
5007                         {"op", "add"},
5008                         {"path", detail::concat(path, "/-")},
5009                         {"value", target[i]}
5010                     });
5011                     ++i;
5012                 }
5013 
5014                 break;
5015             }
5016 
5017             case value_t::object:
5018             {
5019                 // first pass: traverse this object's elements
5020                 for (auto it = source.cbegin(); it != source.cend(); ++it)
5021                 {
5022                     // escape the key name to be used in a JSON patch
5023                     const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
5024 
5025                     if (target.find(it.key()) != target.end())
5026                     {
5027                         // recursive call to compare object values at key it
5028                         auto temp_diff = diff(it.value(), target[it.key()], path_key);
5029                         result.insert(result.end(), temp_diff.begin(), temp_diff.end());
5030                     }
5031                     else
5032                     {
5033                         // found a key that is not in o -> remove it
5034                         result.push_back(object(
5035                         {
5036                             {"op", "remove"}, {"path", path_key}
5037                         }));
5038                     }
5039                 }
5040 
5041                 // second pass: traverse other object's elements
5042                 for (auto it = target.cbegin(); it != target.cend(); ++it)
5043                 {
5044                     if (source.find(it.key()) == source.end())
5045                     {
5046                         // found a key that is not in this -> add it
5047                         const auto path_key = detail::concat(path, '/', detail::escape(it.key()));
5048                         result.push_back(
5049                         {
5050                             {"op", "add"}, {"path", path_key},
5051                             {"value", it.value()}
5052                         });
5053                     }
5054                 }
5055 
5056                 break;
5057             }
5058 
5059             case value_t::null:
5060             case value_t::string:
5061             case value_t::boolean:
5062             case value_t::number_integer:
5063             case value_t::number_unsigned:
5064             case value_t::number_float:
5065             case value_t::binary:
5066             case value_t::discarded:
5067             default:
5068             {
5069                 // both primitive type: replace value
5070                 result.push_back(
5071                 {
5072                     {"op", "replace"}, {"path", path}, {"value", target}
5073                 });
5074                 break;
5075             }
5076         }
5077 
5078         return result;
5079     }
5080     /// @}
5081 
5082     ////////////////////////////////
5083     // JSON Merge Patch functions //
5084     ////////////////////////////////
5085 
5086     /// @name JSON Merge Patch functions
5087     /// @{
5088 
5089     /// @brief applies a JSON Merge Patch
5090     /// @sa https://json.nlohmann.me/api/basic_json/merge_patch/
5091     void merge_patch(const basic_json& apply_patch)
5092     {
5093         if (apply_patch.is_object())
5094         {
5095             if (!is_object())
5096             {
5097                 *this = object();
5098             }
5099             for (auto it = apply_patch.begin(); it != apply_patch.end(); ++it)
5100             {
5101                 if (it.value().is_null())
5102                 {
5103                     erase(it.key());
5104                 }
5105                 else
5106                 {
5107                     operator[](it.key()).merge_patch(it.value());
5108                 }
5109             }
5110         }
5111         else
5112         {
5113             *this = apply_patch;
5114         }
5115     }
5116 
5117     /// @}
5118 };
5119 
5120 /// @brief user-defined to_string function for JSON values
5121 /// @sa https://json.nlohmann.me/api/basic_json/to_string/
5122 NLOHMANN_BASIC_JSON_TPL_DECLARATION
5123 std::string to_string(const NLOHMANN_BASIC_JSON_TPL& j)
5124 {
5125     return j.dump();
5126 }
5127 
5128 inline namespace literals
5129 {
5130 inline namespace json_literals
5131 {
5132 
5133 /// @brief user-defined string literal for JSON values
5134 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json/
5135 JSON_HEDLEY_NON_NULL(1)
5136 inline nlohmann::json operator "" _json(const char* s, std::size_t n)
5137 {
5138     return nlohmann::json::parse(s, s + n);
5139 }
5140 
5141 /// @brief user-defined string literal for JSON pointer
5142 /// @sa https://json.nlohmann.me/api/basic_json/operator_literal_json_pointer/
5143 JSON_HEDLEY_NON_NULL(1)
5144 inline nlohmann::json::json_pointer operator "" _json_pointer(const char* s, std::size_t n)
5145 {
5146     return nlohmann::json::json_pointer(std::string(s, n));
5147 }
5148 
5149 }  // namespace json_literals
5150 }  // namespace literals
5151 NLOHMANN_JSON_NAMESPACE_END
5152 
5153 ///////////////////////
5154 // nonmember support //
5155 ///////////////////////
5156 
5157 namespace std // NOLINT(cert-dcl58-cpp)
5158 {
5159 
5160 /// @brief hash value for JSON objects
5161 /// @sa https://json.nlohmann.me/api/basic_json/std_hash/
5162 NLOHMANN_BASIC_JSON_TPL_DECLARATION
5163 struct hash<nlohmann::NLOHMANN_BASIC_JSON_TPL>
5164 {
5165     std::size_t operator()(const nlohmann::NLOHMANN_BASIC_JSON_TPL& j) const
5166     {
5167         return nlohmann::detail::hash(j);
5168     }
5169 };
5170 
5171 // specialization for std::less<value_t>
5172 template<>
5173 struct less< ::nlohmann::detail::value_t> // do not remove the space after '<', see https://github.com/nlohmann/json/pull/679
5174 {
5175     /*!
5176     @brief compare two value_t enum values
5177     @since version 3.0.0
5178     */
5179     bool operator()(::nlohmann::detail::value_t lhs,
5180                     ::nlohmann::detail::value_t rhs) const noexcept
5181     {
5182 #if JSON_HAS_THREE_WAY_COMPARISON
5183         return std::is_lt(lhs <=> rhs); // *NOPAD*
5184 #else
5185         return ::nlohmann::detail::operator<(lhs, rhs);
5186 #endif
5187     }
5188 };
5189 
5190 // C++20 prohibit function specialization in the std namespace.
5191 #ifndef JSON_HAS_CPP_20
5192 
5193 /// @brief exchanges the values of two JSON objects
5194 /// @sa https://json.nlohmann.me/api/basic_json/std_swap/
5195 NLOHMANN_BASIC_JSON_TPL_DECLARATION
5196 inline void swap(nlohmann::NLOHMANN_BASIC_JSON_TPL& j1, nlohmann::NLOHMANN_BASIC_JSON_TPL& j2) noexcept(  // NOLINT(readability-inconsistent-declaration-parameter-name)
5197     is_nothrow_move_constructible<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value&&                          // NOLINT(misc-redundant-expression)
5198     is_nothrow_move_assignable<nlohmann::NLOHMANN_BASIC_JSON_TPL>::value)
5199 {
5200     j1.swap(j2);
5201 }
5202 
5203 #endif
5204 
5205 }  // namespace std
5206 
5207 #if JSON_USE_GLOBAL_UDLS
5208     using nlohmann::literals::json_literals::operator "" _json; // NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5209     using nlohmann::literals::json_literals::operator "" _json_pointer; //NOLINT(misc-unused-using-decls,google-global-names-in-headers)
5210 #endif
5211 
5212 #include <nlohmann/detail/macro_unscope.hpp>
5213 
5214 #endif  // INCLUDE_NLOHMANN_JSON_HPP_
5215