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