LCOV - code coverage report
Current view: top level - json/impl - value.ipp (source / functions) Coverage Total Hit
Test: coverage_filtered.info Lines: 98.7 % 462 456
Test Date: 2025-12-23 17:20:51 Functions: 100.0 % 70 70

            Line data    Source code
       1              : //
       2              : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
       3              : //
       4              : // Distributed under the Boost Software License, Version 1.0. (See accompanying
       5              : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
       6              : //
       7              : // Official repository: https://github.com/boostorg/json
       8              : //
       9              : 
      10              : #ifndef BOOST_JSON_IMPL_VALUE_IPP
      11              : #define BOOST_JSON_IMPL_VALUE_IPP
      12              : 
      13              : #include <boost/container_hash/hash.hpp>
      14              : #include <boost/json/value.hpp>
      15              : #include <boost/json/parser.hpp>
      16              : #include <cstring>
      17              : #include <istream>
      18              : #include <limits>
      19              : #include <new>
      20              : #include <utility>
      21              : 
      22              : namespace boost {
      23              : namespace json {
      24              : 
      25              : namespace
      26              : {
      27              : 
      28              : int parse_depth_xalloc = std::ios::xalloc();
      29              : int parse_flags_xalloc = std::ios::xalloc();
      30              : 
      31              : struct value_hasher
      32              : {
      33              :     std::size_t& seed;
      34              : 
      35              :     template< class T >
      36          248 :     void operator()( T&& t ) const noexcept
      37              :     {
      38          248 :         boost::hash_combine( seed, t );
      39          248 :     }
      40              : };
      41              : 
      42              : enum class stream_parse_flags
      43              : {
      44              :     allow_comments = 1 << 0,
      45              :     allow_trailing_commas = 1 << 1,
      46              :     allow_invalid_utf8 = 1 << 2,
      47              : };
      48              : 
      49              : long
      50            3 : to_bitmask( parse_options const& opts )
      51              : {
      52              :     using E = stream_parse_flags;
      53              :     return
      54            3 :         (opts.allow_comments ?
      55            3 :             static_cast<long>(E::allow_comments) : 0) |
      56            3 :         (opts.allow_trailing_commas ?
      57              :             static_cast<long>(E::allow_trailing_commas) : 0) |
      58            3 :         (opts.allow_invalid_utf8 ?
      59            3 :             static_cast<long>(E::allow_invalid_utf8) : 0);
      60              : }
      61              : 
      62              : parse_options
      63            9 : get_parse_options( std::istream& is )
      64              : {
      65            9 :     long const flags = is.iword(parse_flags_xalloc);
      66              : 
      67              :     using E = stream_parse_flags;
      68            9 :     parse_options opts;
      69            9 :     opts.allow_comments =
      70            9 :         flags & static_cast<long>(E::allow_comments) ? true : false;
      71            9 :     opts.allow_trailing_commas =
      72            9 :         flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
      73            9 :     opts.allow_invalid_utf8 =
      74            9 :         flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
      75            9 :     return opts;
      76              : }
      77              : 
      78              : } // namespace
      79              : 
      80      2178831 : value::
      81              : ~value() noexcept
      82              : {
      83      2178831 :     switch(kind())
      84              :     {
      85      2112821 :     case json::kind::null:
      86              :     case json::kind::bool_:
      87              :     case json::kind::int64:
      88              :     case json::kind::uint64:
      89              :     case json::kind::double_:
      90      2112821 :         sca_.~scalar();
      91      2112821 :         break;
      92              : 
      93        27658 :     case json::kind::string:
      94        27658 :         str_.~string();
      95        27658 :         break;
      96              : 
      97         3123 :     case json::kind::array:
      98         3123 :         arr_.~array();
      99         3123 :         break;
     100              : 
     101        35229 :     case json::kind::object:
     102        35229 :         obj_.~object();
     103        35229 :         break;
     104              :     }
     105      2178831 : }
     106              : 
     107         9508 : value::
     108              : value(
     109              :     value const& other,
     110         9508 :     storage_ptr sp)
     111              : {
     112         9508 :     switch(other.kind())
     113              :     {
     114         2034 :     case json::kind::null:
     115         6102 :         ::new(&sca_) scalar(
     116         2034 :             std::move(sp));
     117         2034 :         break;
     118              : 
     119          121 :     case json::kind::bool_:
     120          363 :         ::new(&sca_) scalar(
     121          121 :             other.sca_.b,
     122          121 :             std::move(sp));
     123          121 :         break;
     124              : 
     125         7018 :     case json::kind::int64:
     126        21054 :         ::new(&sca_) scalar(
     127         7018 :             other.sca_.i,
     128         7018 :             std::move(sp));
     129         7018 :         break;
     130              : 
     131           35 :     case json::kind::uint64:
     132          105 :         ::new(&sca_) scalar(
     133           35 :             other.sca_.u,
     134           35 :             std::move(sp));
     135           35 :         break;
     136              : 
     137           12 :     case json::kind::double_:
     138           36 :         ::new(&sca_) scalar(
     139           12 :             other.sca_.d,
     140           12 :             std::move(sp));
     141           12 :         break;
     142              : 
     143          136 :     case json::kind::string:
     144           17 :         ::new(&str_) string(
     145          136 :             other.str_,
     146          170 :             std::move(sp));
     147          119 :         break;
     148              : 
     149          122 :     case json::kind::array:
     150           26 :         ::new(&arr_) array(
     151          122 :             other.arr_,
     152          174 :             std::move(sp));
     153           96 :         break;
     154              : 
     155           30 :     case json::kind::object:
     156           10 :         ::new(&obj_) object(
     157           30 :             other.obj_,
     158           50 :             std::move(sp));
     159           20 :         break;
     160              :     }
     161         9455 : }
     162              : 
     163         3802 : value::
     164         3802 : value(value&& other) noexcept
     165              : {
     166         3802 :     relocate(this, other);
     167         3802 :     ::new(&other.sca_) scalar(sp_);
     168         3802 : }
     169              : 
     170        11593 : value::
     171              : value(
     172              :     value&& other,
     173        11593 :     storage_ptr sp)
     174              : {
     175        11593 :     switch(other.kind())
     176              :     {
     177           77 :     case json::kind::null:
     178          229 :         ::new(&sca_) scalar(
     179           77 :             std::move(sp));
     180           77 :         break;
     181              : 
     182          189 :     case json::kind::bool_:
     183          567 :         ::new(&sca_) scalar(
     184          189 :             other.sca_.b, std::move(sp));
     185          189 :         break;
     186              : 
     187        10465 :     case json::kind::int64:
     188        31395 :         ::new(&sca_) scalar(
     189        10465 :             other.sca_.i, std::move(sp));
     190        10465 :         break;
     191              : 
     192           75 :     case json::kind::uint64:
     193          225 :         ::new(&sca_) scalar(
     194           75 :             other.sca_.u, std::move(sp));
     195           75 :         break;
     196              : 
     197           34 :     case json::kind::double_:
     198          102 :         ::new(&sca_) scalar(
     199           34 :             other.sca_.d, std::move(sp));
     200           34 :         break;
     201              : 
     202          454 :     case json::kind::string:
     203            4 :         ::new(&str_) string(
     204          454 :             std::move(other.str_),
     205          916 :             std::move(sp));
     206          450 :         break;
     207              : 
     208          233 :     case json::kind::array:
     209            5 :         ::new(&arr_) array(
     210          233 :             std::move(other.arr_),
     211          476 :             std::move(sp));
     212          228 :         break;
     213              : 
     214           66 :     case json::kind::object:
     215           13 :         ::new(&obj_) object(
     216           66 :             std::move(other.obj_),
     217          158 :             std::move(sp));
     218           53 :         break;
     219              :     }
     220        11571 : }
     221              : 
     222              : //----------------------------------------------------------
     223              : //
     224              : // Conversion
     225              : //
     226              : //----------------------------------------------------------
     227              : 
     228          358 : value::
     229              : value(
     230              :     std::initializer_list<value_ref> init,
     231          358 :     storage_ptr sp)
     232              : {
     233          358 :     if(value_ref::maybe_object(init))
     234              :     {
     235            0 :         ::new(&obj_) object(
     236              :             value_ref::make_object(
     237          109 :                 init, std::move(sp)));
     238              :     }
     239              :     else
     240              :     {
     241          249 :         if( init.size() == 1 )
     242              :         {
     243           12 :             ::new(&sca_) scalar();
     244           12 :             value temp = init.begin()->make_value( std::move(sp) );
     245           12 :             swap(temp);
     246           12 :         }
     247              :         else
     248              :         {
     249            0 :             ::new(&arr_) array(
     250              :                 value_ref::make_array(
     251          237 :                     init, std::move(sp)));
     252              :         }
     253              :     }
     254          358 : }
     255              : 
     256              : //----------------------------------------------------------
     257              : //
     258              : // Assignment
     259              : //
     260              : //----------------------------------------------------------
     261              : 
     262              : value&
     263           35 : value::
     264              : operator=(value const& other)
     265              : {
     266           70 :     value(other,
     267           29 :         storage()).swap(*this);
     268           29 :     return *this;
     269              : }
     270              : 
     271              : value&
     272           92 : value::
     273              : operator=(value&& other)
     274              : {
     275          184 :     value(std::move(other),
     276           73 :         storage()).swap(*this);
     277           73 :     return *this;
     278              : }
     279              : 
     280              : value&
     281           11 : value::
     282              : operator=(
     283              :     std::initializer_list<value_ref> init)
     284              : {
     285           22 :     value(init,
     286           11 :         storage()).swap(*this);
     287           11 :     return *this;
     288              : }
     289              : 
     290              : value&
     291            2 : value::
     292              : operator=(string_view s)
     293              : {
     294            2 :     value(s, storage()).swap(*this);
     295            2 :     return *this;
     296              : }
     297              : 
     298              : value&
     299           28 : value::
     300              : operator=(char const* s)
     301              : {
     302           28 :     value(s, storage()).swap(*this);
     303           28 :     return *this;
     304              : }
     305              : 
     306              : value&
     307           12 : value::
     308              : operator=(string const& str)
     309              : {
     310           12 :     value(str, storage()).swap(*this);
     311           12 :     return *this;
     312              : }
     313              : 
     314              : value&
     315            2 : value::
     316              : operator=(string&& str)
     317              : {
     318            4 :     value(std::move(str),
     319            2 :         storage()).swap(*this);
     320            2 :     return *this;
     321              : }
     322              : 
     323              : value&
     324            1 : value::
     325              : operator=(array const& arr)
     326              : {
     327            1 :     value(arr, storage()).swap(*this);
     328            1 :     return *this;
     329              : }
     330              : 
     331              : value&
     332            5 : value::
     333              : operator=(array&& arr)
     334              : {
     335           10 :     value(std::move(arr),
     336            5 :         storage()).swap(*this);
     337            5 :     return *this;
     338              : }
     339              : 
     340              : value&
     341            1 : value::
     342              : operator=(object const& obj)
     343              : {
     344            1 :     value(obj, storage()).swap(*this);
     345            1 :     return *this;
     346              : }
     347              : 
     348              : value&
     349           22 : value::
     350              : operator=(object&& obj)
     351              : {
     352           44 :     value(std::move(obj),
     353           22 :         storage()).swap(*this);
     354           22 :     return *this;
     355              : }
     356              : 
     357              : //----------------------------------------------------------
     358              : //
     359              : // Accessors
     360              : //
     361              : //----------------------------------------------------------
     362              : 
     363              : system::result<array&>
     364           16 : value::try_as_array() noexcept
     365              : {
     366           16 :     if( is_array() )
     367            9 :         return arr_;
     368              : 
     369            7 :     system::error_code ec;
     370            7 :     BOOST_JSON_FAIL(ec, error::not_array);
     371            7 :     return ec;
     372              : }
     373              : 
     374              : system::result<array const&>
     375          183 : value::try_as_array() const noexcept
     376              : {
     377          183 :     if( is_array() )
     378          155 :         return arr_;
     379              : 
     380           28 :     system::error_code ec;
     381           28 :     BOOST_JSON_FAIL(ec, error::not_array);
     382           28 :     return ec;
     383              : }
     384              : 
     385              : system::result<object&>
     386            9 : value::try_as_object() noexcept
     387              : {
     388            9 :     if( is_object() )
     389            2 :         return obj_;
     390              : 
     391            7 :     system::error_code ec;
     392            7 :     BOOST_JSON_FAIL(ec, error::not_object);
     393            7 :     return ec;
     394              : }
     395              : 
     396              : system::result<object const&>
     397          206 : value::try_as_object() const noexcept
     398              : {
     399          206 :     if( is_object() )
     400          178 :         return obj_;
     401              : 
     402           28 :     system::error_code ec;
     403           28 :     BOOST_JSON_FAIL(ec, error::not_object);
     404           28 :     return ec;
     405              : }
     406              : 
     407              : system::result<string&>
     408            9 : value::try_as_string() noexcept
     409              : {
     410            9 :     if( is_string() )
     411            2 :         return str_;
     412              : 
     413            7 :     system::error_code ec;
     414            7 :     BOOST_JSON_FAIL(ec, error::not_string);
     415            7 :     return ec;
     416              : }
     417              : 
     418              : system::result<string const&>
     419          121 : value::try_as_string() const noexcept
     420              : {
     421          121 :     if( is_string() )
     422           92 :         return str_;
     423              : 
     424           29 :     system::error_code ec;
     425           29 :     BOOST_JSON_FAIL(ec, error::not_string);
     426           29 :     return ec;
     427              : }
     428              : 
     429              : system::result<std::int64_t&>
     430           52 : value::try_as_int64() noexcept
     431              : {
     432           52 :     if( is_int64() )
     433           38 :         return sca_.i;
     434              : 
     435           14 :     system::error_code ec;
     436           14 :     BOOST_JSON_FAIL(ec, error::not_int64);
     437           14 :     return ec;
     438              : }
     439              : 
     440              : system::result<std::int64_t>
     441           33 : value::try_as_int64() const noexcept
     442              : {
     443           33 :     if( is_int64() )
     444           19 :         return sca_.i;
     445              : 
     446           14 :     system::error_code ec;
     447           14 :     BOOST_JSON_FAIL(ec, error::not_int64);
     448           14 :     return ec;
     449              : }
     450              : 
     451              : system::result<std::uint64_t&>
     452           16 : value::try_as_uint64() noexcept
     453              : {
     454           16 :     if( is_uint64() )
     455            2 :         return sca_.u;
     456              : 
     457           14 :     system::error_code ec;
     458           14 :     BOOST_JSON_FAIL(ec, error::not_uint64);
     459           14 :     return ec;
     460              : }
     461              : 
     462              : system::result<std::uint64_t>
     463           16 : value::try_as_uint64() const noexcept
     464              : {
     465           16 :     if( is_uint64() )
     466            2 :         return sca_.u;
     467              : 
     468           14 :     system::error_code ec;
     469           14 :     BOOST_JSON_FAIL(ec, error::not_uint64);
     470           14 :     return ec;
     471              : }
     472              : 
     473              : system::result<double&>
     474      2000657 : value::try_as_double() noexcept
     475              : {
     476      2000657 :     if( is_double() )
     477      2000643 :         return sca_.d;
     478              : 
     479           14 :     system::error_code ec;
     480           14 :     BOOST_JSON_FAIL(ec, error::not_double);
     481           14 :     return ec;
     482              : }
     483              : 
     484              : system::result<double>
     485          580 : value::try_as_double() const noexcept
     486              : {
     487          580 :     if( is_double() )
     488          566 :         return sca_.d;
     489              : 
     490           14 :     system::error_code ec;
     491           14 :     BOOST_JSON_FAIL(ec, error::not_double);
     492           14 :     return ec;
     493              : }
     494              : 
     495              : system::result<bool&>
     496           19 : value::try_as_bool() noexcept
     497              : {
     498           19 :     if( is_bool() )
     499            4 :         return sca_.b;
     500              : 
     501           15 :     system::error_code ec;
     502           15 :     BOOST_JSON_FAIL(ec, error::not_bool);
     503           15 :     return ec;
     504              : }
     505              : 
     506              : system::result<bool>
     507           30 : value::try_as_bool() const noexcept
     508              : {
     509           30 :     if( is_bool() )
     510           16 :         return sca_.b;
     511              : 
     512           14 :     system::error_code ec;
     513           14 :     BOOST_JSON_FAIL(ec, error::not_bool);
     514           14 :     return ec;
     515              : }
     516              : 
     517              : system::result<std::nullptr_t>
     518            2 : value::try_as_null() const noexcept
     519              : {
     520            2 :     if( is_null() )
     521            1 :         return nullptr;
     522              : 
     523            1 :     system::error_code ec;
     524            1 :     BOOST_JSON_FAIL(ec, error::not_null);
     525            1 :     return ec;
     526              : }
     527              : 
     528              : boost::system::result<value&>
     529            1 : value::try_at(string_view key) noexcept
     530              : {
     531            1 :     auto r = try_as_object();
     532            1 :     if( !r )
     533            0 :         return r.error();
     534            1 :     return r->try_at(key);
     535              : }
     536              : 
     537              : boost::system::result<value const&>
     538            3 : value::try_at(string_view key) const noexcept
     539              : {
     540            3 :     auto r = try_as_object();
     541            3 :     if( !r )
     542            0 :         return r.error();
     543            3 :     return r->try_at(key);
     544              : }
     545              : 
     546              : boost::system::result<value&>
     547            8 : value::try_at(std::size_t pos) noexcept
     548              : {
     549            8 :     auto r = try_as_array();
     550            8 :     if( !r )
     551            0 :         return r.error();
     552            8 :     return r->try_at(pos);
     553              : }
     554              : 
     555              : boost::system::result<value const&>
     556            2 : value::try_at(std::size_t pos) const noexcept
     557              : {
     558            2 :     auto r = try_as_array();
     559            2 :     if( !r )
     560            0 :         return r.error();
     561            2 :     return r->try_at(pos);
     562              : }
     563              : 
     564              : object const&
     565          195 : value::as_object(source_location const& loc) const&
     566              : {
     567          195 :     return try_as_object().value(loc);
     568              : }
     569              : 
     570              : array const&
     571          173 : value::as_array(source_location const& loc) const&
     572              : {
     573          173 :     return try_as_array().value(loc);
     574              : }
     575              : 
     576              : string const&
     577          113 : value::as_string(source_location const& loc) const&
     578              : {
     579          113 :     return try_as_string().value(loc);
     580              : }
     581              : 
     582              : std::int64_t&
     583           44 : value::as_int64(source_location const& loc)
     584              : {
     585           44 :     return try_as_int64().value(loc);
     586              : }
     587              : 
     588              : std::int64_t
     589           26 : value::as_int64(source_location const& loc) const
     590              : {
     591           26 :     return try_as_int64().value(loc);
     592              : }
     593              : 
     594              : std::uint64_t&
     595            8 : value::as_uint64(source_location const& loc)
     596              : {
     597            8 :     return try_as_uint64().value(loc);
     598              : }
     599              : 
     600              : std::uint64_t
     601            8 : value::as_uint64(source_location const& loc) const
     602              : {
     603            8 :     return try_as_uint64().value(loc);
     604              : }
     605              : 
     606              : double&
     607      2000649 : value::as_double(source_location const& loc)
     608              : {
     609      2000649 :     return try_as_double().value(loc);
     610              : }
     611              : 
     612              : double
     613          572 : value::as_double(source_location const& loc) const
     614              : {
     615          572 :     return try_as_double().value(loc);
     616              : }
     617              : 
     618              : bool&
     619           10 : value::as_bool(source_location const& loc)
     620              : {
     621           10 :     return try_as_bool().value(loc);
     622              : }
     623              : 
     624              : bool
     625           22 : value::as_bool(source_location const& loc) const
     626              : {
     627           22 :     return try_as_bool().value(loc);
     628              : }
     629              : 
     630              : //----------------------------------------------------------
     631              : //
     632              : // Modifiers
     633              : //
     634              : //----------------------------------------------------------
     635              : 
     636              : string&
     637          158 : value::
     638              : emplace_string() noexcept
     639              : {
     640          158 :     return *::new(&str_) string(destroy());
     641              : }
     642              : 
     643              : array&
     644          260 : value::
     645              : emplace_array() noexcept
     646              : {
     647          260 :     return *::new(&arr_) array(destroy());
     648              : }
     649              : 
     650              : object&
     651           64 : value::
     652              : emplace_object() noexcept
     653              : {
     654           64 :     return *::new(&obj_) object(destroy());
     655              : }
     656              : 
     657              : void
     658          204 : value::
     659              : swap(value& other)
     660              : {
     661          204 :     if(*storage() == *other.storage())
     662              :     {
     663              :         // fast path
     664              :         union U
     665              :         {
     666              :             value tmp;
     667          203 :             U(){}
     668          203 :             ~U(){}
     669              :         };
     670          203 :         U u;
     671          203 :         relocate(&u.tmp, *this);
     672          203 :         relocate(this, other);
     673          203 :         relocate(&other, u.tmp);
     674          203 :         return;
     675          203 :     }
     676              : 
     677              :     // copy
     678              :     value temp1(
     679            1 :         std::move(*this),
     680            2 :         other.storage());
     681              :     value temp2(
     682            1 :         std::move(other),
     683            2 :         this->storage());
     684            1 :     other.~value();
     685            1 :     ::new(&other) value(pilfer(temp1));
     686            1 :     this->~value();
     687            1 :     ::new(this) value(pilfer(temp2));
     688            1 : }
     689              : 
     690              : std::istream&
     691           10 : operator>>(
     692              :     std::istream& is,
     693              :     value& jv)
     694              : {
     695              :     using Traits = std::istream::traits_type;
     696              : 
     697              :     // sentry prepares the stream for reading and finalizes it in destructor
     698           10 :     std::istream::sentry sentry(is);
     699           10 :     if( !sentry )
     700            1 :         return is;
     701              : 
     702            9 :     parse_options opts = get_parse_options( is );
     703            9 :     if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
     704            3 :         opts.max_depth = depth;
     705              : 
     706              :     unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
     707            9 :     stream_parser p( {}, opts, parser_buf );
     708            9 :     p.reset( jv.storage() );
     709              : 
     710              :     char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
     711            9 :     std::streambuf& buf = *is.rdbuf();
     712            9 :     std::ios::iostate err = std::ios::goodbit;
     713              : #ifndef BOOST_NO_EXCEPTIONS
     714              :     try
     715              : #endif
     716              :     {
     717              :         while( true )
     718              :         {
     719           15 :             system::error_code ec;
     720              : 
     721              :             // we peek the buffer; this either makes sure that there's no
     722              :             // more input, or makes sure there's something in the internal
     723              :             // buffer (so in_avail will return a positive number)
     724           15 :             std::istream::int_type c = is.rdbuf()->sgetc();
     725              :             // if we indeed reached EOF, we check if we parsed a full JSON
     726              :             // document; if not, we error out
     727           13 :             if( Traits::eq_int_type(c, Traits::eof()) )
     728              :             {
     729            3 :                 err |= std::ios::eofbit;
     730            3 :                 p.finish(ec);
     731            3 :                 if( ec.failed() )
     732            4 :                     break;
     733              :             }
     734              : 
     735              :             // regardless of reaching EOF, we might have parsed a full JSON
     736              :             // document; if so, we successfully finish
     737           12 :             if( p.done() )
     738              :             {
     739            3 :                 jv = p.release();
     740            3 :                 return is;
     741              :             }
     742              : 
     743              :             // at this point we definitely have more input, specifically in
     744              :             // buf's internal buffer; we also definitely haven't parsed a whole
     745              :             // document
     746            9 :             std::streamsize available = buf.in_avail();
     747              :             // if this assert fails, the streambuf is buggy
     748            9 :             BOOST_ASSERT( available > 0 );
     749              : 
     750           18 :             available = ( std::min )(
     751            9 :                 static_cast<std::size_t>(available), sizeof(read_buf) );
     752              :             // we read from the internal buffer of buf into our buffer
     753            9 :             available = buf.sgetn( read_buf, available );
     754              : 
     755            9 :             std::size_t consumed = p.write_some(
     756              :                 read_buf, static_cast<std::size_t>(available), ec );
     757              :             // if the parser hasn't consumed the entire input we've took from
     758              :             // buf, we put the remaining data back; this should succeed,
     759              :             // because we only read data from buf's internal buffer
     760           21 :             while( consumed++ < static_cast<std::size_t>(available) )
     761              :             {
     762           12 :                 std::istream::int_type const status = buf.sungetc();
     763           12 :                 BOOST_ASSERT( status != Traits::eof() );
     764              :                 (void)status;
     765              :             }
     766              : 
     767            9 :             if( ec.failed() )
     768            3 :                 break;
     769            6 :         }
     770              :     }
     771              : #ifndef BOOST_NO_EXCEPTIONS
     772            2 :     catch(...)
     773              :     {
     774              :         try
     775              :         {
     776            2 :             is.setstate(std::ios::badbit);
     777              :         }
     778              :         // we ignore the exception, because we need to throw the original
     779              :         // exception instead
     780            1 :         catch( std::ios::failure const& ) { }
     781              : 
     782            2 :         if( is.exceptions() & std::ios::badbit )
     783            1 :             throw;
     784            2 :     }
     785              : #endif
     786              : 
     787            5 :     is.setstate(err | std::ios::failbit);
     788            5 :     return is;
     789            9 : }
     790              : 
     791              : std::istream&
     792            3 : operator>>(
     793              :     std::istream& is,
     794              :     parse_options const& opts)
     795              : {
     796            3 :     is.iword(parse_flags_xalloc) = to_bitmask(opts);
     797            3 :     is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
     798            3 :     return is;
     799              : }
     800              : 
     801              : //----------------------------------------------------------
     802              : //
     803              : // private
     804              : //
     805              : //----------------------------------------------------------
     806              : 
     807              : storage_ptr
     808          500 : value::
     809              : destroy() noexcept
     810              : {
     811          500 :     switch(kind())
     812              :     {
     813          481 :     case json::kind::null:
     814              :     case json::kind::bool_:
     815              :     case json::kind::int64:
     816              :     case json::kind::uint64:
     817              :     case json::kind::double_:
     818          481 :         break;
     819              : 
     820           14 :     case json::kind::string:
     821              :     {
     822           14 :         auto sp = str_.storage();
     823           14 :         str_.~string();
     824           14 :         return sp;
     825           14 :     }
     826              : 
     827            2 :     case json::kind::array:
     828              :     {
     829            2 :         auto sp = arr_.storage();
     830            2 :         arr_.~array();
     831            2 :         return sp;
     832            2 :     }
     833              : 
     834            3 :     case json::kind::object:
     835              :     {
     836            3 :         auto sp = obj_.storage();
     837            3 :         obj_.~object();
     838            3 :         return sp;
     839            3 :     }
     840              : 
     841              :     }
     842          481 :     return std::move(sp_);
     843              : }
     844              : 
     845              : bool
     846         4226 : value::
     847              : equal(value const& other) const noexcept
     848              : {
     849         4226 :     switch(kind())
     850              :     {
     851           21 :     default: // unreachable()?
     852              :     case json::kind::null:
     853           21 :         return other.kind() == json::kind::null;
     854              : 
     855           16 :     case json::kind::bool_:
     856              :         return
     857           25 :             other.kind() == json::kind::bool_ &&
     858           25 :             get_bool() == other.get_bool();
     859              : 
     860         3933 :     case json::kind::int64:
     861         3933 :         switch(other.kind())
     862              :         {
     863         3906 :         case json::kind::int64:
     864         3906 :             return get_int64() == other.get_int64();
     865           26 :         case json::kind::uint64:
     866           26 :             if(get_int64() < 0)
     867            1 :                 return false;
     868           25 :             return static_cast<std::uint64_t>(
     869           25 :                 get_int64()) == other.get_uint64();
     870            1 :         default:
     871            1 :             return false;
     872              :         }
     873              : 
     874            7 :     case json::kind::uint64:
     875            7 :         switch(other.kind())
     876              :         {
     877            2 :         case json::kind::uint64:
     878            2 :             return get_uint64() == other.get_uint64();
     879            3 :         case json::kind::int64:
     880            3 :             if(other.get_int64() < 0)
     881            2 :                 return false;
     882            1 :             return static_cast<std::uint64_t>(
     883            1 :                 other.get_int64()) == get_uint64();
     884            2 :         default:
     885            2 :             return false;
     886              :         }
     887              : 
     888           55 :     case json::kind::double_:
     889              :         return
     890          108 :             other.kind() == json::kind::double_ &&
     891          108 :             get_double() == other.get_double();
     892              : 
     893           93 :     case json::kind::string:
     894              :         return
     895          183 :             other.kind() == json::kind::string &&
     896          183 :             get_string() == other.get_string();
     897              : 
     898           73 :     case json::kind::array:
     899              :         return
     900          144 :             other.kind() == json::kind::array &&
     901          144 :             get_array() == other.get_array();
     902              : 
     903           28 :     case json::kind::object:
     904              :         return
     905           53 :             other.kind() == json::kind::object &&
     906           53 :             get_object() == other.get_object();
     907              :     }
     908              : }
     909              : 
     910              : //----------------------------------------------------------
     911              : //
     912              : // key_value_pair
     913              : //
     914              : //----------------------------------------------------------
     915              : 
     916              : // empty keys point here
     917              : BOOST_JSON_REQUIRE_CONST_INIT
     918              : char const
     919              : key_value_pair::empty_[1] = { 0 };
     920              : 
     921        38150 : key_value_pair::
     922              : key_value_pair(
     923              :     pilfered<json::value> key,
     924        38150 :     pilfered<json::value> value) noexcept
     925        38150 :     : value_(value)
     926              : {
     927              :     std::size_t len;
     928        38150 :     key_ = access::release_key(key.get(), len);
     929        38150 :     len_ = static_cast<std::uint32_t>(len);
     930        38150 : }
     931              : 
     932         6876 : key_value_pair::
     933              : key_value_pair(
     934              :     key_value_pair const& other,
     935         6876 :     storage_ptr sp)
     936         6880 :     : value_(other.value_, std::move(sp))
     937              : {
     938              :     auto p = reinterpret_cast<
     939         6872 :         char*>(value_.storage()->
     940         6872 :             allocate(other.len_ + 1,
     941              :                 alignof(char)));
     942         6614 :     std::memcpy(
     943         6614 :         p, other.key_, other.len_);
     944         6614 :     len_ = other.len_;
     945         6614 :     p[len_] = 0;
     946         6614 :     key_ = p;
     947         6872 : }
     948              : 
     949              : //----------------------------------------------------------
     950              : 
     951              : namespace detail
     952              : {
     953              : 
     954              : std::size_t
     955          248 : hash_value_impl( value const& jv ) noexcept
     956              : {
     957          248 :     std::size_t seed = 0;
     958              : 
     959          248 :     kind const k = jv.kind();
     960          248 :     boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
     961              : 
     962          248 :     visit( value_hasher{seed}, jv );
     963          248 :     return seed;
     964              : }
     965              : 
     966              : } // namespace detail
     967              : } // namespace json
     968              : } // namespace boost
     969              : 
     970              : //----------------------------------------------------------
     971              : //
     972              : // std::hash specialization
     973              : //
     974              : //----------------------------------------------------------
     975              : 
     976              : std::size_t
     977           62 : std::hash<::boost::json::value>::operator()(
     978              :     ::boost::json::value const& jv) const noexcept
     979              : {
     980           62 :     return ::boost::hash< ::boost::json::value >()( jv );
     981              : }
     982              : 
     983              : //----------------------------------------------------------
     984              : 
     985              : #endif
        

Generated by: LCOV version 2.1