LCOV - code coverage report
Current view: top level - json/impl - value.ipp (source / functions) Coverage Total Hit Missed
Test: coverage_remapped.info Lines: 99.6 % 457 455 2
Test Date: 2026-06-03 12:39:35 Functions: 100.0 % 74 74

           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         2178639 : value::
      81                 : ~value() noexcept
      82                 : {
      83         2178639 :     switch(kind())
      84                 :     {
      85         2112969 :     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         2112969 :         sca_.~scalar();
      91         2112969 :         break;
      92                 : 
      93           27377 :     case json::kind::string:
      94           27377 :         str_.~string();
      95           27377 :         break;
      96                 : 
      97            3088 :     case json::kind::array:
      98            3088 :         arr_.~array();
      99            3088 :         break;
     100                 : 
     101           35205 :     case json::kind::object:
     102           35205 :         obj_.~object();
     103           35205 :         break;
     104                 :     }
     105         2178639 : }
     106                 : 
     107            9490 : value::
     108                 : value(
     109                 :     value const& other,
     110            9490 :     storage_ptr sp)
     111                 : {
     112            9490 :     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            7006 :     case json::kind::int64:
     126           21018 :         ::new(&sca_) scalar(
     127            7006 :             other.sca_.i,
     128            7006 :             std::move(sp));
     129            7006 :         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             130 :     case json::kind::string:
     144              17 :         ::new(&str_) string(
     145             130 :             other.str_,
     146             164 :             std::move(sp));
     147             113 :         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            9437 : }
     162                 : 
     163            3784 : value::
     164            3784 : value(value&& other) noexcept
     165                 : {
     166            3784 :     relocate(this, other);
     167            3784 :     ::new(&other.sca_) scalar(sp_);
     168            3784 : }
     169                 : 
     170           11452 : value::
     171                 : value(
     172                 :     value&& other,
     173           11452 :     storage_ptr sp)
     174                 : {
     175           11452 :     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             190 :     case json::kind::bool_:
     183             570 :         ::new(&sca_) scalar(
     184             190 :             other.sca_.b, std::move(sp));
     185             190 :         break;
     186                 : 
     187           10452 :     case json::kind::int64:
     188           31356 :         ::new(&sca_) scalar(
     189           10452 :             other.sca_.i, std::move(sp));
     190           10452 :         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             336 :     case json::kind::string:
     203               4 :         ::new(&str_) string(
     204             336 :             std::move(other.str_),
     205             680 :             std::move(sp));
     206             332 :         break;
     207                 : 
     208             224 :     case json::kind::array:
     209               5 :         ::new(&arr_) array(
     210             224 :             std::move(other.arr_),
     211             458 :             std::move(sp));
     212             219 :         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           11430 : }
     221                 : 
     222                 : //----------------------------------------------------------
     223                 : //
     224                 : // Conversion
     225                 : //
     226                 : //----------------------------------------------------------
     227                 : 
     228             336 : value::
     229                 : value(
     230                 :     std::initializer_list<value_ref> init,
     231             336 :     storage_ptr sp)
     232                 : {
     233             336 :     if(value_ref::maybe_object(init))
     234                 :     {
     235 MIS           0 :         ::new(&obj_) object(
     236                 :             value_ref::make_object(
     237 HIT         103 :                 init, std::move(sp)));
     238                 :     }
     239                 :     else
     240                 :     {
     241             233 :         if( init.size() == 1 )
     242                 :         {
     243              13 :             ::new(&sca_) scalar();
     244              13 :             value temp = init.begin()->make_value( std::move(sp) );
     245              13 :             swap(temp);
     246              13 :         }
     247                 :         else
     248                 :         {
     249 MIS           0 :             ::new(&arr_) array(
     250                 :                 value_ref::make_array(
     251 HIT         220 :                     init, std::move(sp)));
     252                 :         }
     253                 :     }
     254             336 : }
     255                 : 
     256                 : //----------------------------------------------------------
     257                 : //
     258                 : // Assignment
     259                 : //
     260                 : //----------------------------------------------------------
     261                 : 
     262                 : value&
     263              38 : value::
     264                 : operator=(value const& other)
     265                 : {
     266              76 :     value(other,
     267              32 :         storage()).swap(*this);
     268              32 :     return *this;
     269                 : }
     270                 : 
     271                 : value&
     272              82 : value::
     273                 : operator=(value&& other)
     274                 : {
     275             164 :     value(std::move(other),
     276              63 :         storage()).swap(*this);
     277              63 :     return *this;
     278                 : }
     279                 : 
     280                 : value&
     281              13 : value::
     282                 : operator=(
     283                 :     std::initializer_list<value_ref> init)
     284                 : {
     285              26 :     value(init,
     286              13 :         storage()).swap(*this);
     287              13 :     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               7 : value::
     316                 : operator=(string&& str)
     317                 : {
     318              14 :     value(std::move(str),
     319               7 :         storage()).swap(*this);
     320               7 :     return *this;
     321                 : }
     322                 : 
     323                 : value&
     324               4 : value::
     325                 : operator=(array const& arr)
     326                 : {
     327               4 :     value(arr, storage()).swap(*this);
     328               4 :     return *this;
     329                 : }
     330                 : 
     331                 : value&
     332              21 : value::
     333                 : operator=(array&& arr)
     334                 : {
     335              42 :     value(std::move(arr),
     336              21 :         storage()).swap(*this);
     337              21 :     return *this;
     338                 : }
     339                 : 
     340                 : value&
     341               4 : value::
     342                 : operator=(object const& obj)
     343                 : {
     344               4 :     value(obj, storage()).swap(*this);
     345               4 :     return *this;
     346                 : }
     347                 : 
     348                 : value&
     349              54 : value::
     350                 : operator=(object&& obj)
     351                 : {
     352             108 :     value(std::move(obj),
     353              54 :         storage()).swap(*this);
     354              54 :     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             305 : value::try_as_array() const noexcept
     376                 : {
     377             305 :     if( is_array() )
     378             265 :         return arr_;
     379                 : 
     380              40 :     system::error_code ec;
     381              40 :     BOOST_JSON_FAIL(ec, error::not_array);
     382              40 :     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             282 : value::try_as_object() const noexcept
     398                 : {
     399             282 :     if( is_object() )
     400             242 :         return obj_;
     401                 : 
     402              40 :     system::error_code ec;
     403              40 :     BOOST_JSON_FAIL(ec, error::not_object);
     404              40 :     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               2 :     return try_as_object() & [key](object& jo) { return jo.try_at(key); };
     532                 : }
     533                 : 
     534                 : boost::system::result<value const&>
     535               3 : value::try_at(string_view key) const noexcept
     536                 : {
     537               6 :     return try_as_object()
     538               6 :         & [key](object const& jo) { return jo.try_at(key); };
     539                 : }
     540                 : 
     541                 : boost::system::result<value&>
     542               8 : value::try_at(std::size_t pos) noexcept
     543                 : {
     544              16 :     return try_as_array() & [pos](array& ja) { return ja.try_at(pos); };
     545                 : }
     546                 : 
     547                 : boost::system::result<value const&>
     548               2 : value::try_at(std::size_t pos) const noexcept
     549                 : {
     550               4 :     return try_as_array() & [pos](array const& ja) { return ja.try_at(pos); };
     551                 : }
     552                 : 
     553                 : object const&
     554             197 : value::as_object(source_location const& loc) const&
     555                 : {
     556             197 :     return try_as_object().value(loc);
     557                 : }
     558                 : 
     559                 : array const&
     560             176 : value::as_array(source_location const& loc) const&
     561                 : {
     562             176 :     return try_as_array().value(loc);
     563                 : }
     564                 : 
     565                 : string const&
     566             113 : value::as_string(source_location const& loc) const&
     567                 : {
     568             113 :     return try_as_string().value(loc);
     569                 : }
     570                 : 
     571                 : std::int64_t&
     572              44 : value::as_int64(source_location const& loc)
     573                 : {
     574              44 :     return try_as_int64().value(loc);
     575                 : }
     576                 : 
     577                 : std::int64_t
     578              26 : value::as_int64(source_location const& loc) const
     579                 : {
     580              26 :     return try_as_int64().value(loc);
     581                 : }
     582                 : 
     583                 : std::uint64_t&
     584               8 : value::as_uint64(source_location const& loc)
     585                 : {
     586               8 :     return try_as_uint64().value(loc);
     587                 : }
     588                 : 
     589                 : std::uint64_t
     590               8 : value::as_uint64(source_location const& loc) const
     591                 : {
     592               8 :     return try_as_uint64().value(loc);
     593                 : }
     594                 : 
     595                 : double&
     596         2000649 : value::as_double(source_location const& loc)
     597                 : {
     598         2000649 :     return try_as_double().value(loc);
     599                 : }
     600                 : 
     601                 : double
     602             572 : value::as_double(source_location const& loc) const
     603                 : {
     604             572 :     return try_as_double().value(loc);
     605                 : }
     606                 : 
     607                 : bool&
     608              10 : value::as_bool(source_location const& loc)
     609                 : {
     610              10 :     return try_as_bool().value(loc);
     611                 : }
     612                 : 
     613                 : bool
     614              22 : value::as_bool(source_location const& loc) const
     615                 : {
     616              22 :     return try_as_bool().value(loc);
     617                 : }
     618                 : 
     619                 : //----------------------------------------------------------
     620                 : //
     621                 : // Modifiers
     622                 : //
     623                 : //----------------------------------------------------------
     624                 : 
     625                 : string&
     626              99 : value::
     627                 : emplace_string() noexcept
     628                 : {
     629              99 :     storage_ptr sp = destroy();
     630              99 :     return *::new(&str_) string(sp);
     631              99 : }
     632                 : 
     633                 : array&
     634             250 : value::
     635                 : emplace_array() noexcept
     636                 : {
     637             250 :     storage_ptr sp = destroy();
     638             250 :     return *::new(&arr_) array(sp);
     639             250 : }
     640                 : 
     641                 : object&
     642              56 : value::
     643                 : emplace_object() noexcept
     644                 : {
     645              56 :     storage_ptr sp = destroy();
     646              56 :     return *::new(&obj_) object(sp);
     647              56 : }
     648                 : 
     649                 : void
     650             259 : value::
     651                 : swap(value& other)
     652                 : {
     653             259 :     if(*storage() == *other.storage())
     654                 :     {
     655                 :         // fast path
     656                 :         union U
     657                 :         {
     658                 :             value tmp;
     659             258 :             U(){}
     660             258 :             ~U(){}
     661                 :         };
     662             258 :         U u;
     663             258 :         relocate(&u.tmp, *this);
     664             258 :         relocate(this, other);
     665             258 :         relocate(&other, u.tmp);
     666             258 :         return;
     667             258 :     }
     668                 : 
     669                 :     // copy
     670                 :     value temp1(
     671               1 :         std::move(*this),
     672               2 :         other.storage());
     673                 :     value temp2(
     674               1 :         std::move(other),
     675               2 :         this->storage());
     676               1 :     other.~value();
     677               1 :     ::new(&other) value(pilfer(temp1));
     678               1 :     this->~value();
     679               1 :     ::new(this) value(pilfer(temp2));
     680               1 : }
     681                 : 
     682                 : std::istream&
     683              10 : operator>>(
     684                 :     std::istream& is,
     685                 :     value& jv)
     686                 : {
     687                 :     using Traits = std::istream::traits_type;
     688                 : 
     689                 :     // sentry prepares the stream for reading and finalizes it in destructor
     690              10 :     std::istream::sentry sentry(is);
     691              10 :     if( !sentry )
     692               1 :         return is;
     693                 : 
     694               9 :     parse_options opts = get_parse_options( is );
     695               9 :     if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
     696               3 :         opts.max_depth = depth;
     697                 : 
     698                 :     unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
     699               9 :     stream_parser p( {}, opts, parser_buf );
     700               9 :     p.reset( jv.storage() );
     701                 : 
     702                 :     char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
     703               9 :     std::streambuf& buf = *is.rdbuf();
     704               9 :     std::ios::iostate err = std::ios::goodbit;
     705                 : #ifndef BOOST_NO_EXCEPTIONS
     706                 :     try
     707                 : #endif
     708                 :     {
     709                 :         while( true )
     710                 :         {
     711              15 :             system::error_code ec;
     712                 : 
     713                 :             // we peek the buffer; this either makes sure that there's no
     714                 :             // more input, or makes sure there's something in the internal
     715                 :             // buffer (so in_avail will return a positive number)
     716              15 :             std::istream::int_type c = is.rdbuf()->sgetc();
     717                 :             // if we indeed reached EOF, we check if we parsed a full JSON
     718                 :             // document; if not, we error out
     719              13 :             if( Traits::eq_int_type(c, Traits::eof()) )
     720                 :             {
     721               3 :                 err |= std::ios::eofbit;
     722               3 :                 p.finish(ec);
     723               3 :                 if( ec.failed() )
     724               4 :                     break;
     725                 :             }
     726                 : 
     727                 :             // regardless of reaching EOF, we might have parsed a full JSON
     728                 :             // document; if so, we successfully finish
     729              12 :             if( p.done() )
     730                 :             {
     731               3 :                 jv = p.release();
     732               3 :                 return is;
     733                 :             }
     734                 : 
     735                 :             // at this point we definitely have more input, specifically in
     736                 :             // buf's internal buffer; we also definitely haven't parsed a whole
     737                 :             // document
     738               9 :             std::streamsize available = buf.in_avail();
     739                 :             // if this assert fails, the streambuf is buggy
     740               9 :             BOOST_ASSERT( available > 0 );
     741                 : 
     742              18 :             available = ( std::min )(
     743               9 :                 static_cast<std::size_t>(available), sizeof(read_buf) );
     744                 :             // we read from the internal buffer of buf into our buffer
     745               9 :             available = buf.sgetn( read_buf, available );
     746                 : 
     747               9 :             std::size_t consumed = p.write_some(
     748                 :                 read_buf, static_cast<std::size_t>(available), ec );
     749                 :             // if the parser hasn't consumed the entire input we've took from
     750                 :             // buf, we put the remaining data back; this should succeed,
     751                 :             // because we only read data from buf's internal buffer
     752              21 :             while( consumed++ < static_cast<std::size_t>(available) )
     753                 :             {
     754              12 :                 std::istream::int_type const status = buf.sungetc();
     755              12 :                 BOOST_ASSERT( status != Traits::eof() );
     756                 :                 (void)status;
     757                 :             }
     758                 : 
     759               9 :             if( ec.failed() )
     760               3 :                 break;
     761               6 :         }
     762                 :     }
     763                 : #ifndef BOOST_NO_EXCEPTIONS
     764               2 :     catch(...)
     765                 :     {
     766                 :         try
     767                 :         {
     768               2 :             is.setstate(std::ios::badbit);
     769                 :         }
     770                 :         // we ignore the exception, because we need to throw the original
     771                 :         // exception instead
     772               1 :         catch( std::ios::failure const& ) { }
     773                 : 
     774               2 :         if( is.exceptions() & std::ios::badbit )
     775               1 :             throw;
     776               2 :     }
     777                 : #endif
     778                 : 
     779               5 :     is.setstate(err | std::ios::failbit);
     780               5 :     return is;
     781               9 : }
     782                 : 
     783                 : std::istream&
     784               3 : operator>>(
     785                 :     std::istream& is,
     786                 :     parse_options const& opts)
     787                 : {
     788               3 :     is.iword(parse_flags_xalloc) = to_bitmask(opts);
     789               3 :     is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
     790               3 :     return is;
     791                 : }
     792                 : 
     793                 : //----------------------------------------------------------
     794                 : //
     795                 : // private
     796                 : //
     797                 : //----------------------------------------------------------
     798                 : 
     799                 : storage_ptr
     800             423 : value::
     801                 : destroy() noexcept
     802                 : {
     803             423 :     switch(kind())
     804                 :     {
     805             404 :     case json::kind::null:
     806                 :     case json::kind::bool_:
     807                 :     case json::kind::int64:
     808                 :     case json::kind::uint64:
     809                 :     case json::kind::double_:
     810             404 :         break;
     811                 : 
     812              14 :     case json::kind::string:
     813                 :     {
     814              14 :         auto sp = str_.storage();
     815              14 :         str_.~string();
     816              14 :         return sp;
     817              14 :     }
     818                 : 
     819               2 :     case json::kind::array:
     820                 :     {
     821               2 :         auto sp = arr_.storage();
     822               2 :         arr_.~array();
     823               2 :         return sp;
     824               2 :     }
     825                 : 
     826               3 :     case json::kind::object:
     827                 :     {
     828               3 :         auto sp = obj_.storage();
     829               3 :         obj_.~object();
     830               3 :         return sp;
     831               3 :     }
     832                 : 
     833                 :     }
     834             404 :     return std::move(sp_);
     835                 : }
     836                 : 
     837                 : bool
     838            4172 : value::
     839                 : equal(value const& other) const noexcept
     840                 : {
     841            4172 :     switch(kind())
     842                 :     {
     843              21 :     default: // unreachable()?
     844                 :     case json::kind::null:
     845              21 :         return other.kind() == json::kind::null;
     846                 : 
     847              17 :     case json::kind::bool_:
     848                 :         return
     849              27 :             other.kind() == json::kind::bool_ &&
     850              27 :             get_bool() == other.get_bool();
     851                 : 
     852            3943 :     case json::kind::int64:
     853            3943 :         switch(other.kind())
     854                 :         {
     855            3916 :         case json::kind::int64:
     856            3916 :             return get_int64() == other.get_int64();
     857              26 :         case json::kind::uint64:
     858              26 :             if(get_int64() < 0)
     859               1 :                 return false;
     860              25 :             return static_cast<std::uint64_t>(
     861              25 :                 get_int64()) == other.get_uint64();
     862               1 :         default:
     863               1 :             return false;
     864                 :         }
     865                 : 
     866               7 :     case json::kind::uint64:
     867               7 :         switch(other.kind())
     868                 :         {
     869               2 :         case json::kind::uint64:
     870               2 :             return get_uint64() == other.get_uint64();
     871               3 :         case json::kind::int64:
     872               3 :             if(other.get_int64() < 0)
     873               2 :                 return false;
     874               1 :             return static_cast<std::uint64_t>(
     875               1 :                 other.get_int64()) == get_uint64();
     876               2 :         default:
     877               2 :             return false;
     878                 :         }
     879                 : 
     880              55 :     case json::kind::double_:
     881                 :         return
     882             108 :             other.kind() == json::kind::double_ &&
     883             108 :             get_double() == other.get_double();
     884                 : 
     885              47 :     case json::kind::string:
     886                 :         return
     887              91 :             other.kind() == json::kind::string &&
     888              91 :             get_string() == other.get_string();
     889                 : 
     890              62 :     case json::kind::array:
     891                 :         return
     892             122 :             other.kind() == json::kind::array &&
     893             122 :             get_array() == other.get_array();
     894                 : 
     895              20 :     case json::kind::object:
     896                 :         return
     897              37 :             other.kind() == json::kind::object &&
     898              37 :             get_object() == other.get_object();
     899                 :     }
     900                 : }
     901                 : 
     902                 : //----------------------------------------------------------
     903                 : //
     904                 : // key_value_pair
     905                 : //
     906                 : //----------------------------------------------------------
     907                 : 
     908                 : // empty keys point here
     909                 : BOOST_JSON_REQUIRE_CONST_INIT
     910                 : char const
     911                 : key_value_pair::empty_[1] = { 0 };
     912                 : 
     913           38150 : key_value_pair::
     914                 : key_value_pair(
     915                 :     pilfered<json::value> key,
     916           38150 :     pilfered<json::value> value) noexcept
     917           38150 :     : value_(value)
     918                 : {
     919                 :     std::size_t len;
     920           38150 :     key_ = access::release_key(key.get(), len);
     921           38150 :     len_ = static_cast<std::uint32_t>(len);
     922           38150 : }
     923                 : 
     924            6858 : key_value_pair::
     925                 : key_value_pair(
     926                 :     key_value_pair const& other,
     927            6858 :     storage_ptr sp)
     928            6862 :     : value_(other.value_, std::move(sp))
     929                 : {
     930                 :     auto p = reinterpret_cast<
     931            6854 :         char*>(value_.storage()->
     932            6854 :             allocate(other.len_ + 1,
     933                 :                 alignof(char)));
     934            6596 :     std::memcpy(
     935            6596 :         p, other.key_, other.len_);
     936            6596 :     len_ = other.len_;
     937            6596 :     p[len_] = 0;
     938            6596 :     key_ = p;
     939            6854 : }
     940                 : 
     941                 : //----------------------------------------------------------
     942                 : 
     943                 : namespace detail
     944                 : {
     945                 : 
     946                 : std::size_t
     947             248 : hash_value_impl( value const& jv ) noexcept
     948                 : {
     949             248 :     std::size_t seed = 0;
     950                 : 
     951             248 :     kind const k = jv.kind();
     952             248 :     boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
     953                 : 
     954             248 :     visit( value_hasher{seed}, jv );
     955             248 :     return seed;
     956                 : }
     957                 : 
     958                 : } // namespace detail
     959                 : } // namespace json
     960                 : } // namespace boost
     961                 : 
     962                 : //----------------------------------------------------------
     963                 : //
     964                 : // std::hash specialization
     965                 : //
     966                 : //----------------------------------------------------------
     967                 : 
     968                 : std::size_t
     969              62 : std::hash<::boost::json::value>::operator()(
     970                 :     ::boost::json::value const& jv) const noexcept
     971                 : {
     972              62 :     return ::boost::hash< ::boost::json::value >()( jv );
     973                 : }
     974                 : 
     975                 : //----------------------------------------------------------
     976                 : 
     977                 : #endif
        

Generated by: LCOV version 2.3