File indexing completed on 2025-09-15 08:39:00
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 if( init.size() == 1 )
0242 {
0243 ::new(&sca_) scalar();
0244 value temp = init.begin()->make_value( std::move(sp) );
0245 swap(temp);
0246 }
0247 else
0248 {
0249 ::new(&arr_) array(
0250 value_ref::make_array(
0251 init, std::move(sp)));
0252 }
0253 }
0254 }
0255
0256
0257
0258
0259
0260
0261
0262 value&
0263 value::
0264 operator=(value const& other)
0265 {
0266 value(other,
0267 storage()).swap(*this);
0268 return *this;
0269 }
0270
0271 value&
0272 value::
0273 operator=(value&& other)
0274 {
0275 value(std::move(other),
0276 storage()).swap(*this);
0277 return *this;
0278 }
0279
0280 value&
0281 value::
0282 operator=(
0283 std::initializer_list<value_ref> init)
0284 {
0285 value(init,
0286 storage()).swap(*this);
0287 return *this;
0288 }
0289
0290 value&
0291 value::
0292 operator=(string_view s)
0293 {
0294 value(s, storage()).swap(*this);
0295 return *this;
0296 }
0297
0298 value&
0299 value::
0300 operator=(char const* s)
0301 {
0302 value(s, storage()).swap(*this);
0303 return *this;
0304 }
0305
0306 value&
0307 value::
0308 operator=(string const& str)
0309 {
0310 value(str, storage()).swap(*this);
0311 return *this;
0312 }
0313
0314 value&
0315 value::
0316 operator=(string&& str)
0317 {
0318 value(std::move(str),
0319 storage()).swap(*this);
0320 return *this;
0321 }
0322
0323 value&
0324 value::
0325 operator=(array const& arr)
0326 {
0327 value(arr, storage()).swap(*this);
0328 return *this;
0329 }
0330
0331 value&
0332 value::
0333 operator=(array&& arr)
0334 {
0335 value(std::move(arr),
0336 storage()).swap(*this);
0337 return *this;
0338 }
0339
0340 value&
0341 value::
0342 operator=(object const& obj)
0343 {
0344 value(obj, storage()).swap(*this);
0345 return *this;
0346 }
0347
0348 value&
0349 value::
0350 operator=(object&& obj)
0351 {
0352 value(std::move(obj),
0353 storage()).swap(*this);
0354 return *this;
0355 }
0356
0357
0358
0359
0360
0361
0362
0363 system::result<array&>
0364 value::try_as_array() noexcept
0365 {
0366 if( is_array() )
0367 return arr_;
0368
0369 system::error_code ec;
0370 BOOST_JSON_FAIL(ec, error::not_array);
0371 return ec;
0372 }
0373
0374 system::result<array const&>
0375 value::try_as_array() const noexcept
0376 {
0377 if( is_array() )
0378 return arr_;
0379
0380 system::error_code ec;
0381 BOOST_JSON_FAIL(ec, error::not_array);
0382 return ec;
0383 }
0384
0385 system::result<object&>
0386 value::try_as_object() noexcept
0387 {
0388 if( is_object() )
0389 return obj_;
0390
0391 system::error_code ec;
0392 BOOST_JSON_FAIL(ec, error::not_object);
0393 return ec;
0394 }
0395
0396 system::result<object const&>
0397 value::try_as_object() const noexcept
0398 {
0399 if( is_object() )
0400 return obj_;
0401
0402 system::error_code ec;
0403 BOOST_JSON_FAIL(ec, error::not_object);
0404 return ec;
0405 }
0406
0407 system::result<string&>
0408 value::try_as_string() noexcept
0409 {
0410 if( is_string() )
0411 return str_;
0412
0413 system::error_code ec;
0414 BOOST_JSON_FAIL(ec, error::not_string);
0415 return ec;
0416 }
0417
0418 system::result<string const&>
0419 value::try_as_string() const noexcept
0420 {
0421 if( is_string() )
0422 return str_;
0423
0424 system::error_code ec;
0425 BOOST_JSON_FAIL(ec, error::not_string);
0426 return ec;
0427 }
0428
0429 system::result<std::int64_t&>
0430 value::try_as_int64() noexcept
0431 {
0432 if( is_int64() )
0433 return sca_.i;
0434
0435 system::error_code ec;
0436 BOOST_JSON_FAIL(ec, error::not_int64);
0437 return ec;
0438 }
0439
0440 system::result<std::int64_t>
0441 value::try_as_int64() const noexcept
0442 {
0443 if( is_int64() )
0444 return sca_.i;
0445
0446 system::error_code ec;
0447 BOOST_JSON_FAIL(ec, error::not_int64);
0448 return ec;
0449 }
0450
0451 system::result<std::uint64_t&>
0452 value::try_as_uint64() noexcept
0453 {
0454 if( is_uint64() )
0455 return sca_.u;
0456
0457 system::error_code ec;
0458 BOOST_JSON_FAIL(ec, error::not_uint64);
0459 return ec;
0460 }
0461
0462 system::result<std::uint64_t>
0463 value::try_as_uint64() const noexcept
0464 {
0465 if( is_uint64() )
0466 return sca_.u;
0467
0468 system::error_code ec;
0469 BOOST_JSON_FAIL(ec, error::not_uint64);
0470 return ec;
0471 }
0472
0473 system::result<double&>
0474 value::try_as_double() noexcept
0475 {
0476 if( is_double() )
0477 return sca_.d;
0478
0479 system::error_code ec;
0480 BOOST_JSON_FAIL(ec, error::not_double);
0481 return ec;
0482 }
0483
0484 system::result<double>
0485 value::try_as_double() const noexcept
0486 {
0487 if( is_double() )
0488 return sca_.d;
0489
0490 system::error_code ec;
0491 BOOST_JSON_FAIL(ec, error::not_double);
0492 return ec;
0493 }
0494
0495 system::result<bool&>
0496 value::try_as_bool() noexcept
0497 {
0498 if( is_bool() )
0499 return sca_.b;
0500
0501 system::error_code ec;
0502 BOOST_JSON_FAIL(ec, error::not_bool);
0503 return ec;
0504 }
0505
0506 system::result<bool>
0507 value::try_as_bool() const noexcept
0508 {
0509 if( is_bool() )
0510 return sca_.b;
0511
0512 system::error_code ec;
0513 BOOST_JSON_FAIL(ec, error::not_bool);
0514 return ec;
0515 }
0516
0517 system::result<std::nullptr_t>
0518 value::try_as_null() const noexcept
0519 {
0520 if( is_null() )
0521 return nullptr;
0522
0523 system::error_code ec;
0524 BOOST_JSON_FAIL(ec, error::not_null);
0525 return ec;
0526 }
0527
0528 boost::system::result<value&>
0529 value::try_at(string_view key) noexcept
0530 {
0531 auto r = try_as_object();
0532 if( !r )
0533 return r.error();
0534 return r->try_at(key);
0535 }
0536
0537 boost::system::result<value const&>
0538 value::try_at(string_view key) const noexcept
0539 {
0540 auto r = try_as_object();
0541 if( !r )
0542 return r.error();
0543 return r->try_at(key);
0544 }
0545
0546 boost::system::result<value&>
0547 value::try_at(std::size_t pos) noexcept
0548 {
0549 auto r = try_as_array();
0550 if( !r )
0551 return r.error();
0552 return r->try_at(pos);
0553 }
0554
0555 boost::system::result<value const&>
0556 value::try_at(std::size_t pos) const noexcept
0557 {
0558 auto r = try_as_array();
0559 if( !r )
0560 return r.error();
0561 return r->try_at(pos);
0562 }
0563
0564 object const&
0565 value::as_object(source_location const& loc) const&
0566 {
0567 return try_as_object().value(loc);
0568 }
0569
0570 array const&
0571 value::as_array(source_location const& loc) const&
0572 {
0573 return try_as_array().value(loc);
0574 }
0575
0576 string const&
0577 value::as_string(source_location const& loc) const&
0578 {
0579 return try_as_string().value(loc);
0580 }
0581
0582 std::int64_t&
0583 value::as_int64(source_location const& loc)
0584 {
0585 return try_as_int64().value(loc);
0586 }
0587
0588 std::int64_t
0589 value::as_int64(source_location const& loc) const
0590 {
0591 return try_as_int64().value(loc);
0592 }
0593
0594 std::uint64_t&
0595 value::as_uint64(source_location const& loc)
0596 {
0597 return try_as_uint64().value(loc);
0598 }
0599
0600 std::uint64_t
0601 value::as_uint64(source_location const& loc) const
0602 {
0603 return try_as_uint64().value(loc);
0604 }
0605
0606 double&
0607 value::as_double(source_location const& loc)
0608 {
0609 return try_as_double().value(loc);
0610 }
0611
0612 double
0613 value::as_double(source_location const& loc) const
0614 {
0615 return try_as_double().value(loc);
0616 }
0617
0618 bool&
0619 value::as_bool(source_location const& loc)
0620 {
0621 return try_as_bool().value(loc);
0622 }
0623
0624 bool
0625 value::as_bool(source_location const& loc) const
0626 {
0627 return try_as_bool().value(loc);
0628 }
0629
0630
0631
0632
0633
0634
0635
0636 string&
0637 value::
0638 emplace_string() noexcept
0639 {
0640 return *::new(&str_) string(destroy());
0641 }
0642
0643 array&
0644 value::
0645 emplace_array() noexcept
0646 {
0647 return *::new(&arr_) array(destroy());
0648 }
0649
0650 object&
0651 value::
0652 emplace_object() noexcept
0653 {
0654 return *::new(&obj_) object(destroy());
0655 }
0656
0657 void
0658 value::
0659 swap(value& other)
0660 {
0661 if(*storage() == *other.storage())
0662 {
0663
0664 union U
0665 {
0666 value tmp;
0667 U(){}
0668 ~U(){}
0669 };
0670 U u;
0671 relocate(&u.tmp, *this);
0672 relocate(this, other);
0673 relocate(&other, u.tmp);
0674 return;
0675 }
0676
0677
0678 value temp1(
0679 std::move(*this),
0680 other.storage());
0681 value temp2(
0682 std::move(other),
0683 this->storage());
0684 other.~value();
0685 ::new(&other) value(pilfer(temp1));
0686 this->~value();
0687 ::new(this) value(pilfer(temp2));
0688 }
0689
0690 std::istream&
0691 operator>>(
0692 std::istream& is,
0693 value& jv)
0694 {
0695 using Traits = std::istream::traits_type;
0696
0697
0698 std::istream::sentry sentry(is);
0699 if( !sentry )
0700 return is;
0701
0702 parse_options opts = get_parse_options( is );
0703 if( auto depth = static_cast<std::size_t>( is.iword(parse_depth_xalloc) ) )
0704 opts.max_depth = depth;
0705
0706 unsigned char parser_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
0707 stream_parser p( {}, opts, parser_buf );
0708 p.reset( jv.storage() );
0709
0710 char read_buf[BOOST_JSON_STACK_BUFFER_SIZE / 2];
0711 std::streambuf& buf = *is.rdbuf();
0712 std::ios::iostate err = std::ios::goodbit;
0713 #ifndef BOOST_NO_EXCEPTIONS
0714 try
0715 #endif
0716 {
0717 while( true )
0718 {
0719 system::error_code ec;
0720
0721
0722
0723
0724 std::istream::int_type c = is.rdbuf()->sgetc();
0725
0726
0727 if( Traits::eq_int_type(c, Traits::eof()) )
0728 {
0729 err |= std::ios::eofbit;
0730 p.finish(ec);
0731 if( ec.failed() )
0732 break;
0733 }
0734
0735
0736
0737 if( p.done() )
0738 {
0739 jv = p.release();
0740 return is;
0741 }
0742
0743
0744
0745
0746 std::streamsize available = buf.in_avail();
0747
0748 BOOST_ASSERT( available > 0 );
0749
0750 available = ( std::min )(
0751 static_cast<std::size_t>(available), sizeof(read_buf) );
0752
0753 available = buf.sgetn( read_buf, available );
0754
0755 std::size_t consumed = p.write_some(
0756 read_buf, static_cast<std::size_t>(available), ec );
0757
0758
0759
0760 while( consumed++ < static_cast<std::size_t>(available) )
0761 {
0762 std::istream::int_type const status = buf.sungetc();
0763 BOOST_ASSERT( status != Traits::eof() );
0764 (void)status;
0765 }
0766
0767 if( ec.failed() )
0768 break;
0769 }
0770 }
0771 #ifndef BOOST_NO_EXCEPTIONS
0772 catch(...)
0773 {
0774 try
0775 {
0776 is.setstate(std::ios::badbit);
0777 }
0778
0779
0780 catch( std::ios::failure const& ) { }
0781
0782 if( is.exceptions() & std::ios::badbit )
0783 throw;
0784 }
0785 #endif
0786
0787 is.setstate(err | std::ios::failbit);
0788 return is;
0789 }
0790
0791 std::istream&
0792 operator>>(
0793 std::istream& is,
0794 parse_options const& opts)
0795 {
0796 is.iword(parse_flags_xalloc) = to_bitmask(opts);
0797 is.iword(parse_depth_xalloc) = static_cast<long>(opts.max_depth);
0798 return is;
0799 }
0800
0801
0802
0803
0804
0805
0806
0807 storage_ptr
0808 value::
0809 destroy() noexcept
0810 {
0811 switch(kind())
0812 {
0813 case json::kind::null:
0814 case json::kind::bool_:
0815 case json::kind::int64:
0816 case json::kind::uint64:
0817 case json::kind::double_:
0818 break;
0819
0820 case json::kind::string:
0821 {
0822 auto sp = str_.storage();
0823 str_.~string();
0824 return sp;
0825 }
0826
0827 case json::kind::array:
0828 {
0829 auto sp = arr_.storage();
0830 arr_.~array();
0831 return sp;
0832 }
0833
0834 case json::kind::object:
0835 {
0836 auto sp = obj_.storage();
0837 obj_.~object();
0838 return sp;
0839 }
0840
0841 }
0842 return std::move(sp_);
0843 }
0844
0845 bool
0846 value::
0847 equal(value const& other) const noexcept
0848 {
0849 switch(kind())
0850 {
0851 default:
0852 case json::kind::null:
0853 return other.kind() == json::kind::null;
0854
0855 case json::kind::bool_:
0856 return
0857 other.kind() == json::kind::bool_ &&
0858 get_bool() == other.get_bool();
0859
0860 case json::kind::int64:
0861 switch(other.kind())
0862 {
0863 case json::kind::int64:
0864 return get_int64() == other.get_int64();
0865 case json::kind::uint64:
0866 if(get_int64() < 0)
0867 return false;
0868 return static_cast<std::uint64_t>(
0869 get_int64()) == other.get_uint64();
0870 default:
0871 return false;
0872 }
0873
0874 case json::kind::uint64:
0875 switch(other.kind())
0876 {
0877 case json::kind::uint64:
0878 return get_uint64() == other.get_uint64();
0879 case json::kind::int64:
0880 if(other.get_int64() < 0)
0881 return false;
0882 return static_cast<std::uint64_t>(
0883 other.get_int64()) == get_uint64();
0884 default:
0885 return false;
0886 }
0887
0888 case json::kind::double_:
0889 return
0890 other.kind() == json::kind::double_ &&
0891 get_double() == other.get_double();
0892
0893 case json::kind::string:
0894 return
0895 other.kind() == json::kind::string &&
0896 get_string() == other.get_string();
0897
0898 case json::kind::array:
0899 return
0900 other.kind() == json::kind::array &&
0901 get_array() == other.get_array();
0902
0903 case json::kind::object:
0904 return
0905 other.kind() == json::kind::object &&
0906 get_object() == other.get_object();
0907 }
0908 }
0909
0910
0911
0912
0913
0914
0915
0916
0917 BOOST_JSON_REQUIRE_CONST_INIT
0918 char const
0919 key_value_pair::empty_[1] = { 0 };
0920
0921 key_value_pair::
0922 key_value_pair(
0923 pilfered<json::value> key,
0924 pilfered<json::value> value) noexcept
0925 : value_(value)
0926 {
0927 std::size_t len;
0928 key_ = access::release_key(key.get(), len);
0929 len_ = static_cast<std::uint32_t>(len);
0930 }
0931
0932 key_value_pair::
0933 key_value_pair(
0934 key_value_pair const& other,
0935 storage_ptr sp)
0936 : value_(other.value_, std::move(sp))
0937 {
0938 auto p = reinterpret_cast<
0939 char*>(value_.storage()->
0940 allocate(other.len_ + 1,
0941 alignof(char)));
0942 std::memcpy(
0943 p, other.key_, other.len_);
0944 len_ = other.len_;
0945 p[len_] = 0;
0946 key_ = p;
0947 }
0948
0949
0950
0951 namespace detail
0952 {
0953
0954 std::size_t
0955 hash_value_impl( value const& jv ) noexcept
0956 {
0957 std::size_t seed = 0;
0958
0959 kind const k = jv.kind();
0960 boost::hash_combine( seed, k != kind::int64 ? k : kind::uint64 );
0961
0962 visit( value_hasher{seed}, jv );
0963 return seed;
0964 }
0965
0966 }
0967 }
0968 }
0969
0970
0971
0972
0973
0974
0975
0976 std::size_t
0977 std::hash<::boost::json::value>::operator()(
0978 ::boost::json::value const& jv) const noexcept
0979 {
0980 return ::boost::hash< ::boost::json::value >()( jv );
0981 }
0982
0983
0984
0985 #endif