GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: value.hpp
Date: 2026-01-02 17:31:41
Exec Total Coverage
Lines: 516 522 98.9%
Functions: 192 196 98.0%
Branches: 142 164 86.6%

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