LCOV - code coverage report
Current view: top level - json - value.hpp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 98.9 % 522 516
Test Date: 2026-01-05 13:48:39 Functions: 98.0 % 196 192

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

Generated by: LCOV version 2.1