LCOV - code coverage report
Current view: top level - json/impl - value.ipp (source / functions) Coverage Total Hit
Test: coverage_remapped.info Lines: 100.0 % 462 462
Test Date: 2026-09-26 20:51:00 Functions: 100.0 % 70 70

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

Generated by: LCOV version 2.3