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