GCC Code Coverage Report


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