Line data Source code
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 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 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 17178 : : str_(s, std::move(sp))
391 : {
392 17170 : }
393 :
394 : /// Overload
395 134 : value(
396 : char const* s,
397 : storage_ptr sp = {})
398 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 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 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 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 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 4 : : obj_( obj, std::move(sp) )
488 : {
489 4 : }
490 :
491 : /// Overload
492 57 : value(
493 : object&& obj,
494 : storage_ptr sp)
495 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 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 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 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 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 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 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 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 15 : sca_.k != json::kind::object &&
1355 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 92 : kind() == json::kind::int64 ||
1375 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 3594 : to_number(system::error_code& ec) const noexcept
1697 : {
1698 : error e;
1699 3594 : auto result = to_number<T>(e);
1700 3594 : BOOST_JSON_FAIL(ec, e);
1701 3594 : 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 194 : to_number() const
1736 : {
1737 194 : 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 196 : try_to_number() const noexcept
1784 : {
1785 196 : system::error_code ec;
1786 196 : T result = to_number<T>(ec);
1787 196 : if( ec )
1788 78 : return {system::in_place_error, ec};
1789 :
1790 118 : 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 38 : BOOST_ASSERT(is_object());
2388 38 : return obj_;
2389 : }
2390 :
2391 : object&&
2392 1 : get_object() && noexcept
2393 : {
2394 1 : BOOST_ASSERT(is_object());
2395 1 : return std::move(obj_);
2396 : }
2397 :
2398 : object const&
2399 52930 : get_object() const& noexcept
2400 : {
2401 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 25 : BOOST_ASSERT(is_array());
2429 25 : return arr_;
2430 : }
2431 :
2432 : array&&
2433 1 : get_array() && noexcept
2434 : {
2435 1 : BOOST_ASSERT(is_array());
2436 1 : return std::move(arr_);
2437 : }
2438 :
2439 : array const&
2440 5699 : get_array() const& noexcept
2441 : {
2442 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 8971 : BOOST_ASSERT(is_string());
2470 8971 : return str_;
2471 : }
2472 :
2473 : string&&
2474 1 : get_string() && noexcept
2475 : {
2476 1 : BOOST_ASSERT(is_string());
2477 1 : return std::move(str_);
2478 : }
2479 :
2480 : string const&
2481 40931 : get_string() const& noexcept
2482 : {
2483 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 4 : BOOST_ASSERT(is_int64());
2511 4 : return sca_.i;
2512 : }
2513 :
2514 : std::int64_t
2515 14262 : get_int64() const noexcept
2516 : {
2517 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 4 : BOOST_ASSERT(is_uint64());
2545 4 : return sca_.u;
2546 : }
2547 :
2548 : std::uint64_t
2549 212 : get_uint64() const noexcept
2550 : {
2551 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 4 : BOOST_ASSERT(is_double());
2579 4 : return sca_.d;
2580 : }
2581 :
2582 : double
2583 39178 : get_double() const noexcept
2584 : {
2585 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 4 : BOOST_ASSERT(is_bool());
2613 4 : return sca_.b;
2614 : }
2615 :
2616 : bool
2617 804 : get_bool() const noexcept
2618 : {
2619 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 3408 : 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 3408 : if(sca_.k == json::kind::int64)
3214 : {
3215 3321 : auto const i = sca_.i;
3216 6636 : if( i >= (std::numeric_limits<T>::min)() &&
3217 3315 : i <= (std::numeric_limits<T>::max)())
3218 : {
3219 3309 : e = {};
3220 3309 : return static_cast<T>(i);
3221 : }
3222 12 : e = error::not_exact;
3223 : }
3224 87 : else if(sca_.k == json::kind::uint64)
3225 : {
3226 20 : auto const u = sca_.u;
3227 20 : if(u <= static_cast<std::uint64_t>((
3228 20 : std::numeric_limits<T>::max)()))
3229 : {
3230 10 : e = {};
3231 10 : return static_cast<T>(u);
3232 : }
3233 10 : e = error::not_exact;
3234 : }
3235 67 : else if(sca_.k == json::kind::double_)
3236 : {
3237 20 : auto const d = sca_.d;
3238 20 : if( d >= static_cast<double>(
3239 40 : (detail::to_number_limit<T>::min)()) &&
3240 : d <= static_cast<double>(
3241 40 : (detail::to_number_limit<T>::max)()) &&
3242 20 : static_cast<T>(d) == d)
3243 : {
3244 9 : e = {};
3245 9 : return static_cast<T>(d);
3246 : }
3247 11 : e = error::not_exact;
3248 : }
3249 : else
3250 : {
3251 47 : e = error::not_number;
3252 : }
3253 80 : return T{};
3254 : }
3255 :
3256 : template<class T>
3257 : auto
3258 119 : 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 119 : if(sca_.k == json::kind::int64)
3265 : {
3266 44 : auto const i = sca_.i;
3267 72 : if( i >= 0 && static_cast<std::uint64_t>(i) <=
3268 28 : (std::numeric_limits<T>::max)())
3269 : {
3270 22 : e = {};
3271 22 : return static_cast<T>(i);
3272 : }
3273 22 : e = error::not_exact;
3274 : }
3275 75 : else if(sca_.k == json::kind::uint64)
3276 : {
3277 58 : auto const u = sca_.u;
3278 58 : if(u <= (std::numeric_limits<T>::max)())
3279 : {
3280 52 : e = {};
3281 52 : return static_cast<T>(u);
3282 : }
3283 6 : e = error::not_exact;
3284 : }
3285 17 : else if(sca_.k == json::kind::double_)
3286 : {
3287 12 : auto const d = sca_.d;
3288 8 : if( d >= 0 &&
3289 20 : d <= (detail::to_number_limit<T>::max)() &&
3290 8 : static_cast<T>(d) == d)
3291 : {
3292 4 : e = {};
3293 4 : return static_cast<T>(d);
3294 : }
3295 8 : e = error::not_exact;
3296 : }
3297 : else
3298 : {
3299 5 : e = error::not_number;
3300 : }
3301 41 : return T{};
3302 : }
3303 :
3304 : template<class T>
3305 : auto
3306 67 : to_number(error& e) const noexcept ->
3307 : typename std::enable_if<
3308 : std::is_floating_point<
3309 : T>::value, T>::type
3310 : {
3311 67 : if(sca_.k == json::kind::int64)
3312 : {
3313 16 : e = {};
3314 16 : return static_cast<T>(sca_.i);
3315 : }
3316 51 : if(sca_.k == json::kind::uint64)
3317 : {
3318 10 : e = {};
3319 10 : return static_cast<T>(sca_.u);
3320 : }
3321 41 : if(sca_.k == json::kind::double_)
3322 : {
3323 27 : e = {};
3324 27 : return static_cast<T>(sca_.d);
3325 : }
3326 14 : e = error::not_number;
3327 14 : 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 58816 : if(sp.is_not_shared_and_deallocate_is_trivial())
3378 0 : return;
3379 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 7766 : key_value_pair(
3435 : string_view key,
3436 : Args&&... args)
3437 7767 : : value_(std::forward<Args>(args)...)
3438 : {
3439 7765 : if(key.size() > string::max_size())
3440 : {
3441 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
3442 1 : detail::throw_system_error( error::key_too_large, &loc );
3443 : }
3444 : auto s = reinterpret_cast<
3445 7764 : char*>(value_.storage()->
3446 7764 : allocate(key.size() + 1, alignof(char)));
3447 7458 : std::memcpy(s, key.data(), key.size());
3448 7458 : s[key.size()] = 0;
3449 7458 : key_ = s;
3450 7458 : len_ = static_cast<
3451 7458 : std::uint32_t>(key.size());
3452 7765 : }
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 0 : key_value_pair(
3463 : std::pair<
3464 : string_view,
3465 : json::value> const& p,
3466 : storage_ptr sp = {})
3467 0 : : key_value_pair(
3468 : p.first,
3469 0 : p.second,
3470 0 : std::move(sp))
3471 : {
3472 0 : }
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 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
|