GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: value.hpp
Date: 2026-01-06 06:25:57
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 2150 value(
76 detail::unchecked_array&& ua)
77 2150 : arr_(std::move(ua))
78 {
79 2112 }
80
81 explicit
82 34935 value(
83 detail::unchecked_object&& uo)
84 34935 : obj_(std::move(uo))
85 {
86 34896 }
87
88 30407 value(
89 detail::key_t const&,
90 string_view s,
91 storage_ptr sp)
92
1/1
✓ Branch 3 taken 30347 times.
30407 : str_(detail::key_t{}, s, std::move(sp))
93 {
94 30347 }
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 5873 value(
306 long i,
307 storage_ptr sp = {}) noexcept
308 5873 : sca_(static_cast<std::int64_t>(i),
309 5873 std::move(sp))
310 {
311 5873 }
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 17217 value(
389 string_view s,
390 storage_ptr sp = {})
391
1/1
✓ Branch 3 taken 17209 times.
17217 : str_(s, std::move(sp))
392 {
393 17209 }
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 24 value(value const& other)
523
1/1
✓ Branch 3 taken 24 times.
24 : value(other, other.storage())
524 {
525 24 }
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 2129250 value(pilfered<value> other) noexcept
545 2129250 {
546 2129250 relocate(this, other.get());
547 2129250 ::new(&other.get().sca_) scalar();
548 2129250 }
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 4610808 kind() const noexcept
1169 {
1170 return static_cast<json::kind>(
1171 static_cast<unsigned char>(
1172 4610808 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 6085 is_array() const noexcept
1189 {
1190 6085 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 53385 is_object() const noexcept
1207 {
1208 53385 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 88436 is_string() const noexcept
1225 {
1226 88436 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 14930 is_int64() const noexcept
1243 {
1244 14930 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 76236 storage() const noexcept
1813 {
1814 76236 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 84 get_object() & noexcept
2387 {
2388
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 84 times.
84 BOOST_ASSERT(is_object());
2389 84 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 53020 get_object() const& noexcept
2401 {
2402
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 53020 times.
53020 BOOST_ASSERT(is_object());
2403 53020 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 57 get_array() & noexcept
2428 {
2429
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 57 times.
57 BOOST_ASSERT(is_array());
2430 57 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 5739 get_array() const& noexcept
2442 {
2443
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 5739 times.
5739 BOOST_ASSERT(is_array());
2444 5739 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 40977 get_string() const& noexcept
2483 {
2484
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 40977 times.
40977 BOOST_ASSERT(is_string());
2485 40977 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 14342 get_int64() const noexcept
2517 {
2518
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14342 times.
14342 BOOST_ASSERT(is_int64());
2519 14342 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 /** Remove an element via JSON Pointer.
3039
3040 @{
3041 */
3042 BOOST_JSON_DECL
3043 bool
3044 erase_at_pointer(
3045 string_view sv,
3046 system::error_code& ec);
3047
3048 /// @}
3049 //------------------------------------------------------
3050
3051 /** Check if two values are equal.
3052
3053 Two values are equal when they are the same kind and their referenced
3054 values are equal, or when they are both integral types and their
3055 integral representations are equal.
3056
3057 @par Complexity
3058 Constant or linear in the size of the underlying @ref array, @ref object,
3059 or @ref string.
3060
3061 @par Exception Safety
3062 No-throw guarantee.
3063 */
3064 // inline friend speeds up overload resolution
3065 friend
3066 bool
3067 4260 operator==(
3068 value const& lhs,
3069 value const& rhs) noexcept
3070 {
3071 4260 return lhs.equal(rhs);
3072 }
3073
3074 /** Check if two values are not equal.
3075
3076 Two values are equal when they are the same kind and their referenced
3077 values are equal, or when they are both integral types and their
3078 integral representations are equal.
3079
3080 @par Complexity
3081 Constant or linear in the size of the underlying @ref array,
3082 @ref object, or @ref string.
3083
3084 @par Exception Safety
3085 No-throw guarantee.
3086 */
3087 friend
3088 bool
3089 4073 operator!=(
3090 value const& lhs,
3091 value const& rhs) noexcept
3092 {
3093 4073 return ! (lhs == rhs);
3094 }
3095
3096 /** Serialize @ref value to an output stream.
3097
3098 This function serializes a `value` as JSON text into the output stream.
3099
3100 @return Reference to `os`.
3101
3102 @par Complexity
3103 Constant or linear in the size of `jv`.
3104
3105 @par Exception Safety
3106 Strong guarantee.
3107 Calls to `memory_resource::allocate` may throw.
3108
3109 @param os The output stream to serialize to.
3110
3111 @param jv The value to serialize.
3112 */
3113 BOOST_JSON_DECL
3114 friend
3115 std::ostream&
3116 operator<<(
3117 std::ostream& os,
3118 value const& jv);
3119
3120 /** Parse @ref value from an input stream.
3121
3122 This function parses JSON from an input stream into a `value`. If
3123 parsing fails, @ref std::ios_base::failbit will be set for `is` and
3124 `jv` will be left unchanged. Regardless of whether @ref
3125 std::ios_base::skipws flag is set on `is`, consumes whitespace before
3126 and after JSON, because whitespace is considered a part of JSON.
3127 Behaves as
3128 [_FormattedInputFunction_](https://en.cppreference.com/w/cpp/named_req/FormattedInputFunction).
3129
3130 @note This operator cannot assume that the stream only contains a
3131 single JSON document, which may result in **very underwhelming
3132 performance**, if the stream isn't cooperative. If you know that your
3133 input consists of a single JSON document, consider using @ref parse
3134 function instead.
3135
3136 @return Reference to `is`.
3137
3138 @par Complexity
3139 Linear in the size of JSON data.
3140
3141 @par Exception Safety
3142 Basic guarantee.
3143 Calls to `memory_resource::allocate` may throw.
3144 The stream may throw as configured by @ref std::ios::exceptions.
3145
3146 @param is The input stream to parse from.
3147
3148 @param jv The value to parse into.
3149
3150 @see @ref parse.
3151 */
3152 BOOST_JSON_DECL
3153 friend
3154 std::istream&
3155 operator>>(
3156 std::istream& is,
3157 value& jv);
3158
3159 /** Helper for @ref boost::hash support.
3160
3161 Computes a hash value for `jv`. This function is used by
3162 `boost::hash<value>`. Similar overloads for @ref array, @ref object,
3163 and @ref string do not exist, because those types are supported by
3164 `boost::hash` out of the box.
3165
3166 @return hash value for `jv`.
3167
3168 @param jv `value` for which a hash is to be computed.
3169
3170 @see [Boost.ContainerHash](https://boost.org/libs/container_hash).
3171 */
3172 #ifndef BOOST_JSON_DOCS
3173 template<
3174 class T,
3175 typename std::enable_if<
3176 std::is_same< detail::remove_cvref<T>, value >::value >::type*
3177 = nullptr>
3178 friend
3179 std::size_t
3180 248 hash_value( T const& jv ) noexcept
3181 #else
3182 friend
3183 inline
3184 std::size_t
3185 hash_value( value const& jv ) noexcept
3186 #endif
3187 {
3188 248 return detail::hash_value_impl(jv);
3189 }
3190
3191 private:
3192 static
3193 void
3194 2133583 relocate(
3195 value* dest,
3196 value const& src) noexcept
3197 {
3198 2133583 std::memcpy(
3199 static_cast<void*>(dest),
3200 &src,
3201 sizeof(src));
3202 2133583 }
3203
3204 BOOST_JSON_DECL
3205 storage_ptr
3206 destroy() noexcept;
3207
3208 BOOST_JSON_DECL
3209 bool
3210 equal(value const& other) const noexcept;
3211
3212 template<class T>
3213 auto
3214 6803 to_number(error& e) const noexcept ->
3215 typename std::enable_if<
3216 std::is_signed<T>::value &&
3217 ! std::is_floating_point<T>::value,
3218 T>::type
3219 {
3220
2/2
✓ Branch 0 taken 3321 times.
✓ Branch 1 taken 87 times.
6803 if(sca_.k == json::kind::int64)
3221 {
3222 6629 auto const i = sca_.i;
3223
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)() &&
3224
2/2
✓ Branch 1 taken 3287 times.
✓ Branch 2 taken 6 times.
6617 i <= (std::numeric_limits<T>::max)())
3225 {
3226 6605 e = {};
3227 6605 return static_cast<T>(i);
3228 }
3229 24 e = error::not_exact;
3230 }
3231
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 67 times.
174 else if(sca_.k == json::kind::uint64)
3232 {
3233 40 auto const u = sca_.u;
3234
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 10 times.
40 if(u <= static_cast<std::uint64_t>((
3235 40 std::numeric_limits<T>::max)()))
3236 {
3237 20 e = {};
3238 20 return static_cast<T>(u);
3239 }
3240 20 e = error::not_exact;
3241 }
3242
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 47 times.
134 else if(sca_.k == json::kind::double_)
3243 {
3244 40 auto const d = sca_.d;
3245 40 if( d >= static_cast<double>(
3246
1/2
✓ Branch 1 taken 20 times.
✗ Branch 2 not taken.
80 (detail::to_number_limit<T>::min)()) &&
3247 d <= static_cast<double>(
3248
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)()) &&
3249
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 11 times.
40 static_cast<T>(d) == d)
3250 {
3251 18 e = {};
3252 18 return static_cast<T>(d);
3253 }
3254 22 e = error::not_exact;
3255 }
3256 else
3257 {
3258 94 e = error::not_number;
3259 }
3260 160 return T{};
3261 }
3262
3263 template<class T>
3264 auto
3265 222 to_number(error& e) const noexcept ->
3266 typename std::enable_if<
3267 std::is_unsigned<T>::value &&
3268 ! std::is_same<T, bool>::value,
3269 T>::type
3270 {
3271
2/2
✓ Branch 0 taken 44 times.
✓ Branch 1 taken 75 times.
222 if(sca_.k == json::kind::int64)
3272 {
3273 76 auto const i = sca_.i;
3274
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) <=
3275
2/2
✓ Branch 1 taken 18 times.
✓ Branch 2 taken 6 times.
44 (std::numeric_limits<T>::max)())
3276 {
3277 32 e = {};
3278 32 return static_cast<T>(i);
3279 }
3280 44 e = error::not_exact;
3281 }
3282
2/2
✓ Branch 0 taken 58 times.
✓ Branch 1 taken 17 times.
146 else if(sca_.k == json::kind::uint64)
3283 {
3284 112 auto const u = sca_.u;
3285
2/2
✓ Branch 1 taken 52 times.
✓ Branch 2 taken 6 times.
112 if(u <= (std::numeric_limits<T>::max)())
3286 {
3287 100 e = {};
3288 100 return static_cast<T>(u);
3289 }
3290 12 e = error::not_exact;
3291 }
3292
2/2
✓ Branch 0 taken 12 times.
✓ Branch 1 taken 5 times.
34 else if(sca_.k == json::kind::double_)
3293 {
3294 24 auto const d = sca_.d;
3295
1/2
✓ Branch 0 taken 8 times.
✗ Branch 1 not taken.
16 if( d >= 0 &&
3296
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)() &&
3297
2/2
✓ Branch 0 taken 4 times.
✓ Branch 1 taken 4 times.
16 static_cast<T>(d) == d)
3298 {
3299 8 e = {};
3300 8 return static_cast<T>(d);
3301 }
3302 16 e = error::not_exact;
3303 }
3304 else
3305 {
3306 10 e = error::not_number;
3307 }
3308 82 return T{};
3309 }
3310
3311 template<class T>
3312 auto
3313 134 to_number(error& e) const noexcept ->
3314 typename std::enable_if<
3315 std::is_floating_point<
3316 T>::value, T>::type
3317 {
3318
2/2
✓ Branch 0 taken 16 times.
✓ Branch 1 taken 51 times.
134 if(sca_.k == json::kind::int64)
3319 {
3320 32 e = {};
3321 32 return static_cast<T>(sca_.i);
3322 }
3323
2/2
✓ Branch 0 taken 10 times.
✓ Branch 1 taken 41 times.
102 if(sca_.k == json::kind::uint64)
3324 {
3325 20 e = {};
3326 20 return static_cast<T>(sca_.u);
3327 }
3328
2/2
✓ Branch 0 taken 27 times.
✓ Branch 1 taken 14 times.
82 if(sca_.k == json::kind::double_)
3329 {
3330 54 e = {};
3331 54 return static_cast<T>(sca_.d);
3332 }
3333 28 e = error::not_number;
3334 28 return {};
3335 }
3336 };
3337
3338 // Make sure things are as big as we think they should be
3339 #if BOOST_JSON_ARCH == 64
3340 BOOST_CORE_STATIC_ASSERT( sizeof(value) == 24 );
3341 #elif BOOST_JSON_ARCH == 32
3342 BOOST_CORE_STATIC_ASSERT( sizeof(value) == 16 );
3343 #else
3344 # error Unknown architecture
3345 #endif
3346
3347 //----------------------------------------------------------
3348
3349 /** A key/value pair.
3350
3351 This is the type of element used by the @ref object container.
3352 */
3353 class key_value_pair
3354 {
3355 #ifndef BOOST_JSON_DOCS
3356 friend struct detail::access;
3357 using access = detail::access;
3358 #endif
3359
3360 BOOST_JSON_DECL
3361 static char const empty_[1];
3362
3363 inline
3364 key_value_pair(
3365 pilfered<json::value> k,
3366 pilfered<json::value> v) noexcept;
3367
3368 public:
3369 /** Assignment
3370
3371 This type is not copy or move-assignable. The copy assignment operator
3372 is deleted.
3373 */
3374 key_value_pair&
3375 operator=(key_value_pair const&) = delete;
3376
3377 /** Destructor.
3378
3379 The value is destroyed and all internally allocated memory is freed.
3380 */
3381 59355 ~key_value_pair() noexcept
3382 52605 {
3383 59355 auto const& sp = value_.storage();
3384
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 59355 times.
59355 if(sp.is_not_shared_and_deallocate_is_trivial())
3385 return;
3386
2/2
✓ Branch 0 taken 6750 times.
✓ Branch 1 taken 52605 times.
59355 if(key_ == empty_)
3387 6750 return;
3388 52605 sp->deallocate(const_cast<char*>(key_),
3389 52605 len_ + 1, alignof(char));
3390 59355 }
3391
3392 /** Constructors.
3393
3394 Construct a key/value pair.
3395
3396 @li **(1)** uses a copy of the characters of `key`, and constructs the
3397 value as if by `value(std::forward<Args>(args)...)`.
3398 @li **(2)** equivalent to `key_value_pair(p.first, p.second, sp)`.
3399 @li **(3)** equivalent to
3400 `key_value_pair(p.first, std::move(p.second), sp)`.
3401 @li **(4)** equivalent to
3402 `key_value_pair(other.key(), other.value(), sp)`.
3403 @li **(5)** equivalent to
3404 `key_value_pair(other.key(), other.value(), other.storage())`.
3405 @li **(6)** the pair s constructed by acquiring ownership of the
3406 contents of `other` using move semantics.
3407 @li **(7)** the pair is constructed by acquiring ownership of the
3408 contents of `other` using pilfer semantics. This is more efficient
3409 than move construction, when it is known that the moved-from object
3410 will be immediately destroyed afterwards.
3411
3412 With **(2)**, **(3)**, **(4)** the pair uses the memory resource of
3413 `sp`. With **(5)**, **(6)**, **(7)** it uses the memory resource of
3414 `other.storage()`. With **(1)** it uses whatever memory resource
3415 `value(std::forward<Args>(args)...)` would use. In any case the pair
3416 acquires shared ownership of its memory resource
3417
3418 After **(6)** `other` holds an empty key, and a null value with its
3419 current storage pointer.
3420
3421 After **(7)** `other` is not in a usable state and may only be destroyed.
3422
3423 @par Complexity
3424 Constant.
3425
3426 @par Exception Safety
3427 Strong guarantee. Calls to `memory_resource::allocate` may throw.
3428 @param key The key string to use.
3429 @param args Optional arguments forwarded to the @ref value constructor.
3430
3431 @throw boost::system::system_error The size of the key would exceed
3432 @ref string::max_size.
3433
3434 @see @ref pilfer,
3435 [Valueless Variants Considered Harmful](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html).
3436
3437 @{
3438 */
3439 template<class... Args>
3440 explicit
3441 15556 key_value_pair(
3442 string_view key,
3443 Args&&... args)
3444
2/2
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 3720 times.
15558 : value_(std::forward<Args>(args)...)
3445 {
3446
2/2
✓ Branch 2 taken 1 times.
✓ Branch 3 taken 7880 times.
15554 if(key.size() > string::max_size())
3447 {
3448 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
3449 2 detail::throw_system_error( error::key_too_large, &loc );
3450 }
3451 auto s = reinterpret_cast<
3452 15552 char*>(value_.storage()->
3453
1/1
✓ Branch 3 taken 7574 times.
15552 allocate(key.size() + 1, alignof(char)));
3454 14940 std::memcpy(s, key.data(), key.size());
3455 14940 s[key.size()] = 0;
3456 14940 key_ = s;
3457 14940 len_ = static_cast<
3458 14940 std::uint32_t>(key.size());
3459 15554 }
3460
3461 /** Overload
3462
3463 @param p A `std::pair` with the key string and @ref value to construct
3464 with.
3465 @param sp A pointer to the @ref boost::container::pmr::memory_resource
3466 to use.
3467 */
3468 explicit
3469 key_value_pair(
3470 std::pair<
3471 string_view,
3472 json::value> const& p,
3473 storage_ptr sp = {})
3474 : key_value_pair(
3475 p.first,
3476 p.second,
3477 std::move(sp))
3478 {
3479 }
3480
3481 /// Overload
3482 explicit
3483 3125 key_value_pair(
3484 std::pair<
3485 string_view,
3486 json::value>&& p,
3487 storage_ptr sp = {})
3488 3125 : key_value_pair(
3489 p.first,
3490 3125 std::move(p).second,
3491 6250 std::move(sp))
3492 {
3493 2978 }
3494
3495 /** Overload
3496
3497 @param other Another key/value pair.
3498 @param sp
3499 */
3500 BOOST_JSON_DECL
3501 key_value_pair(
3502 key_value_pair const& other,
3503 storage_ptr sp);
3504
3505 /// Overload
3506 827 key_value_pair(
3507 key_value_pair const& other)
3508 827 : key_value_pair(other,
3509
1/1
✓ Branch 3 taken 827 times.
827 other.storage())
3510 {
3511 827 }
3512
3513 /// Overload
3514 1 key_value_pair(
3515 key_value_pair&& other) noexcept
3516 1 : value_(std::move(other.value_))
3517 2 , key_(detail::exchange(
3518 1 other.key_, empty_))
3519 2 , len_(detail::exchange(
3520 1 other.len_, 0))
3521 {
3522 1 }
3523
3524 /// Overload
3525 6749 key_value_pair(
3526 pilfered<key_value_pair> other) noexcept
3527 6749 : value_(pilfer(other.get().value_))
3528 13498 , key_(detail::exchange(
3529 6749 other.get().key_, empty_))
3530 13498 , len_(detail::exchange(
3531 6749 other.get().len_, 0))
3532 {
3533 6749 }
3534 /// @}
3535
3536 /** The associated memory resource.
3537
3538 Returns a pointer to the memory resource used to construct the value.
3539
3540 @par Complexity
3541 Constant.
3542
3543 @par Exception Safety
3544 No-throw guarantee.
3545 */
3546 storage_ptr const&
3547 827 storage() const noexcept
3548 {
3549 827 return value_.storage();
3550 }
3551
3552 /** The pair's key.
3553
3554 After construction, the key may not be modified.
3555
3556 @par Complexity
3557 Constant.
3558
3559 @par Exception Safety
3560 No-throw guarantee.
3561 */
3562 string_view const
3563 143977 key() const noexcept
3564 {
3565 143977 return { key_, len_ };
3566 }
3567
3568 /** The pair's key as a null-terminated string.
3569
3570 @par Complexity
3571 Constant.
3572
3573 @par Exception Safety
3574 No-throw guarantee.
3575 */
3576 char const*
3577 1 key_c_str() const noexcept
3578 {
3579 1 return key_;
3580 }
3581
3582 /** The pair's value.
3583
3584 @par Complexity
3585 Constant.
3586
3587 @par Exception Safety
3588 No-throw guarantee.
3589
3590 @{
3591 */
3592 json::value const&
3593 65290 value() const& noexcept
3594 {
3595 65290 return value_;
3596 }
3597
3598 json::value&&
3599 value() && noexcept
3600 {
3601 return std::move( value() );
3602 }
3603
3604 json::value&
3605 1176 value() & noexcept
3606 {
3607 1176 return value_;
3608 }
3609 /// @}
3610
3611 private:
3612 json::value value_;
3613 char const* key_;
3614 std::uint32_t len_;
3615 std::uint32_t next_;
3616 };
3617
3618 //----------------------------------------------------------
3619
3620 #ifdef BOOST_JSON_DOCS
3621
3622 /** Tuple-like element access.
3623
3624 This overload of `get` permits the key and value of a @ref key_value_pair
3625 to be accessed by index. For example:
3626
3627 @code
3628 key_value_pair kvp("num", 42);
3629 string_view key = get<0>(kvp);
3630 value& jv = get<1>(kvp);
3631 @endcode
3632
3633 @par Structured Bindings
3634 When using C++17 or greater, objects of type @ref key_value_pair may be
3635 used to initialize structured bindings:
3636
3637 @code
3638 key_value_pair kvp("num", 42);
3639 auto& [key, value] = kvp;
3640 @endcode
3641
3642 Depending on the value of `I`, the return type will be:
3643
3644 @li `string_view const` if `I == 0`, or
3645 @li `value&`, `value const&`, or `value&&` if `I == 1`.
3646
3647 Using any other value for `I` is ill-formed.
3648
3649 @par Constraints
3650 `std::is_same_v< std::remove_cvref_t<T>, key_value_pair >`
3651
3652 @tparam I The element index to access.
3653
3654 @return `kvp.key()` if `I == 0`, or `kvp.value()` if `I == 1`.
3655
3656 @param kvp The @ref key_value_pair object to access.
3657 */
3658 template<
3659 std::size_t I,
3660 class T>
3661 __see_below__
3662 get(T&& kvp) noexcept;
3663
3664 #else
3665
3666 template<std::size_t I>
3667 auto
3668 get(key_value_pair const&) noexcept ->
3669 typename std::conditional<I == 0,
3670 string_view const,
3671 value const&>::type
3672 {
3673 static_assert(I == 0,
3674 "key_value_pair index out of range");
3675 }
3676
3677 template<std::size_t I>
3678 auto
3679 get(key_value_pair&) noexcept ->
3680 typename std::conditional<I == 0,
3681 string_view const,
3682 value&>::type
3683 {
3684 static_assert(I == 0,
3685 "key_value_pair index out of range");
3686 }
3687
3688 template<std::size_t I>
3689 auto
3690 get(key_value_pair&&) noexcept ->
3691 typename std::conditional<I == 0,
3692 string_view const,
3693 value&&>::type
3694 {
3695 static_assert(I == 0,
3696 "key_value_pair index out of range");
3697 }
3698
3699 /** Extracts a key_value_pair's key using tuple-like interface
3700 */
3701 template<>
3702 inline
3703 string_view const
3704 19609 get<0>(key_value_pair const& kvp) noexcept
3705 {
3706 19609 return kvp.key();
3707 }
3708
3709 /** Extracts a key_value_pair's key using tuple-like interface
3710 */
3711 template<>
3712 inline
3713 string_view const
3714 7 get<0>(key_value_pair& kvp) noexcept
3715 {
3716 7 return kvp.key();
3717 }
3718
3719 /** Extracts a key_value_pair's key using tuple-like interface
3720 */
3721 template<>
3722 inline
3723 string_view const
3724 get<0>(key_value_pair&& kvp) noexcept
3725 {
3726 return kvp.key();
3727 }
3728
3729 /** Extracts a key_value_pair's value using tuple-like interface
3730 */
3731 template<>
3732 inline
3733 value const&
3734 28299 get<1>(key_value_pair const& kvp) noexcept
3735 {
3736 28299 return kvp.value();
3737 }
3738
3739 /** Extracts a key_value_pair's value using tuple-like interface
3740 */
3741 template<>
3742 inline
3743 value&
3744 7 get<1>(key_value_pair& kvp) noexcept
3745 {
3746 7 return kvp.value();
3747 }
3748
3749 /** Extracts a key_value_pair's value using tuple-like interface
3750 */
3751 template<>
3752 inline
3753 value&&
3754 get<1>(key_value_pair&& kvp) noexcept
3755 {
3756 return std::move(kvp.value());
3757 }
3758
3759 #endif
3760
3761 } // namespace json
3762 } // namespace boost
3763
3764 #ifdef __clang__
3765 # pragma clang diagnostic push
3766 # pragma clang diagnostic ignored "-Wmismatched-tags"
3767 #endif
3768
3769 #ifndef BOOST_JSON_DOCS
3770
3771 namespace std {
3772
3773 /** Tuple-like size access for key_value_pair
3774 */
3775 template<>
3776 struct tuple_size< ::boost::json::key_value_pair >
3777 : std::integral_constant<std::size_t, 2>
3778 {
3779 };
3780
3781 /** Tuple-like access for the key type of key_value_pair
3782 */
3783 template<>
3784 struct tuple_element<0, ::boost::json::key_value_pair>
3785 {
3786 using type = ::boost::json::string_view const;
3787 };
3788
3789 /** Tuple-like access for the value type of key_value_pair
3790 */
3791 template<>
3792 struct tuple_element<1, ::boost::json::key_value_pair>
3793 {
3794 using type = ::boost::json::value&;
3795 };
3796
3797 /** Tuple-like access for the value type of key_value_pair
3798 */
3799 template<>
3800 struct tuple_element<1, ::boost::json::key_value_pair const>
3801 {
3802 using type = ::boost::json::value const&;
3803 };
3804
3805 } // std
3806
3807 #endif
3808
3809 // std::hash specialization
3810 #ifndef BOOST_JSON_DOCS
3811 namespace std {
3812 template <>
3813 struct hash< ::boost::json::value > {
3814 BOOST_JSON_DECL
3815 std::size_t
3816 operator()(::boost::json::value const& jv) const noexcept;
3817 };
3818 } // std
3819 #endif
3820
3821
3822 #ifdef __clang__
3823 # pragma clang diagnostic pop
3824 #endif
3825
3826 // These are here because value, array,
3827 // and object form cyclic references.
3828
3829 #include <boost/json/detail/impl/array.hpp>
3830 #include <boost/json/impl/array.hpp>
3831 #include <boost/json/impl/object.hpp>
3832 #include <boost/json/impl/value.hpp>
3833
3834 // These must come after array and object
3835 #include <boost/json/impl/value_ref.hpp>
3836
3837 #endif
3838