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 % 451 449 2
Test Date: 2026-03-04 10:03:37 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         2178636 : value::
      81                 : ~value() noexcept
      82                 : {
      83         2178636 :     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           27376 :     case json::kind::string:
      94           27376 :         str_.~string();
      95           27376 :         break;
      96                 : 
      97            3087 :     case json::kind::array:
      98            3087 :         arr_.~array();
      99            3087 :         break;
     100                 : 
     101           35204 :     case json::kind::object:
     102           35204 :         obj_.~object();
     103           35204 :         break;
     104                 :     }
     105         2178636 : }
     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             186 : value::try_as_array() const noexcept
     376                 : {
     377             186 :     if( is_array() )
     378             158 :         return arr_;
     379                 : 
     380              28 :     system::error_code ec;
     381              28 :     BOOST_JSON_FAIL(ec, error::not_array);
     382              28 :     return ec;
     383                 : }
     384                 : 
     385                 : system::result<object&>
     386               9 : value::try_as_object() noexcept
     387                 : {
     388               9 :     if( is_object() )
     389               2 :         return obj_;
     390                 : 
     391               7 :     system::error_code ec;
     392               7 :     BOOST_JSON_FAIL(ec, error::not_object);
     393               7 :     return ec;
     394                 : }
     395                 : 
     396                 : system::result<object const&>
     397             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              98 : value::
     627                 : emplace_string() noexcept
     628                 : {
     629              98 :     return *::new(&str_) string(destroy());
     630                 : }
     631                 : 
     632                 : array&
     633             249 : value::
     634                 : emplace_array() noexcept
     635                 : {
     636             249 :     return *::new(&arr_) array(destroy());
     637                 : }
     638                 : 
     639                 : object&
     640              55 : value::
     641                 : emplace_object() noexcept
     642                 : {
     643              55 :     return *::new(&obj_) object(destroy());
     644                 : }
     645                 : 
     646                 : void
     647             259 : value::
     648                 : swap(value& other)
     649                 : {
     650             259 :     if(*storage() == *other.storage())
     651                 :     {
     652                 :         // fast path
     653                 :         union U
     654                 :         {
     655                 :             value tmp;
     656             258 :             U(){}
     657             258 :             ~U(){}
     658                 :         };
     659             258 :         U u;
     660             258 :         relocate(&u.tmp, *this);
     661             258 :         relocate(this, other);
     662             258 :         relocate(&other, u.tmp);
     663             258 :         return;
     664             258 :     }
     665                 : 
     666                 :     // copy
     667                 :     value temp1(
     668               1 :         std::move(*this),
     669               2 :         other.storage());
     670                 :     value temp2(
     671               1 :         std::move(other),
     672               2 :         this->storage());
     673               1 :     other.~value();
     674               1 :     ::new(&other) value(pilfer(temp1));
     675               1 :     this->~value();
     676               1 :     ::new(this) value(pilfer(temp2));
     677               1 : }
     678                 : 
     679                 : std::istream&
     680              10 : operator>>(
     681                 :     std::istream& is,
     682                 :     value& jv)
     683                 : {
     684                 :     using Traits = std::istream::traits_type;
     685                 : 
     686                 :     // sentry prepares the stream for reading and finalizes it in destructor
     687              10 :     std::istream::sentry sentry(is);
     688              10 :     if( !sentry )
     689               1 :         return is;
     690                 : 
     691               9 :     parse_options opts = get_parse_options( is );
     692               9 :     if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
     693               3 :         opts.max_depth = depth;
     694                 : 
     695                 :     unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
     696               9 :     stream_parser p( {}, opts, parser_buf );
     697               9 :     p.reset( jv.storage() );
     698                 : 
     699                 :     char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
     700               9 :     std::streambuf& buf = *is.rdbuf();
     701               9 :     std::ios::iostate err = std::ios::goodbit;
     702                 : #ifndef BOOST_NO_EXCEPTIONS
     703                 :     try
     704                 : #endif
     705                 :     {
     706                 :         while( true )
     707                 :         {
     708              15 :             system::error_code ec;
     709                 : 
     710                 :             // we peek the buffer; this either makes sure that there's no
     711                 :             // more input, or makes sure there's something in the internal
     712                 :             // buffer (so in_avail will return a positive number)
     713              15 :             std::istream::int_type c = is.rdbuf()->sgetc();
     714                 :             // if we indeed reached EOF, we check if we parsed a full JSON
     715                 :             // document; if not, we error out
     716              13 :             if( Traits::eq_int_type(c, Traits::eof()) )
     717                 :             {
     718               3 :                 err |= std::ios::eofbit;
     719               3 :                 p.finish(ec);
     720               3 :                 if( ec.failed() )
     721               4 :                     break;
     722                 :             }
     723                 : 
     724                 :             // regardless of reaching EOF, we might have parsed a full JSON
     725                 :             // document; if so, we successfully finish
     726              12 :             if( p.done() )
     727                 :             {
     728               3 :                 jv = p.release();
     729               3 :                 return is;
     730                 :             }
     731                 : 
     732                 :             // at this point we definitely have more input, specifically in
     733                 :             // buf's internal buffer; we also definitely haven't parsed a whole
     734                 :             // document
     735               9 :             std::streamsize available = buf.in_avail();
     736                 :             // if this assert fails, the streambuf is buggy
     737               9 :             BOOST_ASSERT( available > 0 );
     738                 : 
     739              18 :             available = ( std::min )(
     740               9 :                 static_cast<std::size_t>(available), sizeof(read_buf) );
     741                 :             // we read from the internal buffer of buf into our buffer
     742               9 :             available = buf.sgetn( read_buf, available );
     743                 : 
     744               9 :             std::size_t consumed = p.write_some(
     745                 :                 read_buf, static_cast<std::size_t>(available), ec );
     746                 :             // if the parser hasn't consumed the entire input we've took from
     747                 :             // buf, we put the remaining data back; this should succeed,
     748                 :             // because we only read data from buf's internal buffer
     749              21 :             while( consumed++ < static_cast<std::size_t>(available) )
     750                 :             {
     751              12 :                 std::istream::int_type const status = buf.sungetc();
     752              12 :                 BOOST_ASSERT( status != Traits::eof() );
     753                 :                 (void)status;
     754                 :             }
     755                 : 
     756               9 :             if( ec.failed() )
     757               3 :                 break;
     758               6 :         }
     759                 :     }
     760                 : #ifndef BOOST_NO_EXCEPTIONS
     761               2 :     catch(...)
     762                 :     {
     763                 :         try
     764                 :         {
     765               2 :             is.setstate(std::ios::badbit);
     766                 :         }
     767                 :         // we ignore the exception, because we need to throw the original
     768                 :         // exception instead
     769               1 :         catch( std::ios::failure const& ) { }
     770                 : 
     771               2 :         if( is.exceptions() & std::ios::badbit )
     772               1 :             throw;
     773               2 :     }
     774                 : #endif
     775                 : 
     776               5 :     is.setstate(err | std::ios::failbit);
     777               5 :     return is;
     778               9 : }
     779                 : 
     780                 : std::istream&
     781               3 : operator>>(
     782                 :     std::istream& is,
     783                 :     parse_options const& opts)
     784                 : {
     785               3 :     is.iword(parse_flags_xalloc) = to_bitmask(opts);
     786               3 :     is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
     787               3 :     return is;
     788                 : }
     789                 : 
     790                 : //----------------------------------------------------------
     791                 : //
     792                 : // private
     793                 : //
     794                 : //----------------------------------------------------------
     795                 : 
     796                 : storage_ptr
     797             420 : value::
     798                 : destroy() noexcept
     799                 : {
     800             420 :     switch(kind())
     801                 :     {
     802             401 :     case json::kind::null:
     803                 :     case json::kind::bool_:
     804                 :     case json::kind::int64:
     805                 :     case json::kind::uint64:
     806                 :     case json::kind::double_:
     807             401 :         break;
     808                 : 
     809              14 :     case json::kind::string:
     810                 :     {
     811              14 :         auto sp = str_.storage();
     812              14 :         str_.~string();
     813              14 :         return sp;
     814              14 :     }
     815                 : 
     816               2 :     case json::kind::array:
     817                 :     {
     818               2 :         auto sp = arr_.storage();
     819               2 :         arr_.~array();
     820               2 :         return sp;
     821               2 :     }
     822                 : 
     823               3 :     case json::kind::object:
     824                 :     {
     825               3 :         auto sp = obj_.storage();
     826               3 :         obj_.~object();
     827               3 :         return sp;
     828               3 :     }
     829                 : 
     830                 :     }
     831             401 :     return std::move(sp_);
     832                 : }
     833                 : 
     834                 : bool
     835            4172 : value::
     836                 : equal(value const& other) const noexcept
     837                 : {
     838            4172 :     switch(kind())
     839                 :     {
     840              21 :     default: // unreachable()?
     841                 :     case json::kind::null:
     842              21 :         return other.kind() == json::kind::null;
     843                 : 
     844              17 :     case json::kind::bool_:
     845                 :         return
     846              27 :             other.kind() == json::kind::bool_ &&
     847              27 :             get_bool() == other.get_bool();
     848                 : 
     849            3943 :     case json::kind::int64:
     850            3943 :         switch(other.kind())
     851                 :         {
     852            3916 :         case json::kind::int64:
     853            3916 :             return get_int64() == other.get_int64();
     854              26 :         case json::kind::uint64:
     855              26 :             if(get_int64() < 0)
     856               1 :                 return false;
     857              25 :             return static_cast<std::uint64_t>(
     858              25 :                 get_int64()) == other.get_uint64();
     859               1 :         default:
     860               1 :             return false;
     861                 :         }
     862                 : 
     863               7 :     case json::kind::uint64:
     864               7 :         switch(other.kind())
     865                 :         {
     866               2 :         case json::kind::uint64:
     867               2 :             return get_uint64() == other.get_uint64();
     868               3 :         case json::kind::int64:
     869               3 :             if(other.get_int64() < 0)
     870               2 :                 return false;
     871               1 :             return static_cast<std::uint64_t>(
     872               1 :                 other.get_int64()) == get_uint64();
     873               2 :         default:
     874               2 :             return false;
     875                 :         }
     876                 : 
     877              55 :     case json::kind::double_:
     878                 :         return
     879             108 :             other.kind() == json::kind::double_ &&
     880             108 :             get_double() == other.get_double();
     881                 : 
     882              47 :     case json::kind::string:
     883                 :         return
     884              91 :             other.kind() == json::kind::string &&
     885              91 :             get_string() == other.get_string();
     886                 : 
     887              62 :     case json::kind::array:
     888                 :         return
     889             122 :             other.kind() == json::kind::array &&
     890             122 :             get_array() == other.get_array();
     891                 : 
     892              20 :     case json::kind::object:
     893                 :         return
     894              37 :             other.kind() == json::kind::object &&
     895              37 :             get_object() == other.get_object();
     896                 :     }
     897                 : }
     898                 : 
     899                 : //----------------------------------------------------------
     900                 : //
     901                 : // key_value_pair
     902                 : //
     903                 : //----------------------------------------------------------
     904                 : 
     905                 : // empty keys point here
     906                 : BOOST_JSON_REQUIRE_CONST_INIT
     907                 : char const
     908                 : key_value_pair::empty_[1] = { 0 };
     909                 : 
     910           38150 : key_value_pair::
     911                 : key_value_pair(
     912                 :     pilfered<json::value> key,
     913           38150 :     pilfered<json::value> value) noexcept
     914           38150 :     : value_(value)
     915                 : {
     916                 :     std::size_t len;
     917           38150 :     key_ = access::release_key(key.get(), len);
     918           38150 :     len_ = static_cast<std::uint32_t>(len);
     919           38150 : }
     920                 : 
     921            6858 : key_value_pair::
     922                 : key_value_pair(
     923                 :     key_value_pair const& other,
     924            6858 :     storage_ptr sp)
     925            6862 :     : value_(other.value_, std::move(sp))
     926                 : {
     927                 :     auto p = reinterpret_cast<
     928            6854 :         char*>(value_.storage()->
     929            6854 :             allocate(other.len_ + 1,
     930                 :                 alignof(char)));
     931            6596 :     std::memcpy(
     932            6596 :         p, other.key_, other.len_);
     933            6596 :     len_ = other.len_;
     934            6596 :     p[len_] = 0;
     935            6596 :     key_ = p;
     936            6854 : }
     937                 : 
     938                 : //----------------------------------------------------------
     939                 : 
     940                 : namespace detail
     941                 : {
     942                 : 
     943                 : std::size_t
     944             248 : hash_value_impl( value const& jv ) noexcept
     945                 : {
     946             248 :     std::size_t seed = 0;
     947                 : 
     948             248 :     kind const k = jv.kind();
     949             248 :     boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
     950                 : 
     951             248 :     visit( value_hasher{seed}, jv );
     952             248 :     return seed;
     953                 : }
     954                 : 
     955                 : } // namespace detail
     956                 : } // namespace json
     957                 : } // namespace boost
     958                 : 
     959                 : //----------------------------------------------------------
     960                 : //
     961                 : // std::hash specialization
     962                 : //
     963                 : //----------------------------------------------------------
     964                 : 
     965                 : std::size_t
     966              62 : std::hash<::boost::json::value>::operator()(
     967                 :     ::boost::json::value const& jv) const noexcept
     968                 : {
     969              62 :     return ::boost::hash< ::boost::json::value >()( jv );
     970                 : }
     971                 : 
     972                 : //----------------------------------------------------------
     973                 : 
     974                 : #endif
        

Generated by: LCOV version 2.3