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 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 6696 : inline bool is_scalar() const noexcept
106 : {
107 6696 : return sca_.k < json::kind::string;
108 : }
109 :
110 : public:
111 : /// Associated [Allocator](https://en.cppreference.com/w/cpp/named_req/Allocator)
112 : using allocator_type = container::pmr::polymorphic_allocator<value>;
113 :
114 : /** Destructor.
115 :
116 : The value and all of its contents are destroyed. Any dynamically
117 : allocated memory that was allocated internally is freed.
118 :
119 : @par Complexity
120 : Constant, or linear in size for array or object.
121 :
122 : @par Exception Safety
123 : No-throw guarantee.
124 : */
125 : BOOST_JSON_DECL
126 : ~value() noexcept;
127 :
128 : /** Constructors.
129 :
130 : Construct a new `value`.
131 :
132 : @li **(1)**--**(3)** the constructed value is null.
133 : @li **(4)** the constructed value contains a copy of `b`.
134 : @li **(5)**--**(9)** the constructed value contains a copy of `i`.
135 : @li **(10)**--**(14)** the constructed value contains a copy of `u`.
136 : @li **(15)** the constructed value contains a copy of `d`.
137 : @li **(16)**, **(19)** the constructed value contains a copy of the
138 : string `s`.
139 : @li **(17)** the constructed value contains a copy of the
140 : null-terminated string `s`.
141 : @li **(18)** the constructed value takes ownership of `s`'s storage.
142 : @li **(20)** if `*s.storage() == *sp` equivalent to **(18)**, otherwise
143 : equivalent to **(19)**.
144 : @li **(21)** the constructed value contains an empty string.
145 : @li **(22)** the constructed value takes ownership of `arr`'s storage.
146 : @li **(23)** the constructed value contains an element-wise copy of the
147 : array `arr`.
148 : @li **(24)** if `*arr.storage() == *sp` equivalent to **(22)**,
149 : otherwise equivalent to **(23)**.
150 : @li **(25)** the constructed value contains an empty array.
151 : @li **(26)** the constructed value takes ownership of `obj`'s storage.
152 : @li **(27)** the constructed value contains an element-wise copy of the
153 : object `obj`.
154 : @li **(28)** if `*obj.storage() == *sp` equivalent to **(26)**,
155 : otherwise equivalent to **(27)**.
156 : @li **(29)** the constructed value contains an empty object.
157 : @li **(30)** the constructed value's contents are formed by
158 : constructing from `init` and `sp` (see \<\<initializer_lists\>\>).
159 : @li **(31)**, **(32)** the constructed value contains a copy of the
160 : contents of `other`.
161 : @li **(33)** the constructed value acquires ownership of the contents
162 : of `other`.
163 : @li **(34)** equivalent to **(33)** if `*sp == *other.storage()`;
164 : otherwise equivalent to **(32)**.
165 : @li **(35)** the constructed value acquires ownership of the contents
166 : of `other` using pilfer semantics. This is more efficient than move
167 : construction, when it is known that the moved-from object will be
168 : immediately destroyed afterwards.
169 :
170 : With **(2)**--**(17)**, **(19)**--**(21)**, **(23)**--**(25)**,
171 : {sp} **(27)**--**(30)**, **(32)**, and **(34)** the constructed value
172 : uses memory resource of `sp`. With **(18)**, **(22)**, **(26)**,
173 : {sp} **(31)**, **(33)**, and **(35)** it uses the memory resource of
174 : the argument (`s`, `arr`, obj`, or `value`). In either case the value
175 : will share the ownership of the memory resource. With **(1)**
176 : it uses the \<\<default_memory_resource, default memory resource\>\>.
177 :
178 : After **(18)**, **(22)**, **(26)**, and **(33)** the argument behaves
179 : as if newly constructed with its current storage pointer (i.e. becomes
180 : an empty string, array, object, or null value).
181 :
182 : After **(35)** `other` is not in a usable state and may only be
183 : destroyed.
184 :
185 : @par Complexity
186 : @li **(1)**--**(15)**, **(18)**, **(21)**, **(22)**, **(25)**,
187 : {sp} **(26)**, **(29)**, **(33)**, **(35)** constant.
188 : @li **(16)**, **(19)** linear in `s.size()`.
189 : @li **(17)** linear in `std::strlen(s)`.
190 : @li **(20)** if `*s.storage() == *sp` constant, otherwise linear
191 : in `s.size()`.
192 : @li **(23)** linear in `arr.size()`.
193 : @li **(24)** if `*arr.storage() == *sp` constant, otherwise linear
194 : in `arr.size()`.
195 : @li **(27)** linear in `obj.size()`.
196 : @li **(28)** if `*obj.storage() == *sp` constant, otherwise linear
197 : in `obj.size()`.
198 : @li **(30)** linear in `init.size()`.
199 : @li **(31)**, **(32)** linear in the size of `other`.
200 : @li **(34)** constant if `*sp == *other.storage()`; otherwise linear in
201 : the size of `other`.
202 :
203 : The size of `other` is either the size of the underlying container
204 : (if there is one), or can be considered to be 1.
205 :
206 : @par Exception Safety
207 : @li **(1)**--**(15)**, **(18)**, **(21)**, **(22)**, **(25)**,
208 : **(26)**, **(29)**, **(33)**, **(35)** no-throw guarantee.
209 : @li **(16)**, **(17)**, **(19)**, **(23)**, **(27)**,
210 : **(30)**--**(32)** strong guarantee.
211 : @li **(20)** if `*s.storage() == *sp` no-throw guarantee, otherwise
212 : strong guarantee.
213 : @li **(24)** if `*arr.storage() == *sp` no-throw guarantee, otherwise
214 : strong guarantee.
215 : @li **(28)** if `*obj.storage() == *sp` no-throw guarantee, otherwise
216 : strong guarantee.
217 : @li **(33)** if `*other.storage() == *sp` no-throw guarantee, otherwise
218 : strong guarantee.
219 :
220 : Calls to `memory_resource::allocate` may throw.
221 :
222 : @see @ref pilfer,
223 : [Valueless Variants Considered Harmful](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html).
224 : //
225 : @{
226 : */
227 207 : value() noexcept
228 207 : : sca_()
229 : {
230 207 : }
231 :
232 : /** Overload
233 :
234 : @param sp A pointer to the @ref boost::container::pmr::memory_resource
235 : to use.
236 : */
237 : explicit
238 7052 : value(storage_ptr sp) noexcept
239 7052 : : sca_(std::move(sp))
240 : {
241 7052 : }
242 :
243 : /// Overload
244 9679 : value(
245 : std::nullptr_t,
246 : storage_ptr sp = {}) noexcept
247 9679 : : sca_(std::move(sp))
248 : {
249 9679 : }
250 :
251 : /** Overload
252 :
253 : @param b The boolean to construct with.
254 : @param sp
255 : */
256 : #ifdef BOOST_JSON_DOCS
257 : value(
258 : bool b,
259 : storage_ptr sp = {}) noexcept;
260 : #else
261 : template<class T
262 : ,class = typename std::enable_if<
263 : std::is_same<T, bool>::value>::type
264 : >
265 774 : value(
266 : T b,
267 : storage_ptr sp = {}) noexcept
268 774 : : sca_(b, std::move(sp))
269 : {
270 774 : }
271 : #endif
272 :
273 : /** Overload
274 :
275 : @param i The number to construct with.
276 : @param sp
277 : */
278 3 : value(
279 : signed char i,
280 : storage_ptr sp = {}) noexcept
281 3 : : sca_(static_cast<std::int64_t>(
282 3 : i), std::move(sp))
283 : {
284 3 : }
285 :
286 : /// Overload
287 4 : value(
288 : short i,
289 : storage_ptr sp = {}) noexcept
290 4 : : sca_(static_cast<std::int64_t>(
291 4 : i), std::move(sp))
292 : {
293 4 : }
294 :
295 : /// Overload
296 11257 : value(
297 : int i,
298 : storage_ptr sp = {}) noexcept
299 11257 : : sca_(static_cast<std::int64_t>(i),
300 11257 : std::move(sp))
301 : {
302 11257 : }
303 :
304 : /// Overload
305 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 134 : value(
397 : char const* s,
398 : storage_ptr sp = {})
399 134 : : str_(s, std::move(sp))
400 : {
401 134 : }
402 :
403 : /// Overload
404 399 : value(
405 : string s) noexcept
406 399 : : str_(std::move(s))
407 : {
408 399 : }
409 :
410 : /// Overload
411 12 : value(
412 : string const& s,
413 : storage_ptr sp)
414 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 180 : value(array arr) noexcept
443 180 : : arr_(std::move(arr))
444 : {
445 180 : }
446 :
447 : /// Overload
448 4 : value(
449 : array const& arr,
450 : storage_ptr sp)
451 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 2129126 : value(pilfered<value> other) noexcept
545 2129126 : {
546 2129126 : relocate(this, other.get());
547 2129126 : ::new(&other.get().sca_) scalar();
548 2129126 : }
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 6518 : value& operator=(int i) noexcept
715 : {
716 6518 : return operator=(
717 6518 : static_cast<long long>(i));
718 : }
719 :
720 : /// Overload
721 12 : value& operator=(long i) noexcept
722 : {
723 12 : return operator=(
724 12 : static_cast<long long>(i));
725 : }
726 :
727 : /// Overload
728 6548 : value& operator=(long long i) noexcept
729 : {
730 6548 : if(is_scalar())
731 : {
732 6545 : sca_.i = i;
733 6545 : sca_.k = json::kind::int64;
734 : }
735 : else
736 : {
737 9 : ::new(&sca_) scalar(static_cast<
738 3 : std::int64_t>(i), destroy());
739 : }
740 6548 : return *this;
741 : }
742 :
743 : /** Overload
744 :
745 : @param u The new value.
746 : */
747 6 : value& operator=(unsigned char u) noexcept
748 : {
749 6 : return operator=(static_cast<
750 6 : unsigned long long>(u));
751 : }
752 :
753 : /// Overload
754 8 : value& operator=(unsigned short u) noexcept
755 : {
756 8 : return operator=(static_cast<
757 8 : unsigned long long>(u));
758 : }
759 :
760 : /// Overload
761 8 : value& operator=(unsigned int u) noexcept
762 : {
763 8 : return operator=(static_cast<
764 8 : unsigned long long>(u));
765 : }
766 :
767 : /// Overload
768 17 : value& operator=(unsigned long u) noexcept
769 : {
770 17 : return operator=(static_cast<
771 17 : unsigned long long>(u));
772 : }
773 :
774 : /// Overload
775 47 : value& operator=(unsigned long long u) noexcept
776 : {
777 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 4609459 : kind() const noexcept
1169 : {
1170 : return static_cast<json::kind>(
1171 : static_cast<unsigned char>(
1172 4609459 : 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 6013 : is_array() const noexcept
1189 : {
1190 6013 : 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 53265 : is_object() const noexcept
1207 : {
1208 53265 : 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 88279 : is_string() const noexcept
1225 : {
1226 88279 : 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 14882 : is_int64() const noexcept
1243 : {
1244 14882 : return kind() == json::kind::int64;
1245 : }
1246 :
1247 : /** Checks if this is a `std::uint64_t`.
1248 :
1249 : Returns `true` if the value's @ref kind() is `kind::uint64`.
1250 :
1251 : @returns `this->kind() == kind::uint64`.
1252 :
1253 : @par Complexity
1254 : Constant.
1255 :
1256 : @par Exception Safety
1257 : No-throw guarantee.
1258 : */
1259 : bool
1260 340 : is_uint64() const noexcept
1261 : {
1262 340 : return kind() == json::kind::uint64;
1263 : }
1264 :
1265 : /** Check if this is a `double`.
1266 :
1267 : Returns `true` if the value's @ref kind() is `kind::double_`.
1268 :
1269 : @returns `this->kind() == kind::double_`.
1270 :
1271 : @par Complexity
1272 : Constant.
1273 :
1274 : @par Exception Safety
1275 : No-throw guarantee.
1276 : */
1277 : bool
1278 2078681 : is_double() const noexcept
1279 : {
1280 2078681 : return kind() == json::kind::double_;
1281 : }
1282 :
1283 : /** Check if this is a `bool`.
1284 :
1285 : Returns `true` if the value's @ref kind() is `kind::bool_`.
1286 :
1287 : @returns `this->kind() == kind::bool_`.
1288 :
1289 : @par Complexity
1290 : Constant.
1291 :
1292 : @par Exception Safety
1293 : No-throw guarantee.
1294 : */
1295 : bool
1296 952 : is_bool() const noexcept
1297 : {
1298 952 : return kind() == json::kind::bool_;
1299 : }
1300 :
1301 : /** Check if this is a null value.
1302 :
1303 : Returns `true` if the value's @ref kind() is `kind::null`.
1304 :
1305 : @returns `this->kind() == kind::null`.
1306 :
1307 : @par Complexity
1308 : Constant.
1309 :
1310 : @par Exception Safety
1311 : No-throw guarantee.
1312 : */
1313 : bool
1314 148 : is_null() const noexcept
1315 : {
1316 148 : return kind() == json::kind::null;
1317 : }
1318 :
1319 : /** Checks if this is an @ref array or an @ref object.
1320 :
1321 : This function returns `true` if @ref kind() is either `kind::object` or
1322 : `kind::array`.
1323 :
1324 : @par Complexity
1325 : Constant.
1326 :
1327 : @par Exception Safety
1328 : No-throw guarantee.
1329 : */
1330 : bool
1331 8 : is_structured() const noexcept
1332 : {
1333 : // VFALCO Could use bit 0x20 for this
1334 : return
1335 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 254 : if_array() const noexcept
1405 : {
1406 254 : if(kind() == json::kind::array)
1407 217 : return &arr_;
1408 37 : return nullptr;
1409 : }
1410 :
1411 : array*
1412 9 : if_array() noexcept
1413 : {
1414 9 : if(kind() == json::kind::array)
1415 2 : return &arr_;
1416 7 : return nullptr;
1417 : }
1418 : /// @}
1419 :
1420 : /** Return a pointer to the underlying @ref object.
1421 :
1422 : If `this->kind() == kind::object`, returns a pointer to the underlying
1423 : object. Otherwise, returns `nullptr`.
1424 :
1425 : @par Example
1426 : The return value is used in both a boolean context and
1427 : to assign a variable:
1428 : @code
1429 : if( auto p = jv.if_object() )
1430 : return *p;
1431 : @endcode
1432 :
1433 : @par Complexity
1434 : Constant.
1435 :
1436 : @par Exception Safety
1437 : No-throw guarantee.
1438 :
1439 : @{
1440 : */
1441 : object const*
1442 94 : if_object() const noexcept
1443 : {
1444 94 : if(kind() == json::kind::object)
1445 69 : return &obj_;
1446 25 : return nullptr;
1447 : }
1448 :
1449 : object*
1450 10 : if_object() noexcept
1451 : {
1452 10 : if(kind() == json::kind::object)
1453 3 : return &obj_;
1454 7 : return nullptr;
1455 : }
1456 : /// @}
1457 :
1458 : /** Return a pointer to the underlying @ref string.
1459 :
1460 : If `this->kind() == kind::string`, returns a pointer to the underlying
1461 : object. Otherwise, returns `nullptr`.
1462 :
1463 : @par Example
1464 : The return value is used in both a boolean context and
1465 : to assign a variable:
1466 : @code
1467 : if( auto p = jv.if_string() )
1468 : return *p;
1469 : @endcode
1470 :
1471 : @par Complexity
1472 : Constant.
1473 :
1474 : @par Exception Safety
1475 : No-throw guarantee.
1476 :
1477 : @{
1478 : */
1479 : string const*
1480 252 : if_string() const noexcept
1481 : {
1482 252 : if(kind() == json::kind::string)
1483 184 : return &str_;
1484 68 : return nullptr;
1485 : }
1486 :
1487 : string*
1488 10 : if_string() noexcept
1489 : {
1490 10 : if(kind() == json::kind::string)
1491 3 : return &str_;
1492 7 : return nullptr;
1493 : }
1494 : /// @}
1495 :
1496 : /** Return a pointer to the underlying `std::int64_t`.
1497 :
1498 : If `this->kind() == kind::int64`, returns a pointer to the underlying
1499 : integer. Otherwise, returns `nullptr`.
1500 :
1501 : @par Example
1502 : The return value is used in both a boolean context and
1503 : to assign a variable:
1504 : @code
1505 : if( auto p = jv.if_int64() )
1506 : return *p;
1507 : @endcode
1508 :
1509 : @par Complexity
1510 : Constant.
1511 :
1512 : @par Exception Safety
1513 : No-throw guarantee.
1514 :
1515 : @{
1516 : */
1517 : std::int64_t const*
1518 8 : if_int64() const noexcept
1519 : {
1520 8 : if(kind() == json::kind::int64)
1521 1 : return &sca_.i;
1522 7 : return nullptr;
1523 : }
1524 :
1525 : std::int64_t*
1526 10 : if_int64() noexcept
1527 : {
1528 10 : if(kind() == json::kind::int64)
1529 3 : return &sca_.i;
1530 7 : return nullptr;
1531 : }
1532 : /// @}
1533 :
1534 : /** Return a pointer to the underlying `std::uint64_t`.
1535 :
1536 : If `this->kind() == kind::uint64`, returns a pointer to the underlying
1537 : unsigned integer. Otherwise, returns `nullptr`.
1538 :
1539 : @par Example
1540 : The return value is used in both a boolean context and
1541 : to assign a variable:
1542 : @code
1543 : if( auto p = jv.if_uint64() )
1544 : return *p;
1545 : @endcode
1546 :
1547 : @par Complexity
1548 : Constant.
1549 :
1550 : @par Exception Safety
1551 : No-throw guarantee.
1552 :
1553 : @{
1554 : */
1555 : std::uint64_t const*
1556 8 : if_uint64() const noexcept
1557 : {
1558 8 : if(kind() == json::kind::uint64)
1559 1 : return &sca_.u;
1560 7 : return nullptr;
1561 : }
1562 :
1563 : std::uint64_t*
1564 8 : if_uint64() noexcept
1565 : {
1566 8 : if(kind() == json::kind::uint64)
1567 1 : return &sca_.u;
1568 7 : return nullptr;
1569 : }
1570 : /// @}
1571 :
1572 : /** Return a pointer to the underlying `double`.
1573 :
1574 : If `this->kind() == kind::double_`, returns a pointer to the underlying
1575 : double. Otherwise, returns `nullptr`.
1576 :
1577 : @par Example
1578 : The return value is used in both a boolean context and
1579 : to assign a variable:
1580 : @code
1581 : if( auto p = jv.if_double() )
1582 : return *p;
1583 : @endcode
1584 :
1585 : @par Complexity
1586 : Constant.
1587 :
1588 : @par Exception Safety
1589 : No-throw guarantee.
1590 :
1591 : @{
1592 : */
1593 : double const*
1594 8 : if_double() const noexcept
1595 : {
1596 8 : if(kind() == json::kind::double_)
1597 1 : return &sca_.d;
1598 7 : return nullptr;
1599 : }
1600 :
1601 : double*
1602 8 : if_double() noexcept
1603 : {
1604 8 : if(kind() == json::kind::double_)
1605 1 : return &sca_.d;
1606 7 : return nullptr;
1607 : }
1608 : /// @}
1609 :
1610 : /** Return a pointer to the underlying `bool` .
1611 :
1612 : If `this->kind() == kind::bool_`, returns a pointer to the underlying
1613 : boolean. Otherwise, returns `nullptr`.
1614 :
1615 : @par Example
1616 : The return value is used in both a boolean context and
1617 : to assign a variable:
1618 : @code
1619 : if( auto p = jv.if_bool() )
1620 : return *p;
1621 : @endcode
1622 :
1623 : @par Complexity
1624 : Constant.
1625 :
1626 : @par Exception Safety
1627 : No-throw guarantee.
1628 :
1629 : @{
1630 : */
1631 : bool const*
1632 57 : if_bool() const noexcept
1633 : {
1634 57 : if(kind() == json::kind::bool_)
1635 43 : return &sca_.b;
1636 14 : return nullptr;
1637 : }
1638 :
1639 : bool*
1640 8 : if_bool() noexcept
1641 : {
1642 8 : if(kind() == json::kind::bool_)
1643 1 : return &sca_.b;
1644 7 : return nullptr;
1645 : }
1646 : /// @}
1647 :
1648 : //------------------------------------------------------
1649 :
1650 : /** Return the stored number cast to an arithmetic type.
1651 :
1652 : This function attempts to return the stored value converted to the
1653 : arithmetic type `T` which may not be `bool`:
1654 :
1655 : @li If `T` is an integral type and the stored value is a number which
1656 : can be losslessly converted, the conversion is performed without
1657 : error and the converted number is returned.
1658 : @li If `T` is an integral type and the stored value is a number which
1659 : cannot be losslessly converted, then the operation fails with
1660 : an error.
1661 : @li If `T` is a floating point type and the stored value is a number,
1662 : the conversion is performed without error. The converted number is
1663 : returned, with a possible loss of precision.
1664 : @li Otherwise, if the stored value is not a number; that is, if
1665 : @ref is_number() returns `false`, then the operation fails with
1666 : an error.
1667 :
1668 : @par Constraints
1669 : @code
1670 : std::is_arithmetic< T >::value && ! std::is_same< T, bool >::value
1671 : @endcode
1672 :
1673 : @par Complexity
1674 : Constant.
1675 :
1676 : @par Exception Safety
1677 : @li **(1)**, **(2)** no-throw guarantee.
1678 : @li **(3)** strong guarantee.
1679 :
1680 : @return The converted number.
1681 :
1682 : @param ec Set to the error, if any occurred.
1683 :
1684 : @return The converted number.
1685 :
1686 : @{
1687 : */
1688 : template<class T>
1689 : #ifdef BOOST_JSON_DOCS
1690 : T
1691 : #else
1692 : typename std::enable_if<
1693 : std::is_arithmetic<T>::value &&
1694 : ! std::is_same<T, bool>::value,
1695 : T>::type
1696 : #endif
1697 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 : @throws boost::system::system_error Overload **(3)** reports errors by
1725 : throwing an exception.
1726 : */
1727 : template<class T>
1728 : #ifdef BOOST_JSON_DOCS
1729 : T
1730 : #else
1731 : typename std::enable_if<
1732 : std::is_arithmetic<T>::value &&
1733 : ! std::is_same<T, bool>::value,
1734 : T>::type
1735 : #endif
1736 194 : to_number() const
1737 : {
1738 194 : return try_to_number<T>().value();
1739 : }
1740 : /// @}
1741 :
1742 : /** Return the stored number as @ref boost::system::result.
1743 :
1744 : This function attempts to return the stored value converted to the
1745 : arithmetic type `T` which may not be `bool`:
1746 :
1747 : @li If `T` is an integral type and the stored value is a number which
1748 : can be losslessly converted, the conversion is performed without
1749 : error and `result<T>` containing the converted number is returned.
1750 : @li If `T` is an integral type and the stored value is a number which
1751 : cannot be losslessly converted, then `result<T>` containing the
1752 : corresponding `error_code` is returned.
1753 : @li If `T` is a floating point type and the stored value is a number,
1754 : the conversion is performed without error. `result<T>` containing
1755 : the converted number, with a possible loss of precision, is
1756 : returned.
1757 : @li Otherwise, if the stored value is not a number; that is, if
1758 : `this->is_number()` returns `false`, then `result<T>` containing
1759 : the corresponding `error_code` is returned.
1760 :
1761 : @par Constraints
1762 : @code
1763 : std::is_arithmetic< T >::value && ! std::is_same< T, bool >::value
1764 : @endcode
1765 :
1766 : @par Complexity
1767 : Constant.
1768 :
1769 : @par Exception Safety
1770 : No-throw guarantee.
1771 :
1772 : @return `boost::system::result<T>` with either the converted number or
1773 : an `error_code`.
1774 : */
1775 : template<class T>
1776 : #ifdef BOOST_JSON_DOCS
1777 : system::result<T>
1778 : #else
1779 : typename std::enable_if<
1780 : std::is_arithmetic<T>::value && ! std::is_same<T, bool>::value,
1781 : system::result<T>
1782 : >::type
1783 : #endif
1784 196 : try_to_number() const noexcept
1785 : {
1786 196 : system::error_code ec;
1787 196 : T result = to_number<T>(ec);
1788 196 : if( ec )
1789 78 : return {system::in_place_error, ec};
1790 :
1791 118 : return {system::in_place_value, result};
1792 : }
1793 :
1794 : //------------------------------------------------------
1795 : //
1796 : // Accessors
1797 : //
1798 : //------------------------------------------------------
1799 :
1800 : /** Return the associated memory resource.
1801 :
1802 : This function returns a smart pointer to the
1803 : @ref boost::container::pmr::memory_resource used by the container.
1804 :
1805 : @par Complexity
1806 : Constant.
1807 :
1808 : @par Exception Safety
1809 : No-throw guarantee.
1810 : */
1811 : storage_ptr const&
1812 75659 : storage() const noexcept
1813 : {
1814 75659 : return sp_;
1815 : }
1816 :
1817 : /** Return the associated allocator.
1818 :
1819 : This function returns an instance of @ref allocator_type constructed
1820 : from the associated @ref boost::container::pmr::memory_resource.
1821 :
1822 : @par Complexity
1823 : Constant.
1824 :
1825 : @par Exception Safety
1826 : No-throw guarantee.
1827 : */
1828 : allocator_type
1829 1 : get_allocator() const noexcept
1830 : {
1831 1 : return sp_.get();
1832 : }
1833 :
1834 : //------------------------------------------------------
1835 :
1836 : /** Return `result` with a reference to the underlying @ref array
1837 :
1838 : If @ref is_array() is `true`, the result contains a reference to the
1839 : underlying @ref array, otherwise it contains an `error_code`.
1840 :
1841 : @par Example
1842 : The return value can be used in both a boolean context and
1843 : to assign a variable:
1844 : @code
1845 : if( auto r = jv.try_as_array() )
1846 : return *r;
1847 : @endcode
1848 :
1849 : But can also be used to throw an exception on error:
1850 : @code
1851 : return jv.try_as_array().value();
1852 : @endcode
1853 :
1854 : @par Complexity
1855 : Constant.
1856 :
1857 : @par Exception Safety
1858 : No-throw guarantee.
1859 :
1860 : @{
1861 : */
1862 : BOOST_JSON_DECL
1863 : system::result<array&>
1864 : try_as_array() noexcept;
1865 :
1866 : BOOST_JSON_DECL
1867 : system::result<array const&>
1868 : try_as_array() const noexcept;
1869 : /// @}
1870 :
1871 : /** Return `result` with a reference to the underlying @ref object.
1872 :
1873 : If @ref is_object() is `true`, the result contains a reference to the
1874 : underlying @ref object, otherwise it contains an `error_code`.
1875 :
1876 : @par Example
1877 : The return value can be used in both a boolean context and
1878 : to assign a variable:
1879 : @code
1880 : if( auto r = jv.try_as_object() )
1881 : return *r;
1882 : @endcode
1883 :
1884 : But can also be used to throw an exception on error:
1885 : @code
1886 : return jv.try_as_object().value();
1887 : @endcode
1888 :
1889 : @par Complexity
1890 : Constant.
1891 :
1892 : @par Exception Safety
1893 : No-throw guarantee.
1894 :
1895 : @{
1896 : */
1897 : BOOST_JSON_DECL
1898 : system::result<object&>
1899 : try_as_object() noexcept;
1900 :
1901 : BOOST_JSON_DECL
1902 : system::result<object const&>
1903 : try_as_object() const noexcept;
1904 : /// @}
1905 :
1906 : /** Return `result` with a reference to the underlying @ref string.
1907 :
1908 : If @ref is_string() is `true`, the result contains a reference to the
1909 : underlying @ref string, otherwise it contains an `error_code`.
1910 :
1911 : @par Example
1912 : The return value can be used in both a boolean context and
1913 : to assign a variable:
1914 : @code
1915 : if( auto r = jv.try_as_string() )
1916 : return *r;
1917 : @endcode
1918 :
1919 : But can also be used to throw an exception on error:
1920 : @code
1921 : return jv.try_as_string().value();
1922 : @endcode
1923 :
1924 : @par Complexity
1925 : Constant.
1926 :
1927 : @par Exception Safety
1928 : No-throw guarantee.
1929 :
1930 : @{
1931 : */
1932 : BOOST_JSON_DECL
1933 : system::result<string&>
1934 : try_as_string() noexcept;
1935 :
1936 : BOOST_JSON_DECL
1937 : system::result<string const&>
1938 : try_as_string() const noexcept;
1939 : /// @}
1940 :
1941 : /** Return `result` with the underlying `std::int64_t`
1942 :
1943 : If @ref is_int64() is `true`, the result contains a reference to **(1)**
1944 : or a copy of **(2)** the underlying `std::int64_t`, otherwise it
1945 : contains an `error_code`.
1946 :
1947 : @par Example
1948 : The return value can be used in both a boolean context and
1949 : to assign a variable:
1950 : @code
1951 : if( auto r = jv.try_as_int64() )
1952 : return *r;
1953 : @endcode
1954 :
1955 : But can also be used to throw an exception on error:
1956 : @code
1957 : return jv.try_as_int64().value();
1958 : @endcode
1959 :
1960 : @par Complexity
1961 : Constant.
1962 :
1963 : @par Exception Safety
1964 : No-throw guarantee.
1965 :
1966 : @{
1967 : */
1968 : BOOST_JSON_DECL
1969 : system::result<std::int64_t&>
1970 : try_as_int64() noexcept;
1971 :
1972 : BOOST_JSON_DECL
1973 : system::result<std::int64_t>
1974 : try_as_int64() const noexcept;
1975 : /// @}
1976 :
1977 : /** Return `result` with the underlying `std::uint64_t`.
1978 :
1979 : If @ref is_uint64() is `true`, the result contains a reference to **(1)**
1980 : or a copy of **(2)** the underlying `std::uint64_t`, otherwise it
1981 : contains an `error_code`.
1982 :
1983 : @par Example
1984 : The return value can be used in both a boolean context and
1985 : to assign a variable:
1986 : @code
1987 : if( auto r = jv.try_as_uint64() )
1988 : return *r;
1989 : @endcode
1990 :
1991 : But can also be used to throw an exception on error:
1992 : @code
1993 : return jv.try_as_uint64().value();
1994 : @endcode
1995 :
1996 : @par Complexity
1997 : Constant.
1998 :
1999 : @par Exception Safety
2000 : No-throw guarantee.
2001 :
2002 : @{
2003 : */
2004 : BOOST_JSON_DECL
2005 : system::result<std::uint64_t&>
2006 : try_as_uint64() noexcept;
2007 :
2008 : BOOST_JSON_DECL
2009 : system::result<std::uint64_t>
2010 : try_as_uint64() const noexcept;
2011 : /// @}
2012 :
2013 : /** Return `result` with the underlying `double`
2014 :
2015 : If @ref is_double() is `true`, the result contains a reference to **(1)**
2016 : or a copy of **(2)** the underlying `double`, otherwise it
2017 : contains an `error_code`.
2018 :
2019 : @par Example
2020 : The return value can be used in both a boolean context and
2021 : to assign a variable:
2022 : @code
2023 : if( auto r = jv.try_as_double() )
2024 : return *r;
2025 : @endcode
2026 :
2027 : But can also be used to throw an exception on error:
2028 : @code
2029 : return jv.try_as_double().value();
2030 : @endcode
2031 :
2032 : @par Complexity
2033 : Constant.
2034 :
2035 : @par Exception Safety
2036 : No-throw guarantee.
2037 :
2038 : @{
2039 : */
2040 : BOOST_JSON_DECL
2041 : system::result<double&>
2042 : try_as_double() noexcept;
2043 :
2044 : BOOST_JSON_DECL
2045 : system::result<double>
2046 : try_as_double() const noexcept;
2047 : /// @}
2048 :
2049 : /** Return `result` with the underlying `bool`
2050 :
2051 : If @ref is_bool() is `true`, the result contains a reference to **(1)**
2052 : or a copy to **(2)** the underlying `bool`, otherwise it contains an
2053 : `error_code`.
2054 :
2055 : @par Example
2056 : The return value can be used in both a boolean context and
2057 : to assign a variable:
2058 : @code
2059 : if( auto r = jv.try_as_bool() )
2060 : return *r;
2061 : @endcode
2062 :
2063 : But can also be used to throw an exception on error:
2064 : @code
2065 : return jv.try_as_bool().value();
2066 : @endcode
2067 :
2068 : @par Complexity
2069 : Constant.
2070 :
2071 : @par Exception Safety
2072 : No-throw guarantee.
2073 :
2074 : @{
2075 : */
2076 : BOOST_JSON_DECL
2077 : system::result<bool&>
2078 : try_as_bool() noexcept;
2079 :
2080 : BOOST_JSON_DECL
2081 : system::result<bool>
2082 : try_as_bool() const noexcept;
2083 : /// @}
2084 :
2085 : /** Return engaged `result` if the `value` is null.
2086 :
2087 : If @ref is_null() is `true`, the result is engaged, otherwise it
2088 : contains an `error_code`.
2089 :
2090 : @par Example
2091 : The return value can be used in both a boolean context and
2092 : to assign a variable:
2093 : @code
2094 : if( auto r = jv.try_as_null() )
2095 : return *r;
2096 : @endcode
2097 :
2098 : But can also be used to throw an exception on error:
2099 : @code
2100 : return jv.try_as_null().value();
2101 : @endcode
2102 :
2103 : @par Complexity
2104 : Constant.
2105 :
2106 : @par Exception Safety
2107 : No-throw guarantee.
2108 : */
2109 : BOOST_JSON_DECL
2110 : system::result<std::nullptr_t>
2111 : try_as_null() const noexcept;
2112 :
2113 : //------------------------------------------------------
2114 :
2115 : /** Return the underlying @ref object, or throw an exception.
2116 :
2117 : If @ref is_object() is `true`, returns a reference to the underlying
2118 : @ref object, otherwise throws an exception.
2119 :
2120 : @par Exception Safety
2121 : Strong guarantee.
2122 :
2123 : @throw boost::system::system_error `! this->is_object()`.
2124 :
2125 : @param loc @ref boost::source_location to use in thrown exception; the
2126 : source location of the call site by default.
2127 :
2128 : @par Complexity
2129 : Constant.
2130 :
2131 : @{
2132 : */
2133 : object&
2134 165 : as_object(source_location const& loc = BOOST_CURRENT_LOCATION) &
2135 : {
2136 165 : auto& self = const_cast<value const&>(*this);
2137 165 : return const_cast<object&>( self.as_object(loc) );
2138 : }
2139 :
2140 : /// Overload
2141 : object&&
2142 97 : as_object(source_location const& loc = BOOST_CURRENT_LOCATION) &&
2143 : {
2144 97 : return std::move( as_object(loc) );
2145 : }
2146 :
2147 : /// Overload
2148 : BOOST_JSON_DECL
2149 : object const&
2150 : as_object(source_location const& loc = BOOST_CURRENT_LOCATION) const&;
2151 : /// @}
2152 :
2153 : /** Return the underlying @ref array, or throw an exception.
2154 :
2155 : If @ref is_array() is `true`, returns a reference to the underlying
2156 : @ref array, otherwise throws an exception.
2157 :
2158 : @par Exception Safety
2159 : Strong guarantee.
2160 :
2161 : @throw boost::system::system_error `! this->is_array()`.
2162 :
2163 : @param loc @ref boost::source_location to use in thrown exception; the
2164 : source location of the call site by default.
2165 :
2166 : @par Complexity
2167 : Constant.
2168 :
2169 : @{
2170 : */
2171 : array&
2172 92 : as_array(source_location const& loc = BOOST_CURRENT_LOCATION) &
2173 : {
2174 92 : auto& self = const_cast<value const&>(*this);
2175 92 : return const_cast<array&>( self.as_array(loc) );
2176 : }
2177 :
2178 : /// Overload
2179 : array&&
2180 10 : as_array(source_location const& loc = BOOST_CURRENT_LOCATION) &&
2181 : {
2182 10 : return std::move( as_array(loc) );
2183 : }
2184 :
2185 : /// Overload
2186 : BOOST_JSON_DECL
2187 : array const&
2188 : as_array(source_location const& loc = BOOST_CURRENT_LOCATION) const&;
2189 : /// @}
2190 :
2191 : /** Return the underlying @ref string, or throw an exception.
2192 :
2193 : If @ref is_string() is `true`, returns a reference to the underlying
2194 : @ref string, otherwise throws an exception.
2195 :
2196 : @par Exception Safety
2197 : Strong guarantee.
2198 :
2199 : @throw boost::system::system_error `! this->is_string()`.
2200 :
2201 : @param loc @ref boost::source_location to use in thrown exception; the
2202 : source location of the call site by default.
2203 :
2204 : @par Complexity
2205 : Constant.
2206 :
2207 : @{
2208 : */
2209 : string&
2210 34 : as_string(source_location const& loc = BOOST_CURRENT_LOCATION) &
2211 : {
2212 34 : auto& self = const_cast<value const&>(*this);
2213 34 : return const_cast<string&>( self.as_string(loc) );
2214 : }
2215 :
2216 : /// Overload
2217 : string&&
2218 12 : as_string(source_location const& loc = BOOST_CURRENT_LOCATION) &&
2219 : {
2220 12 : return std::move( as_string(loc) );
2221 : }
2222 :
2223 : /// Overload
2224 : BOOST_JSON_DECL
2225 : string const&
2226 : as_string(source_location const& loc = BOOST_CURRENT_LOCATION) const&;
2227 : /// @}
2228 :
2229 : /** Return the underlying `std::int64_t`, or throw an exception.
2230 :
2231 : If @ref is_int64() is `true`, returns a reference to **(1)** or a copy
2232 : of **(2)** the underlying `std::int64_t`, otherwise throws an
2233 : exception.
2234 :
2235 : @note This function is the intended for direct access to the underlying
2236 : object, __if__ it has the type `std::int64_t`. It does not convert the
2237 : underlying object to the type `std::int64_t` even if a lossless
2238 : conversion is possible. If you are not sure which kind your `value`
2239 : has, and you only care about getting a `std::int64_t` number, consider
2240 : using @ref to_number instead.
2241 :
2242 : @par Exception Safety
2243 : Strong guarantee.
2244 :
2245 : @throw boost::system::system_error `! this->is_int64()`.
2246 :
2247 : @param loc @ref boost::source_location to use in thrown exception; the
2248 : source location of the call site by default.
2249 :
2250 : @par Complexity
2251 : Constant.
2252 :
2253 : @{
2254 : */
2255 : BOOST_JSON_DECL
2256 : std::int64_t&
2257 : as_int64(source_location const& loc = BOOST_CURRENT_LOCATION);
2258 :
2259 : /// Overload
2260 : BOOST_JSON_DECL
2261 : std::int64_t
2262 : as_int64(source_location const& loc = BOOST_CURRENT_LOCATION) const;
2263 : /// @}
2264 :
2265 : /** Return the underlying `std::uint64_t`, or throw an exception.
2266 :
2267 : If @ref is_uint64() is `true`, returns a reference to **(1)** or a
2268 : copy of **(2)** the underlying `std::uint64_t`, otherwise throws an
2269 : exception.
2270 :
2271 : @note This function is intended for direct access to the underlying
2272 : object, __if__ it has the type `std::uint64_t`. It does not convert the
2273 : underlying object to the type `std::uint64_t` even if a lossless
2274 : conversion is possible. If you are not sure which kind your `value`
2275 : has, and you only care about getting a `std::uint64_t` number, consider
2276 : using @ref to_number instead.
2277 :
2278 : @par Exception Safety
2279 : Strong guarantee.
2280 :
2281 : @throw boost::system::system_error `! this->is_uint64()`.
2282 :
2283 : @param loc @ref boost::source_location to use in thrown exception; the
2284 : source location of the call site by default.
2285 :
2286 : @par Complexity
2287 : Constant.
2288 :
2289 : @{
2290 : */
2291 : BOOST_JSON_DECL
2292 : std::uint64_t&
2293 : as_uint64(source_location const& loc = BOOST_CURRENT_LOCATION);
2294 :
2295 : /// Overload
2296 : BOOST_JSON_DECL
2297 : std::uint64_t
2298 : as_uint64(source_location const& loc = BOOST_CURRENT_LOCATION) const;
2299 : /// @}
2300 :
2301 : /** Return the underlying `double`, or throw an exception.
2302 :
2303 : If @ref is_double() is `true`, returns a reference to **(1)** or a copy
2304 : of **(2)** the underlying `double`, otherwise throws an exception.
2305 :
2306 : @note This function is intended for direct access to the underlying
2307 : object, __if__ it has the type `double`. It does not convert the
2308 : underlying object to type `double` even if a lossless conversion is
2309 : possible. If you are not sure which kind your `value` has, and you only
2310 : care about getting a `double` number, consider using @ref to_number
2311 : instead.
2312 :
2313 : @par Exception Safety
2314 : Strong guarantee.
2315 :
2316 : @throw boost::system::system_error `! this->is_double()`.
2317 :
2318 : @param loc @ref boost::source_location to use in thrown exception; the
2319 : source location of the call site by default.
2320 :
2321 : @par Complexity
2322 : Constant.
2323 :
2324 : @{
2325 : */
2326 : BOOST_JSON_DECL
2327 : double&
2328 : as_double(source_location const& loc = BOOST_CURRENT_LOCATION);
2329 :
2330 : /// Overload
2331 : BOOST_JSON_DECL
2332 : double
2333 : as_double(source_location const& loc = BOOST_CURRENT_LOCATION) const;
2334 : /// @}
2335 :
2336 : /** Return the underlying `bool`, or throw an exception.
2337 :
2338 : If @ref is_bool() is `true`, returns a reference to **(1)** or a copy
2339 : of **(2)** the underlying `bool`, otherwise throws an exception.
2340 :
2341 : @par Exception Safety
2342 : Strong guarantee.
2343 :
2344 : @throw boost::system::system_error `! this->is_bool()`.
2345 :
2346 : @param loc @ref boost::source_location to use in thrown exception; the
2347 : source location of the call site by default.
2348 :
2349 : @par Complexity
2350 : Constant.
2351 :
2352 : @{
2353 : */
2354 : BOOST_JSON_DECL
2355 : bool&
2356 : as_bool(source_location const& loc = BOOST_CURRENT_LOCATION);
2357 :
2358 : /// Overload
2359 : BOOST_JSON_DECL
2360 : bool
2361 : as_bool(source_location const& loc = BOOST_CURRENT_LOCATION) const;
2362 : /// @}
2363 :
2364 : //------------------------------------------------------
2365 :
2366 : /** Return the underlying @ref object, without checking.
2367 :
2368 : This is the fastest way to access the underlying representation when
2369 : the kind is known in advance.
2370 :
2371 : @par Preconditions
2372 :
2373 : @code
2374 : this->is_object()
2375 : @endcode
2376 :
2377 : @par Complexity
2378 : Constant.
2379 :
2380 : @par Exception Safety
2381 : No-throw guarantee.
2382 :
2383 : @{
2384 : */
2385 : object&
2386 38 : get_object() & noexcept
2387 : {
2388 38 : BOOST_ASSERT(is_object());
2389 38 : return obj_;
2390 : }
2391 :
2392 : object&&
2393 1 : get_object() && noexcept
2394 : {
2395 1 : BOOST_ASSERT(is_object());
2396 1 : return std::move(obj_);
2397 : }
2398 :
2399 : object const&
2400 52946 : get_object() const& noexcept
2401 : {
2402 52946 : BOOST_ASSERT(is_object());
2403 52946 : return obj_;
2404 : }
2405 : /// @}
2406 :
2407 : /** Return the underlying @ref array, without checking.
2408 :
2409 : This is the fastest way to access the underlying representation when
2410 : the kind is known in advance.
2411 :
2412 : @par Preconditions
2413 :
2414 : @code
2415 : this->is_array()
2416 : @endcode
2417 :
2418 : @par Complexity
2419 : Constant.
2420 :
2421 : @par Exception Safety
2422 : No-throw guarantee.
2423 :
2424 : @{
2425 : */
2426 : array&
2427 25 : get_array() & noexcept
2428 : {
2429 25 : BOOST_ASSERT(is_array());
2430 25 : return arr_;
2431 : }
2432 :
2433 : array&&
2434 1 : get_array() && noexcept
2435 : {
2436 1 : BOOST_ASSERT(is_array());
2437 1 : return std::move(arr_);
2438 : }
2439 :
2440 : array const&
2441 5699 : get_array() const& noexcept
2442 : {
2443 5699 : BOOST_ASSERT(is_array());
2444 5699 : return arr_;
2445 : }
2446 : /// @}
2447 :
2448 : /** Return the underlying @ref string, without checking.
2449 :
2450 : This is the fastest way to access the underlying representation when
2451 : the kind is known in advance.
2452 :
2453 : @par Preconditions
2454 :
2455 : @code
2456 : this->is_string()
2457 : @endcode
2458 :
2459 : @par Complexity
2460 : Constant.
2461 :
2462 : @par Exception Safety
2463 : No-throw guarantee.
2464 :
2465 : @{
2466 : */
2467 : string&
2468 8971 : get_string() & noexcept
2469 : {
2470 8971 : BOOST_ASSERT(is_string());
2471 8971 : return str_;
2472 : }
2473 :
2474 : string&&
2475 1 : get_string() && noexcept
2476 : {
2477 1 : BOOST_ASSERT(is_string());
2478 1 : return std::move(str_);
2479 : }
2480 :
2481 : string const&
2482 40931 : get_string() const& noexcept
2483 : {
2484 40931 : BOOST_ASSERT(is_string());
2485 40931 : return str_;
2486 : }
2487 : /// @}
2488 :
2489 : /** Return the underlying `std::int64_t`, without checking.
2490 :
2491 : This is the fastest way to access the underlying representation when
2492 : the kind is known in advance.
2493 :
2494 : @par Preconditions
2495 :
2496 : @code
2497 : this->is_int64()
2498 : @endcode
2499 :
2500 : @par Complexity
2501 : Constant.
2502 :
2503 : @par Exception Safety
2504 : No-throw guarantee.
2505 :
2506 : @{
2507 : */
2508 : std::int64_t&
2509 4 : get_int64() noexcept
2510 : {
2511 4 : BOOST_ASSERT(is_int64());
2512 4 : return sca_.i;
2513 : }
2514 :
2515 : std::int64_t
2516 14294 : get_int64() const noexcept
2517 : {
2518 14294 : BOOST_ASSERT(is_int64());
2519 14294 : return sca_.i;
2520 : }
2521 : /// @}
2522 :
2523 : /** Return the underlying `std::uint64_t`, without checking.
2524 :
2525 : This is the fastest way to access the underlying representation when
2526 : the kind is known in advance.
2527 :
2528 : @par Preconditions
2529 :
2530 : @code
2531 : this->is_uint64()
2532 : @endcode
2533 :
2534 : @par Complexity
2535 : Constant.
2536 :
2537 : @par Exception Safety
2538 : No-throw guarantee.
2539 :
2540 : @{
2541 : */
2542 : std::uint64_t&
2543 4 : get_uint64() noexcept
2544 : {
2545 4 : BOOST_ASSERT(is_uint64());
2546 4 : return sca_.u;
2547 : }
2548 :
2549 : std::uint64_t
2550 212 : get_uint64() const noexcept
2551 : {
2552 212 : BOOST_ASSERT(is_uint64());
2553 212 : return sca_.u;
2554 : }
2555 : /// @}
2556 :
2557 : /** Return the underlying `double`, without checking.
2558 :
2559 : This is the fastest way to access the underlying
2560 : representation when the kind is known in advance.
2561 :
2562 : @par Preconditions
2563 :
2564 : @code
2565 : this->is_double()
2566 : @endcode
2567 :
2568 : @par Complexity
2569 : Constant.
2570 :
2571 : @par Exception Safety
2572 : No-throw guarantee.
2573 :
2574 : @{
2575 : */
2576 : double&
2577 4 : get_double() noexcept
2578 : {
2579 4 : BOOST_ASSERT(is_double());
2580 4 : return sca_.d;
2581 : }
2582 :
2583 : double
2584 39178 : get_double() const noexcept
2585 : {
2586 39178 : BOOST_ASSERT(is_double());
2587 39178 : return sca_.d;
2588 : }
2589 : /// @}
2590 :
2591 : /** Return the underlying `bool`, without checking.
2592 :
2593 : This is the fastest way to access the underlying representation when
2594 : the kind is known in advance.
2595 :
2596 : @par Preconditions
2597 :
2598 : @code
2599 : this->is_bool()
2600 : @endcode
2601 :
2602 : @par Complexity
2603 : Constant.
2604 :
2605 : @par Exception Safety
2606 : No-throw guarantee.
2607 :
2608 : @{
2609 : */
2610 : bool&
2611 4 : get_bool() noexcept
2612 : {
2613 4 : BOOST_ASSERT(is_bool());
2614 4 : return sca_.b;
2615 : }
2616 :
2617 : bool
2618 804 : get_bool() const noexcept
2619 : {
2620 804 : BOOST_ASSERT(is_bool());
2621 804 : return sca_.b;
2622 : }
2623 : /// @}
2624 :
2625 : //------------------------------------------------------
2626 :
2627 : /** Access an element, with bounds checking.
2628 :
2629 : Returns `boost::system::result` containing a reference to the element
2630 : of the underlying ccontainer, if such element exists. If the underlying
2631 : value is not a container of the suitable type or the container doesn't
2632 : have a corresponding element the result contains an `error_code`.
2633 :
2634 : , if `pos` is within its range. If `pos` is
2635 : outside of that range, or the underlying value is not an object the
2636 :
2637 : Returns @ref boost::system::result containing a reference to the
2638 : element of the underlying @ref array, if `pos` is within its range. If
2639 : `pos` is outside of that range, or the underlying value is not an array
2640 : the result contains an `error_code`.
2641 :
2642 : This function is used to access elements of
2643 : the underlying container, or throw an exception if that could not be
2644 : done.
2645 :
2646 : @li **(1)**, **(2)** require the underlying container to be an
2647 : @ref object, and look for an element with the key `key`.
2648 : @li **(3)**, **(4)** require the underlying container to be an
2649 : @ref array, and look for an element at index `pos`.
2650 :
2651 : @par Exception Safety
2652 : No-throw guarantee.
2653 :
2654 : @param key The key of the element to find.
2655 :
2656 : @par Complexity
2657 : Constant.
2658 :
2659 : @par Exception Safety
2660 : No-throw guarantee.
2661 :
2662 : @{
2663 : */
2664 : BOOST_JSON_DECL
2665 : boost::system::result<value&>
2666 : try_at(string_view key) noexcept;
2667 :
2668 : BOOST_JSON_DECL
2669 : boost::system::result<value const&>
2670 : try_at(string_view key) const noexcept;
2671 :
2672 : /** Overload
2673 :
2674 : @param pos A zero-based array index.
2675 : */
2676 : BOOST_JSON_DECL
2677 : boost::system::result<value&>
2678 : try_at(std::size_t pos) noexcept;
2679 :
2680 : /// Overload
2681 : BOOST_JSON_DECL
2682 : boost::system::result<value const&>
2683 : try_at(std::size_t pos) const noexcept;
2684 : /// @}
2685 :
2686 :
2687 : /** Access an element, with bounds checking.
2688 :
2689 : This function is used to access elements of
2690 : the underlying container, or throw an exception if that could not be
2691 : done.
2692 :
2693 : @li **(1)**--**(3)** is equivalent to
2694 : `this->as_object(loc).at(key, loc)`.
2695 : @li **(4)**--**(6)** is equivalent to
2696 : `this->as_array(loc).at(pos, loc)`.
2697 :
2698 : @par Complexity
2699 : Constant.
2700 :
2701 : @par Exception Safety
2702 : Strong guarantee.
2703 :
2704 : @param key The key of the element to find.
2705 : @param loc @ref boost::source_location to use in thrown exception; the
2706 : source location of the call site by default.
2707 :
2708 : @throw boost::system::system_error The underlying type of value is not
2709 : the container type corresponding to the first argument (i.e.
2710 : using an index with an @ref object).
2711 : @throw boost::system::system_error An element corresponding to the
2712 : first argument was not found.
2713 :
2714 : @see @ref as_array, @ref as_object.
2715 :
2716 : @{
2717 : */
2718 : value&
2719 12 : at(string_view key, source_location const& loc = BOOST_CURRENT_LOCATION) &
2720 : {
2721 12 : return as_object(loc).at(key, loc);
2722 : }
2723 :
2724 : /// Overload
2725 : value&&
2726 1 : at(string_view key, source_location const& loc = BOOST_CURRENT_LOCATION) &&
2727 : {
2728 1 : return std::move( as_object(loc) ).at(key, loc);
2729 : }
2730 :
2731 : /// Overload
2732 : value const&
2733 18 : at(
2734 : string_view key,
2735 : source_location const& loc = BOOST_CURRENT_LOCATION) const&
2736 : {
2737 18 : return as_object(loc).at(key, loc);
2738 : }
2739 :
2740 : /** Overload
2741 :
2742 : @param pos A zero-based array index.
2743 : @param loc
2744 : */
2745 : value &
2746 12 : at(std::size_t pos, source_location const& loc = BOOST_CURRENT_LOCATION) &
2747 : {
2748 12 : return as_array(loc).at(pos, loc);
2749 : }
2750 :
2751 : /// Overload
2752 : value&&
2753 10 : at(std::size_t pos, source_location const& loc = BOOST_CURRENT_LOCATION) &&
2754 : {
2755 10 : return std::move( as_array(loc) ).at(pos, loc);
2756 : }
2757 :
2758 : /// Overload
2759 : value const&
2760 56 : at(std::size_t pos,
2761 : source_location const& loc = BOOST_CURRENT_LOCATION) const&
2762 : {
2763 56 : return as_array(loc).at(pos, loc);
2764 : }
2765 : /// @}
2766 :
2767 : /** Access an element via JSON Pointer.
2768 :
2769 : This function is used to access a (potentially nested) element of the
2770 : value using a JSON Pointer string.
2771 :
2772 : @par Complexity
2773 : Linear in the sizes of `ptr` and underlying array, object, or string.
2774 :
2775 : @par Exception Safety
2776 : No-throw guarantee.
2777 :
2778 : @param ptr JSON Pointer string.
2779 :
2780 : @return @ref boost::system::result containing either a reference to the
2781 : element identified by `ptr` or a corresponding `error_code`.
2782 :
2783 : @see
2784 : [RFC 6901 - JavaScript Object Notation (JSON) Pointer](https://datatracker.ietf.org/doc/html/rfc6901).
2785 :
2786 : @{
2787 : */
2788 : BOOST_JSON_DECL
2789 : system::result<value const&>
2790 : try_at_pointer(string_view ptr) const noexcept;
2791 :
2792 : BOOST_JSON_DECL
2793 : system::result<value&>
2794 : try_at_pointer(string_view ptr) noexcept;
2795 : /// @}
2796 :
2797 : /** Access an element via JSON Pointer.
2798 :
2799 : This function is used to access a (potentially nested) element of the
2800 : value using a JSON Pointer string.
2801 :
2802 : @par Complexity
2803 : Linear in the sizes of `ptr` and the underlying container.
2804 :
2805 : @par Exception Safety
2806 : Strong guarantee.
2807 :
2808 : @param ptr JSON Pointer string.
2809 : @param loc @ref boost::source_location to use in thrown exception; the
2810 : source location of the call site by default.
2811 :
2812 : @return reference to the element identified by `ptr`.
2813 :
2814 : @throw boost::system::system_error if an error occurs.
2815 :
2816 : @see
2817 : [RFC 6901 - JavaScript Object Notation (JSON) Pointer](https://datatracker.ietf.org/doc/html/rfc6901).
2818 :
2819 : @{
2820 : */
2821 : BOOST_JSON_DECL
2822 : value const&
2823 : at_pointer(
2824 : string_view ptr,
2825 : source_location const& loc = BOOST_CURRENT_LOCATION) const&;
2826 :
2827 : /// Overload
2828 : inline
2829 : value&&
2830 : at_pointer(
2831 : string_view ptr,
2832 : source_location const& loc = BOOST_CURRENT_LOCATION) &&;
2833 :
2834 : /// Overload
2835 : inline
2836 : value&
2837 : at_pointer(
2838 : string_view ptr,
2839 : source_location const& loc = BOOST_CURRENT_LOCATION) &;
2840 : /// @}
2841 :
2842 : /** Access an element via JSON Pointer.
2843 :
2844 : This function is used to access a (potentially nested) element of the
2845 : value using a JSON Pointer string.
2846 :
2847 : @par Complexity
2848 : Linear in the sizes of `ptr` and underlying container.
2849 :
2850 : @par Exception Safety
2851 : No-throw guarantee.
2852 :
2853 : @param ptr JSON Pointer string.
2854 : @param ec Set to the error, if any occurred.
2855 :
2856 : @return pointer to the element identified by `ptr`.
2857 :
2858 : @see
2859 : [RFC 6901 - JavaScript Object Notation (JSON) Pointer](https://datatracker.ietf.org/doc/html/rfc6901)
2860 :
2861 : @{
2862 : */
2863 : BOOST_JSON_DECL
2864 : value const*
2865 : find_pointer(string_view ptr, system::error_code& ec) const noexcept;
2866 :
2867 : BOOST_JSON_DECL
2868 : value*
2869 : find_pointer(string_view ptr, system::error_code& ec) noexcept;
2870 :
2871 : BOOST_JSON_DECL
2872 : value const*
2873 : find_pointer(string_view ptr, std::error_code& ec) const noexcept;
2874 :
2875 : BOOST_JSON_DECL
2876 : value*
2877 : find_pointer(string_view ptr, std::error_code& ec) noexcept;
2878 : /// @}
2879 :
2880 : //------------------------------------------------------
2881 :
2882 : /** Set an element via JSON Pointer.
2883 :
2884 : This function is used to insert or assign to a potentially nested
2885 : element of the value using a JSON Pointer string. The function may
2886 : create intermediate elements corresponding to pointer segments.
2887 :
2888 : The particular conditions when and what kind of intermediate element
2889 : is created is governed by the `ptr` parameter.
2890 :
2891 : Each pointer token is considered in sequence. For each token
2892 :
2893 : - if the containing value is an @ref object, then a new `null`
2894 : element is created with key equal to unescaped token string;
2895 : otherwise
2896 :
2897 : - if the containing value is an @ref array, and the token represents a
2898 : past-the-end marker, then a `null` element is appended to the array;
2899 : otherwise
2900 :
2901 : - if the containing value is an @ref array, and the token represents a
2902 : number, then if the difference between the number and array's size
2903 : is smaller than `opts.max_created_elements`, then the size of the
2904 : array is increased, so that the number can reference an element in the
2905 : array; otherwise
2906 :
2907 : - if the containing value is of different @ref kind and
2908 : `opts.replace_any_scalar` is `true`, or the value is `null`, then
2909 :
2910 : - if `opts.create_arrays` is `true` and the token either represents
2911 : past-the-end marker or a number, then the value is replaced with
2912 : an empty array and the token is considered again; otherwise
2913 :
2914 : - if `opts.create_objects` is `true`, then the value is replaced
2915 : with an empty object and the token is considered again; otherwise
2916 :
2917 : - an error is produced.
2918 :
2919 : @par Complexity
2920 : Linear in the sum of size of `ptr`, size of underlying array, object,
2921 : or string and `opts.max_created_elements`.
2922 :
2923 : @par Exception Safety
2924 : Basic guarantee. Calls to `memory_resource::allocate` may throw.
2925 :
2926 : @param sv JSON Pointer string.
2927 : @param ref The value to assign to pointed element.
2928 : @param opts The options for the algorithm.
2929 :
2930 : @return @ref boost::system::result containing either a reference to the
2931 : element identified by `ptr` or a corresponding `error_code`.
2932 :
2933 : @see
2934 : @ref set_pointer_options,
2935 : [RFC 6901 - JavaScript Object Notation (JSON) Pointer](https://datatracker.ietf.org/doc/html/rfc6901).
2936 : */
2937 : BOOST_JSON_DECL
2938 : system::result<value&>
2939 : try_set_at_pointer(
2940 : string_view sv,
2941 : value_ref ref,
2942 : set_pointer_options const& opts = {} );
2943 :
2944 : /** Set an element via JSON Pointer.
2945 :
2946 : This function is used to insert or assign to a potentially nested
2947 : element of the value using a JSON Pointer string. The function may
2948 : create intermediate elements corresponding to pointer segments.
2949 :
2950 : The particular conditions when and what kind of intermediate element
2951 : is created is governed by the `ptr` parameter.
2952 :
2953 : Each pointer token is considered in sequence. For each token
2954 :
2955 : - if the containing value is an @ref object, then a new `null`
2956 : element is created with key equal to unescaped token string; otherwise
2957 :
2958 : - if the containing value is an @ref array, and the token represents a
2959 : past-the-end marker, then a `null` element is appended to the array;
2960 : otherwise
2961 :
2962 : - if the containing value is an @ref array, and the token represents a
2963 : number, then if the difference between the number and array's size
2964 : is smaller than `opts.max_created_elements`, then the size of the
2965 : array is increased, so that the number can reference an element in the
2966 : array; otherwise
2967 :
2968 : - if the containing value is of different @ref kind and
2969 : `opts.replace_any_scalar` is `true`, or the value is `null`, then
2970 :
2971 : - if `opts.create_arrays` is `true` and the token either represents
2972 : past-the-end marker or a number, then the value is replaced with
2973 : an empty array and the token is considered again; otherwise
2974 :
2975 : - if `opts.create_objects` is `true`, then the value is replaced
2976 : with an empty object and the token is considered again; otherwise
2977 :
2978 : - an error is produced.
2979 :
2980 : @par Complexity
2981 : Linear in the sum of size of `ptr`, size of underlying array, object,
2982 : or string and `opts.max_created_elements`.
2983 :
2984 : @par Exception Safety
2985 : Basic guarantee.
2986 : Calls to `memory_resource::allocate` may throw.
2987 :
2988 : @param sv JSON Pointer string.
2989 :
2990 : @param ref The value to assign to pointed element.
2991 :
2992 : @param opts The options for the algorithm.
2993 :
2994 : @return Reference to the element identified by `ptr`.
2995 :
2996 : @throws boost::system::system_error Overload **(1)** reports errors by
2997 : throwing exceptions.
2998 :
2999 : @see @ref set_pointer_options,
3000 : [RFC 6901 - JavaScript Object Notation (JSON) Pointer](https://datatracker.ietf.org/doc/html/rfc6901">).
3001 :
3002 : @{
3003 : */
3004 : BOOST_JSON_DECL
3005 : value&
3006 : set_at_pointer(
3007 : string_view sv,
3008 : value_ref ref,
3009 : set_pointer_options const& opts = {} );
3010 :
3011 : /** Overload
3012 :
3013 : @param ec Set to the error, if any occurred.
3014 : @param sv
3015 : @param ref
3016 : @param opts
3017 : */
3018 : BOOST_JSON_DECL
3019 : value*
3020 : set_at_pointer(
3021 : string_view sv,
3022 : value_ref ref,
3023 : system::error_code& ec,
3024 : set_pointer_options const& opts = {} );
3025 :
3026 : /// Overload
3027 : BOOST_JSON_DECL
3028 : value*
3029 : set_at_pointer(
3030 : string_view sv,
3031 : value_ref ref,
3032 : std::error_code& ec,
3033 : set_pointer_options const& opts = {} );
3034 : /// @}
3035 :
3036 : //------------------------------------------------------
3037 :
3038 : /** Check if two values are equal.
3039 :
3040 : Two values are equal when they are the same kind and their referenced
3041 : values are equal, or when they are both integral types and their
3042 : integral representations are equal.
3043 :
3044 : @par Complexity
3045 : Constant or linear in the size of the underlying @ref array, @ref object,
3046 : or @ref string.
3047 :
3048 : @par Exception Safety
3049 : No-throw guarantee.
3050 : */
3051 : // inline friend speeds up overload resolution
3052 : friend
3053 : bool
3054 4156 : operator==(
3055 : value const& lhs,
3056 : value const& rhs) noexcept
3057 : {
3058 4156 : return lhs.equal(rhs);
3059 : }
3060 :
3061 : /** Check if two values are not equal.
3062 :
3063 : Two values are equal when they are the same kind and their referenced
3064 : values are equal, or when they are both integral types and their
3065 : integral representations are equal.
3066 :
3067 : @par Complexity
3068 : Constant or linear in the size of the underlying @ref array,
3069 : @ref object, or @ref string.
3070 :
3071 : @par Exception Safety
3072 : No-throw guarantee.
3073 : */
3074 : friend
3075 : bool
3076 3978 : operator!=(
3077 : value const& lhs,
3078 : value const& rhs) noexcept
3079 : {
3080 3978 : return ! (lhs == rhs);
3081 : }
3082 :
3083 : /** Serialize @ref value to an output stream.
3084 :
3085 : This function serializes a `value` as JSON text into the output stream.
3086 :
3087 : @return Reference to `os`.
3088 :
3089 : @par Complexity
3090 : Constant or linear in the size of `jv`.
3091 :
3092 : @par Exception Safety
3093 : Strong guarantee.
3094 : Calls to `memory_resource::allocate` may throw.
3095 :
3096 : @param os The output stream to serialize to.
3097 :
3098 : @param jv The value to serialize.
3099 : */
3100 : BOOST_JSON_DECL
3101 : friend
3102 : std::ostream&
3103 : operator<<(
3104 : std::ostream& os,
3105 : value const& jv);
3106 :
3107 : /** Parse @ref value from an input stream.
3108 :
3109 : This function parses JSON from an input stream into a `value`. If
3110 : parsing fails, @ref std::ios_base::failbit will be set for `is` and
3111 : `jv` will be left unchanged. Regardless of whether @ref
3112 : std::ios_base::skipws flag is set on `is`, consumes whitespace before
3113 : and after JSON, because whitespace is considered a part of JSON.
3114 : Behaves as
3115 : [_FormattedInputFunction_](https://en.cppreference.com/w/cpp/named_req/FormattedInputFunction).
3116 :
3117 : @note This operator cannot assume that the stream only contains a
3118 : single JSON document, which may result in **very underwhelming
3119 : performance**, if the stream isn't cooperative. If you know that your
3120 : input consists of a single JSON document, consider using @ref parse
3121 : function instead.
3122 :
3123 : @return Reference to `is`.
3124 :
3125 : @par Complexity
3126 : Linear in the size of JSON data.
3127 :
3128 : @par Exception Safety
3129 : Basic guarantee.
3130 : Calls to `memory_resource::allocate` may throw.
3131 : The stream may throw as configured by @ref std::ios::exceptions.
3132 :
3133 : @param is The input stream to parse from.
3134 :
3135 : @param jv The value to parse into.
3136 :
3137 : @see @ref parse.
3138 : */
3139 : BOOST_JSON_DECL
3140 : friend
3141 : std::istream&
3142 : operator>>(
3143 : std::istream& is,
3144 : value& jv);
3145 :
3146 : /** Helper for @ref boost::hash support.
3147 :
3148 : Computes a hash value for `jv`. This function is used by
3149 : `boost::hash<value>`. Similar overloads for @ref array, @ref object,
3150 : and @ref string do not exist, because those types are supported by
3151 : `boost::hash` out of the box.
3152 :
3153 : @return hash value for `jv`.
3154 :
3155 : @param jv `value` for which a hash is to be computed.
3156 :
3157 : @see [Boost.ContainerHash](https://boost.org/libs/container_hash).
3158 : */
3159 : #ifndef BOOST_JSON_DOCS
3160 : template<
3161 : class T,
3162 : typename std::enable_if<
3163 : std::is_same< detail::remove_cvref<T>, value >::value >::type*
3164 : = nullptr>
3165 : friend
3166 : std::size_t
3167 248 : hash_value( T const& jv ) noexcept
3168 : #else
3169 : friend
3170 : inline
3171 : std::size_t
3172 : hash_value( value const& jv ) noexcept
3173 : #endif
3174 : {
3175 248 : return detail::hash_value_impl(jv);
3176 : }
3177 :
3178 : private:
3179 : static
3180 : void
3181 2133459 : relocate(
3182 : value* dest,
3183 : value const& src) noexcept
3184 : {
3185 2133459 : std::memcpy(
3186 : static_cast<void*>(dest),
3187 : &src,
3188 : sizeof(src));
3189 2133459 : }
3190 :
3191 : BOOST_JSON_DECL
3192 : storage_ptr
3193 : destroy() noexcept;
3194 :
3195 : BOOST_JSON_DECL
3196 : bool
3197 : equal(value const& other) const noexcept;
3198 :
3199 : template<class T>
3200 : auto
3201 3408 : to_number(error& e) const noexcept ->
3202 : typename std::enable_if<
3203 : std::is_signed<T>::value &&
3204 : ! std::is_floating_point<T>::value,
3205 : T>::type
3206 : {
3207 3408 : if(sca_.k == json::kind::int64)
3208 : {
3209 3321 : auto const i = sca_.i;
3210 6636 : if( i >= (std::numeric_limits<T>::min)() &&
3211 3315 : i <= (std::numeric_limits<T>::max)())
3212 : {
3213 3309 : e = {};
3214 3309 : return static_cast<T>(i);
3215 : }
3216 12 : e = error::not_exact;
3217 : }
3218 87 : else if(sca_.k == json::kind::uint64)
3219 : {
3220 20 : auto const u = sca_.u;
3221 20 : if(u <= static_cast<std::uint64_t>((
3222 20 : std::numeric_limits<T>::max)()))
3223 : {
3224 10 : e = {};
3225 10 : return static_cast<T>(u);
3226 : }
3227 10 : e = error::not_exact;
3228 : }
3229 67 : else if(sca_.k == json::kind::double_)
3230 : {
3231 20 : auto const d = sca_.d;
3232 20 : if( d >= static_cast<double>(
3233 40 : (detail::to_number_limit<T>::min)()) &&
3234 : d <= static_cast<double>(
3235 40 : (detail::to_number_limit<T>::max)()) &&
3236 20 : static_cast<T>(d) == d)
3237 : {
3238 9 : e = {};
3239 9 : return static_cast<T>(d);
3240 : }
3241 11 : e = error::not_exact;
3242 : }
3243 : else
3244 : {
3245 47 : e = error::not_number;
3246 : }
3247 80 : return T{};
3248 : }
3249 :
3250 : template<class T>
3251 : auto
3252 119 : to_number(error& e) const noexcept ->
3253 : typename std::enable_if<
3254 : std::is_unsigned<T>::value &&
3255 : ! std::is_same<T, bool>::value,
3256 : T>::type
3257 : {
3258 119 : if(sca_.k == json::kind::int64)
3259 : {
3260 44 : auto const i = sca_.i;
3261 72 : if( i >= 0 && static_cast<std::uint64_t>(i) <=
3262 28 : (std::numeric_limits<T>::max)())
3263 : {
3264 22 : e = {};
3265 22 : return static_cast<T>(i);
3266 : }
3267 22 : e = error::not_exact;
3268 : }
3269 75 : else if(sca_.k == json::kind::uint64)
3270 : {
3271 58 : auto const u = sca_.u;
3272 58 : if(u <= (std::numeric_limits<T>::max)())
3273 : {
3274 52 : e = {};
3275 52 : return static_cast<T>(u);
3276 : }
3277 6 : e = error::not_exact;
3278 : }
3279 17 : else if(sca_.k == json::kind::double_)
3280 : {
3281 12 : auto const d = sca_.d;
3282 8 : if( d >= 0 &&
3283 20 : d <= (detail::to_number_limit<T>::max)() &&
3284 8 : static_cast<T>(d) == d)
3285 : {
3286 4 : e = {};
3287 4 : return static_cast<T>(d);
3288 : }
3289 8 : e = error::not_exact;
3290 : }
3291 : else
3292 : {
3293 5 : e = error::not_number;
3294 : }
3295 41 : return T{};
3296 : }
3297 :
3298 : template<class T>
3299 : auto
3300 67 : to_number(error& e) const noexcept ->
3301 : typename std::enable_if<
3302 : std::is_floating_point<
3303 : T>::value, T>::type
3304 : {
3305 67 : if(sca_.k == json::kind::int64)
3306 : {
3307 16 : e = {};
3308 16 : return static_cast<T>(sca_.i);
3309 : }
3310 51 : if(sca_.k == json::kind::uint64)
3311 : {
3312 10 : e = {};
3313 10 : return static_cast<T>(sca_.u);
3314 : }
3315 41 : if(sca_.k == json::kind::double_)
3316 : {
3317 27 : e = {};
3318 27 : return static_cast<T>(sca_.d);
3319 : }
3320 14 : e = error::not_number;
3321 14 : return {};
3322 : }
3323 : };
3324 :
3325 : // Make sure things are as big as we think they should be
3326 : #if BOOST_JSON_ARCH == 64
3327 : BOOST_CORE_STATIC_ASSERT( sizeof(value) == 24 );
3328 : #elif BOOST_JSON_ARCH == 32
3329 : BOOST_CORE_STATIC_ASSERT( sizeof(value) == 16 );
3330 : #else
3331 : # error Unknown architecture
3332 : #endif
3333 :
3334 : //----------------------------------------------------------
3335 :
3336 : /** A key/value pair.
3337 :
3338 : This is the type of element used by the @ref object container.
3339 : */
3340 : class key_value_pair
3341 : {
3342 : #ifndef BOOST_JSON_DOCS
3343 : friend struct detail::access;
3344 : using access = detail::access;
3345 : #endif
3346 :
3347 : BOOST_JSON_DECL
3348 : static char const empty_[1];
3349 :
3350 : inline
3351 : key_value_pair(
3352 : pilfered<json::value> k,
3353 : pilfered<json::value> v) noexcept;
3354 :
3355 : public:
3356 : /** Assignment
3357 :
3358 : This type is not copy or move-assignable. The copy assignment operator
3359 : is deleted.
3360 : */
3361 : key_value_pair&
3362 : operator=(key_value_pair const&) = delete;
3363 :
3364 : /** Destructor.
3365 :
3366 : The value is destroyed and all internally allocated memory is freed.
3367 : */
3368 59048 : ~key_value_pair() noexcept
3369 52298 : {
3370 59048 : auto const& sp = value_.storage();
3371 59048 : if(sp.is_not_shared_and_deallocate_is_trivial())
3372 0 : return;
3373 59048 : if(key_ == empty_)
3374 6750 : return;
3375 52298 : sp->deallocate(const_cast<char*>(key_),
3376 52298 : len_ + 1, alignof(char));
3377 59048 : }
3378 :
3379 : /** Constructors.
3380 :
3381 : Construct a key/value pair.
3382 :
3383 : @li **(1)** uses a copy of the characters of `key`, and constructs the
3384 : value as if by `value(std::forward<Args>(args)...)`.
3385 : @li **(2)** equivalent to `key_value_pair(p.first, p.second, sp)`.
3386 : @li **(3)** equivalent to
3387 : `key_value_pair(p.first, std::move(p.second), sp)`.
3388 : @li **(4)** equivalent to
3389 : `key_value_pair(other.key(), other.value(), sp)`.
3390 : @li **(5)** equivalent to
3391 : `key_value_pair(other.key(), other.value(), other.storage())`.
3392 : @li **(6)** the pair s constructed by acquiring ownership of the
3393 : contents of `other` using move semantics.
3394 : @li **(7)** the pair is constructed by acquiring ownership of the
3395 : contents of `other` using pilfer semantics. This is more efficient
3396 : than move construction, when it is known that the moved-from object
3397 : will be immediately destroyed afterwards.
3398 :
3399 : With **(2)**, **(3)**, **(4)** the pair uses the memory resource of
3400 : `sp`. With **(5)**, **(6)**, **(7)** it uses the memory resource of
3401 : `other.storage()`. With **(1)** it uses whatever memory resource
3402 : `value(std::forward<Args>(args)...)` would use. In any case the pair
3403 : acquires shared ownership of its memory resource
3404 :
3405 : After **(6)** `other` holds an empty key, and a null value with its
3406 : current storage pointer.
3407 :
3408 : After **(7)** `other` is not in a usable state and may only be destroyed.
3409 :
3410 : @par Complexity
3411 : Constant.
3412 :
3413 : @par Exception Safety
3414 : Strong guarantee. Calls to `memory_resource::allocate` may throw.
3415 : @param key The key string to use.
3416 : @param args Optional arguments forwarded to the @ref value constructor.
3417 :
3418 : @throw boost::system::system_error The size of the key would exceed
3419 : @ref string::max_size.
3420 :
3421 : @see @ref pilfer,
3422 : [Valueless Variants Considered Harmful](http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2016/p0308r0.html).
3423 :
3424 : @{
3425 : */
3426 : template<class... Args>
3427 : explicit
3428 7882 : key_value_pair(
3429 : string_view key,
3430 : Args&&... args)
3431 7883 : : value_(std::forward<Args>(args)...)
3432 : {
3433 7881 : if(key.size() > string::max_size())
3434 : {
3435 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
3436 1 : detail::throw_system_error( error::key_too_large, &loc );
3437 : }
3438 : auto s = reinterpret_cast<
3439 7880 : char*>(value_.storage()->
3440 7880 : allocate(key.size() + 1, alignof(char)));
3441 7574 : std::memcpy(s, key.data(), key.size());
3442 7574 : s[key.size()] = 0;
3443 7574 : key_ = s;
3444 7574 : len_ = static_cast<
3445 7574 : std::uint32_t>(key.size());
3446 7881 : }
3447 :
3448 : /** Overload
3449 :
3450 : @param p A `std::pair` with the key string and @ref value to construct
3451 : with.
3452 : @param sp A pointer to the @ref boost::container::pmr::memory_resource
3453 : to use.
3454 : */
3455 : explicit
3456 0 : key_value_pair(
3457 : std::pair<
3458 : string_view,
3459 : json::value> const& p,
3460 : storage_ptr sp = {})
3461 0 : : key_value_pair(
3462 : p.first,
3463 0 : p.second,
3464 0 : std::move(sp))
3465 : {
3466 0 : }
3467 :
3468 : /// Overload
3469 : explicit
3470 3125 : key_value_pair(
3471 : std::pair<
3472 : string_view,
3473 : json::value>&& p,
3474 : storage_ptr sp = {})
3475 3125 : : key_value_pair(
3476 : p.first,
3477 3125 : std::move(p).second,
3478 6250 : std::move(sp))
3479 : {
3480 2978 : }
3481 :
3482 : /** Overload
3483 :
3484 : @param other Another key/value pair.
3485 : @param sp
3486 : */
3487 : BOOST_JSON_DECL
3488 : key_value_pair(
3489 : key_value_pair const& other,
3490 : storage_ptr sp);
3491 :
3492 : /// Overload
3493 758 : key_value_pair(
3494 : key_value_pair const& other)
3495 758 : : key_value_pair(other,
3496 758 : other.storage())
3497 : {
3498 758 : }
3499 :
3500 : /// Overload
3501 1 : key_value_pair(
3502 : key_value_pair&& other) noexcept
3503 1 : : value_(std::move(other.value_))
3504 2 : , key_(detail::exchange(
3505 1 : other.key_, empty_))
3506 2 : , len_(detail::exchange(
3507 1 : other.len_, 0))
3508 : {
3509 1 : }
3510 :
3511 : /// Overload
3512 6749 : key_value_pair(
3513 : pilfered<key_value_pair> other) noexcept
3514 6749 : : value_(pilfer(other.get().value_))
3515 13498 : , key_(detail::exchange(
3516 6749 : other.get().key_, empty_))
3517 13498 : , len_(detail::exchange(
3518 6749 : other.get().len_, 0))
3519 : {
3520 6749 : }
3521 : /// @}
3522 :
3523 : /** The associated memory resource.
3524 :
3525 : Returns a pointer to the memory resource used to construct the value.
3526 :
3527 : @par Complexity
3528 : Constant.
3529 :
3530 : @par Exception Safety
3531 : No-throw guarantee.
3532 : */
3533 : storage_ptr const&
3534 758 : storage() const noexcept
3535 : {
3536 758 : return value_.storage();
3537 : }
3538 :
3539 : /** The pair's key.
3540 :
3541 : After construction, the key may not be modified.
3542 :
3543 : @par Complexity
3544 : Constant.
3545 :
3546 : @par Exception Safety
3547 : No-throw guarantee.
3548 : */
3549 : string_view const
3550 143493 : key() const noexcept
3551 : {
3552 143493 : return { key_, len_ };
3553 : }
3554 :
3555 : /** The pair's key as a null-terminated string.
3556 :
3557 : @par Complexity
3558 : Constant.
3559 :
3560 : @par Exception Safety
3561 : No-throw guarantee.
3562 : */
3563 : char const*
3564 1 : key_c_str() const noexcept
3565 : {
3566 1 : return key_;
3567 : }
3568 :
3569 : /** The pair's value.
3570 :
3571 : @par Complexity
3572 : Constant.
3573 :
3574 : @par Exception Safety
3575 : No-throw guarantee.
3576 :
3577 : @{
3578 : */
3579 : json::value const&
3580 65221 : value() const& noexcept
3581 : {
3582 65221 : return value_;
3583 : }
3584 :
3585 : json::value&&
3586 : value() && noexcept
3587 : {
3588 : return std::move( value() );
3589 : }
3590 :
3591 : json::value&
3592 1076 : value() & noexcept
3593 : {
3594 1076 : return value_;
3595 : }
3596 : /// @}
3597 :
3598 : private:
3599 : json::value value_;
3600 : char const* key_;
3601 : std::uint32_t len_;
3602 : std::uint32_t next_;
3603 : };
3604 :
3605 : //----------------------------------------------------------
3606 :
3607 : #ifdef BOOST_JSON_DOCS
3608 :
3609 : /** Tuple-like element access.
3610 :
3611 : This overload of `get` permits the key and value of a @ref key_value_pair
3612 : to be accessed by index. For example:
3613 :
3614 : @code
3615 : key_value_pair kvp("num", 42);
3616 : string_view key = get<0>(kvp);
3617 : value& jv = get<1>(kvp);
3618 : @endcode
3619 :
3620 : @par Structured Bindings
3621 : When using C++17 or greater, objects of type @ref key_value_pair may be
3622 : used to initialize structured bindings:
3623 :
3624 : @code
3625 : key_value_pair kvp("num", 42);
3626 : auto& [key, value] = kvp;
3627 : @endcode
3628 :
3629 : Depending on the value of `I`, the return type will be:
3630 :
3631 : @li `string_view const` if `I == 0`, or
3632 : @li `value&`, `value const&`, or `value&&` if `I == 1`.
3633 :
3634 : Using any other value for `I` is ill-formed.
3635 :
3636 : @par Constraints
3637 : `std::is_same_v< std::remove_cvref_t<T>, key_value_pair >`
3638 :
3639 : @tparam I The element index to access.
3640 :
3641 : @return `kvp.key()` if `I == 0`, or `kvp.value()` if `I == 1`.
3642 :
3643 : @param kvp The @ref key_value_pair object to access.
3644 : */
3645 : template<
3646 : std::size_t I,
3647 : class T>
3648 : __see_below__
3649 : get(T&& kvp) noexcept;
3650 :
3651 : #else
3652 :
3653 : template<std::size_t I>
3654 : auto
3655 : get(key_value_pair const&) noexcept ->
3656 : typename std::conditional<I == 0,
3657 : string_view const,
3658 : value const&>::type
3659 : {
3660 : static_assert(I == 0,
3661 : "key_value_pair index out of range");
3662 : }
3663 :
3664 : template<std::size_t I>
3665 : auto
3666 : get(key_value_pair&) noexcept ->
3667 : typename std::conditional<I == 0,
3668 : string_view const,
3669 : value&>::type
3670 : {
3671 : static_assert(I == 0,
3672 : "key_value_pair index out of range");
3673 : }
3674 :
3675 : template<std::size_t I>
3676 : auto
3677 : get(key_value_pair&&) noexcept ->
3678 : typename std::conditional<I == 0,
3679 : string_view const,
3680 : value&&>::type
3681 : {
3682 : static_assert(I == 0,
3683 : "key_value_pair index out of range");
3684 : }
3685 :
3686 : /** Extracts a key_value_pair's key using tuple-like interface
3687 : */
3688 : template<>
3689 : inline
3690 : string_view const
3691 19609 : get<0>(key_value_pair const& kvp) noexcept
3692 : {
3693 19609 : return kvp.key();
3694 : }
3695 :
3696 : /** Extracts a key_value_pair's key using tuple-like interface
3697 : */
3698 : template<>
3699 : inline
3700 : string_view const
3701 7 : get<0>(key_value_pair& kvp) noexcept
3702 : {
3703 7 : return kvp.key();
3704 : }
3705 :
3706 : /** Extracts a key_value_pair's key using tuple-like interface
3707 : */
3708 : template<>
3709 : inline
3710 : string_view const
3711 : get<0>(key_value_pair&& kvp) noexcept
3712 : {
3713 : return kvp.key();
3714 : }
3715 :
3716 : /** Extracts a key_value_pair's value using tuple-like interface
3717 : */
3718 : template<>
3719 : inline
3720 : value const&
3721 28299 : get<1>(key_value_pair const& kvp) noexcept
3722 : {
3723 28299 : return kvp.value();
3724 : }
3725 :
3726 : /** Extracts a key_value_pair's value using tuple-like interface
3727 : */
3728 : template<>
3729 : inline
3730 : value&
3731 7 : get<1>(key_value_pair& kvp) noexcept
3732 : {
3733 7 : return kvp.value();
3734 : }
3735 :
3736 : /** Extracts a key_value_pair's value using tuple-like interface
3737 : */
3738 : template<>
3739 : inline
3740 : value&&
3741 : get<1>(key_value_pair&& kvp) noexcept
3742 : {
3743 : return std::move(kvp.value());
3744 : }
3745 :
3746 : #endif
3747 :
3748 : } // namespace json
3749 : } // namespace boost
3750 :
3751 : #ifdef __clang__
3752 : # pragma clang diagnostic push
3753 : # pragma clang diagnostic ignored "-Wmismatched-tags"
3754 : #endif
3755 :
3756 : #ifndef BOOST_JSON_DOCS
3757 :
3758 : namespace std {
3759 :
3760 : /** Tuple-like size access for key_value_pair
3761 : */
3762 : template<>
3763 : struct tuple_size< ::boost::json::key_value_pair >
3764 : : std::integral_constant<std::size_t, 2>
3765 : {
3766 : };
3767 :
3768 : /** Tuple-like access for the key type of key_value_pair
3769 : */
3770 : template<>
3771 : struct tuple_element<0, ::boost::json::key_value_pair>
3772 : {
3773 : using type = ::boost::json::string_view const;
3774 : };
3775 :
3776 : /** Tuple-like access for the value type of key_value_pair
3777 : */
3778 : template<>
3779 : struct tuple_element<1, ::boost::json::key_value_pair>
3780 : {
3781 : using type = ::boost::json::value&;
3782 : };
3783 :
3784 : /** Tuple-like access for the value type of key_value_pair
3785 : */
3786 : template<>
3787 : struct tuple_element<1, ::boost::json::key_value_pair const>
3788 : {
3789 : using type = ::boost::json::value const&;
3790 : };
3791 :
3792 : } // std
3793 :
3794 : #endif
3795 :
3796 : // std::hash specialization
3797 : #ifndef BOOST_JSON_DOCS
3798 : namespace std {
3799 : template <>
3800 : struct hash< ::boost::json::value > {
3801 : BOOST_JSON_DECL
3802 : std::size_t
3803 : operator()(::boost::json::value const& jv) const noexcept;
3804 : };
3805 : } // std
3806 : #endif
3807 :
3808 :
3809 : #ifdef __clang__
3810 : # pragma clang diagnostic pop
3811 : #endif
3812 :
3813 : // These are here because value, array,
3814 : // and object form cyclic references.
3815 :
3816 : #include <boost/json/detail/impl/array.hpp>
3817 : #include <boost/json/impl/array.hpp>
3818 : #include <boost/json/impl/object.hpp>
3819 : #include <boost/json/impl/value.hpp>
3820 :
3821 : // These must come after array and object
3822 : #include <boost/json/impl/value_ref.hpp>
3823 :
3824 : #endif
|