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