]> git.proxmox.com Git - ceph.git/blob - ceph/src/boost/boost/json/value.hpp
import quincy beta 17.1.0
[ceph.git] / ceph / src / boost / boost / json / value.hpp
1 //
2 // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 //
5 // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 //
8 // Official repository: https://github.com/boostorg/json
9 //
10
11 #ifndef BOOST_JSON_VALUE_HPP
12 #define BOOST_JSON_VALUE_HPP
13
14 #include <boost/json/detail/config.hpp>
15 #include <boost/json/array.hpp>
16 #include <boost/json/kind.hpp>
17 #include <boost/json/object.hpp>
18 #include <boost/json/pilfer.hpp>
19 #include <boost/json/storage_ptr.hpp>
20 #include <boost/json/string.hpp>
21 #include <boost/json/string_view.hpp>
22 #include <boost/json/value_ref.hpp>
23 #include <boost/json/detail/except.hpp>
24 #include <boost/json/detail/value.hpp>
25 #include <cstdlib>
26 #include <cstring>
27 #include <initializer_list>
28 #include <iosfwd>
29 #include <limits>
30 #include <new>
31 #include <type_traits>
32 #include <utility>
33
34 BOOST_JSON_NS_BEGIN
35
36 //----------------------------------------------------------
37
38 /** The type used to represent any JSON value
39
40 This is a
41 <a href="https://en.cppreference.com/w/cpp/concepts/regular"><em>Regular</em></a>.
42 <em>Regular</em>
43 type which works like
44 a variant of the basic JSON data types: array,
45 object, string, number, boolean, and null.
46
47 @par Thread Safety
48
49 Distinct instances may be accessed concurrently.
50 Non-const member functions of a shared instance
51 may not be called concurrently with any other
52 member functions of that instance.
53 */
54 class value
55 {
56 #ifndef BOOST_JSON_DOCS
57 using scalar = detail::scalar;
58
59 union
60 {
61 storage_ptr sp_; // must come first
62 array arr_;
63 object obj_;
64 string str_;
65 scalar sca_;
66 };
67 #endif
68
69 struct init_iter;
70
71 #ifndef BOOST_JSON_DOCS
72 // VFALCO doc toolchain incorrectly treats this as public
73 friend struct detail::access;
74 #endif
75
76 explicit
77 value(
78 detail::unchecked_array&& ua)
79 : arr_(std::move(ua))
80 {
81 }
82
83 explicit
84 value(
85 detail::unchecked_object&& uo)
86 : obj_(std::move(uo))
87 {
88 }
89
90 value(
91 detail::key_t const&,
92 string_view s,
93 storage_ptr sp)
94 : str_(detail::key_t{}, s, std::move(sp))
95 {
96 }
97
98 value(
99 detail::key_t const&,
100 string_view s1,
101 string_view s2,
102 storage_ptr sp)
103 : str_(detail::key_t{}, s1, s2, std::move(sp))
104 {
105 }
106
107 inline bool is_scalar() const noexcept
108 {
109 return sca_.k < json::kind::string;
110 }
111
112 public:
113 /** The type of _Allocator_ returned by @ref get_allocator
114
115 This type is a @ref polymorphic_allocator.
116 */
117 #ifdef BOOST_JSON_DOCS
118 // VFALCO doc toolchain renders this incorrectly
119 using allocator_type = __see_below__;
120 #else
121 using allocator_type = polymorphic_allocator<value>;
122 #endif
123
124 /** Destructor.
125
126 The value and all of its contents are destroyed.
127 Any dynamically allocated memory that was allocated
128 internally is freed.
129
130 @par Complexity
131 Constant, or linear in size for array or object.
132
133 @par Exception Safety
134 No-throw guarantee.
135 */
136 BOOST_JSON_DECL
137 ~value();
138
139 /** Default constructor.
140
141 The constructed value is null,
142 using the default memory resource.
143
144 @par Complexity
145 Constant.
146
147 @par Exception Safety
148 No-throw guarantee.
149 */
150 value() noexcept
151 : sca_()
152 {
153 }
154
155 /** Constructor.
156
157 The constructed value is null,
158 using the specified @ref memory_resource.
159
160 @par Complexity
161 Constant.
162
163 @par Exception Safety
164 No-throw guarantee.
165
166 @param sp A pointer to the @ref memory_resource
167 to use. The container will acquire shared
168 ownership of the memory resource.
169 */
170 explicit
171 value(storage_ptr sp) noexcept
172 : sca_(std::move(sp))
173 {
174 }
175
176 /** Pilfer constructor.
177
178 The value is constructed by acquiring ownership
179 of the contents of `other` using pilfer semantics.
180 This is more efficient than move construction, when
181 it is known that the moved-from object will be
182 immediately destroyed afterwards.
183
184 @par Complexity
185 Constant.
186
187 @par Exception Safety
188 No-throw guarantee.
189
190 @param other The value to pilfer. After pilfer
191 construction, `other` is not in a usable state
192 and may only be destroyed.
193
194 @see @ref pilfer,
195 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
196 Valueless Variants Considered Harmful</a>
197 */
198 value(pilfered<value> other) noexcept
199 {
200 relocate(this, other.get());
201 ::new(&other.get().sca_) scalar();
202 }
203
204 /** Copy constructor.
205
206 The value is constructed with a copy of the
207 contents of `other`, using the same
208 memory resource as `other`.
209
210 @par Complexity
211 Linear in the size of `other`.
212
213 @par Exception Safety
214 Strong guarantee.
215 Calls to `memory_resource::allocate` may throw.
216
217 @param other The value to copy.
218 */
219 value(value const& other)
220 : value(other, other.storage())
221 {
222 }
223
224 /** Copy constructor
225
226 The value is constructed with a copy of the
227 contents of `other`, using the
228 specified memory resource.
229
230 @par Complexity
231 Linear in the size of `other`.
232
233 @par Exception Safety
234 Strong guarantee.
235 Calls to `memory_resource::allocate` may throw.
236
237 @param other The value to copy.
238
239 @param sp A pointer to the @ref memory_resource
240 to use. The container will acquire shared
241 ownership of the memory resource.
242 */
243 BOOST_JSON_DECL
244 value(
245 value const& other,
246 storage_ptr sp);
247
248 /** Move constructor
249
250 The value is constructed by acquiring ownership of
251 the contents of `other` and shared ownership of
252 `other`'s memory resource.
253
254 @note
255
256 After construction, the moved-from value becomes a
257 null value with its current storage pointer.
258
259 @par Complexity
260 Constant.
261
262 @par Exception Safety
263 No-throw guarantee.
264
265 @param other The value to move.
266 */
267 BOOST_JSON_DECL
268 value(value&& other) noexcept;
269
270 /** Move constructor
271
272 The value is constructed with the contents of
273 `other` by move semantics, using the specified
274 memory resource:
275
276 @li If `*other.storage() == *sp`, ownership of
277 the underlying memory is transferred in constant
278 time, with no possibility of exceptions.
279 After construction, the moved-from value becomes
280 a null value with its current storage pointer.
281
282 @li If `*other.storage() != *sp`, an
283 element-wise copy is performed if
284 `other.is_structured() == true`, which may throw.
285 In this case, the moved-from value is not
286 changed.
287
288 @par Complexity
289 Constant or linear in the size of `other`.
290
291 @par Exception Safety
292 Strong guarantee.
293 Calls to `memory_resource::allocate` may throw.
294
295 @param other The value to move.
296
297 @param sp A pointer to the @ref memory_resource
298 to use. The container will acquire shared
299 ownership of the memory resource.
300 */
301 BOOST_JSON_DECL
302 value(
303 value&& other,
304 storage_ptr sp);
305
306 //------------------------------------------------------
307 //
308 // Conversion
309 //
310 //------------------------------------------------------
311
312 /** Construct a null.
313
314 A null value is a monostate.
315
316 @par Complexity
317 Constant.
318
319 @par Exception Safety
320 No-throw guarantee.
321
322 @param sp A pointer to the @ref memory_resource
323 to use. The container will acquire shared
324 ownership of the memory resource.
325 */
326 value(
327 std::nullptr_t,
328 storage_ptr sp = {}) noexcept
329 : sca_(std::move(sp))
330 {
331 }
332
333 /** Construct a bool.
334
335 This constructs a `bool` value using
336 the specified memory resource.
337
338 @par Complexity
339 Constant.
340
341 @par Exception Safety
342 No-throw guarantee.
343
344 @param b The initial value.
345
346 @param sp A pointer to the @ref memory_resource
347 to use. The container will acquire shared
348 ownership of the memory resource.
349 */
350 #ifdef BOOST_JSON_DOCS
351 value(
352 bool b,
353 storage_ptr sp = {}) noexcept;
354 #else
355 template<class Bool
356 ,class = typename std::enable_if<
357 std::is_same<Bool, bool>::value>::type
358 >
359 value(
360 Bool b,
361 storage_ptr sp = {}) noexcept
362 : sca_(b, std::move(sp))
363 {
364 }
365 #endif
366
367 /** Construct a `std::int64_t`.
368
369 @par Complexity
370 Constant.
371
372 @par Exception Safety
373 No-throw guarantee.
374
375 @param i The initial value.
376
377 @param sp A pointer to the @ref memory_resource
378 to use. The container will acquire shared
379 ownership of the memory resource.
380 */
381 value(
382 signed char i,
383 storage_ptr sp = {}) noexcept
384 : sca_(static_cast<std::int64_t>(
385 i), std::move(sp))
386 {
387 }
388
389 /** Construct a `std::int64_t`.
390
391 @par Complexity
392 Constant.
393
394 @par Exception Safety
395 No-throw guarantee.
396
397 @param i The initial value.
398
399 @param sp A pointer to the @ref memory_resource
400 to use. The container will acquire shared
401 ownership of the memory resource.
402 */
403 value(
404 short i,
405 storage_ptr sp = {}) noexcept
406 : sca_(static_cast<std::int64_t>(
407 i), std::move(sp))
408 {
409 }
410
411 /** Construct a `std::int64_t`.
412
413 @par Complexity
414 Constant.
415
416 @par Exception Safety
417 No-throw guarantee.
418
419 @param i The initial value.
420
421 @param sp A pointer to the @ref memory_resource
422 to use. The container will acquire shared
423 ownership of the memory resource.
424 */
425 value(
426 int i,
427 storage_ptr sp = {}) noexcept
428 : sca_(static_cast<std::int64_t>(i),
429 std::move(sp))
430 {
431 }
432
433 /** Construct a `std::int64_t`.
434
435 @par Complexity
436 Constant.
437
438 @par Exception Safety
439 No-throw guarantee.
440
441 @param i The initial value.
442
443 @param sp A pointer to the @ref memory_resource
444 to use. The container will acquire shared
445 ownership of the memory resource.
446 */
447 value(
448 long i,
449 storage_ptr sp = {}) noexcept
450 : sca_(static_cast<std::int64_t>(i),
451 std::move(sp))
452 {
453 }
454
455 /** Construct a `std::int64_t`.
456
457 @par Complexity
458 Constant.
459
460 @par Exception Safety
461 No-throw guarantee.
462
463 @param i The initial value.
464
465 @param sp A pointer to the @ref memory_resource
466 to use. The container will acquire shared
467 ownership of the memory resource.
468 */
469 value(
470 long long i,
471 storage_ptr sp = {}) noexcept
472 : sca_(static_cast<std::int64_t>(i),
473 std::move(sp))
474 {
475 }
476
477 /** Construct a `std::uint64_t`.
478
479 @par Complexity
480 Constant.
481
482 @par Exception Safety
483 No-throw guarantee.
484
485 @param u The initial value.
486
487 @param sp A pointer to the @ref memory_resource
488 to use. The container will acquire shared
489 ownership of the memory resource.
490 */
491 value(
492 unsigned char u,
493 storage_ptr sp = {}) noexcept
494 : sca_(static_cast<std::uint64_t>(
495 u), std::move(sp))
496 {
497 }
498
499 /** Construct a `std::uint64_t`.
500
501 @par Complexity
502 Constant.
503
504 @par Exception Safety
505 No-throw guarantee.
506
507 @param u The initial value.
508
509 @param sp A pointer to the @ref memory_resource
510 to use. The container will acquire shared
511 ownership of the memory resource.
512 */
513 value(
514 unsigned short u,
515 storage_ptr sp = {}) noexcept
516 : sca_(static_cast<std::uint64_t>(u),
517 std::move(sp))
518 {
519 }
520
521 /** Construct a `std::uint64_t`.
522
523 @par Complexity
524 Constant.
525
526 @par Exception Safety
527 No-throw guarantee.
528
529 @param u The initial value.
530
531 @param sp A pointer to the @ref memory_resource
532 to use. The container will acquire shared
533 ownership of the memory resource.
534 */
535 value(
536 unsigned int u,
537 storage_ptr sp = {}) noexcept
538 : sca_(static_cast<std::uint64_t>(u),
539 std::move(sp))
540 {
541 }
542
543 /** Construct a `std::uint64_t`.
544
545 @par Complexity
546 Constant.
547
548 @par Exception Safety
549 No-throw guarantee.
550
551 @param u The initial value.
552
553 @param sp A pointer to the @ref memory_resource
554 to use. The container will acquire shared
555 ownership of the memory resource.
556 */
557 value(
558 unsigned long u,
559 storage_ptr sp = {}) noexcept
560 : sca_(static_cast<std::uint64_t>(u),
561 std::move(sp))
562 {
563 }
564
565 /** Construct a `std::uint64_t`.
566
567 @par Complexity
568 Constant.
569
570 @par Exception Safety
571 No-throw guarantee.
572
573 @param u The initial value.
574
575 @param sp A pointer to the @ref memory_resource
576 to use. The container will acquire shared
577 ownership of the memory resource.
578 */
579 value(
580 unsigned long long u,
581 storage_ptr sp = {}) noexcept
582 : sca_(static_cast<std::uint64_t>(u),
583 std::move(sp))
584 {
585 }
586
587 /** Construct a `double`.
588
589 @par Complexity
590 Constant.
591
592 @par Exception Safety
593 No-throw guarantee.
594
595 @param d The initial value.
596
597 @param sp A pointer to the @ref memory_resource
598 to use. The container will acquire shared
599 ownership of the memory resource.
600 */
601 value(
602 double d,
603 storage_ptr sp = {}) noexcept
604 : sca_(d, std::move(sp))
605 {
606 }
607
608 /** Construct a @ref string.
609
610 The string is constructed with a copy of the
611 string view `s`, using the specified memory resource.
612
613 @par Complexity
614 Linear in `s.size()`.
615
616 @par Exception Safety
617 Strong guarantee.
618 Calls to `memory_resource::allocate` may throw.
619
620 @param s The string view to construct with.
621
622 @param sp A pointer to the @ref memory_resource
623 to use. The container will acquire shared
624 ownership of the memory resource.
625 */
626 value(
627 string_view s,
628 storage_ptr sp = {})
629 : str_(s, std::move(sp))
630 {
631 }
632
633 /** Construct a @ref string.
634
635 The string is constructed with a copy of the
636 null-terminated string `s`, using the specified
637 memory resource.
638
639 @par Complexity
640 Linear in `std::strlen(s)`.
641
642 @par Exception Safety
643 Strong guarantee.
644 Calls to `memory_resource::allocate` may throw.
645
646 @param s The null-terminated string to construct
647 with.
648
649 @param sp A pointer to the @ref memory_resource
650 to use. The container will acquire shared
651 ownership of the memory resource.
652 */
653 value(
654 char const* s,
655 storage_ptr sp = {})
656 : str_(s, std::move(sp))
657 {
658 }
659
660 /** Construct a @ref string.
661
662 The value is constructed from `other`, using the
663 same memory resource. To transfer ownership, use `std::move`:
664
665 @par Example
666 @code
667 string str = "The Boost C++ Library Collection";
668
669 // transfer ownership
670 value jv( std::move(str) );
671
672 assert( str.empty() );
673 assert( *str.storage() == *jv.storage() );
674 @endcode
675
676 @par Complexity
677 Constant.
678
679 @par Exception Safety
680 No-throw guarantee.
681
682 @param other The string to construct with.
683 */
684 value(
685 string other) noexcept
686 : str_(std::move(other))
687 {
688 }
689
690 /** Construct a @ref string.
691
692 The value is copy constructed from `other`,
693 using the specified memory resource.
694
695 @par Complexity
696 Linear in `other.size()`.
697
698 @par Exception Safety
699 Strong guarantee.
700 Calls to `memory_resource::allocate` may throw.
701
702 @param other The string to construct with.
703
704 @param sp A pointer to the @ref memory_resource
705 to use. The container will acquire shared
706 ownership of the memory resource.
707 */
708 value(
709 string const& other,
710 storage_ptr sp)
711 : str_(
712 other,
713 std::move(sp))
714 {
715 }
716
717 /** Construct a @ref string.
718
719 The value is move constructed from `other`,
720 using the specified memory resource.
721
722 @par Complexity
723 Constant or linear in `other.size()`.
724
725 @par Exception Safety
726 Strong guarantee.
727 Calls to `memory_resource::allocate` may throw.
728
729 @param other The string to construct with.
730
731 @param sp A pointer to the @ref memory_resource
732 to use. The container will acquire shared
733 ownership of the memory resource.
734 */
735 value(
736 string&& other,
737 storage_ptr sp)
738 : str_(
739 std::move(other),
740 std::move(sp))
741 {
742 }
743
744 /** Construct a @ref string.
745
746 This is the fastest way to construct
747 an empty string, using the specified
748 memory resource. The variable @ref string_kind
749 may be passed as the first parameter
750 to select this overload:
751
752 @par Example
753 @code
754 // Construct an empty string
755
756 value jv( string_kind );
757 @endcode
758
759 @par Complexity
760 Constant.
761
762 @par Exception Safety
763 No-throw guarantee.
764
765 @param sp A pointer to the @ref memory_resource
766 to use. The container will acquire shared
767 ownership of the memory resource.
768
769 @see @ref string_kind
770 */
771 value(
772 string_kind_t,
773 storage_ptr sp = {}) noexcept
774 : str_(std::move(sp))
775 {
776 }
777
778 /** Construct an @ref array.
779
780 The value is constructed from `other`, using the
781 same memory resource. To transfer ownership, use `std::move`:
782
783 @par Example
784 @code
785 array arr( {1, 2, 3, 4, 5} );
786
787 // transfer ownership
788 value jv( std::move(arr) );
789
790 assert( arr.empty() );
791 assert( *arr.storage() == *jv.storage() );
792 @endcode
793
794 @par Complexity
795 Constant.
796
797 @par Exception Safety
798 No-throw guarantee.
799
800 @param other The array to construct with.
801 */
802 value(array other) noexcept
803 : arr_(std::move(other))
804 {
805 }
806
807 /** Construct an @ref array.
808
809 The value is copy constructed from `other`,
810 using the specified memory resource.
811
812 @par Complexity
813 Linear in `other.size()`.
814
815 @par Exception Safety
816 Strong guarantee.
817 Calls to `memory_resource::allocate` may throw.
818
819 @param other The array to construct with.
820
821 @param sp A pointer to the @ref memory_resource
822 to use. The container will acquire shared
823 ownership of the memory resource.
824 */
825 value(
826 array const& other,
827 storage_ptr sp)
828 : arr_(
829 other,
830 std::move(sp))
831 {
832 }
833
834 /** Construct an @ref array.
835
836 The value is move-constructed from `other`,
837 using the specified memory resource.
838
839 @par Complexity
840 Constant or linear in `other.size()`.
841
842 @par Exception Safety
843 Strong guarantee.
844 Calls to `memory_resource::allocate` may throw.
845
846 @param other The array to construct with.
847
848 @param sp A pointer to the @ref memory_resource
849 to use. The container will acquire shared
850 ownership of the memory resource.
851 */
852 value(
853 array&& other,
854 storage_ptr sp)
855 : arr_(
856 std::move(other),
857 std::move(sp))
858 {
859 }
860
861 /** Construct an @ref array.
862
863 This is the fastest way to construct
864 an empty array, using the specified
865 memory resource. The variable @ref array_kind
866 may be passed as the first parameter
867 to select this overload:
868
869 @par Example
870 @code
871 // Construct an empty array
872
873 value jv( array_kind );
874 @endcode
875
876 @par Complexity
877 Constant.
878
879 @par Exception Safety
880 No-throw guarantee.
881
882 @param sp A pointer to the @ref memory_resource
883 to use. The container will acquire shared
884 ownership of the memory resource.
885
886 @see @ref array_kind
887 */
888 value(
889 array_kind_t,
890 storage_ptr sp = {}) noexcept
891 : arr_(std::move(sp))
892 {
893 }
894
895 /** Construct an @ref object.
896
897 The value is constructed from `other`, using the
898 same memory resource. To transfer ownership, use `std::move`:
899
900 @par Example
901 @code
902 object obj( {{"a",1}, {"b",2}, {"c"},3}} );
903
904 // transfer ownership
905 value jv( std::move(obj) );
906
907 assert( obj.empty() );
908 assert( *obj.storage() == *jv.storage() );
909 @endcode
910
911 @par Complexity
912 Constant.
913
914 @par Exception Safety
915 No-throw guarantee.
916
917 @param other The object to construct with.
918 */
919 value(object other) noexcept
920 : obj_(std::move(other))
921 {
922 }
923
924 /** Construct an @ref object.
925
926 The value is copy constructed from `other`,
927 using the specified memory resource.
928
929 @par Complexity
930 Linear in `other.size()`.
931
932 @par Exception Safety
933 Strong guarantee.
934 Calls to `memory_resource::allocate` may throw.
935
936 @param other The object to construct with.
937
938 @param sp A pointer to the @ref memory_resource
939 to use. The container will acquire shared
940 ownership of the memory resource.
941 */
942 value(
943 object const& other,
944 storage_ptr sp)
945 : obj_(
946 other,
947 std::move(sp))
948 {
949 }
950
951 /** Construct an @ref object.
952
953 The value is move constructed from `other`,
954 using the specified memory resource.
955
956 @par Complexity
957 Constant or linear in `other.size()`.
958
959 @par Exception Safety
960 Strong guarantee.
961 Calls to `memory_resource::allocate` may throw.
962
963 @param other The object to construct with.
964
965 @param sp A pointer to the @ref memory_resource
966 to use. The container will acquire shared
967 ownership of the memory resource.
968 */
969 value(
970 object&& other,
971 storage_ptr sp)
972 : obj_(
973 std::move(other),
974 std::move(sp))
975 {
976 }
977
978 /** Construct an @ref object.
979
980 This is the fastest way to construct
981 an empty object, using the specified
982 memory resource. The variable @ref object_kind
983 may be passed as the first parameter
984 to select this overload:
985
986 @par Example
987 @code
988 // Construct an empty object
989
990 value jv( object_kind );
991 @endcode
992
993 @par Complexity
994 Constant.
995
996 @par Exception Safety
997 No-throw guarantee.
998
999 @param sp A pointer to the @ref memory_resource
1000 to use. The container will acquire shared
1001 ownership of the memory resource.
1002
1003 @see @ref object_kind
1004 */
1005 value(
1006 object_kind_t,
1007 storage_ptr sp = {}) noexcept
1008 : obj_(std::move(sp))
1009 {
1010 }
1011
1012 /** Construct from an initializer-list
1013
1014 If the initializer list consists of key/value
1015 pairs, an @ref object is created. Otherwise
1016 an @ref array is created. The contents of the
1017 initializer list are copied to the newly constructed
1018 value using the specified memory resource.
1019
1020 @par Complexity
1021 Linear in `init.size()`.
1022
1023 @par Exception Safety
1024 Strong guarantee.
1025 Calls to `memory_resource::allocate` may throw.
1026
1027 @param init The initializer list to construct from.
1028
1029 @param sp A pointer to the @ref memory_resource
1030 to use. The container will acquire shared
1031 ownership of the memory resource.
1032 */
1033 BOOST_JSON_DECL
1034 value(
1035 std::initializer_list<value_ref> init,
1036 storage_ptr sp = {});
1037
1038 //------------------------------------------------------
1039 //
1040 // Assignment
1041 //
1042 //------------------------------------------------------
1043
1044 /** Copy assignment.
1045
1046 The contents of the value are replaced with an
1047 element-wise copy of the contents of `other`.
1048
1049 @par Complexity
1050 Linear in the size of `*this` plus `other`.
1051
1052 @par Exception Safety
1053 Strong guarantee.
1054 Calls to `memory_resource::allocate` may throw.
1055
1056 @param other The value to copy.
1057 */
1058 BOOST_JSON_DECL
1059 value&
1060 operator=(value const& other);
1061
1062 /** Move assignment.
1063
1064 The contents of the value are replaced with the
1065 contents of `other` using move semantics:
1066
1067 @li If `*other.storage() == *sp`, ownership of
1068 the underlying memory is transferred in constant
1069 time, with no possibility of exceptions.
1070 After assignment, the moved-from value becomes
1071 a null with its current storage pointer.
1072
1073 @li If `*other.storage() != *sp`, an
1074 element-wise copy is performed if
1075 `other.is_structured() == true`, which may throw.
1076 In this case, the moved-from value is not
1077 changed.
1078
1079 @par Complexity
1080 Constant, or linear in
1081 `this->size()` plus `other.size()`.
1082
1083 @par Exception Safety
1084 Strong guarantee.
1085 Calls to `memory_resource::allocate` may throw.
1086
1087 @param other The value to assign from.
1088 */
1089 BOOST_JSON_DECL
1090 value&
1091 operator=(value&& other);
1092
1093 /** Assignment.
1094
1095 Replace `*this` with the value formed by
1096 constructing from `init` and `this->storage()`.
1097 If the initializer list consists of key/value
1098 pairs, the resulting @ref object is assigned.
1099 Otherwise an @ref array is assigned. The contents
1100 of the initializer list are moved to `*this`
1101 using the existing memory resource.
1102
1103 @par Complexity
1104 Linear in `init.size()`.
1105
1106 @par Exception Safety
1107 Strong guarantee.
1108 Calls to `memory_resource::allocate` may throw.
1109
1110 @param init The initializer list to assign from.
1111 */
1112 BOOST_JSON_DECL
1113 value&
1114 operator=(
1115 std::initializer_list<value_ref> init);
1116
1117 /** Assignment.
1118
1119 Replace `*this` with null.
1120
1121 @par Exception Safety
1122 No-throw guarantee.
1123
1124 @par Complexity
1125 Linear in the size of `*this`.
1126 */
1127 value&
1128 operator=(std::nullptr_t) noexcept
1129 {
1130 if(is_scalar())
1131 {
1132 sca_.k = json::kind::null;
1133 }
1134 else
1135 {
1136 ::new(&sca_) scalar(
1137 destroy());
1138 }
1139 return *this;
1140 }
1141
1142 /** Assignment.
1143
1144 Replace `*this` with `b`.
1145
1146 @par Exception Safety
1147 No-throw guarantee.
1148
1149 @par Complexity
1150 Linear in the size of `*this`.
1151
1152 @param b The new value.
1153 */
1154 #ifdef BOOST_JSON_DOCS
1155 value& operator=(bool b) noexcept;
1156 #else
1157 template<class Bool
1158 ,class = typename std::enable_if<
1159 std::is_same<Bool, bool>::value>::type
1160 >
1161 value& operator=(Bool b) noexcept
1162 {
1163 if(is_scalar())
1164 {
1165 sca_.b = b;
1166 sca_.k = json::kind::bool_;
1167 }
1168 else
1169 {
1170 ::new(&sca_) scalar(
1171 b, destroy());
1172 }
1173 return *this;
1174 }
1175 #endif
1176
1177 /** Assignment.
1178
1179 Replace `*this` with `i`.
1180
1181 @par Exception Safety
1182 No-throw guarantee.
1183
1184 @par Complexity
1185 Linear in the size of `*this`.
1186
1187 @param i The new value.
1188 */
1189 /** @{ */
1190 value& operator=(signed char i) noexcept
1191 {
1192 return operator=(
1193 static_cast<long long>(i));
1194 }
1195
1196 value& operator=(short i) noexcept
1197 {
1198 return operator=(
1199 static_cast<long long>(i));
1200 }
1201
1202 value& operator=(int i) noexcept
1203 {
1204 return operator=(
1205 static_cast<long long>(i));
1206 }
1207
1208 value& operator=(long i) noexcept
1209 {
1210 return operator=(
1211 static_cast<long long>(i));
1212 }
1213
1214 value& operator=(long long i) noexcept
1215 {
1216 if(is_scalar())
1217 {
1218 sca_.i = i;
1219 sca_.k = json::kind::int64;
1220 }
1221 else
1222 {
1223 ::new(&sca_) scalar(static_cast<
1224 std::int64_t>(i), destroy());
1225 }
1226 return *this;
1227 }
1228 /** @} */
1229
1230 /** Assignment.
1231
1232 Replace `*this` with `i`.
1233
1234 @par Exception Safety
1235 No-throw guarantee.
1236
1237 @par Complexity
1238 Linear in the size of `*this`.
1239
1240 @param u The new value.
1241 */
1242 /** @{ */
1243 value& operator=(unsigned char u) noexcept
1244 {
1245 return operator=(static_cast<
1246 unsigned long long>(u));
1247 }
1248
1249 value& operator=(unsigned short u) noexcept
1250 {
1251 return operator=(static_cast<
1252 unsigned long long>(u));
1253 }
1254
1255 value& operator=(unsigned int u) noexcept
1256 {
1257 return operator=(static_cast<
1258 unsigned long long>(u));
1259 }
1260
1261 value& operator=(unsigned long u) noexcept
1262 {
1263 return operator=(static_cast<
1264 unsigned long long>(u));
1265 }
1266
1267 value& operator=(unsigned long long u) noexcept
1268 {
1269 if(is_scalar())
1270 {
1271 sca_.u = u;
1272 sca_.k = json::kind::uint64;
1273 }
1274 else
1275 {
1276 ::new(&sca_) scalar(static_cast<
1277 std::uint64_t>(u), destroy());
1278 }
1279 return *this;
1280 }
1281 /** @} */
1282
1283 /** Assignment.
1284
1285 Replace `*this` with `d`.
1286
1287 @par Exception Safety
1288 No-throw guarantee.
1289
1290 @par Complexity
1291 Linear in the size of `*this`.
1292
1293 @param d The new value.
1294 */
1295 value& operator=(double d) noexcept
1296 {
1297 if(is_scalar())
1298 {
1299 sca_.d = d;
1300 sca_.k = json::kind::double_;
1301 }
1302 else
1303 {
1304 ::new(&sca_) scalar(
1305 d, destroy());
1306 }
1307 return *this;
1308 }
1309
1310 /** Assignment.
1311
1312 Replace `*this` with a copy of the string `s`.
1313
1314 @par Exception Safety
1315 Strong guarantee.
1316 Calls to `memory_resource::allocate` may throw.
1317
1318 @par Complexity
1319 Linear in the sum of sizes of `*this` and `s`
1320
1321 @param s The new string.
1322 */
1323 /** @{ */
1324 BOOST_JSON_DECL value& operator=(string_view s);
1325 BOOST_JSON_DECL value& operator=(char const* s);
1326 BOOST_JSON_DECL value& operator=(string const& s);
1327 /** @} */
1328
1329 /** Assignment.
1330
1331 The contents of the value are replaced with the
1332 contents of `s` using move semantics:
1333
1334 @li If `*other.storage() == *this->storage()`,
1335 ownership of the underlying memory is transferred
1336 in constant time, with no possibility of exceptions.
1337 After assignment, the moved-from string becomes
1338 empty with its current storage pointer.
1339
1340 @li If `*other.storage() != *this->storage()`, an
1341 element-wise copy is performed, which may throw.
1342 In this case, the moved-from string is not
1343 changed.
1344
1345 @par Complexity
1346 Constant, or linear in the size of `*this` plus `s.size()`.
1347
1348 @par Exception Safety
1349 Strong guarantee.
1350 Calls to `memory_resource::allocate` may throw.
1351
1352 @param s The string to move-assign from.
1353 */
1354 BOOST_JSON_DECL value& operator=(string&& s);
1355
1356 /** Assignment.
1357
1358 Replace `*this` with a copy of the array `arr`.
1359
1360 @par Exception Safety
1361 Strong guarantee.
1362 Calls to `memory_resource::allocate` may throw.
1363
1364 @par Complexity
1365 Linear in the sum of sizes of `*this` and `arr`
1366
1367 @param arr The new array.
1368 */
1369 BOOST_JSON_DECL value& operator=(array const& arr);
1370
1371 /** Assignment.
1372
1373 The contents of the value are replaced with the
1374 contents of `arr` using move semantics:
1375
1376 @li If `*arr.storage() == *this->storage()`,
1377 ownership of the underlying memory is transferred
1378 in constant time, with no possibility of exceptions.
1379 After assignment, the moved-from array becomes
1380 empty with its current storage pointer.
1381
1382 @li If `*arr.storage() != *this->storage()`, an
1383 element-wise copy is performed, which may throw.
1384 In this case, the moved-from array is not
1385 changed.
1386
1387 @par Complexity
1388 Constant, or linear in the size of `*this` plus `arr.size()`.
1389
1390 @par Exception Safety
1391 Strong guarantee.
1392 Calls to `memory_resource::allocate` may throw.
1393
1394 @param arr The array to move-assign from.
1395 */
1396 BOOST_JSON_DECL value& operator=(array&& arr);
1397
1398 /** Assignment.
1399
1400 Replace `*this` with a copy of the obect `obj`.
1401
1402 @par Exception Safety
1403 Strong guarantee.
1404 Calls to `memory_resource::allocate` may throw.
1405
1406 @par Complexity
1407 Linear in the sum of sizes of `*this` and `obj`
1408
1409 @param obj The new object.
1410 */
1411 BOOST_JSON_DECL value& operator=(object const& obj);
1412
1413 /** Assignment.
1414
1415 The contents of the value are replaced with the
1416 contents of `obj` using move semantics:
1417
1418 @li If `*obj.storage() == *this->storage()`,
1419 ownership of the underlying memory is transferred
1420 in constant time, with no possibility of exceptions.
1421 After assignment, the moved-from object becomes
1422 empty with its current storage pointer.
1423
1424 @li If `*obj.storage() != *this->storage()`, an
1425 element-wise copy is performed, which may throw.
1426 In this case, the moved-from object is not
1427 changed.
1428
1429 @par Complexity
1430 Constant, or linear in the size of `*this` plus `obj.size()`.
1431
1432 @par Exception Safety
1433 Strong guarantee.
1434 Calls to `memory_resource::allocate` may throw.
1435
1436 @param obj The object to move-assign from.
1437 */
1438 BOOST_JSON_DECL value& operator=(object&& obj);
1439
1440 //------------------------------------------------------
1441 //
1442 // Modifiers
1443 //
1444 //------------------------------------------------------
1445
1446 /** Change the kind to null, discarding the previous contents.
1447
1448 The value is replaced with a null,
1449 destroying the previous contents.
1450
1451 @par Complexity
1452 Linear in the size of `*this`.
1453
1454 @par Exception Safety
1455 No-throw guarantee.
1456 */
1457 void
1458 emplace_null() noexcept
1459 {
1460 *this = nullptr;
1461 }
1462
1463 /** Return a reference to a `bool`, changing the kind and replacing the contents.
1464
1465 The value is replaced with a `bool`
1466 initialized to `false`, destroying the
1467 previous contents.
1468
1469 @par Complexity
1470 Linear in the size of `*this`.
1471
1472 @par Exception Safety
1473 No-throw guarantee.
1474 */
1475 bool&
1476 emplace_bool() noexcept
1477 {
1478 *this = false;
1479 return sca_.b;
1480 }
1481
1482 /** Return a reference to a `std::int64_t`, changing the kind and replacing the contents.
1483
1484 The value is replaced with a `std::int64_t`
1485 initialized to zero, destroying the
1486 previous contents.
1487
1488 @par Complexity
1489 Linear in the size of `*this`.
1490
1491 @par Exception Safety
1492 No-throw guarantee.
1493 */
1494 std::int64_t&
1495 emplace_int64() noexcept
1496 {
1497 *this = std::int64_t{};
1498 return sca_.i;
1499 }
1500
1501 /** Return a reference to a `std::uint64_t`, changing the kind and replacing the contents.
1502
1503 The value is replaced with a `std::uint64_t`
1504 initialized to zero, destroying the
1505 previous contents.
1506
1507 @par Complexity
1508 Linear in the size of `*this`.
1509
1510 @par Exception Safety
1511 No-throw guarantee.
1512 */
1513 std::uint64_t&
1514 emplace_uint64() noexcept
1515 {
1516 *this = std::uint64_t{};
1517 return sca_.u;
1518 }
1519
1520 /** Return a reference to a `double`, changing the kind and replacing the contents.
1521
1522 The value is replaced with a `double`
1523 initialized to zero, destroying the
1524 previous contents.
1525
1526 @par Complexity
1527 Linear in the size of `*this`.
1528
1529 @par Exception Safety
1530 No-throw guarantee.
1531 */
1532 double&
1533 emplace_double() noexcept
1534 {
1535 *this = double{};
1536 return sca_.d;
1537 }
1538
1539 /** Return a reference to a @ref string, changing the kind and replacing the contents.
1540
1541 The value is replaced with an empty @ref string
1542 using the current memory resource, destroying the
1543 previous contents.
1544
1545 @par Complexity
1546 Linear in the size of `*this`.
1547
1548 @par Exception Safety
1549 No-throw guarantee.
1550 */
1551 BOOST_JSON_DECL
1552 string&
1553 emplace_string() noexcept;
1554
1555 /** Return a reference to an @ref array, changing the kind and replacing the contents.
1556
1557 The value is replaced with an empty @ref array
1558 using the current memory resource, destroying the
1559 previous contents.
1560
1561 @par Complexity
1562 Linear in the size of `*this`.
1563
1564 @par Exception Safety
1565 No-throw guarantee.
1566 */
1567 BOOST_JSON_DECL
1568 array&
1569 emplace_array() noexcept;
1570
1571 /** Return a reference to an @ref object, changing the kind and replacing the contents.
1572
1573 The contents are replaced with an empty @ref object
1574 using the current @ref memory_resource. All
1575 previously obtained iterators and references
1576 obtained beforehand are invalidated.
1577
1578 @par Complexity
1579 Linear in the size of `*this`.
1580
1581 @par Exception Safety
1582 No-throw guarantee.
1583 */
1584 BOOST_JSON_DECL
1585 object&
1586 emplace_object() noexcept;
1587
1588 /** Swap the given values.
1589
1590 Exchanges the contents of this value with another
1591 value. Ownership of the respective @ref memory_resource
1592 objects is not transferred:
1593
1594 @li If `*other.storage() == *this->storage()`,
1595 ownership of the underlying memory is swapped in
1596 constant time, with no possibility of exceptions.
1597 All iterators and references remain valid.
1598
1599 @li If `*other.storage() != *this->storage()`,
1600 the contents are logically swapped by making copies,
1601 which can throw. In this case all iterators and
1602 references are invalidated.
1603
1604 @par Complexity
1605 Constant or linear in the sum of the sizes of
1606 the values.
1607
1608 @par Exception Safety
1609 Strong guarantee.
1610 Calls to `memory_resource::allocate` may throw.
1611
1612 @param other The value to swap with.
1613 If `this == &other`, this function call has no effect.
1614 */
1615 BOOST_JSON_DECL
1616 void
1617 swap(value& other);
1618
1619 /** Swap the given values.
1620
1621 Exchanges the contents of value `lhs` with
1622 another value `rhs`. Ownership of the respective
1623 @ref memory_resource objects is not transferred.
1624
1625 @li If `*lhs.storage() == *rhs.storage()`,
1626 ownership of the underlying memory is swapped in
1627 constant time, with no possibility of exceptions.
1628 All iterators and references remain valid.
1629
1630 @li If `*lhs.storage() != *rhs.storage`,
1631 the contents are logically swapped by a copy,
1632 which can throw. In this case all iterators and
1633 references are invalidated.
1634
1635 @par Effects
1636 @code
1637 lhs.swap( rhs );
1638 @endcode
1639
1640 @par Complexity
1641 Constant or linear in the sum of the sizes of
1642 the values.
1643
1644 @par Exception Safety
1645 Strong guarantee.
1646 Calls to `memory_resource::allocate` may throw.
1647
1648 @param lhs The value to exchange.
1649
1650 @param rhs The value to exchange.
1651 If `&lhs == &rhs`, this function call has no effect.
1652
1653 @see @ref value::swap
1654 */
1655 friend
1656 void
1657 swap(value& lhs, value& rhs)
1658 {
1659 lhs.swap(rhs);
1660 }
1661
1662 //------------------------------------------------------
1663 //
1664 // Observers
1665 //
1666 //------------------------------------------------------
1667
1668 /** Returns the kind of this JSON value.
1669
1670 This function returns the discriminating
1671 enumeration constant of type @ref json::kind
1672 corresponding to the underlying representation
1673 stored in the container.
1674
1675 @par Complexity
1676 Constant.
1677
1678 @par Exception Safety
1679 No-throw guarantee.
1680 */
1681 json::kind
1682 kind() const noexcept
1683 {
1684 return static_cast<json::kind>(
1685 static_cast<unsigned char>(
1686 sca_.k) & 0x3f);
1687 }
1688
1689 /** Return `true` if this is an array
1690
1691 This function is used to determine if the underlying
1692 representation is a certain kind.
1693
1694 @par Effects
1695 @code
1696 return this->kind() == kind::array;
1697 @endcode
1698
1699 @par Complexity
1700 Constant.
1701
1702 @par Exception Safety
1703 No-throw guarantee.
1704 */
1705 bool
1706 is_array() const noexcept
1707 {
1708 return kind() == json::kind::array;
1709 }
1710
1711 /** Return `true` if this is an object
1712
1713 This function is used to determine if the underlying
1714 representation is a certain kind.
1715
1716 @par Effects
1717 @code
1718 return this->kind() == kind::object;
1719 @endcode
1720
1721 @par Complexity
1722 Constant.
1723
1724 @par Exception Safety
1725 No-throw guarantee.
1726 */
1727 bool
1728 is_object() const noexcept
1729 {
1730 return kind() == json::kind::object;
1731 }
1732
1733 /** Return `true` if this is a string
1734
1735 This function is used to determine if the underlying
1736 representation is a certain kind.
1737
1738 @par Effects
1739 @code
1740 return this->kind() == kind::string;
1741 @endcode
1742
1743 @par Complexity
1744 Constant.
1745
1746 @par Exception Safety
1747 No-throw guarantee.
1748 */
1749 bool
1750 is_string() const noexcept
1751 {
1752 return kind() == json::kind::string;
1753 }
1754
1755 /** Return `true` if this is a signed integer
1756
1757 This function is used to determine if the underlying
1758 representation is a certain kind.
1759
1760 @par Effects
1761 @code
1762 return this->kind() == kind::int64;
1763 @endcode
1764
1765 @par Complexity
1766 Constant.
1767
1768 @par Exception Safety
1769 No-throw guarantee.
1770 */
1771 bool
1772 is_int64() const noexcept
1773 {
1774 return kind() == json::kind::int64;
1775 }
1776
1777 /** Return `true` if this is a unsigned integer
1778
1779 This function is used to determine if the underlying
1780 representation is a certain kind.
1781
1782 @par Effects
1783 @code
1784 return this->kind() == kind::uint64;
1785 @endcode
1786
1787 @par Complexity
1788 Constant.
1789
1790 @par Exception Safety
1791 No-throw guarantee.
1792 */
1793 bool
1794 is_uint64() const noexcept
1795 {
1796 return kind() == json::kind::uint64;
1797 }
1798
1799 /** Return `true` if this is a double
1800
1801 This function is used to determine if the underlying
1802 representation is a certain kind.
1803
1804 @par Effects
1805 @code
1806 return this->kind() == kind::double_;
1807 @endcode
1808
1809 @par Complexity
1810 Constant.
1811
1812 @par Exception Safety
1813 No-throw guarantee.
1814 */
1815 bool
1816 is_double() const noexcept
1817 {
1818 return kind() == json::kind::double_;
1819 }
1820
1821 /** Return `true` if this is a bool
1822
1823 This function is used to determine if the underlying
1824 representation is a certain kind.
1825
1826 @par Effects
1827 @code
1828 return this->kind() == kind::bool_;
1829 @endcode
1830
1831 @par Complexity
1832 Constant.
1833
1834 @par Exception Safety
1835 No-throw guarantee.
1836 */
1837 bool
1838 is_bool() const noexcept
1839 {
1840 return kind() == json::kind::bool_;
1841 }
1842
1843 /** Returns true if this is a null.
1844
1845 This function is used to determine if the underlying
1846 representation is a certain kind.
1847
1848 @par Effects
1849 @code
1850 return this->kind() == kind::null;
1851 @endcode
1852
1853 @par Complexity
1854 Constant.
1855
1856 @par Exception Safety
1857 No-throw guarantee.
1858 */
1859 bool
1860 is_null() const noexcept
1861 {
1862 return kind() == json::kind::null;
1863 }
1864
1865 /** Returns true if this is an array or object.
1866
1867 This function returns `true` if
1868 @ref kind() is either `kind::object` or
1869 `kind::array`.
1870
1871 @par Complexity
1872 Constant.
1873
1874 @par Exception Safety
1875 No-throw guarantee.
1876 */
1877 bool
1878 is_structured() const noexcept
1879 {
1880 // VFALCO Could use bit 0x20 for this
1881 return
1882 kind() == json::kind::object ||
1883 kind() == json::kind::array;
1884 }
1885
1886 /** Returns true if this is not an array or object.
1887
1888 This function returns `true` if
1889 @ref kind() is neither `kind::object` nor
1890 `kind::array`.
1891
1892 @par Complexity
1893 Constant.
1894
1895 @par Exception Safety
1896 No-throw guarantee.
1897 */
1898 bool
1899 is_primitive() const noexcept
1900 {
1901 // VFALCO Could use bit 0x20 for this
1902 return
1903 sca_.k != json::kind::object &&
1904 sca_.k != json::kind::array;
1905 }
1906
1907 /** Returns true if this is a number.
1908
1909 This function returns `true` when
1910 @ref kind() is one of the following values:
1911 `kind::int64`, `kind::uint64`, or
1912 `kind::double_`.
1913
1914 @par Complexity
1915 Constant.
1916
1917 @par Exception Safety
1918 No-throw guarantee.
1919 */
1920 bool
1921 is_number() const noexcept
1922 {
1923 // VFALCO Could use bit 0x40 for this
1924 return
1925 kind() == json::kind::int64 ||
1926 kind() == json::kind::uint64 ||
1927 kind() == json::kind::double_;
1928 }
1929
1930 //------------------------------------------------------
1931
1932 /** Return an @ref array pointer if this is an array, else return `nullptr`
1933
1934 If `this->kind() == kind::array`, returns a pointer
1935 to the underlying array. Otherwise, returns `nullptr`.
1936
1937 @par Example
1938 The return value is used in both a boolean context and
1939 to assign a variable:
1940 @code
1941 if( auto p = jv.if_array() )
1942 return *p;
1943 @endcode
1944
1945 @par Complexity
1946 Constant.
1947
1948 @par Exception Safety
1949 No-throw guarantee.
1950 */
1951 array const*
1952 if_array() const noexcept
1953 {
1954 if(kind() == json::kind::array)
1955 return &arr_;
1956 return nullptr;
1957 }
1958
1959 /** Return an @ref array pointer if this is an array, else return `nullptr`
1960
1961 If `this->kind() == kind::array`, returns a pointer
1962 to the underlying array. Otherwise, returns `nullptr`.
1963
1964 @par Example
1965 The return value is used in both a boolean context and
1966 to assign a variable:
1967 @code
1968 if( auto p = jv.if_array() )
1969 return *p;
1970 @endcode
1971
1972 @par Complexity
1973 Constant.
1974
1975 @par Exception Safety
1976 No-throw guarantee.
1977 */
1978 array*
1979 if_array() noexcept
1980 {
1981 if(kind() == json::kind::array)
1982 return &arr_;
1983 return nullptr;
1984 }
1985
1986 /** Return an @ref object pointer if this is an object, else return `nullptr`
1987
1988 If `this->kind() == kind::object`, returns a pointer
1989 to the underlying object. Otherwise, returns `nullptr`.
1990
1991 @par Example
1992 The return value is used in both a boolean context and
1993 to assign a variable:
1994 @code
1995 if( auto p = jv.if_object() )
1996 return *p;
1997 @endcode
1998
1999 @par Complexity
2000 Constant.
2001
2002 @par Exception Safety
2003 No-throw guarantee.
2004 */
2005 object const*
2006 if_object() const noexcept
2007 {
2008 if(kind() == json::kind::object)
2009 return &obj_;
2010 return nullptr;
2011 }
2012
2013 /** Return an @ref object pointer if this is an object, else return `nullptr`
2014
2015 If `this->kind() == kind::object`, returns a pointer
2016 to the underlying object. Otherwise, returns `nullptr`.
2017
2018 @par Example
2019 The return value is used in both a boolean context and
2020 to assign a variable:
2021 @code
2022 if( auto p = jv.if_object() )
2023 return *p;
2024 @endcode
2025
2026 @par Complexity
2027 Constant.
2028
2029 @par Exception Safety
2030 No-throw guarantee.
2031 */
2032 object*
2033 if_object() noexcept
2034 {
2035 if(kind() == json::kind::object)
2036 return &obj_;
2037 return nullptr;
2038 }
2039
2040 /** Return a @ref string pointer if this is a string, else return `nullptr`
2041
2042 If `this->kind() == kind::string`, returns a pointer
2043 to the underlying object. Otherwise, returns `nullptr`.
2044
2045 @par Example
2046 The return value is used in both a boolean context and
2047 to assign a variable:
2048 @code
2049 if( auto p = jv.if_string() )
2050 return *p;
2051 @endcode
2052
2053 @par Complexity
2054 Constant.
2055
2056 @par Exception Safety
2057 No-throw guarantee.
2058 */
2059 string const*
2060 if_string() const noexcept
2061 {
2062 if(kind() == json::kind::string)
2063 return &str_;
2064 return nullptr;
2065 }
2066
2067 /** Return a @ref string pointer if this is a string, else return `nullptr`
2068
2069 If `this->kind() == kind::string`, returns a pointer
2070 to the underlying object. Otherwise, returns `nullptr`.
2071
2072 @par Example
2073 The return value is used in both a boolean context and
2074 to assign a variable:
2075 @code
2076 if( auto p = jv.if_string() )
2077 return *p;
2078 @endcode
2079
2080 @par Complexity
2081 Constant.
2082
2083 @par Exception Safety
2084 No-throw guarantee.
2085 */
2086 string*
2087 if_string() noexcept
2088 {
2089 if(kind() == json::kind::string)
2090 return &str_;
2091 return nullptr;
2092 }
2093
2094 /** Return an `int64_t` pointer if this is a signed integer, else return `nullptr`
2095
2096 If `this->kind() == kind::int64`, returns a pointer
2097 to the underlying integer. Otherwise, returns `nullptr`.
2098
2099 @par Example
2100 The return value is used in both a boolean context and
2101 to assign a variable:
2102 @code
2103 if( auto p = jv.if_int64() )
2104 return *p;
2105 @endcode
2106
2107 @par Complexity
2108 Constant.
2109
2110 @par Exception Safety
2111 No-throw guarantee.
2112 */
2113 std::int64_t const*
2114 if_int64() const noexcept
2115 {
2116 if(kind() == json::kind::int64)
2117 return &sca_.i;
2118 return nullptr;
2119 }
2120
2121 /** Return an `int64_t` pointer if this is a signed integer, else return `nullptr`
2122
2123 If `this->kind() == kind::int64`, returns a pointer
2124 to the underlying integer. Otherwise, returns `nullptr`.
2125
2126 @par Example
2127 The return value is used in both a boolean context and
2128 to assign a variable:
2129 @code
2130 if( auto p = jv.if_int64() )
2131 return *p;
2132 @endcode
2133
2134 @par Complexity
2135 Constant.
2136
2137 @par Exception Safety
2138 No-throw guarantee.
2139 */
2140 std::int64_t*
2141 if_int64() noexcept
2142 {
2143 if(kind() == json::kind::int64)
2144 return &sca_.i;
2145 return nullptr;
2146 }
2147
2148 /** Return a `uint64_t` pointer if this is an unsigned integer, else return `nullptr`
2149
2150 If `this->kind() == kind::uint64`, returns a pointer
2151 to the underlying unsigned integer. Otherwise, returns
2152 `nullptr`.
2153
2154 @par Example
2155 The return value is used in both a boolean context and
2156 to assign a variable:
2157 @code
2158 if( auto p = jv.if_uint64() )
2159 return *p;
2160 @endcode
2161
2162 @par Complexity
2163 Constant.
2164
2165 @par Exception Safety
2166 No-throw guarantee.
2167 */
2168 std::uint64_t const*
2169 if_uint64() const noexcept
2170 {
2171 if(kind() == json::kind::uint64)
2172 return &sca_.u;
2173 return nullptr;
2174 }
2175
2176 /** Return a `uint64_t` pointer if this is an unsigned integer, else return `nullptr`
2177
2178 If `this->kind() == kind::uint64`, returns a pointer
2179 to the underlying unsigned integer. Otherwise, returns
2180 `nullptr`.
2181
2182 @par Example
2183 The return value is used in both a boolean context and
2184 to assign a variable:
2185 @code
2186 if( auto p = jv.if_uint64() )
2187 return *p;
2188 @endcode
2189
2190 @par Complexity
2191 Constant.
2192
2193 @par Exception Safety
2194 No-throw guarantee.
2195 */
2196 std::uint64_t*
2197 if_uint64() noexcept
2198 {
2199 if(kind() == json::kind::uint64)
2200 return &sca_.u;
2201 return nullptr;
2202 }
2203
2204 /** Return a `double` pointer if this is a double, else return `nullptr`
2205
2206 If `this->kind() == kind::double_`, returns a pointer
2207 to the underlying double. Otherwise, returns
2208 `nullptr`.
2209
2210 @par Example
2211 The return value is used in both a boolean context and
2212 to assign a variable:
2213 @code
2214 if( auto p = jv.if_double() )
2215 return *p;
2216 @endcode
2217
2218 @par Complexity
2219 Constant.
2220
2221 @par Exception Safety
2222 No-throw guarantee.
2223 */
2224 double const*
2225 if_double() const noexcept
2226 {
2227 if(kind() == json::kind::double_)
2228 return &sca_.d;
2229 return nullptr;
2230 }
2231
2232 /** Return a `double` pointer if this is a double, else return `nullptr`
2233
2234 If `this->kind() == kind::double_`, returns a pointer
2235 to the underlying double. Otherwise, returns
2236 `nullptr`.
2237
2238 @par Example
2239 The return value is used in both a boolean context and
2240 to assign a variable:
2241 @code
2242 if( auto p = jv.if_double() )
2243 return *p;
2244 @endcode
2245
2246 @par Complexity
2247 Constant.
2248
2249 @par Exception Safety
2250 No-throw guarantee.
2251 */
2252 double*
2253 if_double() noexcept
2254 {
2255 if(kind() == json::kind::double_)
2256 return &sca_.d;
2257 return nullptr;
2258 }
2259
2260 /** Return a `bool` pointer if this is a boolean, else return `nullptr`
2261
2262 If `this->kind() == kind::bool_`, returns a pointer
2263 to the underlying boolean. Otherwise, returns
2264 `nullptr`.
2265
2266 @par Example
2267 The return value is used in both a boolean context and
2268 to assign a variable:
2269 @code
2270 if( auto p = jv.if_bool() )
2271 return *p;
2272 @endcode
2273
2274 @par Complexity
2275 Constant.
2276
2277 @par Exception Safety
2278 No-throw guarantee.
2279 */
2280 bool const*
2281 if_bool() const noexcept
2282 {
2283 if(kind() == json::kind::bool_)
2284 return &sca_.b;
2285 return nullptr;
2286 }
2287
2288 /** Return a `bool` pointer if this is a boolean, else return `nullptr`
2289
2290 If `this->kind() == kind::bool_`, returns a pointer
2291 to the underlying boolean. Otherwise, returns
2292 `nullptr`.
2293
2294 @par Example
2295 The return value is used in both a boolean context and
2296 to assign a variable:
2297 @code
2298 if( auto p = jv.if_bool() )
2299 return *p;
2300 @endcode
2301
2302 @par Complexity
2303 Constant.
2304
2305 @par Exception Safety
2306 No-throw guarantee.
2307 */
2308 bool*
2309 if_bool() noexcept
2310 {
2311 if(kind() == json::kind::bool_)
2312 return &sca_.b;
2313 return nullptr;
2314 }
2315
2316 //------------------------------------------------------
2317
2318 /** Return the stored number cast to an arithmetic type.
2319
2320 This function attempts to return the stored value
2321 converted to the arithmetic type `T` which may not
2322 be `bool`:
2323
2324 @li If `T` is an integral type and the stored
2325 value is a number which can be losslessly converted,
2326 the conversion is performed without error and the
2327 converted number is returned.
2328
2329 @li If `T` is an integral type and the stored value
2330 is a number which cannot be losslessly converted,
2331 then the operation fails with an error.
2332
2333 @li If `T` is a floating point type and the stored
2334 value is a number, the conversion is performed
2335 without error. The converted number is returned,
2336 with a possible loss of precision.
2337
2338 @li Otherwise, if the stored value is not a number;
2339 that is, if `this->is_number()` returns `false`, then
2340 the operation fails with an error.
2341
2342 @par Constraints
2343 @code
2344 std::is_arithmetic< T >::value && ! std::is_same< T, bool >::value
2345 @endcode
2346
2347 @par Complexity
2348 Constant.
2349
2350 @par Exception Safety
2351 No-throw guarantee.
2352
2353 @return The converted number.
2354
2355 @param ec Set to the error, if any occurred.
2356 */
2357 #ifdef BOOST_JSON_DOCS
2358 template<class T>
2359 T to_number(error_code& ec) const noexcept;
2360 #endif
2361
2362 /** Return the stored number cast to an arithmetic type.
2363
2364 This function attempts to return the stored value
2365 converted to the arithmetic type `T` which may not
2366 be `bool`:
2367
2368 @li If `T` is an integral type and the stored
2369 value is a number which can be losslessly converted,
2370 the conversion is performed without error and the
2371 converted number is returned.
2372
2373 @li If `T` is an integral type and the stored value
2374 is a number which cannot be losslessly converted,
2375 then the operation fails with an error.
2376
2377 @li If `T` is a floating point type and the stored
2378 value is a number, the conversion is performed
2379 without error. The converted number is returned,
2380 with a possible loss of precision.
2381
2382 @li Otherwise, if the stored value is not a number;
2383 that is, if `this->is_number()` returns `false`, then
2384 the operation fails with an error.
2385
2386 @par Constraints
2387 @code
2388 std::is_arithmetic< T >::value && ! std::is_same< T, bool >::value
2389 @endcode
2390
2391 @par Complexity
2392 Constant.
2393
2394 @return The converted number.
2395
2396 @throw system_error on error.
2397 */
2398 template<class T>
2399 #ifdef BOOST_JSON_DOCS
2400 T
2401 #else
2402 typename std::enable_if<
2403 std::is_arithmetic<T>::value &&
2404 ! std::is_same<T, bool>::value,
2405 T>::type
2406 #endif
2407 to_number() const
2408 {
2409 error_code ec;
2410 auto result = to_number<T>(ec);
2411 if(ec)
2412 detail::throw_system_error(ec,
2413 BOOST_CURRENT_LOCATION);
2414 return result;
2415 }
2416
2417 #ifndef BOOST_JSON_DOCS
2418 template<class T>
2419 auto
2420 to_number(error_code& ec) const noexcept ->
2421 typename std::enable_if<
2422 std::is_signed<T>::value &&
2423 ! std::is_floating_point<T>::value,
2424 T>::type
2425 {
2426 if(sca_.k == json::kind::int64)
2427 {
2428 auto const i = sca_.i;
2429 if( i >= (std::numeric_limits<T>::min)() &&
2430 i <= (std::numeric_limits<T>::max)())
2431 {
2432 ec = {};
2433 return static_cast<T>(i);
2434 }
2435 ec = error::not_exact;
2436 }
2437 else if(sca_.k == json::kind::uint64)
2438 {
2439 auto const u = sca_.u;
2440 if(u <= static_cast<std::uint64_t>((
2441 std::numeric_limits<T>::max)()))
2442 {
2443 ec = {};
2444 return static_cast<T>(u);
2445 }
2446 ec = error::not_exact;
2447 }
2448 else if(sca_.k == json::kind::double_)
2449 {
2450 auto const d = sca_.d;
2451 if( d >= static_cast<double>(
2452 (detail::to_number_limit<T>::min)()) &&
2453 d <= static_cast<double>(
2454 (detail::to_number_limit<T>::max)()) &&
2455 static_cast<T>(d) == d)
2456 {
2457 ec = {};
2458 return static_cast<T>(d);
2459 }
2460 ec = error::not_exact;
2461 }
2462 else
2463 {
2464 ec = error::not_number;
2465 }
2466 return T{};
2467 }
2468
2469 template<class T>
2470 auto
2471 to_number(error_code& ec) const noexcept ->
2472 typename std::enable_if<
2473 std::is_unsigned<T>::value &&
2474 ! std::is_same<T, bool>::value,
2475 T>::type
2476 {
2477 if(sca_.k == json::kind::int64)
2478 {
2479 auto const i = sca_.i;
2480 if( i >= 0 && static_cast<std::uint64_t>(i) <=
2481 (std::numeric_limits<T>::max)())
2482 {
2483 ec = {};
2484 return static_cast<T>(i);
2485 }
2486 ec = error::not_exact;
2487 }
2488 else if(sca_.k == json::kind::uint64)
2489 {
2490 auto const u = sca_.u;
2491 if(u <= (std::numeric_limits<T>::max)())
2492 {
2493 ec = {};
2494 return static_cast<T>(u);
2495 }
2496 ec = error::not_exact;
2497 }
2498 else if(sca_.k == json::kind::double_)
2499 {
2500 auto const d = sca_.d;
2501 if( d >= 0 &&
2502 d <= (detail::to_number_limit<T>::max)() &&
2503 static_cast<T>(d) == d)
2504 {
2505 ec = {};
2506 return static_cast<T>(d);
2507 }
2508 ec = error::not_exact;
2509 }
2510 else
2511 {
2512 ec = error::not_number;
2513 }
2514 return T{};
2515 }
2516
2517 template<class T>
2518 auto
2519 to_number(error_code& ec) const noexcept ->
2520 typename std::enable_if<
2521 std::is_floating_point<
2522 T>::value, T>::type
2523 {
2524 if(sca_.k == json::kind::int64)
2525 {
2526 ec = {};
2527 return static_cast<T>(sca_.i);
2528 }
2529 if(sca_.k == json::kind::uint64)
2530 {
2531 ec = {};
2532 return static_cast<T>(sca_.u);
2533 }
2534 if(sca_.k == json::kind::double_)
2535 {
2536 ec = {};
2537 return static_cast<T>(sca_.d);
2538 }
2539 ec = error::not_number;
2540 return {};
2541 }
2542 #endif
2543
2544 //------------------------------------------------------
2545 //
2546 // Accessors
2547 //
2548 //------------------------------------------------------
2549
2550 /** Return the memory resource associated with the value.
2551
2552 This returns a pointer to the memory resource
2553 that was used to construct the value.
2554
2555 @par Complexity
2556 Constant.
2557
2558 @par Exception Safety
2559 No-throw guarantee.
2560 */
2561 storage_ptr const&
2562 storage() const noexcept
2563 {
2564 return sp_;
2565 }
2566
2567 /** Return the associated @ref memory_resource
2568
2569 This function returns an instance of
2570 @ref polymorphic_allocator constructed from the
2571 associated @ref memory_resource.
2572
2573 @par Complexity
2574 Constant.
2575
2576 @par Exception Safety
2577 No-throw guarantee.
2578 */
2579 allocator_type
2580 get_allocator() const noexcept
2581 {
2582 return sp_.get();
2583 }
2584
2585 //------------------------------------------------------
2586
2587 /** Return a reference to the underlying `object`, or throw an exception.
2588
2589 If @ref is_object() is `true`, returns
2590 a reference to the underlying @ref object,
2591 otherwise throws an exception.
2592
2593 @par Complexity
2594 Constant.
2595
2596 @par Exception Safety
2597 Strong guarantee.
2598
2599 @throw std::invalid_argument `! this->is_object()`
2600 */
2601 object&
2602 as_object()
2603 {
2604 if(! is_object())
2605 detail::throw_invalid_argument(
2606 "not an object",
2607 BOOST_CURRENT_LOCATION);
2608 return obj_;
2609 }
2610
2611 /** Return a reference to the underlying `object`, or throw an exception.
2612
2613 If @ref is_object() is `true`, returns
2614 a reference to the underlying @ref object,
2615 otherwise throws an exception.
2616
2617 @par Complexity
2618 Constant.
2619
2620 @par Exception Safety
2621 Strong guarantee.
2622
2623 @throw std::invalid_argument `! this->is_object()`
2624 */
2625 object const&
2626 as_object() const
2627 {
2628 if(! is_object())
2629 detail::throw_invalid_argument(
2630 "not an object",
2631 BOOST_CURRENT_LOCATION);
2632 return obj_;
2633 }
2634
2635 /** Return a reference to the underlying @ref array, or throw an exception.
2636
2637 If @ref is_array() is `true`, returns
2638 a reference to the underlying @ref array,
2639 otherwise throws an exception.
2640
2641 @par Complexity
2642 Constant.
2643
2644 @par Exception Safety
2645 Strong guarantee.
2646
2647 @throw std::invalid_argument `! this->is_array()`
2648 */
2649 array&
2650 as_array()
2651 {
2652 if(! is_array())
2653 detail::throw_invalid_argument(
2654 "array required",
2655 BOOST_CURRENT_LOCATION);
2656 return arr_;
2657 }
2658
2659 /** Return a reference to the underlying `array`, or throw an exception.
2660
2661 If @ref is_array() is `true`, returns
2662 a reference to the underlying @ref array,
2663 otherwise throws an exception.
2664
2665 @par Complexity
2666 Constant.
2667
2668 @par Exception Safety
2669 Strong guarantee.
2670
2671 @throw std::invalid_argument `! this->is_array()`
2672 */
2673 array const&
2674 as_array() const
2675 {
2676 if(! is_array())
2677 detail::throw_invalid_argument(
2678 "array required",
2679 BOOST_CURRENT_LOCATION);
2680 return arr_;
2681 }
2682
2683 /** Return a reference to the underlying `string`, or throw an exception.
2684
2685 If @ref is_string() is `true`, returns
2686 a reference to the underlying @ref string,
2687 otherwise throws an exception.
2688
2689 @par Complexity
2690 Constant.
2691
2692 @par Exception Safety
2693 Strong guarantee.
2694
2695 @throw std::invalid_argument `! this->is_string()`
2696 */
2697 string&
2698 as_string()
2699 {
2700 if(! is_string())
2701 detail::throw_invalid_argument(
2702 "not a string",
2703 BOOST_CURRENT_LOCATION);
2704 return str_;
2705 }
2706
2707 /** Return a reference to the underlying `string`, or throw an exception.
2708
2709 If @ref is_string() is `true`, returns
2710 a reference to the underlying @ref string,
2711 otherwise throws an exception.
2712
2713 @par Complexity
2714 Constant.
2715
2716 @par Exception Safety
2717 Strong guarantee.
2718
2719 @throw std::invalid_argument `! this->is_string()`
2720 */
2721 string const&
2722 as_string() const
2723 {
2724 if(! is_string())
2725 detail::throw_invalid_argument(
2726 "not a string",
2727 BOOST_CURRENT_LOCATION);
2728 return str_;
2729 }
2730
2731 /** Return a reference to the underlying `std::int64_t`, or throw an exception.
2732
2733 If @ref is_int64() is `true`, returns
2734 a reference to the underlying `std::int64_t`,
2735 otherwise throws an exception.
2736
2737 @par Complexity
2738 Constant.
2739
2740 @par Exception Safety
2741 Strong guarantee.
2742
2743 @throw std::invalid_argument `! this->is_int64()`
2744 */
2745 std::int64_t&
2746 as_int64()
2747 {
2748 if(! is_int64())
2749 detail::throw_invalid_argument(
2750 "not an int64",
2751 BOOST_CURRENT_LOCATION);
2752 return sca_.i;
2753 }
2754
2755 /** Return the underlying `std::int64_t`, or throw an exception.
2756
2757 If @ref is_int64() is `true`, returns
2758 the underlying `std::int64_t`,
2759 otherwise throws an exception.
2760
2761 @par Complexity
2762 Constant.
2763
2764 @par Exception Safety
2765 Strong guarantee.
2766
2767 @throw std::invalid_argument `! this->is_int64()`
2768 */
2769 std::int64_t
2770 as_int64() const
2771 {
2772 if(! is_int64())
2773 detail::throw_invalid_argument(
2774 "not an int64",
2775 BOOST_CURRENT_LOCATION);
2776 return sca_.i;
2777 }
2778
2779 /** Return a reference to the underlying `std::uint64_t`, or throw an exception.
2780
2781 If @ref is_uint64() is `true`, returns
2782 a reference to the underlying `std::uint64_t`,
2783 otherwise throws an exception.
2784
2785 @par Complexity
2786 Constant.
2787
2788 @par Exception Safety
2789 Strong guarantee.
2790
2791 @throw std::invalid_argument `! this->is_uint64()`
2792 */
2793 std::uint64_t&
2794 as_uint64()
2795 {
2796 if(! is_uint64())
2797 detail::throw_invalid_argument(
2798 "not a uint64",
2799 BOOST_CURRENT_LOCATION);
2800 return sca_.u;
2801 }
2802
2803 /** Return the underlying `std::uint64_t`, or throw an exception.
2804
2805 If @ref is_int64() is `true`, returns
2806 the underlying `std::uint64_t`,
2807 otherwise throws an exception.
2808
2809 @par Complexity
2810 Constant.
2811
2812 @par Exception Safety
2813 Strong guarantee.
2814
2815 @throw std::length_error `! this->is_uint64()`
2816 */
2817 std::uint64_t
2818 as_uint64() const
2819 {
2820 if(! is_uint64())
2821 detail::throw_invalid_argument(
2822 "not a uint64",
2823 BOOST_CURRENT_LOCATION);
2824 return sca_.u;
2825 }
2826
2827 /** Return a reference to the underlying `double`, or throw an exception.
2828
2829 If @ref is_double() is `true`, returns
2830 a reference to the underlying `double`,
2831 otherwise throws an exception.
2832
2833 @par Complexity
2834 Constant.
2835
2836 @par Exception Safety
2837 Strong guarantee.
2838
2839 @throw std::invalid_argument `! this->is_double()`
2840 */
2841 double&
2842 as_double()
2843 {
2844 if(! is_double())
2845 detail::throw_invalid_argument(
2846 "not a double",
2847 BOOST_CURRENT_LOCATION);
2848 return sca_.d;
2849 }
2850
2851 /** Return the underlying `double`, or throw an exception.
2852
2853 If @ref is_int64() is `true`, returns
2854 the underlying `double`,
2855 otherwise throws an exception.
2856
2857 @par Complexity
2858 Constant.
2859
2860 @par Exception Safety
2861 Strong guarantee.
2862
2863 @throw std::invalid_argument `! this->is_double()`
2864 */
2865 double
2866 as_double() const
2867 {
2868 if(! is_double())
2869 detail::throw_invalid_argument(
2870 "not a double",
2871 BOOST_CURRENT_LOCATION);
2872 return sca_.d;
2873 }
2874
2875 /** Return a reference to the underlying `bool`, or throw an exception.
2876
2877 If @ref is_bool() is `true`, returns
2878 a reference to the underlying `bool`,
2879 otherwise throws an exception.
2880
2881 @par Complexity
2882 Constant.
2883
2884 @par Exception Safety
2885 Strong guarantee.
2886
2887 @throw std::invalid_argument `! this->is_bool()`
2888 */
2889 bool&
2890 as_bool()
2891 {
2892 if(! is_bool())
2893 detail::throw_invalid_argument(
2894 "bool required",
2895 BOOST_CURRENT_LOCATION);
2896 return sca_.b;
2897 }
2898
2899 /** Return the underlying `bool`, or throw an exception.
2900
2901 If @ref is_bool() is `true`, returns
2902 the underlying `bool`,
2903 otherwise throws an exception.
2904
2905 @par Complexity
2906 Constant.
2907
2908 @par Exception Safety
2909 Strong guarantee.
2910
2911 @throw std::invalid_argument `! this->is_bool()`
2912 */
2913 bool
2914 as_bool() const
2915 {
2916 if(! is_bool())
2917 detail::throw_invalid_argument(
2918 "bool required",
2919 BOOST_CURRENT_LOCATION);
2920 return sca_.b;
2921 }
2922
2923 //------------------------------------------------------
2924
2925 /** Return a reference to the underlying `object`, without checking.
2926
2927 This is the fastest way to access the underlying
2928 representation when the kind is known in advance.
2929
2930 @par Preconditions
2931
2932 @code
2933 this->is_object()
2934 @endcode
2935
2936 @par Complexity
2937 Constant.
2938
2939 @par Exception Safety
2940 No-throw guarantee.
2941 */
2942 object&
2943 get_object() noexcept
2944 {
2945 BOOST_ASSERT(is_object());
2946 return obj_;
2947 }
2948
2949 /** Return a reference to the underlying `object`, without checking.
2950
2951 This is the fastest way to access the underlying
2952 representation when the kind is known in advance.
2953
2954 @par Preconditions
2955
2956 @code
2957 this->is_object()
2958 @endcode
2959
2960 @par Complexity
2961 Constant.
2962
2963 @par Exception Safety
2964 No-throw guarantee.
2965 */
2966 object const&
2967 get_object() const noexcept
2968 {
2969 BOOST_ASSERT(is_object());
2970 return obj_;
2971 }
2972
2973 /** Return a reference to the underlying `array`, without checking.
2974
2975 This is the fastest way to access the underlying
2976 representation when the kind is known in advance.
2977
2978 @par Preconditions
2979
2980 @code
2981 this->is_array()
2982 @endcode
2983
2984 @par Complexity
2985 Constant.
2986
2987 @par Exception Safety
2988 No-throw guarantee.
2989 */
2990 array&
2991 get_array() noexcept
2992 {
2993 BOOST_ASSERT(is_array());
2994 return arr_;
2995 }
2996
2997 /** Return a reference to the underlying `array`, without checking.
2998
2999 This is the fastest way to access the underlying
3000 representation when the kind is known in advance.
3001
3002 @par Preconditions
3003
3004 @code
3005 this->is_array()
3006 @endcode
3007
3008 @par Complexity
3009 Constant.
3010
3011 @par Exception Safety
3012 No-throw guarantee.
3013 */
3014 array const&
3015 get_array() const noexcept
3016 {
3017 BOOST_ASSERT(is_array());
3018 return arr_;
3019 }
3020
3021 /** Return a reference to the underlying `string`, without checking.
3022
3023 This is the fastest way to access the underlying
3024 representation when the kind is known in advance.
3025
3026 @par Preconditions
3027
3028 @code
3029 this->is_string()
3030 @endcode
3031
3032 @par Complexity
3033 Constant.
3034
3035 @par Exception Safety
3036 No-throw guarantee.
3037 */
3038 string&
3039 get_string() noexcept
3040 {
3041 BOOST_ASSERT(is_string());
3042 return str_;
3043 }
3044
3045 /** Return a reference to the underlying `string`, without checking.
3046
3047 This is the fastest way to access the underlying
3048 representation when the kind is known in advance.
3049
3050 @par Preconditions
3051
3052 @code
3053 this->is_string()
3054 @endcode
3055
3056 @par Complexity
3057 Constant.
3058
3059 @par Exception Safety
3060 No-throw guarantee.
3061 */
3062 string const&
3063 get_string() const noexcept
3064 {
3065 BOOST_ASSERT(is_string());
3066 return str_;
3067 }
3068
3069 /** Return a reference to the underlying `std::int64_t`, without checking.
3070
3071 This is the fastest way to access the underlying
3072 representation when the kind is known in advance.
3073
3074 @par Preconditions
3075
3076 @code
3077 this->is_int64()
3078 @endcode
3079
3080 @par Complexity
3081 Constant.
3082
3083 @par Exception Safety
3084 No-throw guarantee.
3085 */
3086 std::int64_t&
3087 get_int64() noexcept
3088 {
3089 BOOST_ASSERT(is_int64());
3090 return sca_.i;
3091 }
3092
3093 /** Return the underlying `std::int64_t`, without checking.
3094
3095 This is the fastest way to access the underlying
3096 representation when the kind is known in advance.
3097
3098 @par Preconditions
3099
3100 @code
3101 this->is_int64()
3102 @endcode
3103
3104 @par Complexity
3105 Constant.
3106
3107 @par Exception Safety
3108 No-throw guarantee.
3109 */
3110 std::int64_t
3111 get_int64() const noexcept
3112 {
3113 BOOST_ASSERT(is_int64());
3114 return sca_.i;
3115 }
3116
3117 /** Return a reference to the underlying `std::uint64_t`, without checking.
3118
3119 This is the fastest way to access the underlying
3120 representation when the kind is known in advance.
3121
3122 @par Preconditions
3123
3124 @code
3125 this->is_uint64()
3126 @endcode
3127
3128 @par Complexity
3129 Constant.
3130
3131 @par Exception Safety
3132 No-throw guarantee.
3133 */
3134 std::uint64_t&
3135 get_uint64() noexcept
3136 {
3137 BOOST_ASSERT(is_uint64());
3138 return sca_.u;
3139 }
3140
3141 /** Return the underlying `std::uint64_t`, without checking.
3142
3143 This is the fastest way to access the underlying
3144 representation when the kind is known in advance.
3145
3146 @par Preconditions
3147
3148 @code
3149 this->is_uint64()
3150 @endcode
3151
3152 @par Complexity
3153 Constant.
3154
3155 @par Exception Safety
3156 No-throw guarantee.
3157 */
3158 std::uint64_t
3159 get_uint64() const noexcept
3160 {
3161 BOOST_ASSERT(is_uint64());
3162 return sca_.u;
3163 }
3164
3165 /** Return a reference to the underlying `double`, without checking.
3166
3167 This is the fastest way to access the underlying
3168 representation when the kind is known in advance.
3169
3170 @par Preconditions
3171
3172 @code
3173 this->is_double()
3174 @endcode
3175
3176 @par Complexity
3177 Constant.
3178
3179 @par Exception Safety
3180 No-throw guarantee.
3181 */
3182 double&
3183 get_double() noexcept
3184 {
3185 BOOST_ASSERT(is_double());
3186 return sca_.d;
3187 }
3188
3189 /** Return the underlying `double`, without checking.
3190
3191 This is the fastest way to access the underlying
3192 representation when the kind is known in advance.
3193
3194 @par Preconditions
3195
3196 @code
3197 this->is_double()
3198 @endcode
3199
3200 @par Complexity
3201 Constant.
3202
3203 @par Exception Safety
3204 No-throw guarantee.
3205 */
3206 double
3207 get_double() const noexcept
3208 {
3209 BOOST_ASSERT(is_double());
3210 return sca_.d;
3211 }
3212
3213 /** Return a reference to the underlying `bool`, without checking.
3214
3215 This is the fastest way to access the underlying
3216 representation when the kind is known in advance.
3217
3218 @par Preconditions
3219
3220 @code
3221 this->is_bool()
3222 @endcode
3223
3224 @par Complexity
3225 Constant.
3226
3227 @par Exception Safety
3228 No-throw guarantee.
3229 */
3230 bool&
3231 get_bool() noexcept
3232 {
3233 BOOST_ASSERT(is_bool());
3234 return sca_.b;
3235 }
3236
3237 /** Return the underlying `bool`, without checking.
3238
3239 This is the fastest way to access the underlying
3240 representation when the kind is known in advance.
3241
3242 @par Preconditions
3243
3244 @code
3245 this->is_bool()
3246 @endcode
3247
3248 @par Complexity
3249 Constant.
3250
3251 @par Exception Safety
3252 No-throw guarantee.
3253 */
3254 bool
3255 get_bool() const noexcept
3256 {
3257 BOOST_ASSERT(is_bool());
3258 return sca_.b;
3259 }
3260
3261 //------------------------------------------------------
3262
3263 /** Access an element, with bounds checking.
3264
3265 This function is used to access elements of
3266 the underlying object, or throw an exception
3267 if the value is not an object.
3268
3269 @par Complexity
3270 Constant.
3271
3272 @par Exception Safety
3273 Strong guarantee.
3274
3275 @param key The key of the element to find.
3276
3277 @return `this->as_object().at( key )`.
3278 */
3279 value const&
3280 at(string_view key) const
3281 {
3282 return as_object().at(key);
3283 }
3284
3285 /** Access an element, with bounds checking.
3286
3287 This function is used to access elements of
3288 the underlying array, or throw an exception
3289 if the value is not an array.
3290
3291 @par Complexity
3292 Constant.
3293
3294 @par Exception Safety
3295 Strong guarantee.
3296
3297 @param pos A zero-based array index.
3298
3299 @return `this->as_array().at( pos )`.
3300 */
3301 value const&
3302 at(std::size_t pos) const
3303 {
3304 return as_array().at(pos);
3305 }
3306
3307 /** Return `true` if two values are equal.
3308
3309 Two values are equal when they are the
3310 same kind and their referenced values
3311 are equal, or when they are both integral
3312 types and their integral representations
3313 are equal.
3314
3315 @par Complexity
3316 Constant or linear in the size of
3317 the array, object, or string.
3318
3319 @par Exception Safety
3320 No-throw guarantee.
3321 */
3322 // inline friend speeds up overload resolution
3323 friend
3324 bool
3325 operator==(
3326 value const& lhs,
3327 value const& rhs) noexcept
3328 {
3329 return lhs.equal(rhs);
3330 }
3331
3332 /** Return `true` if two values are not equal.
3333
3334 Two values are equal when they are the
3335 same kind and their referenced values
3336 are equal, or when they are both integral
3337 types and their integral representations
3338 are equal.
3339
3340 @par Complexity
3341 Constant or linear in the size of
3342 the array, object, or string.
3343
3344 @par Exception Safety
3345 No-throw guarantee.
3346 */
3347 friend
3348 bool
3349 operator!=(
3350 value const& lhs,
3351 value const& rhs) noexcept
3352 {
3353 return ! (lhs == rhs);
3354 }
3355
3356 private:
3357 static
3358 void
3359 relocate(
3360 value* dest,
3361 value const& src) noexcept
3362 {
3363 std::memcpy(
3364 static_cast<void*>(dest),
3365 &src,
3366 sizeof(src));
3367 }
3368
3369 BOOST_JSON_DECL
3370 storage_ptr
3371 destroy() noexcept;
3372
3373 BOOST_JSON_DECL
3374 bool
3375 equal(value const& other) const noexcept;
3376 };
3377
3378 // Make sure things are as big as we think they should be
3379 #if BOOST_JSON_ARCH == 64
3380 BOOST_STATIC_ASSERT(sizeof(value) == 24);
3381 #elif BOOST_JSON_ARCH == 32
3382 BOOST_STATIC_ASSERT(sizeof(value) == 16);
3383 #else
3384 # error Unknown architecture
3385 #endif
3386
3387 //----------------------------------------------------------
3388
3389 /** A key/value pair.
3390
3391 This is the type of element used by the @ref object
3392 container.
3393 */
3394 class key_value_pair
3395 {
3396 #ifndef BOOST_JSON_DOCS
3397 friend struct detail::access;
3398 using access = detail::access;
3399 #endif
3400
3401 BOOST_JSON_DECL
3402 static char const empty_[1];
3403
3404 inline
3405 key_value_pair(
3406 pilfered<json::value> k,
3407 pilfered<json::value> v) noexcept;
3408
3409 public:
3410 /// Copy assignment (deleted).
3411 key_value_pair&
3412 operator=(key_value_pair const&) = delete;
3413
3414 /** Destructor.
3415
3416 The value is destroyed and all internally
3417 allocated memory is freed.
3418 */
3419 ~key_value_pair()
3420 {
3421 auto const& sp = value_.storage();
3422 if(sp.is_not_shared_and_deallocate_is_trivial())
3423 return;
3424 if(key_ == empty_)
3425 return;
3426 sp->deallocate(const_cast<char*>(key_),
3427 len_ + 1, alignof(char));
3428 }
3429
3430 /** Copy constructor.
3431
3432 This constructs a key/value pair with a
3433 copy of another key/value pair, using
3434 the same memory resource as `other`.
3435
3436 @par Exception Safety
3437 Strong guarantee.
3438 Calls to `memory_resource::allocate` may throw.
3439
3440 @param other The key/value pair to copy.
3441 */
3442 key_value_pair(
3443 key_value_pair const& other)
3444 : key_value_pair(other,
3445 other.storage())
3446 {
3447 }
3448
3449 /** Copy constructor.
3450
3451 This constructs a key/value pair with a
3452 copy of another key/value pair, using
3453 the specified memory resource.
3454
3455 @par Exception Safety
3456 Strong guarantee.
3457 Calls to `memory_resource::allocate` may throw.
3458
3459 @param other The key/value pair to copy.
3460
3461 @param sp A pointer to the @ref memory_resource
3462 to use. The element will acquire shared
3463 ownership of the memory resource.
3464 */
3465 BOOST_JSON_DECL
3466 key_value_pair(
3467 key_value_pair const& other,
3468 storage_ptr sp);
3469
3470 /** Move constructor.
3471
3472 The pair is constructed by acquiring
3473 ownership of the contents of `other` and
3474 shared ownership of `other`'s memory resource.
3475
3476 @note
3477
3478 After construction, the moved-from pair holds an
3479 empty key, and a null value with its current
3480 storage pointer.
3481
3482 @par Complexity
3483 Constant.
3484
3485 @par Exception Safety
3486 No-throw guarantee.
3487
3488 @param other The pair to move.
3489 */
3490 key_value_pair(
3491 key_value_pair&& other) noexcept
3492 : value_(std::move(other.value_))
3493 , key_(detail::exchange(
3494 other.key_, empty_))
3495 , len_(detail::exchange(
3496 other.len_, 0))
3497 {
3498 }
3499
3500 /** Pilfer constructor.
3501
3502 The pair is constructed by acquiring ownership
3503 of the contents of `other` using pilfer semantics.
3504 This is more efficient than move construction, when
3505 it is known that the moved-from object will be
3506 immediately destroyed afterwards.
3507
3508 @par Complexity
3509 Constant.
3510
3511 @par Exception Safety
3512 No-throw guarantee.
3513
3514 @param other The value to pilfer. After pilfer
3515 construction, `other` is not in a usable state
3516 and may only be destroyed.
3517
3518 @see @ref pilfer,
3519 <a href="http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html">
3520 Valueless Variants Considered Harmful</a>
3521 */
3522 key_value_pair(
3523 pilfered<key_value_pair> other) noexcept
3524 : value_(pilfer(other.get().value_))
3525 , key_(detail::exchange(
3526 other.get().key_, empty_))
3527 , len_(detail::exchange(
3528 other.get().len_, 0))
3529 {
3530 }
3531
3532 /** Constructor.
3533
3534 This constructs a key/value pair.
3535
3536 @par Exception Safety
3537 Strong guarantee.
3538 Calls to `memory_resource::allocate` may throw.
3539
3540 @param key The key string to use.
3541
3542 @param args Optional arguments forwarded to
3543 the @ref value constructor.
3544 */
3545 template<class... Args>
3546 explicit
3547 key_value_pair(
3548 string_view key,
3549 Args&&... args)
3550 : value_(std::forward<Args>(args)...)
3551 {
3552 if(key.size() > string::max_size())
3553 detail::throw_length_error(
3554 "key too large",
3555 BOOST_CURRENT_LOCATION);
3556 auto s = reinterpret_cast<
3557 char*>(value_.storage()->
3558 allocate(key.size() + 1));
3559 std::memcpy(s, key.data(), key.size());
3560 s[key.size()] = 0;
3561 key_ = s;
3562 len_ = static_cast<
3563 std::uint32_t>(key.size());
3564 }
3565
3566 /** Constructor.
3567
3568 This constructs a key/value pair. A
3569 copy of the specified value is made,
3570 using the specified memory resource.
3571
3572 @par Exception Safety
3573 Strong guarantee.
3574 Calls to `memory_resource::allocate` may throw.
3575
3576 @param p A `std::pair` with the key
3577 string and @ref value to construct with.
3578
3579 @param sp A pointer to the @ref memory_resource
3580 to use. The element will acquire shared
3581 ownership of the memory resource.
3582 */
3583 explicit
3584 key_value_pair(
3585 std::pair<
3586 string_view,
3587 json::value> const& p,
3588 storage_ptr sp = {})
3589 : key_value_pair(
3590 p.first,
3591 p.second,
3592 std::move(sp))
3593 {
3594 }
3595
3596 /** Constructor.
3597
3598 This constructs a key/value pair.
3599 Ownership of the specified value is
3600 transferred by move construction.
3601
3602 @par Exception Safety
3603 Strong guarantee.
3604 Calls to `memory_resource::allocate` may throw.
3605
3606 @param p A `std::pair` with the key
3607 string and @ref value to construct with.
3608
3609 @param sp A pointer to the @ref memory_resource
3610 to use. The element will acquire shared
3611 ownership of the memory resource.
3612 */
3613 explicit
3614 key_value_pair(
3615 std::pair<
3616 string_view,
3617 json::value>&& p,
3618 storage_ptr sp = {})
3619 : key_value_pair(
3620 p.first,
3621 std::move(p).second,
3622 std::move(sp))
3623 {
3624 }
3625
3626 /** Return the associated memory resource.
3627
3628 This returns a pointer to the memory
3629 resource used to construct the value.
3630
3631 @par Complexity
3632 Constant.
3633
3634 @par Exception Safety
3635 No-throw guarantee.
3636 */
3637 storage_ptr const&
3638 storage() const noexcept
3639 {
3640 return value_.storage();
3641 }
3642
3643 /** Return the key of this element.
3644
3645 After construction, the key may
3646 not be modified.
3647
3648 @par Complexity
3649 Constant.
3650
3651 @par Exception Safety
3652 No-throw guarantee.
3653 */
3654 string_view const
3655 key() const noexcept
3656 {
3657 return { key_, len_ };
3658 }
3659
3660 /** Return the key of this element as a null-terminated string.
3661
3662 @par Complexity
3663 Constant.
3664
3665 @par Exception Safety
3666 No-throw guarantee.
3667 */
3668 char const*
3669 key_c_str() const noexcept
3670 {
3671 return key_;
3672 }
3673
3674 /** Return the value of this element.
3675
3676 @par Complexity
3677 Constant.
3678
3679 @par Exception Safety
3680 No-throw guarantee.
3681 */
3682 json::value const&
3683 value() const noexcept
3684 {
3685 return value_;
3686 }
3687
3688 /** Return the value of this element.
3689
3690 @par Complexity
3691 Constant.
3692
3693 @par Exception Safety
3694 No-throw guarantee.
3695 */
3696 json::value&
3697 value() noexcept
3698 {
3699 return value_;
3700 }
3701
3702 private:
3703 json::value value_;
3704 char const* key_;
3705 std::uint32_t len_;
3706 std::uint32_t next_;
3707 };
3708
3709 //----------------------------------------------------------
3710
3711 #ifdef BOOST_JSON_DOCS
3712
3713 /** Tuple-like element access.
3714
3715 This overload permits the key and value
3716 of a `key_value_pair` to be accessed
3717 by index. For example:
3718
3719 @code
3720
3721 key_value_pair kvp("num", 42);
3722
3723 string_view key = get<0>(kvp);
3724 value& jv = get<1>(kvp);
3725
3726 @endcode
3727
3728 @par Structured Bindings
3729
3730 When using C++17 or greater, objects of type
3731 @ref key_value_pair may be used to initialize
3732 structured bindings:
3733
3734 @code
3735
3736 key_value_pair kvp("num", 42);
3737
3738 auto& [key, value] = kvp;
3739
3740 @endcode
3741
3742 Depending on the value of `I`, the return type will be:
3743
3744 @li `string_view const` if `I == 0`, or
3745
3746 @li `value&`, `value const&`, or `value&&` if `I == 1`.
3747
3748 Any other value for `I` is ill-formed.
3749
3750 @tparam I The element index to access.
3751
3752 @par Constraints
3753
3754 `std::is_same_v< std::remove_cvref_t<T>, key_value_pair >`
3755
3756 @return `kvp.key()` if `I == 0`, or `kvp.value()`
3757 if `I == 1`.
3758
3759 @param kvp The @ref key_value_pair object
3760 to access.
3761 */
3762 template<
3763 std::size_t I,
3764 class T>
3765 __see_below__
3766 get(T&& kvp) noexcept;
3767
3768 #else
3769
3770 template<std::size_t I>
3771 auto
3772 get(key_value_pair const&) noexcept ->
3773 typename std::conditional<I == 0,
3774 string_view const,
3775 value const&>::type
3776 {
3777 static_assert(I == 0,
3778 "key_value_pair index out of range");
3779 }
3780
3781 template<std::size_t I>
3782 auto
3783 get(key_value_pair&) noexcept ->
3784 typename std::conditional<I == 0,
3785 string_view const,
3786 value&>::type
3787 {
3788 static_assert(I == 0,
3789 "key_value_pair index out of range");
3790 }
3791
3792 template<std::size_t I>
3793 auto
3794 get(key_value_pair&&) noexcept ->
3795 typename std::conditional<I == 0,
3796 string_view const,
3797 value&&>::type
3798 {
3799 static_assert(I == 0,
3800 "key_value_pair index out of range");
3801 }
3802
3803 /** Extracts a key_value_pair's key using tuple-like interface
3804 */
3805 template<>
3806 inline
3807 string_view const
3808 get<0>(key_value_pair const& kvp) noexcept
3809 {
3810 return kvp.key();
3811 }
3812
3813 /** Extracts a key_value_pair's key using tuple-like interface
3814 */
3815 template<>
3816 inline
3817 string_view const
3818 get<0>(key_value_pair& kvp) noexcept
3819 {
3820 return kvp.key();
3821 }
3822
3823 /** Extracts a key_value_pair's key using tuple-like interface
3824 */
3825 template<>
3826 inline
3827 string_view const
3828 get<0>(key_value_pair&& kvp) noexcept
3829 {
3830 return kvp.key();
3831 }
3832
3833 /** Extracts a key_value_pair's value using tuple-like interface
3834 */
3835 template<>
3836 inline
3837 value const&
3838 get<1>(key_value_pair const& kvp) noexcept
3839 {
3840 return kvp.value();
3841 }
3842
3843 /** Extracts a key_value_pair's value using tuple-like interface
3844 */
3845 template<>
3846 inline
3847 value&
3848 get<1>(key_value_pair& kvp) noexcept
3849 {
3850 return kvp.value();
3851 }
3852
3853 /** Extracts a key_value_pair's value using tuple-like interface
3854 */
3855 template<>
3856 inline
3857 value&&
3858 get<1>(key_value_pair&& kvp) noexcept
3859 {
3860 return std::move(kvp.value());
3861 }
3862
3863 #endif
3864
3865 BOOST_JSON_NS_END
3866
3867 #ifdef __clang__
3868 # pragma clang diagnostic push
3869 # pragma clang diagnostic ignored "-Wmismatched-tags"
3870 #endif
3871
3872 #ifndef BOOST_JSON_DOCS
3873
3874 namespace std {
3875
3876 /** Tuple-like size access for key_value_pair
3877 */
3878 template<>
3879 struct tuple_size< ::boost::json::key_value_pair >
3880 : std::integral_constant<std::size_t, 2>
3881 {
3882 };
3883
3884 /** Tuple-like access for the key type of key_value_pair
3885 */
3886 template<>
3887 struct tuple_element<0, ::boost::json::key_value_pair>
3888 {
3889 using type = ::boost::json::string_view const;
3890 };
3891
3892 /** Tuple-like access for the value type of key_value_pair
3893 */
3894 template<>
3895 struct tuple_element<1, ::boost::json::key_value_pair>
3896 {
3897 using type = ::boost::json::value&;
3898 };
3899
3900 /** Tuple-like access for the value type of key_value_pair
3901 */
3902 template<>
3903 struct tuple_element<1, ::boost::json::key_value_pair const>
3904 {
3905 using type = ::boost::json::value const&;
3906 };
3907
3908 } // std
3909
3910 #endif
3911
3912 #ifdef __clang__
3913 # pragma clang diagnostic pop
3914 #endif
3915
3916 // These are here because value, array,
3917 // and object form cyclic references.
3918
3919 #include <boost/json/detail/impl/array.hpp>
3920 #include <boost/json/impl/array.hpp>
3921 #include <boost/json/impl/object.hpp>
3922
3923 // These must come after array and object
3924 #include <boost/json/impl/value_ref.hpp>
3925
3926 #endif