GCC Code Coverage Report


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