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