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