File indexing completed on 2025-01-18 09:39:04
0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011 #ifndef BOOST_JSON_BASIC_PARSER_IMPL_HPP
0012 #define BOOST_JSON_BASIC_PARSER_IMPL_HPP
0013
0014 #include <boost/json/detail/config.hpp>
0015 #include <boost/json/basic_parser.hpp>
0016 #include <boost/json/error.hpp>
0017 #include <boost/json/detail/buffer.hpp>
0018 #include <boost/json/detail/charconv/from_chars.hpp>
0019 #include <boost/json/detail/sse2.hpp>
0020 #include <cmath>
0021 #include <limits>
0022 #include <cstring>
0023
0024 #ifdef _MSC_VER
0025 #pragma warning(push)
0026 #pragma warning(disable: 4702)
0027 #pragma warning(disable: 4127)
0028 #endif
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044 #ifndef BOOST_JSON_DOCS
0045
0046 namespace boost {
0047 namespace json {
0048 namespace detail {
0049
0050 inline
0051 double
0052 pow10(int exp) noexcept
0053 {
0054 static double const tab[618] = {
0055 1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
0056
0057 1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
0058 1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
0059 1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
0060 1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
0061 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
0062 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
0063 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
0064 1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
0065 1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
0066 1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
0067
0068 1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
0069 1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
0070 1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
0071 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
0072 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
0073 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
0074 1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
0075 1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
0076 1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
0077 1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
0078
0079 1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
0080 1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
0081 1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
0082 1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
0083 1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
0084 1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
0085 1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
0086 1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
0087 1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
0088 1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
0089
0090 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
0091 1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
0092 1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
0093 1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
0094 1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
0095 1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
0096 1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
0097 1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
0098 1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
0099 1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
0100
0101 1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
0102 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
0103 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
0104 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
0105 1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
0106 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
0107 1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
0108 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
0109 1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
0110 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
0111
0112 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
0113 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
0114 1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
0115 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
0116 1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
0117 1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
0118 1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
0119 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
0120 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
0121 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
0122
0123 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
0124
0125 if( exp > 308 )
0126 {
0127 return std::numeric_limits<double>::infinity();
0128 }
0129 else if( exp < -308 )
0130 {
0131
0132
0133 return 0.0;
0134 }
0135 else
0136 {
0137 exp += 308;
0138 BOOST_ASSERT(exp >= 0 && exp < 618);
0139 return tab[exp];
0140 }
0141 }
0142
0143 inline
0144 double
0145 dec_to_float(
0146 std::uint64_t m,
0147 std::int32_t e,
0148 bool neg) noexcept
0149 {
0150
0151 double x = static_cast<double>(m);
0152 if(neg)
0153 x = -x;
0154
0155 if(e < -305)
0156 {
0157 x *= 1e-305 ;
0158 e += 305;
0159 }
0160
0161 if(e >= -22 && e < 0)
0162 return x / pow10(-e);
0163
0164 return x * pow10(e);
0165 }
0166
0167 inline
0168 bool
0169 is_control(char c) noexcept
0170 {
0171 return static_cast<unsigned char>(c) < 32;
0172 }
0173
0174 inline
0175 int
0176 hex_digit(unsigned char c) noexcept
0177 {
0178
0179 if( c >= '0' && c <= '9' )
0180 return c - '0';
0181 c &= ~0x20;
0182 if( c >= 'A' && c <= 'F' )
0183 return 10 + c - 'A';
0184 return -1;
0185 }
0186
0187 enum json_literal
0188 {
0189 null_literal = 0,
0190 true_literal,
0191 false_literal,
0192 infinity_literal,
0193 neg_infinity_literal,
0194 nan_literal,
0195 resume_literal = -1
0196 };
0197
0198 }
0199
0200
0201
0202 template< class Handler >
0203 template< bool StackEmpty_, char First_ >
0204 struct basic_parser<Handler>::
0205 parse_number_helper
0206 {
0207 basic_parser* parser;
0208 char const* p;
0209
0210 template< std::size_t N >
0211 char const*
0212 operator()( mp11::mp_size_t<N> ) const
0213 {
0214 return parser->parse_number(
0215 p,
0216 std::integral_constant<bool, StackEmpty_>(),
0217 std::integral_constant<char, First_>(),
0218 std::integral_constant<
0219 number_precision, static_cast<number_precision>(N)>() );
0220 }
0221 };
0222
0223
0224
0225 template<class Handler>
0226 void
0227 basic_parser<Handler>::
0228 reserve()
0229 {
0230 if(BOOST_JSON_LIKELY(
0231 ! st_.empty()))
0232 return;
0233
0234
0235 st_.reserve(
0236 sizeof(state) +
0237 (sizeof(state) +
0238 sizeof(std::size_t)) * depth() +
0239 sizeof(state) +
0240 sizeof(std::size_t) +
0241 sizeof(state));
0242 }
0243
0244
0245
0246
0247
0248
0249
0250
0251 template<class Handler>
0252 const char*
0253 basic_parser<Handler>::
0254 sentinel()
0255 {
0256
0257
0258 return reinterpret_cast<
0259 const char*>(this) + 1;
0260 }
0261
0262 template<class Handler>
0263 bool
0264 basic_parser<Handler>::
0265 incomplete(
0266 const detail::const_stream_wrapper& cs)
0267 {
0268 return cs.begin() == sentinel();
0269 }
0270
0271
0272
0273
0274
0275
0276
0277
0278 template<class Handler>
0279 const char*
0280 basic_parser<Handler>::
0281 suspend_or_fail(state st)
0282 {
0283 if(BOOST_JSON_LIKELY(
0284 ! ec_ && more_))
0285 {
0286
0287 reserve();
0288 st_.push_unchecked(st);
0289 }
0290 return sentinel();
0291 }
0292
0293 template<class Handler>
0294 const char*
0295 basic_parser<Handler>::
0296 suspend_or_fail(
0297 state st,
0298 std::size_t n)
0299 {
0300 if(BOOST_JSON_LIKELY(
0301 ! ec_ && more_))
0302 {
0303
0304 reserve();
0305 st_.push_unchecked(n);
0306 st_.push_unchecked(st);
0307 }
0308 return sentinel();
0309 }
0310
0311
0312 template<class Handler>
0313 const char*
0314 basic_parser<Handler>::
0315 fail(const char* p) noexcept
0316 {
0317 BOOST_ASSERT( p != sentinel() );
0318 end_ = p;
0319 return sentinel();
0320 }
0321
0322 template<class Handler>
0323 const char*
0324 basic_parser<Handler>::
0325 fail(
0326 const char* p,
0327 error ev,
0328 source_location const* loc) noexcept
0329 {
0330 BOOST_ASSERT( p != sentinel() );
0331 end_ = p;
0332 ec_.assign(ev, loc);
0333 return sentinel();
0334 }
0335
0336 template<class Handler>
0337 const char*
0338 basic_parser<Handler>::
0339 maybe_suspend(
0340 const char* p,
0341 state st)
0342 {
0343 if( p != sentinel() )
0344 end_ = p;
0345 if(BOOST_JSON_LIKELY(more_))
0346 {
0347
0348 reserve();
0349 st_.push_unchecked(st);
0350 }
0351 return sentinel();
0352 }
0353
0354 template<class Handler>
0355 const char*
0356 basic_parser<Handler>::
0357 maybe_suspend(
0358 const char* p,
0359 state st,
0360 std::size_t n)
0361 {
0362 BOOST_ASSERT( p != sentinel() );
0363 end_ = p;
0364 if(BOOST_JSON_LIKELY(more_))
0365 {
0366
0367 reserve();
0368 st_.push_unchecked(n);
0369 st_.push_unchecked(st);
0370 }
0371 return sentinel();
0372 }
0373
0374 template<class Handler>
0375 const char*
0376 basic_parser<Handler>::
0377 maybe_suspend(
0378 const char* p,
0379 state st,
0380 const number& num)
0381 {
0382 BOOST_ASSERT( p != sentinel() );
0383 end_ = p;
0384 if(BOOST_JSON_LIKELY(more_))
0385 {
0386
0387 num_ = num;
0388 reserve();
0389 st_.push_unchecked(st);;
0390 }
0391 return sentinel();
0392 }
0393
0394 template<class Handler>
0395 const char*
0396 basic_parser<Handler>::
0397 suspend(
0398 const char* p,
0399 state st)
0400 {
0401 BOOST_ASSERT( p != sentinel() );
0402 end_ = p;
0403
0404 reserve();
0405 st_.push_unchecked(st);
0406 return sentinel();
0407 }
0408
0409 template<class Handler>
0410 const char*
0411 basic_parser<Handler>::
0412 suspend(
0413 const char* p,
0414 state st,
0415 const number& num)
0416 {
0417 BOOST_ASSERT( p != sentinel() );
0418 end_ = p;
0419
0420 num_ = num;
0421 reserve();
0422 st_.push_unchecked(st);
0423 return sentinel();
0424 }
0425
0426 template<class Handler>
0427 template<
0428 bool StackEmpty_
0429 >
0430 const char*
0431 basic_parser<Handler>::
0432 parse_comment(const char* p,
0433 std::integral_constant<bool, StackEmpty_> stack_empty,
0434 bool terminal)
0435 {
0436 detail::const_stream_wrapper cs(p, end_);
0437 const char* start = cs.begin();
0438 std::size_t remain;
0439 if(! stack_empty && ! st_.empty())
0440 {
0441 state st;
0442 st_.pop(st);
0443 switch(st)
0444 {
0445 default: BOOST_JSON_UNREACHABLE();
0446 case state::com1: goto do_com1;
0447 case state::com2: goto do_com2;
0448 case state::com3: goto do_com3;
0449 case state::com4: goto do_com4;
0450 }
0451 }
0452 BOOST_ASSERT(*cs == '/');
0453 ++cs;
0454 do_com1:
0455 if(BOOST_JSON_UNLIKELY(! cs))
0456 return maybe_suspend(cs.begin(), state::com1);
0457 switch(*cs)
0458 {
0459 default:
0460 {
0461 BOOST_STATIC_CONSTEXPR source_location loc
0462 = BOOST_CURRENT_LOCATION;
0463 return fail(cs.begin(), error::syntax, &loc);
0464 }
0465 case '/':
0466 ++cs;
0467 do_com2:
0468
0469 remain = cs.remain();
0470 cs = remain ? static_cast<const char*>(
0471 std::memchr(cs.begin(), '\n', remain)) : sentinel();
0472 if(! cs.begin())
0473 cs = sentinel();
0474 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
0475 {
0476
0477
0478
0479 if(terminal && ! more_)
0480 {
0481 if(BOOST_JSON_UNLIKELY(! h_.on_comment(
0482 {start, cs.remain(start)}, ec_)))
0483 return fail(cs.end());
0484 return cs.end();
0485 }
0486 if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
0487 {start, cs.remain(start)}, ec_)))
0488 return fail(cs.end());
0489 if(terminal)
0490 return suspend(cs.end(), state::com2);
0491 return maybe_suspend(cs.end(), state::com2);
0492 }
0493 break;
0494 case '*':
0495 do
0496 {
0497 ++cs;
0498 do_com3:
0499
0500 remain = cs.remain();
0501 cs = remain ? static_cast<const char*>(
0502 std::memchr(cs.begin(), '*', remain)) : sentinel();
0503 if(! cs.begin())
0504 cs = sentinel();
0505
0506 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
0507 {
0508 if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
0509 {start, cs.remain(start)}, ec_)))
0510 return fail(cs.end());
0511 return maybe_suspend(cs.end(), state::com3);
0512 }
0513
0514 ++cs;
0515 do_com4:
0516 if(BOOST_JSON_UNLIKELY(! cs))
0517 {
0518 if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
0519 {start, cs.used(start)}, ec_)))
0520 return fail(cs.begin());
0521 return maybe_suspend(cs.begin(), state::com4);
0522 }
0523 }
0524 while(*cs != '/');
0525 }
0526 ++cs;
0527 if(BOOST_JSON_UNLIKELY(! h_.on_comment(
0528 {start, cs.used(start)}, ec_)))
0529 return fail(cs.begin());
0530 return cs.begin();
0531 }
0532
0533 template<class Handler>
0534 template<bool StackEmpty_>
0535 const char*
0536 basic_parser<Handler>::
0537 parse_document(const char* p,
0538 std::integral_constant<bool, StackEmpty_> stack_empty)
0539 {
0540 detail::const_stream_wrapper cs(p, end_);
0541 if(! stack_empty && ! st_.empty())
0542 {
0543 state st;
0544 st_.peek(st);
0545 switch(st)
0546 {
0547 default: goto do_doc2;
0548 case state::doc1:
0549 st_.pop(st);
0550 goto do_doc1;
0551 case state::doc3:
0552 st_.pop(st);
0553 goto do_doc3;
0554 case state::com1: case state::com2:
0555 case state::com3: case state::com4:
0556 goto do_doc4;
0557 }
0558 }
0559 do_doc1:
0560 cs = detail::count_whitespace(cs.begin(), cs.end());
0561 if(BOOST_JSON_UNLIKELY(! cs))
0562 return maybe_suspend(cs.begin(), state::doc1);
0563 do_doc2:
0564 switch(+opt_.allow_comments |
0565 (opt_.allow_trailing_commas << 1) |
0566 (opt_.allow_invalid_utf8 << 2))
0567 {
0568
0569 default:
0570 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type());
0571 break;
0572
0573 case 1:
0574 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type());
0575 break;
0576
0577 case 2:
0578 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type());
0579 break;
0580
0581 case 3:
0582 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type());
0583 break;
0584
0585 case 4:
0586 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type());
0587 break;
0588
0589 case 5:
0590 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type());
0591 break;
0592
0593 case 6:
0594 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type());
0595 break;
0596
0597 case 7:
0598 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type());
0599 break;
0600 }
0601 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
0602
0603 return sentinel();
0604 do_doc3:
0605 cs = detail::count_whitespace(cs.begin(), cs.end());
0606 if(BOOST_JSON_UNLIKELY(! cs))
0607 {
0608 if(more_)
0609 return suspend(cs.begin(), state::doc3);
0610 }
0611 else if(opt_.allow_comments && *cs == '/')
0612 {
0613 do_doc4:
0614 cs = parse_comment(cs.begin(), stack_empty, std::true_type());
0615 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
0616 return sentinel();
0617 goto do_doc3;
0618 }
0619 return cs.begin();
0620 }
0621
0622 template<class Handler>
0623 template<
0624 bool StackEmpty_,
0625 bool AllowComments_
0626
0627 >
0628 const char*
0629 basic_parser<Handler>::
0630 parse_value(const char* p,
0631 std::integral_constant<bool, StackEmpty_> stack_empty,
0632 std::integral_constant<bool, AllowComments_> allow_comments,
0633 bool allow_trailing,
0634 bool allow_bad_utf8)
0635 {
0636 if(stack_empty || st_.empty())
0637 {
0638 loop:
0639 switch(*p)
0640 {
0641 case '0':
0642 return mp11::mp_with_index<3>(
0643 static_cast<unsigned char>(opt_.numbers),
0644 parse_number_helper<true, '0'>{ this, p });
0645 case '-':
0646 return mp11::mp_with_index<3>(
0647 static_cast<unsigned char>(opt_.numbers),
0648 parse_number_helper<true, '-'>{ this, p });
0649 case '1': case '2': case '3':
0650 case '4': case '5': case '6':
0651 case '7': case '8': case '9':
0652 return mp11::mp_with_index<3>(
0653 static_cast<unsigned char>(opt_.numbers),
0654 parse_number_helper<true, '+'>{ this, p });
0655 case 'n':
0656 return parse_literal( p, mp11::mp_int<detail::null_literal>() );
0657 case 't':
0658 return parse_literal( p, mp11::mp_int<detail::true_literal>() );
0659 case 'f':
0660 return parse_literal( p, mp11::mp_int<detail::false_literal>() );
0661 case 'I':
0662 if( !opt_.allow_infinity_and_nan )
0663 {
0664 BOOST_STATIC_CONSTEXPR source_location loc
0665 = BOOST_CURRENT_LOCATION;
0666 return fail(p, error::syntax, &loc);
0667 }
0668 return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
0669 case 'N':
0670 if( !opt_.allow_infinity_and_nan )
0671 {
0672 BOOST_STATIC_CONSTEXPR source_location loc
0673 = BOOST_CURRENT_LOCATION;
0674 return fail(p, error::syntax, &loc);
0675 }
0676 return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
0677 case '"':
0678 return parse_unescaped(p, std::true_type(), std::false_type(), allow_bad_utf8);
0679 case '[':
0680 return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
0681 case '{':
0682 return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
0683 case '/':
0684 if(! allow_comments)
0685 {
0686 BOOST_STATIC_CONSTEXPR source_location loc
0687 = BOOST_CURRENT_LOCATION;
0688 return fail(p, error::syntax, &loc);
0689 }
0690 p = parse_comment(p, stack_empty, std::false_type());
0691
0692
0693
0694 if(BOOST_JSON_UNLIKELY(p == sentinel()))
0695 return maybe_suspend(p, state::val2);
0696
0697 case ' ':
0698 case '\t':
0699 case '\n':
0700 case '\r':
0701 p = detail::count_whitespace(p, end_);
0702 if(BOOST_JSON_UNLIKELY(p == end_))
0703 return maybe_suspend(p, state::val1);
0704 goto loop;
0705 default:
0706 {
0707 BOOST_STATIC_CONSTEXPR source_location loc
0708 = BOOST_CURRENT_LOCATION;
0709 return fail(p, error::syntax, &loc);
0710 }
0711 }
0712 }
0713 return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8);
0714 }
0715
0716 template<class Handler>
0717 template<
0718 bool AllowComments_
0719
0720 >
0721 const char*
0722 basic_parser<Handler>::
0723 resume_value(const char* p,
0724 std::integral_constant<bool, AllowComments_> allow_comments,
0725 bool allow_trailing,
0726 bool allow_bad_utf8)
0727 {
0728 state st;
0729 st_.peek(st);
0730 switch(st)
0731 {
0732 default: BOOST_JSON_UNREACHABLE();
0733 case state::lit1:
0734 return parse_literal(p, mp11::mp_int<detail::resume_literal>() );
0735
0736 case state::str1:
0737 return parse_unescaped(p, std::false_type(), std::false_type(), allow_bad_utf8);
0738
0739 case state::str2: case state::str3:
0740 case state::str4: case state::str5:
0741 case state::str6: case state::str7:
0742 case state::str8:
0743 case state::sur1: case state::sur2:
0744 case state::sur3: case state::sur4:
0745 case state::sur5: case state::sur6:
0746 return parse_escaped(p, 0, std::false_type(), std::false_type(), allow_bad_utf8);
0747
0748 case state::arr1: case state::arr2:
0749 case state::arr3: case state::arr4:
0750 case state::arr5: case state::arr6:
0751 return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
0752
0753 case state::obj1: case state::obj2:
0754 case state::obj3: case state::obj4:
0755 case state::obj5: case state::obj6:
0756 case state::obj7: case state::obj8:
0757 case state::obj9: case state::obj10:
0758 case state::obj11:
0759 return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
0760
0761 case state::num1: case state::num2:
0762 case state::num3: case state::num4:
0763 case state::num5: case state::num6:
0764 case state::num7: case state::num8:
0765 case state::exp1: case state::exp2:
0766 case state::exp3:
0767 return mp11::mp_with_index<3>(
0768 static_cast<unsigned char>(opt_.numbers),
0769 parse_number_helper<false, 0>{ this, p });
0770
0771
0772 case state::val1:
0773 {
0774 st_.pop(st);
0775 BOOST_ASSERT(st_.empty());
0776 p = detail::count_whitespace(p, end_);
0777 if(BOOST_JSON_UNLIKELY(p == end_))
0778 return maybe_suspend(p, state::val1);
0779 return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
0780 }
0781
0782 case state::val2:
0783 {
0784 st_.pop(st);
0785 p = parse_comment(p, std::false_type(), std::false_type());
0786 if(BOOST_JSON_UNLIKELY(p == sentinel()))
0787 return maybe_suspend(p, state::val2);
0788 if(BOOST_JSON_UNLIKELY( p == end_ ))
0789 return maybe_suspend(p, state::val3);
0790 BOOST_ASSERT(st_.empty());
0791 return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
0792 }
0793
0794 case state::val3:
0795 {
0796 st_.pop(st);
0797 return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
0798 }
0799 }
0800 }
0801
0802 template<class Handler>
0803 template<int Literal>
0804 const char*
0805 basic_parser<Handler>::
0806 parse_literal(const char* p,
0807 std::integral_constant<int, Literal> literal)
0808 {
0809 constexpr char const* literals[] = {
0810 "null",
0811 "true",
0812 "false",
0813 "Infinity",
0814 "-Infinity",
0815 "NaN",
0816 };
0817
0818 constexpr std::size_t literal_sizes[] = {
0819 4,
0820 4,
0821 5,
0822 8,
0823 9,
0824 3,
0825 };
0826
0827 std::size_t cur_lit;
0828 std::size_t offset;
0829
0830 detail::const_stream_wrapper cs(p, end_);
0831 BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
0832 {
0833 BOOST_ASSERT( literal >= 0 );
0834 if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
0835 {
0836 int const cmp = std::memcmp(
0837 cs.begin(), literals[literal], literal_sizes[literal] );
0838 if( cmp != 0 )
0839 {
0840 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
0841 return fail(cs.begin(), error::syntax, &loc);
0842 }
0843
0844 BOOST_IF_CONSTEXPR( literal == detail::null_literal )
0845 {
0846 if(BOOST_JSON_UNLIKELY(
0847 ! h_.on_null(ec_)))
0848 return fail(cs.begin());
0849 }
0850 else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
0851 {
0852 if(BOOST_JSON_UNLIKELY(
0853 ! h_.on_bool(true, ec_)))
0854 return fail(cs.begin());
0855 }
0856 else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
0857 {
0858 if(BOOST_JSON_UNLIKELY(
0859 ! h_.on_bool(false, ec_)))
0860 return fail(cs.begin());
0861 }
0862 else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
0863 {
0864 if(BOOST_JSON_UNLIKELY(
0865 ! h_.on_double(
0866 std::numeric_limits<double>::infinity(),
0867 string_view(
0868 literals[detail::infinity_literal],
0869 literal_sizes[detail::infinity_literal]),
0870 ec_)))
0871 return fail(cs.begin());
0872 }
0873 else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
0874 {
0875 if(BOOST_JSON_UNLIKELY(
0876 ! h_.on_double(
0877 -std::numeric_limits<double>::infinity(),
0878 string_view(
0879 literals[detail::neg_infinity_literal],
0880 literal_sizes[detail::neg_infinity_literal]),
0881 ec_)))
0882 return fail(cs.begin());
0883 }
0884 else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
0885 {
0886 if(BOOST_JSON_UNLIKELY(
0887 ! h_.on_double(
0888 std::numeric_limits<double>::quiet_NaN(),
0889 string_view(
0890 literals[detail::nan_literal],
0891 literal_sizes[detail::nan_literal]),
0892 ec_)))
0893 return fail(cs.begin());
0894 }
0895 else
0896 {
0897 BOOST_JSON_UNREACHABLE();
0898 }
0899
0900 cs += literal_sizes[literal];
0901 return cs.begin();
0902 }
0903
0904 offset = 0;
0905 cur_lit = literal;
0906 }
0907 else
0908 {
0909 state st;
0910 st_.pop(st);
0911 BOOST_ASSERT( st == state::lit1 );
0912
0913 cur_lit = cur_lit_;
0914 offset = lit_offset_;
0915 }
0916
0917 std::size_t const size = (std::min)(
0918 literal_sizes[cur_lit] - offset, cs.remain() );
0919 int cmp = 0;
0920 if(BOOST_JSON_LIKELY( cs.begin() ))
0921 cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
0922 if( cmp != 0 )
0923 {
0924 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
0925 return fail(cs.begin(), error::syntax, &loc);
0926 }
0927
0928 if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
0929 {
0930 BOOST_ASSERT( cur_lit < 256 );
0931 cur_lit_ = static_cast<unsigned char>( cur_lit );
0932 BOOST_ASSERT( offset + size < 256 );
0933 lit_offset_ = static_cast<unsigned char>( offset + size );
0934 return maybe_suspend(cs.begin() + size, state::lit1);
0935 }
0936
0937 switch( cur_lit )
0938 {
0939 case detail::null_literal:
0940 if(BOOST_JSON_UNLIKELY(
0941 ! h_.on_null(ec_)))
0942 return fail(cs.begin());
0943 break;
0944 case detail::true_literal:
0945 if(BOOST_JSON_UNLIKELY(
0946 ! h_.on_bool(true, ec_)))
0947 return fail(cs.begin());
0948 break;
0949 case detail::false_literal:
0950 if(BOOST_JSON_UNLIKELY(
0951 ! h_.on_bool(false, ec_)))
0952 return fail(cs.begin());
0953 break;
0954 case detail::infinity_literal:
0955 if(BOOST_JSON_UNLIKELY(
0956 ! h_.on_double(
0957 std::numeric_limits<double>::infinity(),
0958 string_view(
0959 literals[detail::infinity_literal],
0960 literal_sizes[detail::infinity_literal]),
0961 ec_)))
0962 return fail(cs.begin());
0963 break;
0964 case detail::neg_infinity_literal:
0965 if(BOOST_JSON_UNLIKELY(
0966 ! h_.on_double(
0967 -std::numeric_limits<double>::infinity(),
0968 string_view(
0969 literals[detail::neg_infinity_literal],
0970 literal_sizes[detail::neg_infinity_literal]),
0971 ec_)))
0972 return fail(cs.begin());
0973 break;
0974 case detail::nan_literal:
0975 if(BOOST_JSON_UNLIKELY(
0976 ! h_.on_double(
0977 std::numeric_limits<double>::quiet_NaN(),
0978 string_view(
0979 literals[detail::nan_literal],
0980 literal_sizes[detail::nan_literal]),
0981 ec_)))
0982 return fail(cs.begin());
0983 break;
0984 default: BOOST_JSON_UNREACHABLE();
0985 }
0986
0987 cs += size;
0988 return cs.begin();
0989 }
0990
0991
0992
0993 template<class Handler>
0994 template<
0995 bool StackEmpty_,
0996 bool IsKey_
0997 >
0998 const char*
0999 basic_parser<Handler>::
1000 parse_string(const char* p,
1001 std::integral_constant<bool, StackEmpty_> stack_empty,
1002 std::integral_constant<bool, IsKey_> is_key,
1003 bool allow_bad_utf8)
1004 {
1005 if(! stack_empty && ! st_.empty())
1006 {
1007 state st;
1008 st_.peek(st);
1009 switch(st)
1010 {
1011 default: BOOST_JSON_UNREACHABLE();
1012 case state::str1:
1013 return parse_unescaped(p, stack_empty, is_key, allow_bad_utf8);
1014
1015 case state::str2: case state::str3:
1016 case state::str4: case state::str5:
1017 case state::str6: case state::str7:
1018 case state::str8:
1019 case state::sur1: case state::sur2:
1020 case state::sur3: case state::sur4:
1021 case state::sur5: case state::sur6:
1022 return parse_escaped(p, 0, stack_empty, is_key, allow_bad_utf8);
1023 }
1024 }
1025
1026 return parse_unescaped(p, std::true_type(), is_key, allow_bad_utf8);
1027 }
1028
1029 template<class Handler>
1030 template<
1031 bool StackEmpty_,
1032 bool IsKey_
1033 >
1034 const char*
1035 basic_parser<Handler>::
1036 parse_unescaped(const char* p,
1037 std::integral_constant<bool, StackEmpty_> stack_empty,
1038 std::integral_constant<bool, IsKey_> is_key,
1039 bool allow_bad_utf8)
1040 {
1041 detail::const_stream_wrapper cs(p, end_);
1042 std::size_t total;
1043 if(stack_empty || st_.empty())
1044 {
1045 BOOST_ASSERT(*cs == '\x22');
1046 ++cs;
1047 total = 0;
1048 }
1049 else
1050 {
1051 state st;
1052 st_.pop(st);
1053 st_.pop(total);
1054 }
1055 char const* start = cs.begin();
1056 cs = allow_bad_utf8?
1057 detail::count_valid<true>(cs.begin(), cs.end()):
1058 detail::count_valid<false>(cs.begin(), cs.end());
1059 std::size_t size = cs.used(start);
1060 if(is_key)
1061 {
1062 BOOST_ASSERT(total <= Handler::max_key_size);
1063 if(BOOST_JSON_UNLIKELY(size >
1064 Handler::max_key_size - total))
1065 {
1066 BOOST_STATIC_CONSTEXPR source_location loc
1067 = BOOST_CURRENT_LOCATION;
1068 return fail(cs.begin(), error::key_too_large, &loc);
1069 }
1070 }
1071 else
1072 {
1073 BOOST_ASSERT(total <= Handler::max_string_size);
1074 if(BOOST_JSON_UNLIKELY(size >
1075 Handler::max_string_size - total))
1076 {
1077 BOOST_STATIC_CONSTEXPR source_location loc
1078 = BOOST_CURRENT_LOCATION;
1079 return fail(cs.begin(), error::string_too_large, &loc);
1080 }
1081 }
1082 total += size;
1083 if(BOOST_JSON_UNLIKELY(! cs))
1084 {
1085
1086 if(BOOST_JSON_LIKELY(size))
1087 {
1088 {
1089 bool r = is_key?
1090 h_.on_key_part( {start, size}, total, ec_ ):
1091 h_.on_string_part( {start, size}, total, ec_ );
1092
1093 if(BOOST_JSON_UNLIKELY(!r))
1094 {
1095 return fail(cs.begin());
1096 }
1097 }
1098 }
1099 return maybe_suspend(cs.begin(), state::str1, total);
1100 }
1101
1102
1103
1104 if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1105 {
1106
1107 if((*cs & 0x80) && !allow_bad_utf8)
1108 {
1109 seq_.save(cs.begin(), cs.remain());
1110 if(BOOST_JSON_UNLIKELY(seq_.complete()))
1111 {
1112 BOOST_STATIC_CONSTEXPR source_location loc
1113 = BOOST_CURRENT_LOCATION;
1114 return fail(cs.begin(), error::syntax, &loc);
1115 }
1116 if(BOOST_JSON_LIKELY(size))
1117 {
1118 {
1119 bool r = is_key?
1120 h_.on_key_part( {start, size}, total, ec_ ):
1121 h_.on_string_part( {start, size}, total, ec_ );
1122
1123 if(BOOST_JSON_UNLIKELY(!r))
1124 {
1125 return fail(cs.begin());
1126 }
1127 }
1128 }
1129 return maybe_suspend(cs.end(), state::str8, total);
1130 }
1131 else if(BOOST_JSON_LIKELY(*cs == '\\'))
1132 {
1133
1134 if(BOOST_JSON_LIKELY(size))
1135 {
1136 {
1137 bool r = is_key?
1138 h_.on_key_part( {start, size}, total, ec_ ):
1139 h_.on_string_part( {start, size}, total, ec_ );
1140
1141 if(BOOST_JSON_UNLIKELY(!r))
1142 {
1143 return fail(cs.begin());
1144 }
1145 }
1146 }
1147 return parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf8);
1148 }
1149
1150 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1151 return fail(cs.begin(), error::syntax, &loc);
1152 }
1153
1154 {
1155 bool r = is_key?
1156 h_.on_key( {start, size}, total, ec_ ):
1157 h_.on_string( {start, size}, total, ec_ );
1158
1159 if(BOOST_JSON_UNLIKELY(!r))
1160 {
1161 return fail(cs.begin());
1162 }
1163 }
1164
1165 ++cs;
1166 return cs.begin();
1167 }
1168
1169 template<class Handler>
1170 template<
1171 bool StackEmpty_
1172
1173 >
1174 const char*
1175 basic_parser<Handler>::
1176 parse_escaped(
1177 const char* p,
1178 std::size_t total,
1179 std::integral_constant<bool, StackEmpty_> stack_empty,
1180 bool is_key,
1181 bool allow_bad_utf8)
1182 {
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192
1193
1194
1195
1196 auto const ev_too_large = is_key?
1197 error::key_too_large : error::string_too_large;
1198 auto const max_size = is_key?
1199 Handler::max_key_size : Handler::max_string_size;
1200 detail::clipped_const_stream cs(p, end_);
1201 detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1202 int digit;
1203 char c;
1204 cs.clip(temp.max_size());
1205 if(! stack_empty && ! st_.empty())
1206 {
1207 state st;
1208 st_.pop(st);
1209 st_.pop(total);
1210 switch(st)
1211 {
1212 default: BOOST_JSON_UNREACHABLE();
1213 case state::str2: goto do_str2;
1214 case state::str3: goto do_str3;
1215 case state::str4: goto do_str4;
1216 case state::str5: goto do_str5;
1217 case state::str6: goto do_str6;
1218 case state::str7: goto do_str7;
1219 case state::str8: goto do_str8;
1220 case state::sur1: goto do_sur1;
1221 case state::sur2: goto do_sur2;
1222 case state::sur3: goto do_sur3;
1223 case state::sur4: goto do_sur4;
1224 case state::sur5: goto do_sur5;
1225 case state::sur6: goto do_sur6;
1226 }
1227 }
1228
1229
1230
1231
1232
1233 BOOST_ASSERT(*cs == '\\');
1234 ++cs;
1235 do_str3:
1236 if(BOOST_JSON_UNLIKELY(! cs))
1237 {
1238 if(BOOST_JSON_LIKELY(! temp.empty()))
1239 {
1240 BOOST_ASSERT(total <= max_size);
1241 if(BOOST_JSON_UNLIKELY(
1242 temp.size() > max_size - total))
1243 {
1244 BOOST_STATIC_CONSTEXPR source_location loc
1245 = BOOST_CURRENT_LOCATION;
1246 return fail(cs.begin(), ev_too_large, &loc);
1247 }
1248 total += temp.size();
1249 {
1250 bool r = is_key
1251 ? h_.on_key_part(temp.get(), total, ec_)
1252 : h_.on_string_part(temp.get(), total, ec_);
1253
1254 if(BOOST_JSON_UNLIKELY(!r))
1255 {
1256 return fail(cs.begin());
1257 }
1258 }
1259 temp.clear();
1260 }
1261 cs.clip(temp.max_size());
1262 if(BOOST_JSON_UNLIKELY(! cs))
1263 return maybe_suspend(cs.begin(), state::str3, total);
1264 }
1265 switch(*cs)
1266 {
1267 default:
1268 {
1269 BOOST_STATIC_CONSTEXPR source_location loc
1270 = BOOST_CURRENT_LOCATION;
1271 return fail(cs.begin(), error::syntax, &loc);
1272 }
1273 case '\x22':
1274 temp.push_back('\x22');
1275 ++cs;
1276 break;
1277 case '\\':
1278 temp.push_back('\\');
1279 ++cs;
1280 break;
1281 case '/':
1282 temp.push_back('/');
1283 ++cs;
1284 break;
1285 case 'b':
1286 temp.push_back('\x08');
1287 ++cs;
1288 break;
1289 case 'f':
1290 temp.push_back('\x0c');
1291 ++cs;
1292 break;
1293 case 'n':
1294 temp.push_back('\x0a');
1295 ++cs;
1296 break;
1297 case 'r':
1298 temp.push_back('\x0d');
1299 ++cs;
1300 break;
1301 case 't':
1302 temp.push_back('\x09');
1303 ++cs;
1304 break;
1305 case 'u':
1306
1307
1308
1309
1310 if(BOOST_JSON_LIKELY(cs.remain() > 10))
1311 {
1312
1313
1314 digit = detail::load_little_endian<4>(
1315 cs.begin() + 1);
1316 int d4 = detail::hex_digit(static_cast<
1317 unsigned char>(digit >> 24));
1318 int d3 = detail::hex_digit(static_cast<
1319 unsigned char>(digit >> 16));
1320 int d2 = detail::hex_digit(static_cast<
1321 unsigned char>(digit >> 8));
1322 int d1 = detail::hex_digit(static_cast<
1323 unsigned char>(digit));
1324 if(BOOST_JSON_UNLIKELY(
1325 (d1 | d2 | d3 | d4) == -1))
1326 {
1327 if(d1 != -1)
1328 ++cs;
1329 if(d2 != -1)
1330 ++cs;
1331 if(d3 != -1)
1332 ++cs;
1333 BOOST_STATIC_CONSTEXPR source_location loc
1334 = BOOST_CURRENT_LOCATION;
1335 return fail(cs.begin(), error::expected_hex_digit, &loc);
1336 }
1337
1338 unsigned const u1 =
1339 (d1 << 12) + (d2 << 8) +
1340 (d3 << 4) + d4;
1341
1342
1343
1344
1345 if(BOOST_JSON_LIKELY(
1346 u1 < 0xd800 || u1 > 0xdfff))
1347 {
1348 cs += 5;
1349 temp.append_utf8(u1);
1350 break;
1351 }
1352 if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1353 {
1354 BOOST_STATIC_CONSTEXPR source_location loc
1355 = BOOST_CURRENT_LOCATION;
1356 return fail(cs.begin(), error::illegal_leading_surrogate,
1357 &loc);
1358 }
1359 cs += 5;
1360
1361
1362
1363 if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1364 {
1365 BOOST_STATIC_CONSTEXPR source_location loc
1366 = BOOST_CURRENT_LOCATION;
1367 return fail(cs.begin(), error::syntax, &loc);
1368 }
1369 ++cs;
1370 if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1371 {
1372 BOOST_STATIC_CONSTEXPR source_location loc
1373 = BOOST_CURRENT_LOCATION;
1374 return fail(cs.begin(), error::syntax, &loc);
1375 }
1376 ++cs;
1377 digit = detail::load_little_endian<4>(cs.begin());
1378 d4 = detail::hex_digit(static_cast<
1379 unsigned char>(digit >> 24));
1380 d3 = detail::hex_digit(static_cast<
1381 unsigned char>(digit >> 16));
1382 d2 = detail::hex_digit(static_cast<
1383 unsigned char>(digit >> 8));
1384 d1 = detail::hex_digit(static_cast<
1385 unsigned char>(digit));
1386 if(BOOST_JSON_UNLIKELY(
1387 (d1 | d2 | d3 | d4) == -1))
1388 {
1389 if(d1 != -1)
1390 ++cs;
1391 if(d2 != -1)
1392 ++cs;
1393 if(d3 != -1)
1394 ++cs;
1395 BOOST_STATIC_CONSTEXPR source_location loc
1396 = BOOST_CURRENT_LOCATION;
1397 return fail(cs.begin(), error::expected_hex_digit, &loc);
1398 }
1399 unsigned const u2 =
1400 (d1 << 12) + (d2 << 8) +
1401 (d3 << 4) + d4;
1402
1403 if(BOOST_JSON_UNLIKELY(
1404 u2 < 0xdc00 || u2 > 0xdfff))
1405 {
1406 BOOST_STATIC_CONSTEXPR source_location loc
1407 = BOOST_CURRENT_LOCATION;
1408 return fail(cs.begin(), error::illegal_trailing_surrogate,
1409 &loc);
1410 }
1411 cs += 4;
1412 unsigned cp =
1413 ((u1 - 0xd800) << 10) +
1414 ((u2 - 0xdc00)) +
1415 0x10000;
1416
1417 temp.append_utf8(cp);
1418 break;
1419 }
1420
1421 if(BOOST_JSON_LIKELY(! temp.empty()))
1422 {
1423 BOOST_ASSERT(total <= max_size);
1424 if(BOOST_JSON_UNLIKELY(
1425 temp.size() > max_size - total))
1426 {
1427 BOOST_STATIC_CONSTEXPR source_location loc
1428 = BOOST_CURRENT_LOCATION;
1429 return fail(cs.begin(), ev_too_large, &loc);
1430 }
1431 total += temp.size();
1432 {
1433 bool r = is_key
1434 ? h_.on_key_part(temp.get(), total, ec_)
1435 : h_.on_string_part(temp.get(), total, ec_);
1436
1437 if(BOOST_JSON_UNLIKELY(!r))
1438 {
1439 return fail(cs.begin());
1440 }
1441 }
1442 temp.clear();
1443 cs.clip(temp.max_size());
1444 }
1445 ++cs;
1446
1447 do_str4:
1448 if(BOOST_JSON_UNLIKELY(! cs))
1449 return maybe_suspend(cs.begin(), state::str4, total);
1450 digit = detail::hex_digit(*cs);
1451 if(BOOST_JSON_UNLIKELY(digit == -1))
1452 {
1453 BOOST_STATIC_CONSTEXPR source_location loc
1454 = BOOST_CURRENT_LOCATION;
1455 return fail(cs.begin(), error::expected_hex_digit, &loc);
1456 }
1457 ++cs;
1458 u1_ = digit << 12;
1459 do_str5:
1460 if(BOOST_JSON_UNLIKELY(! cs))
1461 return maybe_suspend(cs.begin(), state::str5, total);
1462 digit = detail::hex_digit(*cs);
1463 if(BOOST_JSON_UNLIKELY(digit == -1))
1464 {
1465 BOOST_STATIC_CONSTEXPR source_location loc
1466 = BOOST_CURRENT_LOCATION;
1467 return fail(cs.begin(), error::expected_hex_digit, &loc);
1468 }
1469 ++cs;
1470 u1_ += digit << 8;
1471 do_str6:
1472 if(BOOST_JSON_UNLIKELY(! cs))
1473 return maybe_suspend(cs.begin(), state::str6, total);
1474 digit = detail::hex_digit(*cs);
1475 if(BOOST_JSON_UNLIKELY(digit == -1))
1476 {
1477 BOOST_STATIC_CONSTEXPR source_location loc
1478 = BOOST_CURRENT_LOCATION;
1479 return fail(cs.begin(), error::expected_hex_digit, &loc);
1480 }
1481 ++cs;
1482 u1_ += digit << 4;
1483 do_str7:
1484 if(BOOST_JSON_UNLIKELY(! cs))
1485 return maybe_suspend(cs.begin(), state::str7, total);
1486 digit = detail::hex_digit(*cs);
1487 if(BOOST_JSON_UNLIKELY(digit == -1))
1488 {
1489 BOOST_STATIC_CONSTEXPR source_location loc
1490 = BOOST_CURRENT_LOCATION;
1491 return fail(cs.begin(), error::expected_hex_digit, &loc);
1492 }
1493 ++cs;
1494 u1_ += digit;
1495 if(BOOST_JSON_LIKELY(
1496 u1_ < 0xd800 || u1_ > 0xdfff))
1497 {
1498 BOOST_ASSERT(temp.empty());
1499
1500 temp.append_utf8(u1_);
1501 break;
1502 }
1503 if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1504 {
1505 BOOST_STATIC_CONSTEXPR source_location loc
1506 = BOOST_CURRENT_LOCATION;
1507 return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1508 }
1509 do_sur1:
1510 if(BOOST_JSON_UNLIKELY(! cs))
1511 return maybe_suspend(cs.begin(), state::sur1, total);
1512 if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1513 {
1514 BOOST_STATIC_CONSTEXPR source_location loc
1515 = BOOST_CURRENT_LOCATION;
1516 return fail(cs.begin(), error::syntax, &loc);
1517 }
1518 ++cs;
1519 do_sur2:
1520 if(BOOST_JSON_UNLIKELY(! cs))
1521 return maybe_suspend(cs.begin(), state::sur2, total);
1522 if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1523 {
1524 BOOST_STATIC_CONSTEXPR source_location loc
1525 = BOOST_CURRENT_LOCATION;
1526 return fail(cs.begin(), error::syntax, &loc);
1527 }
1528 ++cs;
1529 do_sur3:
1530 if(BOOST_JSON_UNLIKELY(! cs))
1531 return maybe_suspend(cs.begin(), state::sur3, total);
1532 digit = detail::hex_digit(*cs);
1533 if(BOOST_JSON_UNLIKELY(digit == -1))
1534 {
1535 BOOST_STATIC_CONSTEXPR source_location loc
1536 = BOOST_CURRENT_LOCATION;
1537 return fail(cs.begin(), error::expected_hex_digit, &loc);
1538 }
1539 ++cs;
1540 u2_ = digit << 12;
1541 do_sur4:
1542 if(BOOST_JSON_UNLIKELY(! cs))
1543 return maybe_suspend(cs.begin(), state::sur4, total);
1544 digit = detail::hex_digit(*cs);
1545 if(BOOST_JSON_UNLIKELY(digit == -1))
1546 {
1547 BOOST_STATIC_CONSTEXPR source_location loc
1548 = BOOST_CURRENT_LOCATION;
1549 return fail(cs.begin(), error::expected_hex_digit, &loc);
1550 }
1551 ++cs;
1552 u2_ += digit << 8;
1553 do_sur5:
1554 if(BOOST_JSON_UNLIKELY(! cs))
1555 return maybe_suspend(cs.begin(), state::sur5, total);
1556 digit = detail::hex_digit(*cs);
1557 if(BOOST_JSON_UNLIKELY(digit == -1))
1558 {
1559 BOOST_STATIC_CONSTEXPR source_location loc
1560 = BOOST_CURRENT_LOCATION;
1561 return fail(cs.begin(), error::expected_hex_digit, &loc);
1562 }
1563 ++cs;
1564 u2_ += digit << 4;
1565 do_sur6:
1566 if(BOOST_JSON_UNLIKELY(! cs))
1567 return maybe_suspend(cs.begin(), state::sur6, total);
1568 digit = detail::hex_digit(*cs);
1569 if(BOOST_JSON_UNLIKELY(digit == -1))
1570 {
1571 BOOST_STATIC_CONSTEXPR source_location loc
1572 = BOOST_CURRENT_LOCATION;
1573 return fail(cs.begin(), error::expected_hex_digit, &loc);
1574 }
1575 ++cs;
1576 u2_ += digit;
1577 if(BOOST_JSON_UNLIKELY(
1578 u2_ < 0xdc00 || u2_ > 0xdfff))
1579 {
1580 BOOST_STATIC_CONSTEXPR source_location loc
1581 = BOOST_CURRENT_LOCATION;
1582 return fail(cs.begin(), error::expected_hex_digit, &loc);
1583 }
1584 unsigned cp =
1585 ((u1_ - 0xd800) << 10) +
1586 ((u2_ - 0xdc00)) +
1587 0x10000;
1588 BOOST_ASSERT(temp.empty());
1589
1590 temp.append_utf8(cp);
1591 }
1592 do_str2:
1593
1594
1595 for(;;)
1596 {
1597 if(BOOST_JSON_UNLIKELY(! cs || temp.capacity() == 0 ))
1598 {
1599
1600 if(BOOST_JSON_LIKELY(! temp.empty()))
1601 {
1602 BOOST_ASSERT(total <= max_size);
1603 if(BOOST_JSON_UNLIKELY(
1604 temp.size() > max_size - total))
1605 {
1606 BOOST_STATIC_CONSTEXPR source_location loc
1607 = BOOST_CURRENT_LOCATION;
1608 return fail(cs.begin(), ev_too_large, &loc);
1609 }
1610 total += temp.size();
1611 {
1612 bool r = is_key
1613 ? h_.on_key_part(temp.get(), total, ec_)
1614 : h_.on_string_part(temp.get(), total, ec_);
1615
1616 if(BOOST_JSON_UNLIKELY(!r))
1617 {
1618 return fail(cs.begin());
1619 }
1620 }
1621 temp.clear();
1622 }
1623 cs.clip(temp.max_size());
1624 if(BOOST_JSON_UNLIKELY(! cs))
1625 return maybe_suspend(cs.begin(), state::str2, total);
1626 }
1627 c = *cs;
1628 if(BOOST_JSON_LIKELY(c == '\x22'))
1629 {
1630 BOOST_ASSERT(total <= max_size);
1631 if(BOOST_JSON_UNLIKELY(
1632 temp.size() > max_size - total))
1633 {
1634 BOOST_STATIC_CONSTEXPR source_location loc
1635 = BOOST_CURRENT_LOCATION;
1636 return fail(cs.begin(), ev_too_large, &loc);
1637 }
1638 total += temp.size();
1639 {
1640 bool r = is_key
1641 ? h_.on_key(temp.get(), total, ec_)
1642 : h_.on_string(temp.get(), total, ec_);
1643
1644 if(BOOST_JSON_UNLIKELY(!r))
1645 {
1646 return fail(cs.begin());
1647 }
1648 }
1649 ++cs;
1650 return cs.begin();
1651 }
1652 else if((c & 0x80) && !allow_bad_utf8)
1653 {
1654 seq_.save(cs.begin(), cs.remain());
1655 if(BOOST_JSON_UNLIKELY(! seq_.complete()))
1656 {
1657 if(BOOST_JSON_LIKELY(! temp.empty()))
1658 {
1659 BOOST_ASSERT(total <= max_size);
1660 if(BOOST_JSON_UNLIKELY(
1661 temp.size() > max_size - total))
1662 {
1663 BOOST_STATIC_CONSTEXPR source_location loc
1664 = BOOST_CURRENT_LOCATION;
1665 return fail(cs.begin(), ev_too_large, &loc);
1666 }
1667 total += temp.size();
1668 {
1669 bool r = is_key
1670 ? h_.on_key_part(temp.get(), total, ec_)
1671 : h_.on_string_part(temp.get(), total, ec_);
1672
1673 if(BOOST_JSON_UNLIKELY(!r))
1674 {
1675 return fail(cs.begin());
1676 }
1677 }
1678 temp.clear();
1679 }
1680 cs = cs.end();
1681
1682 cs.clip(temp.max_size() - seq_.length());
1683 goto do_str8;
1684 }
1685 if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1686 {
1687 BOOST_STATIC_CONSTEXPR source_location loc
1688 = BOOST_CURRENT_LOCATION;
1689 return fail(cs.begin(), error::syntax, &loc);
1690 }
1691 temp.append(seq_.data(), seq_.length());
1692 cs += seq_.length();
1693 continue;
1694 }
1695 else if(BOOST_JSON_LIKELY(c == '\\'))
1696 {
1697 ++cs;
1698 goto do_str3;
1699 }
1700 else if(BOOST_JSON_UNLIKELY(
1701 detail::is_control(c)))
1702 {
1703 BOOST_STATIC_CONSTEXPR source_location loc
1704 = BOOST_CURRENT_LOCATION;
1705 return fail(cs.begin(), error::syntax, &loc);
1706 }
1707 temp.push_back(c);
1708 ++cs;
1709 }
1710 do_str8:
1711 uint8_t needed = seq_.needed();
1712 if(BOOST_JSON_UNLIKELY(
1713 ! seq_.append(cs.begin(), cs.remain())))
1714 return maybe_suspend(cs.end(), state::str8, total);
1715 if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1716 {
1717 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1718 return fail(cs.begin(), error::syntax, &loc);
1719 }
1720 temp.append(seq_.data(), seq_.length());
1721 cs += needed;
1722 goto do_str2;
1723 }
1724
1725
1726
1727 template<class Handler>
1728 template<
1729 bool StackEmpty_,
1730 bool AllowComments_
1731
1732 >
1733 const char*
1734 basic_parser<Handler>::
1735 parse_object(const char* p,
1736 std::integral_constant<bool, StackEmpty_> stack_empty,
1737 std::integral_constant<bool, AllowComments_> allow_comments,
1738 bool allow_trailing,
1739 bool allow_bad_utf8)
1740 {
1741 detail::const_stream_wrapper cs(p, end_);
1742 std::size_t size;
1743 if(! stack_empty && ! st_.empty())
1744 {
1745
1746 state st;
1747 st_.pop(st);
1748 st_.pop(size);
1749 switch(st)
1750 {
1751 default: BOOST_JSON_UNREACHABLE();
1752 case state::obj1: goto do_obj1;
1753 case state::obj2: goto do_obj2;
1754 case state::obj3: goto do_obj3;
1755 case state::obj4: goto do_obj4;
1756 case state::obj5: goto do_obj5;
1757 case state::obj6: goto do_obj6;
1758 case state::obj7: goto do_obj7;
1759 case state::obj8: goto do_obj8;
1760 case state::obj9: goto do_obj9;
1761 case state::obj10: goto do_obj10;
1762 case state::obj11: goto do_obj11;
1763 }
1764 }
1765 BOOST_ASSERT(*cs == '{');
1766 size = 0;
1767 if(BOOST_JSON_UNLIKELY(! depth_))
1768 {
1769 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1770 return fail(cs.begin(), error::too_deep, &loc);
1771 }
1772 --depth_;
1773 if(BOOST_JSON_UNLIKELY(
1774 ! h_.on_object_begin(ec_)))
1775 return fail(cs.begin());
1776 ++cs;
1777
1778
1779
1780 do_obj1:
1781 cs = detail::count_whitespace(cs.begin(), cs.end());
1782 if(BOOST_JSON_UNLIKELY(! cs))
1783 return maybe_suspend(cs.begin(), state::obj1, size);
1784 if(BOOST_JSON_LIKELY(*cs != '}'))
1785 {
1786 if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1787 {
1788 if(allow_comments && *cs == '/')
1789 {
1790 do_obj2:
1791 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1792 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1793 return suspend_or_fail(state::obj2, size);
1794 goto do_obj1;
1795 }
1796 BOOST_STATIC_CONSTEXPR source_location loc
1797 = BOOST_CURRENT_LOCATION;
1798 return fail(cs.begin(), error::syntax, &loc);
1799 }
1800 loop:
1801 if(BOOST_JSON_UNLIKELY(++size >
1802 Handler::max_object_size))
1803 {
1804 BOOST_STATIC_CONSTEXPR source_location loc
1805 = BOOST_CURRENT_LOCATION;
1806 return fail(cs.begin(), error::object_too_large, &loc);
1807 }
1808 do_obj3:
1809 cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8);
1810 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1811 return suspend_or_fail(state::obj3, size);
1812 do_obj4:
1813 cs = detail::count_whitespace(cs.begin(), cs.end());
1814 if(BOOST_JSON_UNLIKELY(! cs))
1815 return maybe_suspend(cs.begin(), state::obj4, size);
1816 if(BOOST_JSON_UNLIKELY(*cs != ':'))
1817 {
1818 if(allow_comments && *cs == '/')
1819 {
1820 do_obj5:
1821 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1822 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1823 return suspend_or_fail(state::obj5, size);
1824 goto do_obj4;
1825 }
1826 BOOST_STATIC_CONSTEXPR source_location loc
1827 = BOOST_CURRENT_LOCATION;
1828 return fail(cs.begin(), error::syntax, &loc);
1829 }
1830 ++cs;
1831 do_obj6:
1832 cs = detail::count_whitespace(cs.begin(), cs.end());
1833 if(BOOST_JSON_UNLIKELY(! cs))
1834 return maybe_suspend(cs.begin(), state::obj6, size);
1835 do_obj7:
1836 cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1837 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1838 return suspend_or_fail(state::obj7, size);
1839 do_obj8:
1840 cs = detail::count_whitespace(cs.begin(), cs.end());
1841 if(BOOST_JSON_UNLIKELY(! cs))
1842 return maybe_suspend(cs.begin(), state::obj8, size);
1843 if(BOOST_JSON_LIKELY(*cs == ','))
1844 {
1845 ++cs;
1846 do_obj9:
1847 cs = detail::count_whitespace(cs.begin(), cs.end());
1848 if(BOOST_JSON_UNLIKELY(! cs))
1849 return maybe_suspend(cs.begin(), state::obj9, size);
1850
1851
1852 if(BOOST_JSON_LIKELY(*cs == '\x22'))
1853 goto loop;
1854 if(! allow_trailing || *cs != '}')
1855 {
1856 if(allow_comments && *cs == '/')
1857 {
1858 do_obj10:
1859 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1860 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1861 return suspend_or_fail(state::obj10, size);
1862 goto do_obj9;
1863 }
1864 BOOST_STATIC_CONSTEXPR source_location loc
1865 = BOOST_CURRENT_LOCATION;
1866 return fail(cs.begin(), error::syntax, &loc);
1867 }
1868 }
1869 else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1870 {
1871 if(allow_comments && *cs == '/')
1872 {
1873 do_obj11:
1874 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1875 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1876 return suspend_or_fail(state::obj11, size);
1877 goto do_obj8;
1878 }
1879 BOOST_STATIC_CONSTEXPR source_location loc
1880 = BOOST_CURRENT_LOCATION;
1881 return fail(cs.begin(), error::syntax, &loc);
1882 }
1883
1884 }
1885 if(BOOST_JSON_UNLIKELY(
1886 ! h_.on_object_end(size, ec_)))
1887 return fail(cs.begin());
1888 ++depth_;
1889 ++cs;
1890 return cs.begin();
1891 }
1892
1893
1894
1895 template<class Handler>
1896 template<
1897 bool StackEmpty_,
1898 bool AllowComments_
1899
1900 >
1901 const char*
1902 basic_parser<Handler>::
1903 parse_array(const char* p,
1904 std::integral_constant<bool, StackEmpty_> stack_empty,
1905 std::integral_constant<bool, AllowComments_> allow_comments,
1906 bool allow_trailing,
1907 bool allow_bad_utf8)
1908 {
1909 detail::const_stream_wrapper cs(p, end_);
1910 std::size_t size;
1911 if(! stack_empty && ! st_.empty())
1912 {
1913
1914 state st;
1915 st_.pop(st);
1916 st_.pop(size);
1917 switch(st)
1918 {
1919 default: BOOST_JSON_UNREACHABLE();
1920 case state::arr1: goto do_arr1;
1921 case state::arr2: goto do_arr2;
1922 case state::arr3: goto do_arr3;
1923 case state::arr4: goto do_arr4;
1924 case state::arr5: goto do_arr5;
1925 case state::arr6: goto do_arr6;
1926 }
1927 }
1928 BOOST_ASSERT(*cs == '[');
1929 size = 0;
1930 if(BOOST_JSON_UNLIKELY(! depth_))
1931 {
1932 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1933 return fail(cs.begin(), error::too_deep, &loc);
1934 }
1935 --depth_;
1936 if(BOOST_JSON_UNLIKELY(
1937 ! h_.on_array_begin(ec_)))
1938 return fail(cs.begin());
1939 ++cs;
1940
1941
1942
1943 do_arr1:
1944 cs = detail::count_whitespace(cs.begin(), cs.end());
1945 if(BOOST_JSON_UNLIKELY(! cs))
1946 return maybe_suspend(cs.begin(), state::arr1, size);
1947 if(BOOST_JSON_LIKELY(*cs != ']'))
1948 {
1949 loop:
1950 if(allow_comments && *cs == '/')
1951 {
1952 do_arr2:
1953 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1954 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1955 return suspend_or_fail(state::arr2, size);
1956 goto do_arr1;
1957 }
1958 if(BOOST_JSON_UNLIKELY(++size >
1959 Handler::max_array_size))
1960 {
1961 BOOST_STATIC_CONSTEXPR source_location loc
1962 = BOOST_CURRENT_LOCATION;
1963 return fail(cs.begin(), error::array_too_large, &loc);
1964 }
1965 do_arr3:
1966
1967 cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1968 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1969 return suspend_or_fail(state::arr3, size);
1970 do_arr4:
1971 cs = detail::count_whitespace(cs.begin(), cs.end());
1972 if(BOOST_JSON_UNLIKELY(! cs))
1973 return maybe_suspend(cs.begin(), state::arr4, size);
1974 if(BOOST_JSON_LIKELY(*cs == ','))
1975 {
1976 ++cs;
1977 do_arr5:
1978 cs = detail::count_whitespace(cs.begin(), cs.end());
1979 if(BOOST_JSON_UNLIKELY(! cs))
1980 return maybe_suspend(cs.begin(), state::arr5, size);
1981
1982 if(! allow_trailing || *cs != ']')
1983 goto loop;
1984 }
1985 else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1986 {
1987 if(allow_comments && *cs == '/')
1988 {
1989 do_arr6:
1990 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1991 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1992 return suspend_or_fail(state::arr6, size);
1993 goto do_arr4;
1994 }
1995 BOOST_STATIC_CONSTEXPR source_location loc
1996 = BOOST_CURRENT_LOCATION;
1997 return fail(cs.begin(), error::syntax, &loc);
1998 }
1999
2000 }
2001 if(BOOST_JSON_UNLIKELY(
2002 ! h_.on_array_end(size, ec_)))
2003 return fail(cs.begin());
2004 ++depth_;
2005 ++cs;
2006 return cs.begin();
2007 }
2008
2009
2010
2011 template<class Handler>
2012 template<bool StackEmpty_, char First_, number_precision Numbers_>
2013 const char*
2014 basic_parser<Handler>::
2015 parse_number(const char* p,
2016 std::integral_constant<bool, StackEmpty_> stack_empty,
2017 std::integral_constant<char, First_> first,
2018 std::integral_constant<number_precision, Numbers_> mode)
2019 {
2020 constexpr bool precise_parsing = mode == number_precision::precise;
2021 constexpr bool no_parsing = mode == number_precision::none;
2022
2023
2024
2025
2026
2027 bool const negative = first == '-';
2028 bool const zero_first = first == '0';
2029 bool const nonzero_first = first == '+';
2030 detail::const_stream_wrapper cs(p, end_);
2031 number num;
2032 const char* begin = cs.begin();
2033 if(stack_empty || st_.empty())
2034 {
2035 num.bias = 0;
2036 num.exp = 0;
2037 num.frac = false;
2038 num_buf_.clear();
2039
2040
2041
2042
2043
2044
2045 BOOST_ASSERT(cs);
2046 if(negative)
2047 ++cs;
2048
2049 num.neg = negative;
2050 num.frac = false;
2051 num.exp = 0;
2052 num.bias = 0;
2053
2054
2055 if( cs.remain() >= 16 + 1 + 16 )
2056 {
2057 int n1;
2058
2059 if( nonzero_first ||
2060 (negative && *cs != '0') )
2061 {
2062 n1 = detail::count_digits( cs.begin() );
2063 BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2064
2065 if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2066 {
2067 return parse_literal(
2068 p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2069 }
2070
2071 if( ! nonzero_first && n1 == 0 )
2072 {
2073
2074 BOOST_STATIC_CONSTEXPR source_location loc
2075 = BOOST_CURRENT_LOCATION;
2076 return fail(cs.begin(), error::syntax, &loc);
2077 }
2078
2079 BOOST_IF_CONSTEXPR( !no_parsing )
2080 num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2081 else
2082 num.mant = 0;
2083
2084 cs += n1;
2085
2086
2087
2088 if( n1 == 16 )
2089 {
2090 goto do_num2;
2091 }
2092 }
2093 else
2094 {
2095
2096 num.mant = 0;
2097 n1 = 0;
2098 ++cs;
2099 }
2100
2101 {
2102 const char c = *cs;
2103 if(c != '.')
2104 {
2105 if((c | 32) == 'e')
2106 {
2107 ++cs;
2108 goto do_exp1;
2109 }
2110 BOOST_IF_CONSTEXPR( negative && !no_parsing )
2111 num.mant = ~num.mant + 1;
2112 goto finish_signed;
2113 }
2114 }
2115
2116
2117
2118 ++cs;
2119
2120 int n2 = detail::count_digits( cs.begin() );
2121 BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2122
2123 if( n2 == 0 )
2124 {
2125
2126 BOOST_STATIC_CONSTEXPR source_location loc
2127 = BOOST_CURRENT_LOCATION;
2128 return fail(cs.begin(), error::syntax, &loc);
2129 }
2130
2131
2132 if( n1 + n2 >= 19 )
2133 {
2134 goto do_num7;
2135 }
2136
2137 BOOST_IF_CONSTEXPR( !no_parsing )
2138 num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2139
2140 BOOST_ASSERT(num.bias == 0);
2141
2142 num.bias -= n2;
2143
2144 cs += n2;
2145
2146 char ch = *cs;
2147
2148 if( (ch | 32) == 'e' )
2149 {
2150 ++cs;
2151 goto do_exp1;
2152 }
2153 else if( ch >= '0' && ch <= '9' )
2154 {
2155 goto do_num8;
2156 }
2157
2158 goto finish_dub;
2159 }
2160 }
2161 else
2162 {
2163 num = num_;
2164 state st;
2165 st_.pop(st);
2166 switch(st)
2167 {
2168 default: BOOST_JSON_UNREACHABLE();
2169 case state::num1: goto do_num1;
2170 case state::num2: goto do_num2;
2171 case state::num3: goto do_num3;
2172 case state::num4: goto do_num4;
2173 case state::num5: goto do_num5;
2174 case state::num6: goto do_num6;
2175 case state::num7: goto do_num7;
2176 case state::num8: goto do_num8;
2177 case state::exp1: goto do_exp1;
2178 case state::exp2: goto do_exp2;
2179 case state::exp3: goto do_exp3;
2180 }
2181 }
2182
2183
2184
2185
2186
2187
2188 do_num1:
2189 if(zero_first || nonzero_first ||
2190 BOOST_JSON_LIKELY(cs))
2191 {
2192 char const c = *cs;
2193 if(zero_first)
2194 {
2195 ++cs;
2196 num.mant = 0;
2197 goto do_num6;
2198 }
2199 else if(nonzero_first || BOOST_JSON_LIKELY(
2200 c >= '1' && c <= '9'))
2201 {
2202 ++cs;
2203 num.mant = c - '0';
2204 }
2205 else if(BOOST_JSON_UNLIKELY(
2206 c == '0'))
2207 {
2208 ++cs;
2209 num.mant = 0;
2210 goto do_num6;
2211 }
2212 else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2213 {
2214 st_.push(state::lit1);
2215 cur_lit_ = detail::neg_infinity_literal;
2216 lit_offset_ = 1;
2217 return parse_literal(
2218 cs.begin(), mp11::mp_int<detail::resume_literal>() );
2219 }
2220 else
2221 {
2222 BOOST_STATIC_CONSTEXPR source_location loc
2223 = BOOST_CURRENT_LOCATION;
2224 return fail(cs.begin(), error::syntax, &loc);
2225 }
2226 }
2227 else
2228 {
2229 if(BOOST_JSON_UNLIKELY(
2230 ! h_.on_number_part(
2231 {begin, cs.used(begin)}, ec_)))
2232 return fail(cs.begin());
2233
2234 BOOST_IF_CONSTEXPR( precise_parsing )
2235 num_buf_.append( begin, cs.used(begin) );
2236 return maybe_suspend(
2237 cs.begin(), state::num1, num);
2238 }
2239
2240
2241
2242
2243
2244
2245 do_num2:
2246 if(negative || (!stack_empty && num.neg))
2247 {
2248 for(;;)
2249 {
2250 if(BOOST_JSON_UNLIKELY(! cs))
2251 {
2252 if(BOOST_JSON_UNLIKELY(more_))
2253 {
2254 if(BOOST_JSON_UNLIKELY(
2255 ! h_.on_number_part(
2256 {begin, cs.used(begin)}, ec_)))
2257 return fail(cs.begin());
2258
2259 BOOST_IF_CONSTEXPR( precise_parsing )
2260 num_buf_.append( begin, cs.used(begin) );
2261 return suspend(cs.begin(), state::num2, num);
2262 }
2263 goto finish_int;
2264 }
2265 char const c = *cs;
2266 if(BOOST_JSON_LIKELY(
2267 c >= '0' && c <= '9'))
2268 {
2269 ++cs;
2270
2271 if( num.mant > 922337203685477580 || (
2272 num.mant == 922337203685477580 && c > '8'))
2273 break;
2274 BOOST_IF_CONSTEXPR( !no_parsing )
2275 num.mant = 10 * num.mant + ( c - '0' );
2276 continue;
2277 }
2278 goto do_num6;
2279 }
2280 }
2281 else
2282 {
2283 for(;;)
2284 {
2285 if(BOOST_JSON_UNLIKELY(! cs))
2286 {
2287 if(BOOST_JSON_UNLIKELY(more_))
2288 {
2289 if(BOOST_JSON_UNLIKELY(
2290 ! h_.on_number_part(
2291 {begin, cs.used(begin)}, ec_)))
2292 return fail(cs.begin());
2293
2294 BOOST_IF_CONSTEXPR( precise_parsing )
2295 num_buf_.append( begin, cs.used(begin) );
2296 return suspend(cs.begin(), state::num2, num);
2297 }
2298 goto finish_int;
2299 }
2300 char const c = *cs;
2301 if(BOOST_JSON_LIKELY(
2302 c >= '0' && c <= '9'))
2303 {
2304 ++cs;
2305
2306 if( num.mant > 1844674407370955161 || (
2307 num.mant == 1844674407370955161 && c > '5'))
2308 break;
2309 BOOST_IF_CONSTEXPR( !no_parsing )
2310 num.mant = 10 * num.mant + ( c - '0' );
2311 }
2312 else
2313 {
2314 goto do_num6;
2315 }
2316 }
2317 }
2318 ++num.bias;
2319
2320
2321
2322
2323
2324
2325 do_num3:
2326 for(;;)
2327 {
2328 if(BOOST_JSON_UNLIKELY(! cs))
2329 {
2330 if(BOOST_JSON_UNLIKELY(more_))
2331 {
2332 if(BOOST_JSON_UNLIKELY(
2333 ! h_.on_number_part(
2334 {begin, cs.used(begin)}, ec_)))
2335 return fail(cs.begin());
2336
2337 BOOST_IF_CONSTEXPR( precise_parsing )
2338 num_buf_.append( begin, cs.used(begin) );
2339 return suspend(cs.begin(), state::num3, num);
2340 }
2341 goto finish_dub;
2342 }
2343 char const c = *cs;
2344 if(BOOST_JSON_UNLIKELY(
2345 c >= '0' && c <= '9'))
2346 {
2347 if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2348 {
2349 BOOST_STATIC_CONSTEXPR source_location loc
2350 = BOOST_CURRENT_LOCATION;
2351 return fail(cs.begin(), error::exponent_overflow, &loc);
2352 }
2353 ++cs;
2354 ++num.bias;
2355 }
2356 else if(BOOST_JSON_LIKELY(
2357 c == '.'))
2358 {
2359 ++cs;
2360 break;
2361 }
2362 else if((c | 32) == 'e')
2363 {
2364 ++cs;
2365 goto do_exp1;
2366 }
2367 else
2368 {
2369 goto finish_dub;
2370 }
2371 }
2372
2373
2374
2375
2376
2377
2378
2379 do_num4:
2380 {
2381 if(BOOST_JSON_UNLIKELY(! cs))
2382 {
2383 if(BOOST_JSON_UNLIKELY(
2384 ! h_.on_number_part(
2385 {begin, cs.used(begin)}, ec_)))
2386 return fail(cs.begin());
2387
2388 BOOST_IF_CONSTEXPR( precise_parsing )
2389 num_buf_.append( begin, cs.used(begin) );
2390 return maybe_suspend(
2391 cs.begin(), state::num4, num);
2392 }
2393 char const c = *cs;
2394 if(BOOST_JSON_LIKELY(
2395
2396 c >= '0' && c <= '9'))
2397 {
2398 ++cs;
2399 }
2400 else
2401 {
2402
2403 BOOST_STATIC_CONSTEXPR source_location loc
2404 = BOOST_CURRENT_LOCATION;
2405 return fail(cs.begin(), error::syntax, &loc);
2406 }
2407 }
2408
2409
2410
2411
2412
2413
2414
2415 do_num5:
2416 for(;;)
2417 {
2418 if(BOOST_JSON_UNLIKELY(! cs))
2419 {
2420 if(BOOST_JSON_UNLIKELY(more_))
2421 {
2422 if(BOOST_JSON_UNLIKELY(
2423 ! h_.on_number_part(
2424 {begin, cs.used(begin)}, ec_)))
2425 return fail(cs.begin());
2426
2427 BOOST_IF_CONSTEXPR( precise_parsing )
2428 num_buf_.append( begin, cs.used(begin) );
2429 return suspend(cs.begin(), state::num5, num);
2430 }
2431 goto finish_dub;
2432 }
2433 char const c = *cs;
2434 if(BOOST_JSON_LIKELY(
2435 c >= '0' && c <= '9'))
2436 {
2437 ++cs;
2438 }
2439 else if((c | 32) == 'e')
2440 {
2441 ++cs;
2442 goto do_exp1;
2443 }
2444 else
2445 {
2446 goto finish_dub;
2447 }
2448 }
2449
2450
2451
2452
2453
2454 do_num6:
2455 {
2456 if(BOOST_JSON_UNLIKELY(! cs))
2457 {
2458 if(BOOST_JSON_UNLIKELY(more_))
2459 {
2460 if(BOOST_JSON_UNLIKELY(
2461 ! h_.on_number_part(
2462 {begin, cs.used(begin)}, ec_)))
2463 return fail(cs.begin());
2464
2465 BOOST_IF_CONSTEXPR( precise_parsing )
2466 num_buf_.append( begin, cs.used(begin) );
2467 return suspend(cs.begin(), state::num6, num);
2468 }
2469 goto finish_int;
2470 }
2471 char const c = *cs;
2472 if(BOOST_JSON_LIKELY(
2473 c == '.'))
2474 {
2475 ++cs;
2476 }
2477 else if((c | 32) == 'e')
2478 {
2479 ++cs;
2480 goto do_exp1;
2481 }
2482 else
2483 {
2484 goto finish_int;
2485 }
2486 }
2487
2488
2489
2490
2491
2492
2493
2494 do_num7:
2495 {
2496 if(BOOST_JSON_UNLIKELY(! cs))
2497 {
2498 if(BOOST_JSON_UNLIKELY(more_))
2499 {
2500 if(BOOST_JSON_UNLIKELY(
2501 ! h_.on_number_part(
2502 {begin, cs.used(begin)}, ec_)))
2503 return fail(cs.begin());
2504
2505 BOOST_IF_CONSTEXPR( precise_parsing )
2506 num_buf_.append( begin, cs.used(begin) );
2507 return suspend(cs.begin(), state::num7, num);
2508 }
2509
2510 BOOST_STATIC_CONSTEXPR source_location loc
2511 = BOOST_CURRENT_LOCATION;
2512 return fail(cs.begin(), error::syntax, &loc);
2513 }
2514 char const c = *cs;
2515 if(BOOST_JSON_UNLIKELY(
2516 c < '0' || c > '9'))
2517 {
2518
2519 BOOST_STATIC_CONSTEXPR source_location loc
2520 = BOOST_CURRENT_LOCATION;
2521 return fail(cs.begin(), error::syntax, &loc);
2522 }
2523 }
2524
2525
2526
2527
2528
2529
2530
2531 do_num8:
2532 for(;;)
2533 {
2534 if(BOOST_JSON_UNLIKELY(! cs))
2535 {
2536 if(BOOST_JSON_UNLIKELY(more_))
2537 {
2538 if(BOOST_JSON_UNLIKELY(
2539 ! h_.on_number_part(
2540 {begin, cs.used(begin)}, ec_)))
2541 return fail(cs.begin());
2542
2543 BOOST_IF_CONSTEXPR( precise_parsing )
2544 num_buf_.append( begin, cs.used(begin) );
2545 return suspend(cs.begin(), state::num8, num);
2546 }
2547 goto finish_dub;
2548 }
2549 char const c = *cs;
2550 if(BOOST_JSON_LIKELY(
2551 c >= '0' && c <= '9'))
2552 {
2553 ++cs;
2554 if(!no_parsing && BOOST_JSON_LIKELY(
2555 num.mant <= 9007199254740991))
2556 {
2557 if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2558 {
2559 BOOST_STATIC_CONSTEXPR source_location loc
2560 = BOOST_CURRENT_LOCATION;
2561 return fail(cs.begin(), error::exponent_overflow, &loc);
2562 }
2563 --num.bias;
2564 num.mant = 10 * num.mant + ( c - '0' );
2565 }
2566 else
2567 {
2568 goto do_num5;
2569 }
2570 }
2571 else if((c | 32) == 'e')
2572 {
2573 ++cs;
2574 goto do_exp1;
2575 }
2576 else
2577 {
2578 goto finish_dub;
2579 }
2580 }
2581
2582
2583
2584
2585
2586 do_exp1:
2587 if(BOOST_JSON_UNLIKELY(! cs))
2588 {
2589 if(BOOST_JSON_UNLIKELY(
2590 ! h_.on_number_part(
2591 {begin, cs.used(begin)}, ec_)))
2592 return fail(cs.begin());
2593
2594 BOOST_IF_CONSTEXPR( precise_parsing )
2595 num_buf_.append( begin, cs.used(begin) );
2596 return maybe_suspend(
2597 cs.begin(), state::exp1, num);
2598 }
2599 if(*cs == '+')
2600 {
2601 ++cs;
2602 }
2603 else if(*cs == '-')
2604 {
2605 ++cs;
2606 num.frac = true;
2607 }
2608
2609
2610
2611
2612
2613
2614 do_exp2:
2615 {
2616 if(BOOST_JSON_UNLIKELY(! cs))
2617 {
2618 if(BOOST_JSON_UNLIKELY(more_))
2619 {
2620 if(BOOST_JSON_UNLIKELY(
2621 ! h_.on_number_part(
2622 {begin, cs.used(begin)}, ec_)))
2623 return fail(cs.begin());
2624
2625 BOOST_IF_CONSTEXPR( precise_parsing )
2626 num_buf_.append( begin, cs.used(begin) );
2627 return suspend(cs.begin(), state::exp2, num);
2628 }
2629
2630 BOOST_STATIC_CONSTEXPR source_location loc
2631 = BOOST_CURRENT_LOCATION;
2632 return fail(cs.begin(), error::syntax, &loc);
2633 }
2634 char const c = *cs;
2635 if(BOOST_JSON_UNLIKELY(
2636 c < '0' || c > '9'))
2637 {
2638
2639 BOOST_STATIC_CONSTEXPR source_location loc
2640 = BOOST_CURRENT_LOCATION;
2641 return fail(cs.begin(), error::syntax, &loc);
2642 }
2643 ++cs;
2644 num.exp = c - '0';
2645 }
2646
2647
2648
2649
2650
2651
2652 do_exp3:
2653 for(;;)
2654 {
2655 if(BOOST_JSON_UNLIKELY(! cs))
2656 {
2657 if(BOOST_JSON_UNLIKELY(more_))
2658 {
2659 if(BOOST_JSON_UNLIKELY(
2660 ! h_.on_number_part(
2661 {begin, cs.used(begin)}, ec_)))
2662 return fail(cs.begin());
2663
2664 BOOST_IF_CONSTEXPR( precise_parsing )
2665 num_buf_.append( begin, cs.used(begin) );
2666 return suspend(cs.begin(), state::exp3, num);
2667 }
2668 }
2669 else
2670 {
2671 char const c = *cs;
2672 if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2673 {
2674 if(BOOST_JSON_UNLIKELY(
2675
2676 num.exp > 214748364 ||
2677 (num.exp == 214748364 && c > '7')
2678 ))
2679 num.exp = INT_MAX;
2680 else BOOST_IF_CONSTEXPR( !no_parsing )
2681 num.exp = 10 * num.exp + ( c - '0' );
2682
2683 ++cs;
2684 continue;
2685 }
2686 }
2687 BOOST_ASSERT(num.exp >= 0);
2688 if ( num.frac )
2689 {
2690 if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2691 {
2692
2693
2694
2695 if(BOOST_JSON_UNLIKELY(
2696 (num.exp == INT_MAX) &&
2697 (num.bias < 0) &&
2698 (num.exp + num.bias < 308) &&
2699 num.mant ))
2700 {
2701 BOOST_STATIC_CONSTEXPR source_location loc
2702 = BOOST_CURRENT_LOCATION;
2703 return fail(cs.begin(), error::exponent_overflow, &loc);
2704 }
2705
2706 num.bias = 0;
2707 num.exp = INT_MAX;
2708 }
2709 }
2710 else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2711 {
2712
2713
2714
2715 if(BOOST_JSON_UNLIKELY(
2716 (num.exp == INT_MAX) &&
2717 (num.bias > 0) &&
2718 (num.exp - num.bias < 308) &&
2719 num.mant ))
2720 {
2721 BOOST_STATIC_CONSTEXPR source_location loc
2722 = BOOST_CURRENT_LOCATION;
2723 return fail(cs.begin(), error::exponent_overflow, &loc);
2724 }
2725
2726 num.bias = 0;
2727 num.exp = INT_MAX;
2728 }
2729 goto finish_dub;
2730 }
2731
2732 finish_int:
2733 if(negative || (!stack_empty && num.neg))
2734 {
2735 if(BOOST_JSON_UNLIKELY(
2736 ! h_.on_int64(static_cast<
2737 int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2738 return fail(cs.begin());
2739 return cs.begin();
2740 }
2741 if(num.mant <= INT64_MAX)
2742 {
2743 finish_signed:
2744 if(BOOST_JSON_UNLIKELY(
2745 ! h_.on_int64(static_cast<
2746 int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2747 return fail(cs.begin());
2748 return cs.begin();
2749 }
2750 if(BOOST_JSON_UNLIKELY(
2751 ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2752 return fail(cs.begin());
2753 return cs.begin();
2754 finish_dub:
2755 double d;
2756 std::size_t const size = cs.used(begin);
2757 BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2758 BOOST_IF_CONSTEXPR( precise_parsing )
2759 {
2760 char const* data = begin;
2761 std::size_t full_size = size;
2762
2763
2764
2765 if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2766 {
2767 data = num_buf_.append( begin, size );
2768 full_size = num_buf_.size();
2769 }
2770 auto const err = detail::charconv::from_chars(
2771 data, data + full_size, d );
2772 BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2773 BOOST_ASSERT( err.ptr == data + full_size );
2774 (void)err;
2775 }
2776 else BOOST_IF_CONSTEXPR( no_parsing )
2777 d = 0;
2778 else
2779 d = detail::dec_to_float(
2780 num.mant,
2781 num.bias + (num.frac ?
2782 -num.exp : num.exp),
2783 num.neg);
2784 if(BOOST_JSON_UNLIKELY(
2785 ! h_.on_double(d, {begin, size}, ec_)))
2786 return fail(cs.begin());
2787 return cs.begin();
2788 }
2789
2790
2791
2792 template<class Handler>
2793 template<class... Args>
2794 basic_parser<Handler>::
2795 basic_parser(
2796 parse_options const& opt,
2797 Args&&... args)
2798 : h_(std::forward<Args>(args)...)
2799 , opt_(opt)
2800 {
2801 }
2802
2803
2804
2805 template<class Handler>
2806 void
2807 basic_parser<Handler>::
2808 reset() noexcept
2809 {
2810 ec_ = {};
2811 st_.clear();
2812 more_ = true;
2813 done_ = false;
2814 clean_ = true;
2815 num_buf_.clear();
2816 }
2817
2818 template<class Handler>
2819 void
2820 basic_parser<Handler>::
2821 fail(error_code ec) noexcept
2822 {
2823 if(! ec)
2824 {
2825
2826
2827 BOOST_JSON_FAIL(ec_, error::incomplete);
2828 }
2829 else
2830 {
2831 ec_ = ec;
2832 }
2833 done_ = false;
2834 }
2835
2836
2837
2838 template<class Handler>
2839 std::size_t
2840 basic_parser<Handler>::
2841 write_some(
2842 bool more,
2843 char const* data,
2844 std::size_t size,
2845 error_code& ec)
2846 {
2847
2848
2849 if(! clean_)
2850 {
2851
2852 if(! ec_)
2853 {
2854 BOOST_JSON_FAIL(ec_, error::exception);
2855 }
2856 }
2857 if(ec_)
2858 {
2859
2860 ec = ec_;
2861 return 0;
2862 }
2863 clean_ = false;
2864 more_ = more;
2865 end_ = data + size;
2866 const char* p;
2867 if(BOOST_JSON_LIKELY(st_.empty()))
2868 {
2869
2870 depth_ = opt_.max_depth;
2871 if(BOOST_JSON_UNLIKELY(
2872 ! h_.on_document_begin(ec_)))
2873 {
2874 ec = ec_;
2875 return 0;
2876 }
2877 p = parse_document(data, std::true_type());
2878 }
2879 else
2880 {
2881 p = parse_document(data, std::false_type());
2882 }
2883
2884 if(BOOST_JSON_LIKELY(p != sentinel()))
2885 {
2886 BOOST_ASSERT(! ec_);
2887 if(! done_)
2888 {
2889 done_ = true;
2890 h_.on_document_end(ec_);
2891 }
2892 }
2893 else
2894 {
2895 if(! ec_)
2896 {
2897 if(! more_)
2898 {
2899 BOOST_JSON_FAIL(ec_, error::incomplete);
2900 }
2901 else if(! st_.empty())
2902 {
2903
2904
2905
2906 state st;
2907 st_.peek(st);
2908 if( st == state::doc3 &&
2909 ! done_)
2910 {
2911 done_ = true;
2912 h_.on_document_end(ec_);
2913 }
2914 }
2915 }
2916 p = end_;
2917 }
2918 ec = ec_;
2919 clean_ = true;
2920 return p - data;
2921 }
2922
2923 template<class Handler>
2924 std::size_t
2925 basic_parser<Handler>::
2926 write_some(
2927 bool more,
2928 char const* data,
2929 std::size_t size,
2930 std::error_code& ec)
2931 {
2932 error_code jec;
2933 std::size_t const result = write_some(more, data, size, jec);
2934 ec = jec;
2935 return result;
2936 }
2937
2938 #endif
2939
2940 }
2941 }
2942
2943 #ifdef _MSC_VER
2944 #pragma warning(pop)
2945 #endif
2946
2947 #endif