File indexing completed on 2025-01-18 09:39:02
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #ifndef BOOST_JSON_IMPL_VALUE_IPP
0011 #define BOOST_JSON_IMPL_VALUE_IPP
0012
0013 #include <boost/container_hash/hash.hpp>
0014 #include <boost/json/value.hpp>
0015 #include <boost/json/parser.hpp>
0016 #include <cstring>
0017 #include <istream>
0018 #include <limits>
0019 #include <new>
0020 #include <utility>
0021
0022 namespace boost {
0023 namespace json {
0024
0025 namespace
0026 {
0027
0028 int parse_depth_xalloc = std::ios::xalloc();
0029 int parse_flags_xalloc = std::ios::xalloc();
0030
0031 struct value_hasher
0032 {
0033 std::size_t& seed;
0034
0035 template< class T >
0036 void operator()( T&& t ) const noexcept
0037 {
0038 boost::hash_combine( seed, t );
0039 }
0040 };
0041
0042 enum class stream_parse_flags
0043 {
0044 allow_comments = 1 << 0,
0045 allow_trailing_commas = 1 << 1,
0046 allow_invalid_utf8 = 1 << 2,
0047 };
0048
0049 long
0050 to_bitmask( parse_options const& opts )
0051 {
0052 using E = stream_parse_flags;
0053 return
0054 (opts.allow_comments ?
0055 static_cast<long>(E::allow_comments) : 0) |
0056 (opts.allow_trailing_commas ?
0057 static_cast<long>(E::allow_trailing_commas) : 0) |
0058 (opts.allow_invalid_utf8 ?
0059 static_cast<long>(E::allow_invalid_utf8) : 0);
0060 }
0061
0062 parse_options
0063 get_parse_options( std::istream& is )
0064 {
0065 long const flags = is.iword(parse_flags_xalloc);
0066
0067 using E = stream_parse_flags;
0068 parse_options opts;
0069 opts.allow_comments =
0070 flags & static_cast<long>(E::allow_comments) ? true : false;
0071 opts.allow_trailing_commas =
0072 flags & static_cast<long>(E::allow_trailing_commas) ? true : false;
0073 opts.allow_invalid_utf8 =
0074 flags & static_cast<long>(E::allow_invalid_utf8) ? true : false;
0075 return opts;
0076 }
0077
0078 }
0079
0080 value::
0081 ~value() noexcept
0082 {
0083 switch(kind())
0084 {
0085 case json::kind::null:
0086 case json::kind::bool_:
0087 case json::kind::int64:
0088 case json::kind::uint64:
0089 case json::kind::double_:
0090 sca_.~scalar();
0091 break;
0092
0093 case json::kind::string:
0094 str_.~string();
0095 break;
0096
0097 case json::kind::array:
0098 arr_.~array();
0099 break;
0100
0101 case json::kind::object:
0102 obj_.~object();
0103 break;
0104 }
0105 }
0106
0107 value::
0108 value(
0109 value const& other,
0110 storage_ptr sp)
0111 {
0112 switch(other.kind())
0113 {
0114 case json::kind::null:
0115 ::new(&sca_) scalar(
0116 std::move(sp));
0117 break;
0118
0119 case json::kind::bool_:
0120 ::new(&sca_) scalar(
0121 other.sca_.b,
0122 std::move(sp));
0123 break;
0124
0125 case json::kind::int64:
0126 ::new(&sca_) scalar(
0127 other.sca_.i,
0128 std::move(sp));
0129 break;
0130
0131 case json::kind::uint64:
0132 ::new(&sca_) scalar(
0133 other.sca_.u,
0134 std::move(sp));
0135 break;
0136
0137 case json::kind::double_:
0138 ::new(&sca_) scalar(
0139 other.sca_.d,
0140 std::move(sp));
0141 break;
0142
0143 case json::kind::string:
0144 ::new(&str_) string(
0145 other.str_,
0146 std::move(sp));
0147 break;
0148
0149 case json::kind::array:
0150 ::new(&arr_) array(
0151 other.arr_,
0152 std::move(sp));
0153 break;
0154
0155 case json::kind::object:
0156 ::new(&obj_) object(
0157 other.obj_,
0158 std::move(sp));
0159 break;
0160 }
0161 }
0162
0163 value::
0164 value(value&& other) noexcept
0165 {
0166 relocate(this, other);
0167 ::new(&other.sca_) scalar(sp_);
0168 }
0169
0170 value::
0171 value(
0172 value&& other,
0173 storage_ptr sp)
0174 {
0175 switch(other.kind())
0176 {
0177 case json::kind::null:
0178 ::new(&sca_) scalar(
0179 std::move(sp));
0180 break;
0181
0182 case json::kind::bool_:
0183 ::new(&sca_) scalar(
0184 other.sca_.b, std::move(sp));
0185 break;
0186
0187 case json::kind::int64:
0188 ::new(&sca_) scalar(
0189 other.sca_.i, std::move(sp));
0190 break;
0191
0192 case json::kind::uint64:
0193 ::new(&sca_) scalar(
0194 other.sca_.u, std::move(sp));
0195 break;
0196
0197 case json::kind::double_:
0198 ::new(&sca_) scalar(
0199 other.sca_.d, std::move(sp));
0200 break;
0201
0202 case json::kind::string:
0203 ::new(&str_) string(
0204 std::move(other.str_),
0205 std::move(sp));
0206 break;
0207
0208 case json::kind::array:
0209 ::new(&arr_) array(
0210 std::move(other.arr_),
0211 std::move(sp));
0212 break;
0213
0214 case json::kind::object:
0215 ::new(&obj_) object(
0216 std::move(other.obj_),
0217 std::move(sp));
0218 break;
0219 }
0220 }
0221
0222
0223
0224
0225
0226
0227
0228 value::
0229 value(
0230 std::initializer_list<value_ref> init,
0231 storage_ptr sp)
0232 {
0233 if(value_ref::maybe_object(init))
0234 {
0235 ::new(&obj_) object(
0236 value_ref::make_object(
0237 init, std::move(sp)));
0238 }
0239 else
0240 {
0241 #ifndef BOOST_JSON_LEGACY_INIT_LIST_BEHAVIOR
0242 if( init.size() == 1 )
0243 {
0244 ::new(&sca_) scalar();
0245 value temp = init.begin()->make_value( std::move(sp) );
0246 swap(temp);
0247 }
0248 else
0249 #endif
0250 {
0251 ::new(&arr_) array(
0252 value_ref::make_array(
0253 init, std::move(sp)));
0254 }
0255 }
0256 }
0257
0258
0259
0260
0261
0262
0263
0264 value&
0265 value::
0266 operator=(value const& other)
0267 {
0268 value(other,
0269 storage()).swap(*this);
0270 return *this;
0271 }
0272
0273 value&
0274 value::
0275 operator=(value&& other)
0276 {
0277 value(std::move(other),
0278 storage()).swap(*this);
0279 return *this;
0280 }
0281
0282 value&
0283 value::
0284 operator=(
0285 std::initializer_list<value_ref> init)
0286 {
0287 value(init,
0288 storage()).swap(*this);
0289 return *this;
0290 }
0291
0292 value&
0293 value::
0294 operator=(string_view s)
0295 {
0296 value(s, storage()).swap(*this);
0297 return *this;
0298 }
0299
0300 value&
0301 value::
0302 operator=(char const* s)
0303 {
0304 value(s, storage()).swap(*this);
0305 return *this;
0306 }
0307
0308 value&
0309 value::
0310 operator=(string const& str)
0311 {
0312 value(str, storage()).swap(*this);
0313 return *this;
0314 }
0315
0316 value&
0317 value::
0318 operator=(string&& str)
0319 {
0320 value(std::move(str),
0321 storage()).swap(*this);
0322 return *this;
0323 }
0324
0325 value&
0326 value::
0327 operator=(array const& arr)
0328 {
0329 value(arr, storage()).swap(*this);
0330 return *this;
0331 }
0332
0333 value&
0334 value::
0335 operator=(array&& arr)
0336 {
0337 value(std::move(arr),
0338 storage()).swap(*this);
0339 return *this;
0340 }
0341
0342 value&
0343 value::
0344 operator=(object const& obj)
0345 {
0346 value(obj, storage()).swap(*this);
0347 return *this;
0348 }
0349
0350 value&
0351 value::
0352 operator=(object&& obj)
0353 {
0354 value(std::move(obj),
0355 storage()).swap(*this);
0356 return *this;
0357 }
0358
0359
0360
0361
0362
0363
0364
0365 string&
0366 value::
0367 emplace_string() noexcept
0368 {
0369 return *::new(&str_) string(destroy());
0370 }
0371
0372 array&
0373 value::
0374 emplace_array() noexcept
0375 {
0376 return *::new(&arr_) array(destroy());
0377 }
0378
0379 object&
0380 value::
0381 emplace_object() noexcept
0382 {
0383 return *::new(&obj_) object(destroy());
0384 }
0385
0386 void
0387 value::
0388 swap(value& other)
0389 {
0390 if(*storage() == *other.storage())
0391 {
0392
0393 union U
0394 {
0395 value tmp;
0396 U(){}
0397 ~U(){}
0398 };
0399 U u;
0400 relocate(&u.tmp, *this);
0401 relocate(this, other);
0402 relocate(&other, u.tmp);
0403 return;
0404 }
0405
0406
0407 value temp1(
0408 std::move(*this),
0409 other.storage());
0410 value temp2(
0411 std::move(other),
0412 this->storage());
0413 other.~value();
0414 ::new(&other) value(pilfer(temp1));
0415 this->~value();
0416 ::new(this) value(pilfer(temp2));
0417 }
0418
0419 std::istream&
0420 operator>>(
0421 std::istream& is,
0422 value& jv)
0423 {
0424 using Traits = std::istream::traits_type;
0425
0426
0427 std::istream::sentry sentry(is);
0428 if( !sentry )
0429 return is;
0430
0431 parse_options opts = get_parse_options( is );
0432 if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
0433 opts.max_depth = depth;
0434
0435 unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
0436 stream_parser p( {}, opts, parser_buf );
0437 p.reset( jv.storage() );
0438
0439 char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
0440 std::streambuf& buf = *is.rdbuf();
0441 std::ios::iostate err = std::ios::goodbit;
0442 #ifndef BOOST_NO_EXCEPTIONS
0443 try
0444 #endif
0445 {
0446 while( true )
0447 {
0448 error_code ec;
0449
0450
0451
0452
0453 std::istream::int_type c = is.rdbuf()->sgetc();
0454
0455
0456 if( Traits::eq_int_type(c, Traits::eof()) )
0457 {
0458 err |= std::ios::eofbit;
0459 p.finish(ec);
0460 if( ec.failed() )
0461 break;
0462 }
0463
0464
0465
0466 if( p.done() )
0467 {
0468 jv = p.release();
0469 return is;
0470 }
0471
0472
0473
0474
0475 std::streamsize available = buf.in_avail();
0476
0477 BOOST_ASSERT( available > 0 );
0478
0479 available = ( std::min )(
0480 static_cast<std::size_t>(available), sizeof(read_buf) );
0481
0482 available = buf.sgetn( read_buf, available );
0483
0484 std::size_t consumed = p.write_some(
0485 read_buf, static_cast<std::size_t>(available), ec );
0486
0487
0488
0489 while( consumed++ < static_cast<std::size_t>(available) )
0490 {
0491 std::istream::int_type const status = buf.sungetc();
0492 BOOST_ASSERT( status != Traits::eof() );
0493 (void)status;
0494 }
0495
0496 if( ec.failed() )
0497 break;
0498 }
0499 }
0500 #ifndef BOOST_NO_EXCEPTIONS
0501 catch(...)
0502 {
0503 try
0504 {
0505 is.setstate(std::ios::badbit);
0506 }
0507
0508
0509 catch( std::ios::failure const& ) { }
0510
0511 if( is.exceptions() & std::ios::badbit )
0512 throw;
0513 }
0514 #endif
0515
0516 is.setstate(err | std::ios::failbit);
0517 return is;
0518 }
0519
0520 std::istream&
0521 operator>>(
0522 std::istream& is,
0523 parse_options const& opts)
0524 {
0525 is.iword(parse_flags_xalloc) = to_bitmask(opts);
0526 is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
0527 return is;
0528 }
0529
0530
0531
0532
0533
0534
0535
0536 storage_ptr
0537 value::
0538 destroy() noexcept
0539 {
0540 switch(kind())
0541 {
0542 case json::kind::null:
0543 case json::kind::bool_:
0544 case json::kind::int64:
0545 case json::kind::uint64:
0546 case json::kind::double_:
0547 break;
0548
0549 case json::kind::string:
0550 {
0551 auto sp = str_.storage();
0552 str_.~string();
0553 return sp;
0554 }
0555
0556 case json::kind::array:
0557 {
0558 auto sp = arr_.storage();
0559 arr_.~array();
0560 return sp;
0561 }
0562
0563 case json::kind::object:
0564 {
0565 auto sp = obj_.storage();
0566 obj_.~object();
0567 return sp;
0568 }
0569
0570 }
0571 return std::move(sp_);
0572 }
0573
0574 bool
0575 value::
0576 equal(value const& other) const noexcept
0577 {
0578 switch(kind())
0579 {
0580 default:
0581 case json::kind::null:
0582 return other.kind() == json::kind::null;
0583
0584 case json::kind::bool_:
0585 return
0586 other.kind() == json::kind::bool_ &&
0587 get_bool() == other.get_bool();
0588
0589 case json::kind::int64:
0590 switch(other.kind())
0591 {
0592 case json::kind::int64:
0593 return get_int64() == other.get_int64();
0594 case json::kind::uint64:
0595 if(get_int64() < 0)
0596 return false;
0597 return static_cast<std::uint64_t>(
0598 get_int64()) == other.get_uint64();
0599 default:
0600 return false;
0601 }
0602
0603 case json::kind::uint64:
0604 switch(other.kind())
0605 {
0606 case json::kind::uint64:
0607 return get_uint64() == other.get_uint64();
0608 case json::kind::int64:
0609 if(other.get_int64() < 0)
0610 return false;
0611 return static_cast<std::uint64_t>(
0612 other.get_int64()) == get_uint64();
0613 default:
0614 return false;
0615 }
0616
0617 case json::kind::double_:
0618 return
0619 other.kind() == json::kind::double_ &&
0620 get_double() == other.get_double();
0621
0622 case json::kind::string:
0623 return
0624 other.kind() == json::kind::string &&
0625 get_string() == other.get_string();
0626
0627 case json::kind::array:
0628 return
0629 other.kind() == json::kind::array &&
0630 get_array() == other.get_array();
0631
0632 case json::kind::object:
0633 return
0634 other.kind() == json::kind::object &&
0635 get_object() == other.get_object();
0636 }
0637 }
0638
0639
0640
0641
0642
0643
0644
0645
0646 BOOST_JSON_REQUIRE_CONST_INIT
0647 char const
0648 key_value_pair::empty_[1] = { 0 };
0649
0650 key_value_pair::
0651 key_value_pair(
0652 pilfered<json::value> key,
0653 pilfered<json::value> value) noexcept
0654 : value_(value)
0655 {
0656 std::size_t len;
0657 key_ = access::release_key(key.get(), len);
0658 len_ = static_cast<std::uint32_t>(len);
0659 }
0660
0661 key_value_pair::
0662 key_value_pair(
0663 key_value_pair const& other,
0664 storage_ptr sp)
0665 : value_(other.value_, std::move(sp))
0666 {
0667 auto p = reinterpret_cast<
0668 char*>(value_.storage()->
0669 allocate(other.len_ + 1,
0670 alignof(char)));
0671 std::memcpy(
0672 p, other.key_, other.len_);
0673 len_ = other.len_;
0674 p[len_] = 0;
0675 key_ = p;
0676 }
0677
0678
0679
0680 namespace detail
0681 {
0682
0683 std::size_t
0684 hash_value_impl( value const& jv ) noexcept
0685 {
0686 std::size_t seed = 0;
0687
0688 kind const k = jv.kind();
0689 boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
0690
0691 visit( value_hasher{seed}, jv );
0692 return seed;
0693 }
0694
0695 }
0696 }
0697 }
0698
0699
0700
0701
0702
0703
0704
0705 std::size_t
0706 std::hash<::boost::json::value>::operator()(
0707 ::boost::json::value const& jv) const noexcept
0708 {
0709 return ::boost::hash< ::boost::json::value >()( jv );
0710 }
0711
0712
0713
0714 #endif