Line data Source code
1 : //
2 : // Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3 : // Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4 : //
5 : // Distributed under the Boost Software License, Version 1.0. (See accompanying
6 : // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7 : //
8 : // Official repository: https://github.com/boostorg/json
9 : //
10 :
11 : #ifndef BOOST_JSON_BASIC_PARSER_IMPL_HPP
12 : #define BOOST_JSON_BASIC_PARSER_IMPL_HPP
13 :
14 : #include <boost/json/detail/config.hpp>
15 : #include <boost/json/basic_parser.hpp>
16 : #include <boost/json/error.hpp>
17 : #include <boost/json/detail/buffer.hpp>
18 : #include <boost/json/detail/charconv/from_chars.hpp>
19 : #include <boost/json/detail/sse2.hpp>
20 : #include <boost/mp11/algorithm.hpp>
21 : #include <boost/mp11/integral.hpp>
22 : #include <cmath>
23 : #include <limits>
24 : #include <cstring>
25 :
26 : #ifdef _MSC_VER
27 : #pragma warning(push)
28 : #pragma warning(disable: 4702) // unreachable code
29 : #pragma warning(disable: 4127) // conditional expression is constant
30 : #endif
31 :
32 : /* This file must be manually included to get the
33 : function template definitions for basic_parser.
34 : */
35 :
36 : /* Reference:
37 :
38 : https://www.json.org/
39 :
40 : RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
41 : https://tools.ietf.org/html/rfc7159
42 :
43 : https://ampl.com/netlib/fp/dtoa.c
44 : */
45 :
46 : #ifndef BOOST_JSON_DOCS
47 :
48 : namespace boost {
49 : namespace json {
50 : namespace detail {
51 :
52 : inline
53 : double
54 1033693 : pow10(int exp) noexcept
55 : {
56 : static double const tab[618] = {
57 : 1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
58 :
59 : 1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
60 : 1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
61 : 1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
62 : 1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
63 : 1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
64 : 1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
65 : 1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
66 : 1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
67 : 1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
68 : 1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
69 :
70 : 1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
71 : 1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
72 : 1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
73 : 1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
74 : 1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
75 : 1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
76 : 1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
77 : 1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
78 : 1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
79 : 1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
80 :
81 : 1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
82 : 1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
83 : 1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
84 : 1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
85 : 1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
86 : 1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
87 : 1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
88 : 1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
89 : 1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
90 : 1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
91 :
92 : 1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
93 : 1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
94 : 1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
95 : 1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
96 : 1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
97 : 1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
98 : 1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
99 : 1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
100 : 1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
101 : 1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
102 :
103 : 1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
104 : 1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
105 : 1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
106 : 1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
107 : 1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
108 : 1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
109 : 1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
110 : 1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
111 : 1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
112 : 1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
113 :
114 : 1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
115 : 1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
116 : 1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
117 : 1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
118 : 1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
119 : 1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
120 : 1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
121 : 1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
122 : 1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
123 : 1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
124 :
125 : 1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
126 :
127 1033693 : if( exp > 308 )
128 : {
129 341 : return std::numeric_limits<double>::infinity();
130 : }
131 1033352 : else if( exp < -308 )
132 : {
133 : // due to the way pow10 is used by dec_to_float,
134 : // we can afford to return 0.0 here
135 151 : return 0.0;
136 : }
137 : else
138 : {
139 1033201 : exp += 308;
140 1033201 : BOOST_ASSERT(exp >= 0 && exp < 618);
141 1033201 : return tab[exp];
142 : }
143 : }
144 :
145 : inline
146 : double
147 1033693 : dec_to_float(
148 : std::uint64_t m,
149 : std::int32_t e,
150 : bool neg) noexcept
151 : {
152 : // convert to double explicitly to silence warnings
153 1033693 : double x = static_cast<double>(m);
154 1033693 : if(neg)
155 13164 : x = -x;
156 :
157 1033693 : if(e < -305)
158 : {
159 5187 : x *= 1e-305 ;
160 5187 : e += 305;
161 : }
162 :
163 1033693 : if(e >= -22 && e < 0)
164 54813 : return x / pow10(-e);
165 :
166 978880 : return x * pow10(e);
167 : }
168 :
169 : inline
170 : bool
171 : is_control(char c) noexcept
172 : {
173 : return static_cast<unsigned char>(c) < 32;
174 : }
175 :
176 : inline
177 : int
178 66931 : hex_digit(unsigned char c) noexcept
179 : {
180 : // by Peter Dimov
181 66931 : if( c >= '0' && c <= '9' )
182 35759 : return c - '0';
183 31172 : c &= ~0x20;
184 31172 : if( c >= 'A' && c <= 'F' )
185 30562 : return 10 + c - 'A';
186 610 : return -1;
187 : }
188 :
189 : enum json_literal
190 : {
191 : null_literal = 0,
192 : true_literal,
193 : false_literal,
194 : infinity_literal,
195 : neg_infinity_literal,
196 : nan_literal,
197 : resume_literal = -1
198 : };
199 :
200 : } // detail
201 :
202 : //----------------------------------------------------------
203 :
204 : template< class Handler >
205 : template< bool StackEmpty_, char First_ >
206 : struct basic_parser<Handler>::
207 : parse_number_helper
208 : {
209 : basic_parser* parser;
210 : char const* p;
211 :
212 : template< std::size_t N >
213 : char const*
214 2126839 : operator()( mp11::mp_size_t<N> ) const
215 : {
216 4248237 : return parser->parse_number(
217 2126839 : p,
218 : std::integral_constant<bool, StackEmpty_>(),
219 : std::integral_constant<char, First_>(),
220 : std::integral_constant<
221 2121399 : number_precision, static_cast<number_precision>(N)>() );
222 : }
223 : };
224 :
225 : //----------------------------------------------------------
226 :
227 : template<class Handler>
228 : void
229 210492 : basic_parser<Handler>::
230 : reserve()
231 : {
232 210492 : if(BOOST_JSON_LIKELY(
233 : ! st_.empty()))
234 37434 : return;
235 : // Reserve the largest stack we need,
236 : // to avoid reallocation during suspend.
237 346116 : st_.reserve(
238 : sizeof(state) + // document parsing state
239 : (sizeof(state) +
240 173058 : sizeof(std::size_t)) * depth() + // array and object state + size
241 : sizeof(state) + // value parsing state
242 : sizeof(std::size_t) + // string size
243 : sizeof(state)); // comment state
244 : }
245 :
246 : //----------------------------------------------------------
247 : //
248 : // The sentinel value is returned by parse functions
249 : // to indicate that the parser failed, or suspended.
250 : // this is used as it is distinct from all valid values
251 : // for data in write
252 :
253 : template<class Handler>
254 : const char*
255 5340588 : basic_parser<Handler>::
256 : sentinel()
257 : {
258 : // the "+1" ensures that the returned pointer is unique even if
259 : // the given input buffer borders on this object
260 : return reinterpret_cast<
261 5340588 : const char*>(this) + 1;
262 : }
263 :
264 : template<class Handler>
265 : bool
266 2459737 : basic_parser<Handler>::
267 : incomplete(
268 : const detail::const_stream_wrapper& cs)
269 : {
270 2459737 : return cs.begin() == sentinel();
271 : }
272 :
273 : //----------------------------------------------------------
274 : //
275 : // These functions are declared with the BOOST_NOINLINE
276 : // attribute to avoid polluting the parsers hot-path.
277 : // They return the canary value to indicate suspension
278 : // or failure.
279 :
280 : template<class Handler>
281 : const char*
282 : basic_parser<Handler>::
283 : suspend_or_fail(state st)
284 : {
285 : if(BOOST_JSON_LIKELY(
286 : ! ec_ && more_))
287 : {
288 : // suspend
289 : reserve();
290 : st_.push_unchecked(st);
291 : }
292 : return sentinel();
293 : }
294 :
295 : template<class Handler>
296 : const char*
297 56132 : basic_parser<Handler>::
298 : suspend_or_fail(
299 : state st,
300 : std::size_t n)
301 : {
302 56132 : if(BOOST_JSON_LIKELY(
303 : ! ec_ && more_))
304 : {
305 : // suspend
306 35826 : reserve();
307 35826 : st_.push_unchecked(n);
308 35826 : st_.push_unchecked(st);
309 : }
310 56132 : return sentinel();
311 : }
312 :
313 :
314 : template<class Handler>
315 : const char*
316 18979 : basic_parser<Handler>::
317 : fail(const char* p) noexcept
318 : {
319 18979 : BOOST_ASSERT( p != sentinel() );
320 18979 : end_ = p;
321 18979 : return sentinel();
322 : }
323 :
324 : template<class Handler>
325 : const char*
326 7772 : basic_parser<Handler>::
327 : fail(
328 : const char* p,
329 : error ev,
330 : source_location const* loc) noexcept
331 : {
332 7772 : BOOST_ASSERT( p != sentinel() );
333 7772 : end_ = p;
334 7772 : ec_.assign(ev, loc);
335 7772 : return sentinel();
336 : }
337 :
338 : template<class Handler>
339 : const char*
340 11289 : basic_parser<Handler>::
341 : maybe_suspend(
342 : const char* p,
343 : state st)
344 : {
345 11289 : if( p != sentinel() )
346 9424 : end_ = p;
347 11289 : if(BOOST_JSON_LIKELY(more_))
348 : {
349 : // suspend
350 11027 : reserve();
351 11027 : st_.push_unchecked(st);
352 : }
353 11289 : return sentinel();
354 : }
355 :
356 : template<class Handler>
357 : const char*
358 38210 : basic_parser<Handler>::
359 : maybe_suspend(
360 : const char* p,
361 : state st,
362 : std::size_t n)
363 : {
364 38210 : BOOST_ASSERT( p != sentinel() );
365 38210 : end_ = p;
366 38210 : if(BOOST_JSON_LIKELY(more_))
367 : {
368 : // suspend
369 37810 : reserve();
370 37810 : st_.push_unchecked(n);
371 37810 : st_.push_unchecked(st);
372 : }
373 38210 : return sentinel();
374 : }
375 :
376 : template<class Handler>
377 : const char*
378 1123 : basic_parser<Handler>::
379 : maybe_suspend(
380 : const char* p,
381 : state st,
382 : const number& num)
383 : {
384 1123 : BOOST_ASSERT( p != sentinel() );
385 1123 : end_ = p;
386 1123 : if(BOOST_JSON_LIKELY(more_))
387 : {
388 : // suspend
389 1123 : num_ = num;
390 1123 : reserve();
391 1123 : st_.push_unchecked(st);;
392 : }
393 1123 : return sentinel();
394 : }
395 :
396 : template<class Handler>
397 : const char*
398 88657 : basic_parser<Handler>::
399 : suspend(
400 : const char* p,
401 : state st)
402 : {
403 88657 : BOOST_ASSERT( p != sentinel() );
404 88657 : end_ = p;
405 : // suspend
406 88657 : reserve();
407 88657 : st_.push_unchecked(st);
408 88657 : return sentinel();
409 : }
410 :
411 : template<class Handler>
412 : const char*
413 36049 : basic_parser<Handler>::
414 : suspend(
415 : const char* p,
416 : state st,
417 : const number& num)
418 : {
419 36049 : BOOST_ASSERT( p != sentinel() );
420 36049 : end_ = p;
421 : // suspend
422 36049 : num_ = num;
423 36049 : reserve();
424 36049 : st_.push_unchecked(st);
425 36049 : return sentinel();
426 : }
427 :
428 : template<class Handler>
429 : template<
430 : bool StackEmpty_/*,
431 : bool Terminal_*/>
432 : const char*
433 21737 : basic_parser<Handler>::
434 : parse_comment(const char* p,
435 : std::integral_constant<bool, StackEmpty_> stack_empty,
436 : /*std::integral_constant<bool, Terminal_>*/ bool terminal)
437 : {
438 21737 : detail::const_stream_wrapper cs(p, end_);
439 21737 : const char* start = cs.begin();
440 : std::size_t remain;
441 21737 : if(! stack_empty && ! st_.empty())
442 : {
443 : state st;
444 3507 : st_.pop(st);
445 3507 : switch(st)
446 : {
447 0 : default: BOOST_JSON_UNREACHABLE();
448 534 : case state::com1: goto do_com1;
449 2319 : case state::com2: goto do_com2;
450 438 : case state::com3: goto do_com3;
451 216 : case state::com4: goto do_com4;
452 : }
453 : }
454 18230 : BOOST_ASSERT(*cs == '/');
455 18230 : ++cs;
456 18764 : do_com1:
457 18764 : if(BOOST_JSON_UNLIKELY(! cs))
458 551 : return maybe_suspend(cs.begin(), state::com1);
459 18213 : switch(*cs)
460 : {
461 5 : default:
462 : {
463 : BOOST_STATIC_CONSTEXPR source_location loc
464 : = BOOST_CURRENT_LOCATION;
465 5 : return fail(cs.begin(), error::syntax, &loc);
466 : }
467 10524 : case '/':
468 10524 : ++cs;
469 12843 : do_com2:
470 : // KRYSTIAN TODO: this is a mess, we have to fix this
471 12843 : remain = cs.remain();
472 25686 : cs = remain ? static_cast<const char*>(
473 12843 : std::memchr(cs.begin(), '\n', remain)) : sentinel();
474 12843 : if(! cs.begin())
475 2143 : cs = sentinel();
476 12843 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
477 : {
478 : // if the doc does not terminate
479 : // with a newline, treat it as the
480 : // end of the comment
481 2568 : if(terminal && ! more_)
482 : {
483 39 : if(BOOST_JSON_UNLIKELY(! h_.on_comment(
484 : {start, cs.remain(start)}, ec_)))
485 2 : return fail(cs.end());
486 35 : return cs.end();
487 : }
488 2529 : if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
489 : {start, cs.remain(start)}, ec_)))
490 95 : return fail(cs.end());
491 2339 : if(terminal)
492 106 : return suspend(cs.end(), state::com2);
493 2233 : return maybe_suspend(cs.end(), state::com2);
494 : }
495 10275 : break;
496 1684 : case '*':
497 : do
498 : {
499 9368 : ++cs;
500 9806 : do_com3:
501 : // KRYSTIAN TODO: this is a mess, we have to fix this
502 9806 : remain = cs.remain();
503 19612 : cs = remain ? static_cast<const char*>(
504 9806 : std::memchr(cs.begin(), '*', remain)) : sentinel();
505 9806 : if(! cs.begin())
506 242 : cs = sentinel();
507 : // stopped inside a c comment
508 9806 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
509 : {
510 503 : if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511 : {start, cs.remain(start)}, ec_)))
512 30 : return fail(cs.end());
513 443 : return maybe_suspend(cs.end(), state::com3);
514 : }
515 : // found a asterisk, check if the next char is a slash
516 9303 : ++cs;
517 9519 : do_com4:
518 9519 : if(BOOST_JSON_UNLIKELY(! cs))
519 : {
520 259 : if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
521 : {start, cs.used(start)}, ec_)))
522 18 : return fail(cs.begin());
523 223 : return maybe_suspend(cs.begin(), state::com4);
524 : }
525 : }
526 9260 : while(*cs != '/');
527 : }
528 17851 : ++cs;
529 17851 : if(BOOST_JSON_UNLIKELY(! h_.on_comment(
530 : {start, cs.used(start)}, ec_)))
531 964 : return fail(cs.begin());
532 15923 : return cs.begin();
533 : }
534 :
535 : template<class Handler>
536 : template<bool StackEmpty_>
537 : const char*
538 2318364 : basic_parser<Handler>::
539 : parse_document(const char* p,
540 : std::integral_constant<bool, StackEmpty_> stack_empty)
541 : {
542 2318364 : detail::const_stream_wrapper cs(p, end_);
543 2318364 : if(! stack_empty && ! st_.empty())
544 : {
545 : state st;
546 169578 : st_.peek(st);
547 169578 : switch(st)
548 : {
549 83514 : default: goto do_doc2;
550 601 : case state::doc1:
551 601 : st_.pop(st);
552 601 : goto do_doc1;
553 85243 : case state::doc3:
554 85243 : st_.pop(st);
555 85243 : goto do_doc3;
556 220 : case state::com1: case state::com2:
557 : case state::com3: case state::com4:
558 220 : goto do_doc4;
559 : }
560 : }
561 2148786 : do_doc1:
562 2149387 : cs = detail::count_whitespace(cs.begin(), cs.end());
563 2149387 : if(BOOST_JSON_UNLIKELY(! cs))
564 633 : return maybe_suspend(cs.begin(), state::doc1);
565 2148754 : do_doc2:
566 2232268 : switch(+opt_.allow_comments |
567 2232268 : (opt_.allow_trailing_commas << 1) |
568 2232268 : (opt_.allow_invalid_utf8 << 2))
569 : {
570 : // no extensions
571 2208603 : default:
572 2208603 : cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
573 2193445 : break;
574 : // comments
575 13534 : case 1:
576 13534 : cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
577 11271 : break;
578 : // trailing
579 6710 : case 2:
580 6710 : cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
581 5117 : break;
582 : // comments & trailing
583 761 : case 3:
584 761 : cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
585 761 : break;
586 : // skip validation
587 760 : case 4:
588 760 : cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
589 760 : break;
590 : // comments & skip validation
591 760 : case 5:
592 760 : cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
593 760 : break;
594 : // trailing & skip validation
595 760 : case 6:
596 760 : cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
597 760 : break;
598 : // comments & trailing & skip validation
599 380 : case 7:
600 380 : cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
601 380 : break;
602 : }
603 2213254 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
604 : // the appropriate state has already been pushed into stack
605 110691 : return sentinel();
606 2102563 : do_doc3:
607 2188138 : cs = detail::count_whitespace(cs.begin(), cs.end());
608 2188138 : if(BOOST_JSON_UNLIKELY(! cs))
609 : {
610 2185540 : if(more_)
611 88551 : return suspend(cs.begin(), state::doc3);
612 : }
613 2598 : else if(opt_.allow_comments && *cs == '/')
614 : {
615 536 : do_doc4:
616 756 : cs = parse_comment(cs.begin(), stack_empty, std::true_type());
617 671 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
618 339 : return sentinel();
619 332 : goto do_doc3;
620 : }
621 2099051 : return cs.begin();
622 : }
623 :
624 : template<class Handler>
625 : template<
626 : bool StackEmpty_,
627 : bool AllowComments_/*,
628 : bool AllowTrailing_,
629 : bool AllowBadUTF8_*/>
630 : const char*
631 2349846 : basic_parser<Handler>::
632 : parse_value(const char* p,
633 : std::integral_constant<bool, StackEmpty_> stack_empty,
634 : std::integral_constant<bool, AllowComments_> allow_comments,
635 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
636 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
637 : bool allow_bad_utf16)
638 : {
639 2349846 : if(stack_empty || st_.empty())
640 : {
641 2247970 : loop:
642 2252886 : switch(*p)
643 : {
644 22753 : case '0':
645 22753 : return mp11::mp_with_index<3>(
646 22753 : static_cast<unsigned char>(opt_.numbers),
647 22092 : parse_number_helper<true, '0'>{ this, p });
648 25177 : case '-':
649 25177 : return mp11::mp_with_index<3>(
650 25177 : static_cast<unsigned char>(opt_.numbers),
651 24065 : parse_number_helper<true, '-'>{ this, p });
652 2041740 : case '1': case '2': case '3':
653 : case '4': case '5': case '6':
654 : case '7': case '8': case '9':
655 2041740 : return mp11::mp_with_index<3>(
656 2041740 : static_cast<unsigned char>(opt_.numbers),
657 2038896 : parse_number_helper<true, '+'>{ this, p });
658 11378 : case 'n':
659 11378 : return parse_literal( p, mp11::mp_int<detail::null_literal>() );
660 663 : case 't':
661 663 : return parse_literal( p, mp11::mp_int<detail::true_literal>() );
662 722 : case 'f':
663 722 : return parse_literal( p, mp11::mp_int<detail::false_literal>() );
664 681 : case 'I':
665 681 : if( !opt_.allow_infinity_and_nan )
666 : {
667 : BOOST_STATIC_CONSTEXPR source_location loc
668 : = BOOST_CURRENT_LOCATION;
669 24 : return fail(p, error::syntax, &loc);
670 : }
671 657 : return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
672 231 : case 'N':
673 231 : if( !opt_.allow_infinity_and_nan )
674 : {
675 : BOOST_STATIC_CONSTEXPR source_location loc
676 : = BOOST_CURRENT_LOCATION;
677 30 : return fail(p, error::syntax, &loc);
678 : }
679 201 : return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
680 47571 : case '"':
681 47571 : return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
682 20605 : case '[':
683 20605 : return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
684 74123 : case '{':
685 74123 : return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
686 6125 : case '/':
687 6125 : if(! allow_comments)
688 : {
689 : BOOST_STATIC_CONSTEXPR source_location loc
690 : = BOOST_CURRENT_LOCATION;
691 284 : return fail(p, error::syntax, &loc);
692 : }
693 5841 : p = parse_comment(p, stack_empty, std::false_type());
694 : // KRYSTIAN NOTE: incomplete takes const_stream, we either
695 : // can add an overload, change the existing one to take a pointer,
696 : // or just leave it as is
697 5605 : if(BOOST_JSON_UNLIKELY(p == sentinel()))
698 591 : return maybe_suspend(p, state::val2);
699 : // intentional fallthrough
700 : case ' ':
701 : case '\t':
702 : case '\n':
703 : case '\r':
704 5026 : p = detail::count_whitespace(p, end_);
705 5026 : if(BOOST_JSON_UNLIKELY(p == end_))
706 110 : return maybe_suspend(p, state::val1);
707 4916 : goto loop;
708 1105 : default:
709 : {
710 : BOOST_STATIC_CONSTEXPR source_location loc
711 : = BOOST_CURRENT_LOCATION;
712 1105 : return fail(p, error::syntax, &loc);
713 : }
714 : }
715 : }
716 101876 : return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
717 : }
718 :
719 : template<class Handler>
720 : template<
721 : bool AllowComments_/*,
722 : bool AllowTrailing_,
723 : bool AllowBadUTF8_*/>
724 : const char*
725 101876 : basic_parser<Handler>::
726 : resume_value(const char* p,
727 : std::integral_constant<bool, AllowComments_> allow_comments,
728 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
729 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
730 : bool allow_bad_utf16)
731 : {
732 : state st;
733 101876 : st_.peek(st);
734 101876 : switch(st)
735 : {
736 0 : default: BOOST_JSON_UNREACHABLE();
737 1924 : case state::lit1:
738 1924 : return parse_literal(p, mp11::mp_int<detail::resume_literal>() );
739 :
740 20256 : case state::str1: case state::str2:
741 : case state::str8:
742 20256 : return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
743 :
744 5705 : case state::arr1: case state::arr2:
745 : case state::arr3: case state::arr4:
746 : case state::arr5: case state::arr6:
747 5705 : return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
748 :
749 35039 : case state::obj1: case state::obj2:
750 : case state::obj3: case state::obj4:
751 : case state::obj5: case state::obj6:
752 : case state::obj7: case state::obj8:
753 : case state::obj9: case state::obj10:
754 : case state::obj11:
755 35039 : return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
756 :
757 37169 : case state::num1: case state::num2:
758 : case state::num3: case state::num4:
759 : case state::num5: case state::num6:
760 : case state::num7: case state::num8:
761 : case state::exp1: case state::exp2:
762 : case state::exp3:
763 37169 : return mp11::mp_with_index<3>(
764 37169 : static_cast<unsigned char>(opt_.numbers),
765 36346 : parse_number_helper<false, 0>{ this, p });
766 :
767 : // KRYSTIAN NOTE: these are special cases
768 108 : case state::val1:
769 : {
770 108 : st_.pop(st);
771 108 : BOOST_ASSERT(st_.empty());
772 108 : p = detail::count_whitespace(p, end_);
773 108 : if(BOOST_JSON_UNLIKELY(p == end_))
774 0 : return maybe_suspend(p, state::val1);
775 108 : return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
776 : }
777 :
778 1608 : case state::val2:
779 : {
780 1608 : st_.pop(st);
781 1608 : p = parse_comment(p, std::false_type(), std::false_type());
782 1590 : if(BOOST_JSON_UNLIKELY(p == sentinel()))
783 1274 : return maybe_suspend(p, state::val2);
784 316 : if(BOOST_JSON_UNLIKELY( p == end_ ))
785 77 : return maybe_suspend(p, state::val3);
786 239 : BOOST_ASSERT(st_.empty());
787 239 : return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
788 : }
789 :
790 67 : case state::val3:
791 : {
792 67 : st_.pop(st);
793 67 : return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
794 : }
795 : }
796 : }
797 :
798 : template<class Handler>
799 : template<int Literal>
800 : const char*
801 16561 : basic_parser<Handler>::
802 : parse_literal(const char* p,
803 : std::integral_constant<int, Literal> literal)
804 : {
805 16561 : constexpr char const* literals[] = {
806 : "null",
807 : "true",
808 : "false",
809 : "Infinity",
810 : "-Infinity",
811 : "NaN",
812 : };
813 :
814 16561 : constexpr std::size_t literal_sizes[] = {
815 : 4,
816 : 4,
817 : 5,
818 : 8,
819 : 9,
820 : 3,
821 : };
822 :
823 : std::size_t cur_lit;
824 : std::size_t offset;
825 :
826 16561 : detail::const_stream_wrapper cs(p, end_);
827 16561 : BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
828 : {
829 0 : BOOST_ASSERT( literal >= 0 );
830 13630 : if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
831 : {
832 11980 : int const cmp = std::memcmp(
833 11980 : cs.begin(), literals[literal], literal_sizes[literal] );
834 11980 : if( cmp != 0 )
835 : {
836 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
837 197 : return fail(cs.begin(), error::syntax, &loc);
838 : }
839 :
840 11783 : BOOST_IF_CONSTEXPR( literal == detail::null_literal )
841 : {
842 10786 : if(BOOST_JSON_UNLIKELY(
843 : ! h_.on_null(ec_)))
844 160 : return fail(cs.begin());
845 : }
846 997 : else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
847 : {
848 383 : if(BOOST_JSON_UNLIKELY(
849 : ! h_.on_bool(true, ec_)))
850 13 : return fail(cs.begin());
851 : }
852 614 : else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
853 : {
854 406 : if(BOOST_JSON_UNLIKELY(
855 : ! h_.on_bool(false, ec_)))
856 13 : return fail(cs.begin());
857 : }
858 208 : else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
859 : {
860 103 : if(BOOST_JSON_UNLIKELY(
861 : ! h_.on_double(
862 : std::numeric_limits<double>::infinity(),
863 : string_view(
864 : literals[detail::infinity_literal],
865 : literal_sizes[detail::infinity_literal]),
866 : ec_)))
867 13 : return fail(cs.begin());
868 : }
869 105 : else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
870 : {
871 9 : if(BOOST_JSON_UNLIKELY(
872 : ! h_.on_double(
873 : -std::numeric_limits<double>::infinity(),
874 : string_view(
875 : literals[detail::neg_infinity_literal],
876 : literal_sizes[detail::neg_infinity_literal]),
877 : ec_)))
878 1 : return fail(cs.begin());
879 : }
880 96 : else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
881 : {
882 96 : if(BOOST_JSON_UNLIKELY(
883 : ! h_.on_double(
884 : std::numeric_limits<double>::quiet_NaN(),
885 : string_view(
886 : literals[detail::nan_literal],
887 : literal_sizes[detail::nan_literal]),
888 : ec_)))
889 12 : return fail(cs.begin());
890 : }
891 : else
892 : {
893 0 : BOOST_JSON_UNREACHABLE();
894 : }
895 :
896 11361 : cs += literal_sizes[literal];
897 11361 : return cs.begin();
898 : }
899 :
900 1650 : offset = 0;
901 1650 : cur_lit = literal;
902 : }
903 : else
904 : {
905 : state st;
906 2931 : st_.pop(st);
907 2931 : BOOST_ASSERT( st == state::lit1 );
908 :
909 2931 : cur_lit = cur_lit_;
910 2931 : offset = lit_offset_;
911 : }
912 :
913 9162 : std::size_t const size = (std::min)(
914 4581 : literal_sizes[cur_lit] - offset, cs.remain() );
915 4581 : int cmp = 0;
916 4581 : if(BOOST_JSON_LIKELY( cs.begin() ))
917 4580 : cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
918 4581 : if( cmp != 0 )
919 : {
920 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
921 699 : return fail(cs.begin(), error::syntax, &loc);
922 : }
923 :
924 3882 : if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
925 : {
926 1990 : BOOST_ASSERT( cur_lit < 256 );
927 1990 : cur_lit_ = static_cast<unsigned char>( cur_lit );
928 1990 : BOOST_ASSERT( offset + size < 256 );
929 1990 : lit_offset_ = static_cast<unsigned char>( offset + size );
930 1990 : return maybe_suspend(cs.begin() + size, state::lit1);
931 : }
932 :
933 1892 : switch( cur_lit )
934 : {
935 472 : case detail::null_literal:
936 472 : if(BOOST_JSON_UNLIKELY(
937 : ! h_.on_null(ec_)))
938 61 : return fail(cs.begin());
939 351 : break;
940 152 : case detail::true_literal:
941 152 : if(BOOST_JSON_UNLIKELY(
942 : ! h_.on_bool(true, ec_)))
943 22 : return fail(cs.begin());
944 109 : break;
945 198 : case detail::false_literal:
946 198 : if(BOOST_JSON_UNLIKELY(
947 : ! h_.on_bool(false, ec_)))
948 28 : return fail(cs.begin());
949 142 : break;
950 308 : case detail::infinity_literal:
951 308 : if(BOOST_JSON_UNLIKELY(
952 : ! h_.on_double(
953 : std::numeric_limits<double>::infinity(),
954 : string_view(
955 : literals[detail::infinity_literal],
956 : literal_sizes[detail::infinity_literal]),
957 : ec_)))
958 49 : return fail(cs.begin());
959 210 : break;
960 686 : case detail::neg_infinity_literal:
961 686 : if(BOOST_JSON_UNLIKELY(
962 : ! h_.on_double(
963 : -std::numeric_limits<double>::infinity(),
964 : string_view(
965 : literals[detail::neg_infinity_literal],
966 : literal_sizes[detail::neg_infinity_literal]),
967 : ec_)))
968 102 : return fail(cs.begin());
969 482 : break;
970 76 : case detail::nan_literal:
971 76 : if(BOOST_JSON_UNLIKELY(
972 : ! h_.on_double(
973 : std::numeric_limits<double>::quiet_NaN(),
974 : string_view(
975 : literals[detail::nan_literal],
976 : literal_sizes[detail::nan_literal]),
977 : ec_)))
978 12 : return fail(cs.begin());
979 52 : break;
980 0 : default: BOOST_JSON_UNREACHABLE();
981 : }
982 :
983 1346 : cs += size;
984 1346 : return cs.begin();
985 : }
986 :
987 : //----------------------------------------------------------
988 :
989 : template<class Handler>
990 : template<bool StackEmpty_, bool IsKey_>
991 : const char*
992 161284 : basic_parser<Handler>::
993 : parse_string(const char* p,
994 : std::integral_constant<bool, StackEmpty_> stack_empty,
995 : std::integral_constant<bool, IsKey_> is_key,
996 : bool allow_bad_utf8,
997 : bool allow_bad_utf16)
998 : {
999 161284 : detail::const_stream_wrapper cs(p, end_);
1000 : std::size_t total;
1001 : char const* start;
1002 : std::size_t size;
1003 161284 : if(! stack_empty && ! st_.empty())
1004 : {
1005 : state st;
1006 32892 : st_.pop(st);
1007 32892 : st_.pop(total);
1008 32892 : switch(st)
1009 : {
1010 0 : default: BOOST_JSON_UNREACHABLE();
1011 3149 : case state::str2: goto do_str2;
1012 1861 : case state::str8: goto do_str8;
1013 27882 : case state::str1: break;
1014 : }
1015 : }
1016 : else
1017 : {
1018 128392 : BOOST_ASSERT(*cs == '\x22'); // '"'
1019 128392 : ++cs;
1020 128392 : total = 0;
1021 : }
1022 :
1023 164766 : do_str1:
1024 164766 : start = cs.begin();
1025 329532 : cs = allow_bad_utf8?
1026 2177 : detail::count_valid<true>(cs.begin(), cs.end()):
1027 162589 : detail::count_valid<false>(cs.begin(), cs.end());
1028 164766 : size = cs.used(start);
1029 164766 : if(is_key)
1030 : {
1031 46677 : BOOST_ASSERT(total <= Handler::max_key_size);
1032 93988 : if(BOOST_JSON_UNLIKELY(size >
1033 : Handler::max_key_size - total))
1034 : {
1035 : BOOST_STATIC_CONSTEXPR source_location loc
1036 : = BOOST_CURRENT_LOCATION;
1037 3 : return fail(cs.begin(), error::key_too_large, &loc);
1038 : }
1039 : }
1040 : else
1041 : {
1042 35316 : BOOST_ASSERT(total <= Handler::max_string_size);
1043 70778 : if(BOOST_JSON_UNLIKELY(size >
1044 : Handler::max_string_size - total))
1045 : {
1046 : BOOST_STATIC_CONSTEXPR source_location loc
1047 : = BOOST_CURRENT_LOCATION;
1048 3 : return fail(cs.begin(), error::string_too_large, &loc);
1049 : }
1050 : }
1051 164760 : total += size;
1052 164760 : if(BOOST_JSON_UNLIKELY(! cs))
1053 : {
1054 : // call handler if the string isn't empty
1055 30216 : if(BOOST_JSON_LIKELY(size))
1056 : {
1057 : {
1058 27060 : bool r = is_key?
1059 12399 : h_.on_key_part( {start, size}, total, ec_ ):
1060 15995 : h_.on_string_part( {start, size}, total, ec_ );
1061 :
1062 25952 : if(BOOST_JSON_UNLIKELY(!r))
1063 : {
1064 1110 : return fail(cs.begin());
1065 : }
1066 : }
1067 : }
1068 27998 : return maybe_suspend(cs.begin(), state::str1, total);
1069 : }
1070 : // at this point all valid characters have been skipped, so any remaining
1071 : // if there are any more characters, they are either escaped, or incomplete
1072 : // utf8, or invalid utf8
1073 134544 : if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1074 : {
1075 : // sequence is invalid or incomplete
1076 15068 : if((*cs & 0x80) && !allow_bad_utf8)
1077 : {
1078 3462 : seq_.save(cs.begin(), cs.remain());
1079 3462 : if(BOOST_JSON_UNLIKELY(seq_.complete()))
1080 : {
1081 : BOOST_STATIC_CONSTEXPR source_location loc
1082 : = BOOST_CURRENT_LOCATION;
1083 1557 : return fail(cs.begin(), error::syntax, &loc);
1084 : }
1085 1905 : if(BOOST_JSON_LIKELY(size))
1086 : {
1087 245 : bool const r = is_key?
1088 22 : h_.on_key_part( {start, size}, total, ec_ ):
1089 245 : h_.on_string_part( {start, size}, total, ec_ );
1090 223 : if(BOOST_JSON_UNLIKELY( !r ))
1091 22 : return fail( cs.begin() );
1092 : }
1093 1861 : return maybe_suspend(cs.end(), state::str8, total);
1094 : }
1095 11606 : else if(BOOST_JSON_LIKELY(*cs == '\\'))
1096 : {
1097 : // flush unescaped run from input
1098 11497 : if(BOOST_JSON_LIKELY(size))
1099 : {
1100 4250 : bool const r = is_key?
1101 1226 : h_.on_key_part( {start, size}, total, ec_ ):
1102 3554 : h_.on_string_part( {start, size}, total, ec_ );
1103 3766 : if(BOOST_JSON_UNLIKELY( !r ))
1104 484 : return fail( cs.begin() );
1105 : }
1106 7247 : do_str2:
1107 13678 : cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1108 12716 : if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1109 5473 : return suspend_or_fail(state::str2, total);
1110 :
1111 7243 : goto do_str1;
1112 : }
1113 : // illegal control
1114 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1115 109 : return fail(cs.begin(), error::syntax, &loc);
1116 : }
1117 :
1118 : {
1119 119476 : bool r = is_key?
1120 84505 : h_.on_key( {start, size}, total, ec_ ):
1121 41980 : h_.on_string( {start, size}, total, ec_ );
1122 :
1123 115102 : if(BOOST_JSON_UNLIKELY(!r))
1124 : {
1125 4313 : return fail(cs.begin());
1126 : }
1127 : }
1128 :
1129 110789 : ++cs;
1130 110789 : return cs.begin();
1131 :
1132 1861 : do_str8:
1133 1861 : uint8_t needed = seq_.needed();
1134 1861 : if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1135 0 : return maybe_suspend(cs.end(), state::str8, total);
1136 1861 : if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1137 : {
1138 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1139 210 : return fail(cs.begin(), error::syntax, &loc);
1140 : }
1141 : {
1142 1651 : bool const r = is_key?
1143 201 : h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1144 1651 : h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1145 1450 : if(BOOST_JSON_UNLIKELY( !r ))
1146 201 : return fail( cs.begin() );
1147 : }
1148 1249 : cs += needed;
1149 1249 : goto do_str1;
1150 : }
1151 :
1152 : template<class Handler>
1153 : template<bool StackEmpty_>
1154 : const char*
1155 13678 : basic_parser<Handler>::
1156 : parse_escaped(
1157 : const char* p,
1158 : std::size_t& total,
1159 : std::integral_constant<bool, StackEmpty_> stack_empty,
1160 : bool is_key,
1161 : bool allow_bad_utf16)
1162 : {
1163 13678 : constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1164 13678 : auto const ev_too_large = is_key?
1165 : error::key_too_large : error::string_too_large;
1166 13678 : auto const max_size = is_key?
1167 : Handler::max_key_size : Handler::max_string_size;
1168 : int digit;
1169 :
1170 : //---------------------------------------------------------------
1171 : //
1172 : // To handle escapes, a local temporary buffer accumulates
1173 : // the unescaped result. The algorithm attempts to fill the
1174 : // buffer to capacity before invoking the handler.
1175 : // In some cases the temporary buffer needs to be flushed
1176 : // before it is full:
1177 : // * When the closing double quote is seen
1178 : // * When there in no more input (and more is expected later)
1179 : // A goal of the algorithm is to call the handler as few times
1180 : // as possible. Thus, when the first escape is encountered,
1181 : // the algorithm attempts to fill the temporary buffer first.
1182 : //
1183 13678 : detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1184 :
1185 : // Unescaped JSON is never larger than its escaped version.
1186 : // To efficiently process only what will fit in the temporary buffer,
1187 : // the size of the input stream is temporarily "clipped" to the size
1188 : // of the temporary buffer.
1189 : // handle escaped character
1190 13678 : detail::clipped_const_stream cs(p, end_);
1191 13678 : cs.clip(temp.max_size());
1192 :
1193 13678 : if(! stack_empty && ! st_.empty())
1194 : {
1195 : state st;
1196 3149 : st_.pop(st);
1197 3149 : switch(st)
1198 : {
1199 0 : default: BOOST_JSON_UNREACHABLE();
1200 528 : case state::str3: goto do_str3;
1201 392 : case state::str4: goto do_str4;
1202 390 : case state::str5: goto do_str5;
1203 389 : case state::str6: goto do_str6;
1204 386 : case state::str7: goto do_str7;
1205 232 : case state::sur1: goto do_sur1;
1206 188 : case state::sur2: goto do_sur2;
1207 164 : case state::sur3: goto do_sur3;
1208 162 : case state::sur4: goto do_sur4;
1209 160 : case state::sur5: goto do_sur5;
1210 158 : case state::sur6: goto do_sur6;
1211 : }
1212 : }
1213 :
1214 3781 : while(true)
1215 : {
1216 14310 : BOOST_ASSERT( temp.capacity() );
1217 14310 : BOOST_ASSERT(*cs == '\\');
1218 14310 : ++cs;
1219 15169 : do_str3:
1220 15374 : if(BOOST_JSON_UNLIKELY(! cs))
1221 : {
1222 561 : if(BOOST_JSON_LIKELY(! temp.empty()))
1223 : {
1224 0 : BOOST_ASSERT(total <= max_size);
1225 100 : if(BOOST_JSON_UNLIKELY(
1226 : temp.size() > max_size - total))
1227 : {
1228 : BOOST_STATIC_CONSTEXPR source_location loc
1229 : = BOOST_CURRENT_LOCATION;
1230 0 : return fail(cs.begin(), ev_too_large, &loc);
1231 : }
1232 100 : total += temp.size();
1233 : {
1234 91 : bool r = is_key
1235 100 : ? h_.on_key_part(temp.get(), total, ec_)
1236 100 : : h_.on_string_part(temp.get(), total, ec_);
1237 :
1238 91 : if(BOOST_JSON_UNLIKELY(!r))
1239 : {
1240 9 : return fail(cs.begin());
1241 : }
1242 : }
1243 82 : temp.clear();
1244 : }
1245 543 : cs.clip(temp.max_size());
1246 543 : if(BOOST_JSON_UNLIKELY(! cs))
1247 543 : return maybe_suspend(cs.begin(), state::str3);
1248 : }
1249 14813 : switch(*cs)
1250 : {
1251 191 : default:
1252 : {
1253 : BOOST_STATIC_CONSTEXPR source_location loc
1254 : = BOOST_CURRENT_LOCATION;
1255 191 : return fail(cs.begin(), error::syntax, &loc);
1256 : }
1257 265 : case '\x22': // '"'
1258 265 : temp.push_back('\x22');
1259 265 : ++cs;
1260 265 : break;
1261 178 : case '\\':
1262 178 : temp.push_back('\\');
1263 178 : ++cs;
1264 178 : break;
1265 96 : case '/':
1266 96 : temp.push_back('/');
1267 96 : ++cs;
1268 96 : break;
1269 112 : case 'b':
1270 112 : temp.push_back('\x08');
1271 112 : ++cs;
1272 112 : break;
1273 108 : case 'f':
1274 108 : temp.push_back('\x0c');
1275 108 : ++cs;
1276 108 : break;
1277 1763 : case 'n':
1278 1763 : temp.push_back('\x0a');
1279 1763 : ++cs;
1280 1763 : break;
1281 146 : case 'r':
1282 146 : temp.push_back('\x0d');
1283 146 : ++cs;
1284 146 : break;
1285 266 : case 't':
1286 266 : temp.push_back('\x09');
1287 266 : ++cs;
1288 266 : break;
1289 11688 : case 'u':
1290 : // utf16 escape
1291 : //
1292 : // fast path only when the buffer
1293 : // is large enough for 2 surrogates
1294 11688 : if(BOOST_JSON_LIKELY(cs.remain() > 10))
1295 : {
1296 : // KRYSTIAN TODO: this could be done
1297 : // with fewer instructions
1298 11394 : digit = detail::load_little_endian<4>(
1299 5697 : cs.begin() + 1);
1300 5697 : int d4 = detail::hex_digit(static_cast<
1301 5697 : unsigned char>(digit >> 24));
1302 5697 : int d3 = detail::hex_digit(static_cast<
1303 5697 : unsigned char>(digit >> 16));
1304 5697 : int d2 = detail::hex_digit(static_cast<
1305 5697 : unsigned char>(digit >> 8));
1306 5697 : int d1 = detail::hex_digit(static_cast<
1307 : unsigned char>(digit));
1308 5697 : if(BOOST_JSON_UNLIKELY(
1309 : (d1 | d2 | d3 | d4) == -1))
1310 : {
1311 60 : if(d1 != -1)
1312 45 : ++cs;
1313 60 : if(d2 != -1)
1314 30 : ++cs;
1315 60 : if(d3 != -1)
1316 15 : ++cs;
1317 : BOOST_STATIC_CONSTEXPR source_location loc
1318 : = BOOST_CURRENT_LOCATION;
1319 60 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1320 : }
1321 : // 32 bit unicode scalar value
1322 5637 : unsigned u1 =
1323 5637 : (d1 << 12) + (d2 << 8) +
1324 5637 : (d3 << 4) + d4;
1325 : // valid unicode scalar values are
1326 : // [0, D7FF] and [E000, 10FFFF]
1327 : // values within this range are valid utf-8
1328 : // code points and invalid leading surrogates.
1329 5637 : if(BOOST_JSON_LIKELY(
1330 : u1 < 0xd800 || u1 > 0xdfff))
1331 : {
1332 1340 : cs += 5;
1333 1340 : temp.append_utf8(u1);
1334 1340 : break;
1335 : }
1336 4297 : if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1337 : {
1338 : // If it's an illegal leading surrogate and
1339 : // the parser does not allow it, return an error.
1340 707 : if(!allow_bad_utf16)
1341 : {
1342 : BOOST_STATIC_CONSTEXPR source_location loc
1343 : = BOOST_CURRENT_LOCATION;
1344 122 : return fail(cs.begin(), error::illegal_leading_surrogate,
1345 122 : &loc);
1346 : }
1347 : // Otherwise, append the Unicode replacement character
1348 : else
1349 : {
1350 585 : cs += 5;
1351 585 : temp.append_utf8(urc);
1352 585 : break;
1353 : }
1354 : }
1355 3590 : cs += 5;
1356 : // KRYSTIAN TODO: this can be a two byte load
1357 : // and a single comparison. We lose error information,
1358 : // but it's faster.
1359 3590 : if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1360 : {
1361 : // If the next character is not a backslash and
1362 : // the parser does not allow it, return a syntax error.
1363 156 : if(!allow_bad_utf16)
1364 : {
1365 : BOOST_STATIC_CONSTEXPR source_location loc
1366 : = BOOST_CURRENT_LOCATION;
1367 15 : return fail(cs.begin(), error::syntax, &loc);
1368 : }
1369 : // Otherwise, append the Unicode replacement character since
1370 : // the first code point is a valid leading surrogate
1371 : else
1372 : {
1373 141 : temp.append_utf8(urc);
1374 141 : break;
1375 : }
1376 : }
1377 3434 : ++cs;
1378 3434 : if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1379 : {
1380 220 : if (!allow_bad_utf16)
1381 : {
1382 : BOOST_STATIC_CONSTEXPR source_location loc
1383 : = BOOST_CURRENT_LOCATION;
1384 15 : return fail(cs.begin(), error::syntax, &loc);
1385 : }
1386 : // Otherwise, append the Unicode replacement character since
1387 : // the first code point is a valid leading surrogate
1388 : else
1389 : {
1390 205 : temp.append_utf8(urc);
1391 205 : goto do_str3;
1392 : }
1393 : }
1394 3214 : ++cs;
1395 3214 : digit = detail::load_little_endian<4>(cs.begin());
1396 3214 : d4 = detail::hex_digit(static_cast<
1397 3214 : unsigned char>(digit >> 24));
1398 3214 : d3 = detail::hex_digit(static_cast<
1399 3214 : unsigned char>(digit >> 16));
1400 3214 : d2 = detail::hex_digit(static_cast<
1401 3214 : unsigned char>(digit >> 8));
1402 3214 : d1 = detail::hex_digit(static_cast<
1403 : unsigned char>(digit));
1404 3214 : if(BOOST_JSON_UNLIKELY(
1405 : (d1 | d2 | d3 | d4) == -1))
1406 : {
1407 90 : if(d1 != -1)
1408 75 : ++cs;
1409 90 : if(d2 != -1)
1410 45 : ++cs;
1411 90 : if(d3 != -1)
1412 15 : ++cs;
1413 : BOOST_STATIC_CONSTEXPR source_location loc
1414 : = BOOST_CURRENT_LOCATION;
1415 90 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1416 : }
1417 3124 : unsigned u2 =
1418 3124 : (d1 << 12) + (d2 << 8) +
1419 3124 : (d3 << 4) + d4;
1420 : // Check if the second code point is a valid trailing surrogate.
1421 : // Valid trailing surrogates are [DC00, DFFF]
1422 3124 : if(BOOST_JSON_UNLIKELY(
1423 : u2 < 0xdc00 || u2 > 0xdfff))
1424 : {
1425 : // If not valid and the parser does not allow it, return an error.
1426 1353 : if(!allow_bad_utf16)
1427 : {
1428 : BOOST_STATIC_CONSTEXPR source_location loc
1429 : = BOOST_CURRENT_LOCATION;
1430 136 : return fail(cs.begin(), error::illegal_trailing_surrogate,
1431 136 : &loc);
1432 : }
1433 : // Append the replacement character for the
1434 : // first leading surrogate.
1435 1217 : cs += 4;
1436 1217 : temp.append_utf8(urc);
1437 : // Check if the second code point is a
1438 : // valid unicode scalar value (invalid leading
1439 : // or trailing surrogate)
1440 1217 : if (u2 < 0xd800 || u2 > 0xdbff)
1441 : {
1442 524 : temp.append_utf8(u2);
1443 524 : break;
1444 : }
1445 : // If it is a valid leading surrogate
1446 : else
1447 : {
1448 693 : u1_ = u2;
1449 693 : goto do_sur1;
1450 : }
1451 : }
1452 1771 : cs += 4;
1453 : // Calculate the Unicode code point from the surrogate pair and
1454 : // append the UTF-8 representation.
1455 1771 : unsigned cp =
1456 1771 : ((u1 - 0xd800) << 10) +
1457 : ((u2 - 0xdc00)) +
1458 : 0x10000;
1459 : // utf-16 surrogate pair
1460 1771 : temp.append_utf8(cp);
1461 1771 : break;
1462 : }
1463 : // flush
1464 5991 : if(BOOST_JSON_LIKELY(! temp.empty()))
1465 : {
1466 3 : BOOST_ASSERT(total <= max_size);
1467 1722 : if(BOOST_JSON_UNLIKELY(
1468 : temp.size() > max_size - total))
1469 : {
1470 : BOOST_STATIC_CONSTEXPR source_location loc
1471 : = BOOST_CURRENT_LOCATION;
1472 0 : return fail(cs.begin(), ev_too_large, &loc);
1473 : }
1474 1722 : total += temp.size();
1475 : {
1476 1582 : bool r = is_key
1477 1722 : ? h_.on_key_part(temp.get(), total, ec_)
1478 1722 : : h_.on_string_part(temp.get(), total, ec_);
1479 :
1480 1582 : if(BOOST_JSON_UNLIKELY(!r))
1481 : {
1482 140 : return fail(cs.begin());
1483 : }
1484 : }
1485 1442 : temp.clear();
1486 1442 : cs.clip(temp.max_size());
1487 : }
1488 5711 : ++cs;
1489 : // utf-16 escape
1490 6103 : do_str4:
1491 6103 : if(BOOST_JSON_UNLIKELY(! cs))
1492 392 : return maybe_suspend(cs.begin(), state::str4);
1493 5711 : digit = detail::hex_digit(*cs);
1494 5711 : if(BOOST_JSON_UNLIKELY(digit == -1))
1495 : {
1496 : BOOST_STATIC_CONSTEXPR source_location loc
1497 : = BOOST_CURRENT_LOCATION;
1498 50 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1499 : }
1500 5661 : ++cs;
1501 5661 : u1_ = digit << 12;
1502 6051 : do_str5:
1503 6051 : if(BOOST_JSON_UNLIKELY(! cs))
1504 390 : return maybe_suspend(cs.begin(), state::str5);
1505 5661 : digit = detail::hex_digit(*cs);
1506 5661 : if(BOOST_JSON_UNLIKELY(digit == -1))
1507 : {
1508 : BOOST_STATIC_CONSTEXPR source_location loc
1509 : = BOOST_CURRENT_LOCATION;
1510 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1511 : }
1512 5641 : ++cs;
1513 5641 : u1_ += digit << 8;
1514 6030 : do_str6:
1515 6030 : if(BOOST_JSON_UNLIKELY(! cs))
1516 389 : return maybe_suspend(cs.begin(), state::str6);
1517 5641 : digit = detail::hex_digit(*cs);
1518 5641 : if(BOOST_JSON_UNLIKELY(digit == -1))
1519 : {
1520 : BOOST_STATIC_CONSTEXPR source_location loc
1521 : = BOOST_CURRENT_LOCATION;
1522 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1523 : }
1524 5621 : ++cs;
1525 5621 : u1_ += digit << 4;
1526 6007 : do_str7:
1527 6007 : if(BOOST_JSON_UNLIKELY(! cs))
1528 386 : return maybe_suspend(cs.begin(), state::str7);
1529 5621 : digit = detail::hex_digit(*cs);
1530 5621 : if(BOOST_JSON_UNLIKELY(digit == -1))
1531 : {
1532 : BOOST_STATIC_CONSTEXPR source_location loc
1533 : = BOOST_CURRENT_LOCATION;
1534 35 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1535 : }
1536 5586 : ++cs;
1537 5586 : u1_ += digit;
1538 5586 : if(BOOST_JSON_LIKELY(
1539 : u1_ < 0xd800 || u1_ > 0xdfff))
1540 : {
1541 1434 : BOOST_ASSERT(temp.empty());
1542 : // utf-8 codepoint
1543 1434 : temp.append_utf8(u1_);
1544 1434 : break;
1545 : }
1546 4152 : if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1547 : {
1548 : // If it's an illegal leading surrogate and
1549 : // the parser does not allow it, return an error.
1550 1585 : if(!allow_bad_utf16)
1551 : {
1552 : BOOST_STATIC_CONSTEXPR source_location loc
1553 : = BOOST_CURRENT_LOCATION;
1554 209 : return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1555 : }
1556 : // Otherwise, append the Unicode replacement character
1557 : else
1558 : {
1559 1376 : BOOST_ASSERT(temp.empty());
1560 1376 : temp.append_utf8(urc);
1561 1376 : break;
1562 : }
1563 : }
1564 2567 : do_sur1:
1565 3792 : if(BOOST_JSON_UNLIKELY(! cs))
1566 232 : return maybe_suspend(cs.begin(), state::sur1);
1567 3560 : if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1568 : {
1569 : // If the next character is not a backslash and
1570 : // the parser does not allow it, return a syntax error.
1571 952 : if(!allow_bad_utf16)
1572 : {
1573 : BOOST_STATIC_CONSTEXPR source_location loc
1574 : = BOOST_CURRENT_LOCATION;
1575 149 : return fail(cs.begin(), error::syntax, &loc);
1576 : }
1577 : // Otherwise, append the Unicode replacement character since
1578 : // the first code point is a valid leading surrogate
1579 : else
1580 : {
1581 803 : temp.append_utf8(urc);
1582 803 : break;
1583 : }
1584 : }
1585 2608 : ++cs;
1586 2796 : do_sur2:
1587 2796 : if(BOOST_JSON_UNLIKELY(! cs))
1588 188 : return maybe_suspend(cs.begin(), state::sur2);
1589 2608 : if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1590 : {
1591 396 : if (!allow_bad_utf16)
1592 : {
1593 : BOOST_STATIC_CONSTEXPR source_location loc
1594 : = BOOST_CURRENT_LOCATION;
1595 65 : return fail(cs.begin(), error::syntax, &loc);
1596 : }
1597 : // Otherwise, append the Unicode replacement character since
1598 : // the first code point is a valid leading surrogate
1599 : else
1600 : {
1601 331 : temp.append_utf8(urc);
1602 331 : goto do_str3;
1603 : }
1604 : }
1605 2212 : ++cs;
1606 2376 : do_sur3:
1607 2376 : if(BOOST_JSON_UNLIKELY(! cs))
1608 164 : return maybe_suspend(cs.begin(), state::sur3);
1609 2212 : digit = detail::hex_digit(*cs);
1610 2212 : if(BOOST_JSON_UNLIKELY(digit == -1))
1611 : {
1612 : BOOST_STATIC_CONSTEXPR source_location loc
1613 : = BOOST_CURRENT_LOCATION;
1614 35 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1615 : }
1616 2177 : ++cs;
1617 2177 : u2_ = digit << 12;
1618 2339 : do_sur4:
1619 2339 : if(BOOST_JSON_UNLIKELY(! cs))
1620 162 : return maybe_suspend(cs.begin(), state::sur4);
1621 2177 : digit = detail::hex_digit(*cs);
1622 2177 : if(BOOST_JSON_UNLIKELY(digit == -1))
1623 : {
1624 : BOOST_STATIC_CONSTEXPR source_location loc
1625 : = BOOST_CURRENT_LOCATION;
1626 35 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1627 : }
1628 2142 : ++cs;
1629 2142 : u2_ += digit << 8;
1630 2302 : do_sur5:
1631 2302 : if(BOOST_JSON_UNLIKELY(! cs))
1632 160 : return maybe_suspend(cs.begin(), state::sur5);
1633 2142 : digit = detail::hex_digit(*cs);
1634 2142 : if(BOOST_JSON_UNLIKELY(digit == -1))
1635 : {
1636 : BOOST_STATIC_CONSTEXPR source_location loc
1637 : = BOOST_CURRENT_LOCATION;
1638 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1639 : }
1640 2122 : ++cs;
1641 2122 : u2_ += digit << 4;
1642 2280 : do_sur6:
1643 2280 : if(BOOST_JSON_UNLIKELY(! cs))
1644 158 : return maybe_suspend(cs.begin(), state::sur6);
1645 2122 : digit = detail::hex_digit(*cs);
1646 2122 : if(BOOST_JSON_UNLIKELY(digit == -1))
1647 : {
1648 : BOOST_STATIC_CONSTEXPR source_location loc
1649 : = BOOST_CURRENT_LOCATION;
1650 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1651 : }
1652 2102 : ++cs;
1653 2102 : u2_ += digit;
1654 : // Check if the second code point is a valid trailing surrogate.
1655 : // Valid trailing surrogates are [DC00, DFFF]
1656 2102 : if(BOOST_JSON_UNLIKELY(
1657 : u2_ < 0xdc00 || u2_ > 0xdfff))
1658 : {
1659 : // If not valid and the parser does not allow it, return an error.
1660 580 : if(!allow_bad_utf16)
1661 : {
1662 : BOOST_STATIC_CONSTEXPR source_location loc
1663 : = BOOST_CURRENT_LOCATION;
1664 60 : return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1665 : }
1666 : // Append the replacement character for the
1667 : // first leading surrogate.
1668 520 : temp.append_utf8(urc);
1669 : // Check if the second code point is a
1670 : // valid unicode scalar value (invalid leading
1671 : // or trailing surrogate)
1672 520 : if (u2_ < 0xd800 || u2_ > 0xdbff)
1673 : {
1674 220 : temp.append_utf8(u2_);
1675 220 : break;
1676 : }
1677 : // If it is a valid leading surrogate
1678 : else
1679 : {
1680 300 : u1_ = u2_;
1681 300 : goto do_sur1;
1682 : }
1683 : }
1684 : // Calculate the Unicode code point from the surrogate pair and
1685 : // append the UTF-8 representation.
1686 1522 : unsigned cp =
1687 1522 : ((u1_ - 0xd800) << 10) +
1688 1522 : ((u2_ - 0xdc00)) +
1689 : 0x10000;
1690 : // utf-16 surrogate pair
1691 1522 : temp.append_utf8(cp);
1692 : }
1693 :
1694 : // flush
1695 12650 : if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1696 8869 : break;
1697 : }
1698 :
1699 8869 : if(BOOST_JSON_LIKELY( temp.size() ))
1700 : {
1701 433 : BOOST_ASSERT(total <= max_size);
1702 8869 : if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1703 : {
1704 : BOOST_STATIC_CONSTEXPR source_location loc
1705 : = BOOST_CURRENT_LOCATION;
1706 0 : return fail(cs.begin(), ev_too_large, &loc);
1707 : }
1708 :
1709 8869 : total += temp.size();
1710 8056 : bool const r = is_key
1711 8869 : ? h_.on_key_part(temp.get(), total, ec_)
1712 8152 : : h_.on_string_part(temp.get(), total, ec_);
1713 8056 : if(BOOST_JSON_UNLIKELY( !r ))
1714 813 : return fail( cs.begin() );
1715 : }
1716 :
1717 7243 : return cs.begin();
1718 : }
1719 :
1720 : //----------------------------------------------------------
1721 :
1722 : template<class Handler>
1723 : template<
1724 : bool StackEmpty_,
1725 : bool AllowComments_/*,
1726 : bool AllowTrailing_,
1727 : bool AllowBadUTF8_*/>
1728 : const char*
1729 109162 : basic_parser<Handler>::
1730 : parse_object(const char* p,
1731 : std::integral_constant<bool, StackEmpty_> stack_empty,
1732 : std::integral_constant<bool, AllowComments_> allow_comments,
1733 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1734 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1735 : bool allow_bad_utf16)
1736 : {
1737 109162 : detail::const_stream_wrapper cs(p, end_);
1738 : std::size_t size;
1739 109162 : if(! stack_empty && ! st_.empty())
1740 : {
1741 : // resume
1742 : state st;
1743 35039 : st_.pop(st);
1744 35039 : st_.pop(size);
1745 35039 : switch(st)
1746 : {
1747 0 : default: BOOST_JSON_UNREACHABLE();
1748 1594 : case state::obj1: goto do_obj1;
1749 235 : case state::obj2: goto do_obj2;
1750 12636 : case state::obj3: goto do_obj3;
1751 1689 : case state::obj4: goto do_obj4;
1752 251 : case state::obj5: goto do_obj5;
1753 1590 : case state::obj6: goto do_obj6;
1754 15443 : case state::obj7: goto do_obj7;
1755 426 : case state::obj8: goto do_obj8;
1756 660 : case state::obj9: goto do_obj9;
1757 181 : case state::obj10: goto do_obj10;
1758 334 : case state::obj11: goto do_obj11;
1759 : }
1760 : }
1761 74123 : BOOST_ASSERT(*cs == '{');
1762 74123 : size = 0;
1763 74123 : if(BOOST_JSON_UNLIKELY(! depth_))
1764 : {
1765 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1766 3 : return fail(cs.begin(), error::too_deep, &loc);
1767 : }
1768 74120 : --depth_;
1769 74120 : if(BOOST_JSON_UNLIKELY(
1770 : ! h_.on_object_begin(ec_)))
1771 2039 : return fail(cs.begin());
1772 70043 : ++cs;
1773 : // object:
1774 : // '{' *ws '}'
1775 : // '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1776 73608 : do_obj1:
1777 73608 : cs = detail::count_whitespace(cs.begin(), cs.end());
1778 73608 : if(BOOST_JSON_UNLIKELY(! cs))
1779 1628 : return maybe_suspend(cs.begin(), state::obj1, size);
1780 71980 : if(BOOST_JSON_LIKELY(*cs != '}'))
1781 : {
1782 69082 : if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1783 : {
1784 2411 : if(allow_comments && *cs == '/')
1785 : {
1786 2139 : do_obj2:
1787 2374 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1788 2290 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1789 319 : return suspend_or_fail(state::obj2, size);
1790 1971 : goto do_obj1;
1791 : }
1792 : BOOST_STATIC_CONSTEXPR source_location loc
1793 : = BOOST_CURRENT_LOCATION;
1794 272 : return fail(cs.begin(), error::syntax, &loc);
1795 : }
1796 66671 : loop:
1797 80822 : if(BOOST_JSON_UNLIKELY(++size >
1798 : Handler::max_object_size))
1799 : {
1800 : BOOST_STATIC_CONSTEXPR source_location loc
1801 : = BOOST_CURRENT_LOCATION;
1802 1 : return fail(cs.begin(), error::object_too_large, &loc);
1803 : }
1804 80821 : do_obj3:
1805 93457 : cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1806 90501 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1807 15580 : return suspend_or_fail(state::obj3, size);
1808 74921 : do_obj4:
1809 79081 : cs = detail::count_whitespace(cs.begin(), cs.end());
1810 79081 : if(BOOST_JSON_UNLIKELY(! cs))
1811 1704 : return maybe_suspend(cs.begin(), state::obj4, size);
1812 77377 : if(BOOST_JSON_UNLIKELY(*cs != ':'))
1813 : {
1814 2925 : if(allow_comments && *cs == '/')
1815 : {
1816 2779 : do_obj5:
1817 3030 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1818 2876 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1819 405 : return suspend_or_fail(state::obj5, size);
1820 2471 : goto do_obj4;
1821 : }
1822 : BOOST_STATIC_CONSTEXPR source_location loc
1823 : = BOOST_CURRENT_LOCATION;
1824 146 : return fail(cs.begin(), error::syntax, &loc);
1825 : }
1826 74452 : ++cs;
1827 76042 : do_obj6:
1828 76042 : cs = detail::count_whitespace(cs.begin(), cs.end());
1829 76042 : if(BOOST_JSON_UNLIKELY(! cs))
1830 1620 : return maybe_suspend(cs.begin(), state::obj6, size);
1831 74422 : do_obj7:
1832 89865 : cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1833 82516 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1834 23585 : return suspend_or_fail(state::obj7, size);
1835 58931 : do_obj8:
1836 61193 : cs = detail::count_whitespace(cs.begin(), cs.end());
1837 61193 : if(BOOST_JSON_UNLIKELY(! cs))
1838 441 : return maybe_suspend(cs.begin(), state::obj8, size);
1839 60752 : if(BOOST_JSON_LIKELY(*cs == ','))
1840 : {
1841 17791 : ++cs;
1842 19706 : do_obj9:
1843 19706 : cs = detail::count_whitespace(cs.begin(), cs.end());
1844 19706 : if(BOOST_JSON_UNLIKELY(! cs))
1845 690 : return maybe_suspend(cs.begin(), state::obj9, size);
1846 :
1847 : // loop for next element
1848 19016 : if(BOOST_JSON_LIKELY(*cs == '\x22'))
1849 14151 : goto loop;
1850 4865 : if(! allow_trailing || *cs != '}')
1851 : {
1852 1644 : if(allow_comments && *cs == '/')
1853 : {
1854 1433 : do_obj10:
1855 1614 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1856 1525 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1857 270 : return suspend_or_fail(state::obj10, size);
1858 1255 : goto do_obj9;
1859 : }
1860 : BOOST_STATIC_CONSTEXPR source_location loc
1861 : = BOOST_CURRENT_LOCATION;
1862 211 : return fail(cs.begin(), error::syntax, &loc);
1863 : }
1864 : }
1865 42961 : else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1866 : {
1867 2325 : if(allow_comments && *cs == '/')
1868 : {
1869 2172 : do_obj11:
1870 2506 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1871 2338 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1872 502 : return suspend_or_fail(state::obj11, size);
1873 1836 : goto do_obj8;
1874 : }
1875 : BOOST_STATIC_CONSTEXPR source_location loc
1876 : = BOOST_CURRENT_LOCATION;
1877 153 : return fail(cs.begin(), error::syntax, &loc);
1878 : }
1879 : // got closing brace, fall through
1880 : }
1881 46755 : if(BOOST_JSON_UNLIKELY(
1882 : ! h_.on_object_end(size, ec_)))
1883 1502 : return fail(cs.begin());
1884 43712 : ++depth_;
1885 43712 : ++cs;
1886 43712 : return cs.begin();
1887 : }
1888 :
1889 : //----------------------------------------------------------
1890 :
1891 : template<class Handler>
1892 : template<
1893 : bool StackEmpty_,
1894 : bool AllowComments_/*,
1895 : bool AllowTrailing_,
1896 : bool AllowBadUTF8_*/>
1897 : const char*
1898 26310 : basic_parser<Handler>::
1899 : parse_array(const char* p,
1900 : std::integral_constant<bool, StackEmpty_> stack_empty,
1901 : std::integral_constant<bool, AllowComments_> allow_comments,
1902 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1903 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1904 : bool allow_bad_utf16)
1905 : {
1906 26310 : detail::const_stream_wrapper cs(p, end_);
1907 : std::size_t size;
1908 26310 : if(! stack_empty && ! st_.empty())
1909 : {
1910 : // resume
1911 : state st;
1912 5705 : st_.pop(st);
1913 5705 : st_.pop(size);
1914 5705 : switch(st)
1915 : {
1916 0 : default: BOOST_JSON_UNREACHABLE();
1917 1050 : case state::arr1: goto do_arr1;
1918 384 : case state::arr2: goto do_arr2;
1919 2919 : case state::arr3: goto do_arr3;
1920 391 : case state::arr4: goto do_arr4;
1921 667 : case state::arr5: goto do_arr5;
1922 294 : case state::arr6: goto do_arr6;
1923 : }
1924 : }
1925 20605 : BOOST_ASSERT(*cs == '[');
1926 20605 : size = 0;
1927 20605 : if(BOOST_JSON_UNLIKELY(! depth_))
1928 : {
1929 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1930 34 : return fail(cs.begin(), error::too_deep, &loc);
1931 : }
1932 20571 : --depth_;
1933 20571 : if(BOOST_JSON_UNLIKELY(
1934 : ! h_.on_array_begin(ec_)))
1935 809 : return fail(cs.begin());
1936 18956 : ++cs;
1937 : // array:
1938 : // '[' *ws ']'
1939 : // '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1940 21539 : do_arr1:
1941 21539 : cs = detail::count_whitespace(cs.begin(), cs.end());
1942 21539 : if(BOOST_JSON_UNLIKELY(! cs))
1943 1071 : return maybe_suspend(cs.begin(), state::arr1, size);
1944 20468 : if(BOOST_JSON_LIKELY(*cs != ']'))
1945 : {
1946 18722 : loop:
1947 26170 : if(allow_comments && *cs == '/')
1948 : {
1949 1789 : do_arr2:
1950 2173 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1951 2045 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1952 512 : return suspend_or_fail(state::arr2, size);
1953 1533 : goto do_arr1;
1954 : }
1955 24381 : if(BOOST_JSON_UNLIKELY(++size >
1956 : Handler::max_array_size))
1957 : {
1958 : BOOST_STATIC_CONSTEXPR source_location loc
1959 : = BOOST_CURRENT_LOCATION;
1960 1 : return fail(cs.begin(), error::array_too_large, &loc);
1961 : }
1962 24380 : do_arr3:
1963 : // array is not empty, value required
1964 27299 : cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1965 24668 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1966 9028 : return suspend_or_fail(state::arr3, size);
1967 15640 : do_arr4:
1968 17261 : cs = detail::count_whitespace(cs.begin(), cs.end());
1969 17261 : if(BOOST_JSON_UNLIKELY(! cs))
1970 500 : return maybe_suspend(cs.begin(), state::arr4, size);
1971 16761 : if(BOOST_JSON_LIKELY(*cs == ','))
1972 : {
1973 9161 : ++cs;
1974 9828 : do_arr5:
1975 9828 : cs = detail::count_whitespace(cs.begin(), cs.end());
1976 9828 : if(BOOST_JSON_UNLIKELY(! cs))
1977 697 : return maybe_suspend(cs.begin(), state::arr5, size);
1978 : // loop for next element
1979 9131 : if(! allow_trailing || *cs != ']')
1980 7448 : goto loop;
1981 : }
1982 7600 : else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1983 : {
1984 1969 : if(allow_comments && *cs == '/')
1985 : {
1986 1541 : do_arr6:
1987 1835 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1988 1688 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1989 458 : return suspend_or_fail(state::arr6, size);
1990 1230 : goto do_arr4;
1991 : }
1992 : BOOST_STATIC_CONSTEXPR source_location loc
1993 : = BOOST_CURRENT_LOCATION;
1994 428 : return fail(cs.begin(), error::syntax, &loc);
1995 : }
1996 : // got closing bracket; fall through
1997 : }
1998 9060 : if(BOOST_JSON_UNLIKELY(
1999 : ! h_.on_array_end(size, ec_)))
2000 542 : return fail(cs.begin());
2001 7939 : ++depth_;
2002 7939 : ++cs;
2003 7939 : return cs.begin();
2004 : }
2005 :
2006 : //----------------------------------------------------------
2007 :
2008 : template<class Handler>
2009 : template<bool StackEmpty_, char First_, number_precision Numbers_>
2010 : const char*
2011 2126839 : basic_parser<Handler>::
2012 : parse_number(const char* p,
2013 : std::integral_constant<bool, StackEmpty_> stack_empty,
2014 : std::integral_constant<char, First_> first,
2015 : std::integral_constant<number_precision, Numbers_> mode)
2016 : {
2017 2126839 : constexpr bool precise_parsing = mode == number_precision::precise;
2018 2126839 : constexpr bool no_parsing = mode == number_precision::none;
2019 :
2020 : // only one of these will be true if we are not resuming
2021 : // if negative then !zero_first && !nonzero_first
2022 : // if zero_first then !nonzero_first && !negative
2023 : // if nonzero_first then !zero_first && !negative
2024 2126839 : bool const negative = first == '-';
2025 2126839 : bool const zero_first = first == '0';
2026 2126839 : bool const nonzero_first = first == '+';
2027 2126839 : detail::const_stream_wrapper cs(p, end_);
2028 : number num;
2029 2126839 : const char* begin = cs.begin();
2030 2126839 : if(stack_empty || st_.empty())
2031 : {
2032 2089670 : num.bias = 0;
2033 2089670 : num.exp = 0;
2034 2089670 : num.frac = false;
2035 2089670 : num_buf_.clear();
2036 :
2037 : //----------------------------------
2038 : //
2039 : // '-'
2040 : // leading minus sign
2041 : //
2042 2089670 : BOOST_ASSERT(cs);
2043 : if(negative)
2044 25177 : ++cs;
2045 :
2046 2089670 : num.neg = negative;
2047 2089670 : num.frac = false;
2048 2089670 : num.exp = 0;
2049 2089670 : num.bias = 0;
2050 :
2051 : // fast path
2052 2089670 : if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2053 : {
2054 : int n1;
2055 :
2056 9988 : if( nonzero_first ||
2057 9988 : (negative && *cs != '0') )
2058 : {
2059 2007317 : n1 = detail::count_digits( cs.begin() );
2060 2007317 : BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2061 :
2062 1836 : if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2063 : {
2064 9 : return parse_literal(
2065 8 : p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2066 : }
2067 :
2068 1827 : if( ! nonzero_first && n1 == 0 )
2069 : {
2070 : // digit required
2071 : BOOST_STATIC_CONSTEXPR source_location loc
2072 : = BOOST_CURRENT_LOCATION;
2073 2 : return fail(cs.begin(), error::syntax, &loc);
2074 : }
2075 :
2076 : BOOST_IF_CONSTEXPR( !no_parsing )
2077 2006458 : num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2078 : else
2079 848 : num.mant = 0;
2080 :
2081 2007306 : cs += n1;
2082 :
2083 : // integer or floating-point with
2084 : // >= 16 leading digits
2085 2007306 : if( n1 == 16 )
2086 : {
2087 2001424 : goto do_num2;
2088 : }
2089 : }
2090 : else
2091 : {
2092 : // 0. floating-point or 0e integer
2093 21187 : num.mant = 0;
2094 21187 : n1 = 0;
2095 21187 : ++cs;
2096 : }
2097 :
2098 : {
2099 27069 : const char c = *cs;
2100 27069 : if(c != '.')
2101 : {
2102 9870 : if((c | 32) == 'e')
2103 : {
2104 6576 : ++cs;
2105 6576 : goto do_exp1;
2106 : }
2107 : BOOST_IF_CONSTEXPR( negative && !no_parsing )
2108 19 : num.mant = ~num.mant + 1;
2109 3294 : goto finish_signed;
2110 : }
2111 : }
2112 :
2113 : // floating-point number
2114 :
2115 17199 : ++cs;
2116 :
2117 17199 : int n2 = detail::count_digits( cs.begin() );
2118 17199 : BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2119 :
2120 17199 : if( n2 == 0 )
2121 : {
2122 : // digit required
2123 : BOOST_STATIC_CONSTEXPR source_location loc
2124 : = BOOST_CURRENT_LOCATION;
2125 3 : return fail(cs.begin(), error::syntax, &loc);
2126 : }
2127 :
2128 : // floating-point mantissa overflow
2129 17196 : if( n1 + n2 >= 19 )
2130 : {
2131 122 : goto do_num7;
2132 : }
2133 :
2134 : BOOST_IF_CONSTEXPR( !no_parsing )
2135 12855 : num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2136 :
2137 17074 : BOOST_ASSERT(num.bias == 0);
2138 :
2139 17074 : num.bias -= n2;
2140 :
2141 17074 : cs += n2;
2142 :
2143 17074 : char ch = *cs;
2144 :
2145 17074 : if( (ch | 32) == 'e' )
2146 : {
2147 110 : ++cs;
2148 110 : goto do_exp1;
2149 : }
2150 16964 : else if( ch >= '0' && ch <= '9' )
2151 : {
2152 10017 : goto do_num8;
2153 : }
2154 :
2155 6947 : goto finish_dub;
2156 : }
2157 : }
2158 : else
2159 : {
2160 37169 : num = num_;
2161 : state st;
2162 37169 : st_.pop(st);
2163 37169 : switch(st)
2164 : {
2165 0 : default: BOOST_JSON_UNREACHABLE();
2166 602 : case state::num1: goto do_num1;
2167 6333 : case state::num2: goto do_num2;
2168 802 : case state::num3: goto do_num3;
2169 52 : case state::num4: goto do_num4;
2170 4537 : case state::num5: goto do_num5;
2171 666 : case state::num6: goto do_num6;
2172 616 : case state::num7: goto do_num7;
2173 10944 : case state::num8: goto do_num8;
2174 469 : case state::exp1: goto do_exp1;
2175 125 : case state::exp2: goto do_exp2;
2176 12023 : case state::exp3: goto do_exp3;
2177 : }
2178 : }
2179 :
2180 : //----------------------------------
2181 : //
2182 : // DIGIT
2183 : // first digit
2184 : //
2185 61768 : do_num1:
2186 15791 : if(zero_first || nonzero_first ||
2187 15791 : BOOST_JSON_LIKELY(cs))
2188 : {
2189 61046 : char const c = *cs;
2190 : if(zero_first)
2191 : {
2192 9718 : ++cs;
2193 9718 : num.mant = 0;
2194 9718 : goto do_num6;
2195 : }
2196 15069 : else if(nonzero_first || BOOST_JSON_LIKELY(
2197 : c >= '1' && c <= '9'))
2198 : {
2199 42506 : ++cs;
2200 42506 : num.mant = c - '0';
2201 : }
2202 8822 : else if(BOOST_JSON_UNLIKELY(
2203 : c == '0'))
2204 : {
2205 7627 : ++cs;
2206 7627 : num.mant = 0;
2207 7627 : goto do_num6;
2208 : }
2209 1195 : else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2210 : {
2211 1007 : st_.push(state::lit1);
2212 1007 : cur_lit_ = detail::neg_infinity_literal;
2213 1007 : lit_offset_ = 1;
2214 1007 : return parse_literal(
2215 961 : cs.begin(), mp11::mp_int<detail::resume_literal>() );
2216 : }
2217 : else
2218 : {
2219 : BOOST_STATIC_CONSTEXPR source_location loc
2220 : = BOOST_CURRENT_LOCATION;
2221 188 : return fail(cs.begin(), error::syntax, &loc);
2222 : }
2223 : }
2224 : else
2225 : {
2226 722 : if(BOOST_JSON_UNLIKELY(
2227 : ! h_.on_number_part(
2228 : {begin, cs.used(begin)}, ec_)))
2229 60 : return fail(cs.begin());
2230 :
2231 : BOOST_IF_CONSTEXPR( precise_parsing )
2232 64 : num_buf_.append( begin, cs.used(begin) );
2233 602 : return maybe_suspend(
2234 602 : cs.begin(), state::num1, num);
2235 : }
2236 :
2237 : //----------------------------------
2238 : //
2239 : // 1*DIGIT
2240 : // significant digits left of decimal
2241 : //
2242 2050263 : do_num2:
2243 2044005 : if(negative || (!stack_empty && num.neg))
2244 : {
2245 22382 : for(;;)
2246 : {
2247 30207 : if(BOOST_JSON_UNLIKELY(! cs))
2248 : {
2249 1920 : if(BOOST_JSON_UNLIKELY(more_))
2250 : {
2251 1469 : if(BOOST_JSON_UNLIKELY(
2252 : ! h_.on_number_part(
2253 : {begin, cs.used(begin)}, ec_)))
2254 69 : return fail(cs.begin());
2255 :
2256 : BOOST_IF_CONSTEXPR( precise_parsing )
2257 32 : num_buf_.append( begin, cs.used(begin) );
2258 1331 : return suspend(cs.begin(), state::num2, num);
2259 : }
2260 451 : goto finish_int;
2261 : }
2262 28287 : char const c = *cs;
2263 28287 : if(BOOST_JSON_LIKELY(
2264 : c >= '0' && c <= '9'))
2265 : {
2266 23205 : ++cs;
2267 : // 9223372036854775808 INT64_MIN
2268 23205 : if( num.mant > 922337203685477580 || (
2269 22490 : num.mant == 922337203685477580 && c > '8'))
2270 : break;
2271 : BOOST_IF_CONSTEXPR( !no_parsing )
2272 22123 : num.mant = 10 * num.mant + ( c - '0' );
2273 22382 : continue;
2274 : }
2275 5082 : goto do_num6; // [.eE]
2276 : }
2277 : }
2278 : else
2279 : {
2280 6884997 : for(;;)
2281 : {
2282 8927435 : if(BOOST_JSON_UNLIKELY(! cs))
2283 : {
2284 6416 : if(BOOST_JSON_UNLIKELY(more_))
2285 : {
2286 5808 : if(BOOST_JSON_UNLIKELY(
2287 : ! h_.on_number_part(
2288 : {begin, cs.used(begin)}, ec_)))
2289 406 : return fail(cs.begin());
2290 :
2291 : BOOST_IF_CONSTEXPR( precise_parsing )
2292 174 : num_buf_.append( begin, cs.used(begin) );
2293 5002 : return suspend(cs.begin(), state::num2, num);
2294 : }
2295 608 : goto finish_int;
2296 : }
2297 8921019 : char const c = *cs;
2298 8921019 : if(BOOST_JSON_LIKELY(
2299 : c >= '0' && c <= '9'))
2300 : {
2301 6888822 : ++cs;
2302 : // 18446744073709551615 UINT64_MAX
2303 6888822 : if( num.mant > 1844674407370955161 || (
2304 6885419 : num.mant == 1844674407370955161 && c > '5'))
2305 : break;
2306 : BOOST_IF_CONSTEXPR( !no_parsing )
2307 6879399 : num.mant = 10 * num.mant + ( c - '0' );
2308 : }
2309 : else
2310 : {
2311 2032197 : goto do_num6; // [.eE]
2312 : }
2313 : }
2314 : }
2315 4648 : ++num.bias;
2316 :
2317 : //----------------------------------
2318 : //
2319 : // 1*DIGIT
2320 : // non-significant digits left of decimal
2321 : //
2322 5450 : do_num3:
2323 11558 : for(;;)
2324 : {
2325 17008 : if(BOOST_JSON_UNLIKELY(! cs))
2326 : {
2327 1527 : if(BOOST_JSON_UNLIKELY(more_))
2328 : {
2329 894 : if(BOOST_JSON_UNLIKELY(
2330 : ! h_.on_number_part(
2331 : {begin, cs.used(begin)}, ec_)))
2332 46 : return fail(cs.begin());
2333 :
2334 : BOOST_IF_CONSTEXPR( precise_parsing )
2335 12 : num_buf_.append( begin, cs.used(begin) );
2336 802 : return suspend(cs.begin(), state::num3, num);
2337 : }
2338 633 : goto finish_dub;
2339 : }
2340 15481 : char const c = *cs;
2341 15481 : if(BOOST_JSON_UNLIKELY(
2342 : c >= '0' && c <= '9'))
2343 : {
2344 11558 : if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2345 : {
2346 : BOOST_STATIC_CONSTEXPR source_location loc
2347 : = BOOST_CURRENT_LOCATION;
2348 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2349 : }
2350 11558 : ++cs;
2351 11558 : ++num.bias;
2352 : }
2353 3923 : else if(BOOST_JSON_LIKELY(
2354 : c == '.'))
2355 : {
2356 2028 : ++cs;
2357 2028 : break;
2358 : }
2359 1895 : else if((c | 32) == 'e')
2360 : {
2361 546 : ++cs;
2362 546 : goto do_exp1;
2363 : }
2364 : else
2365 : {
2366 1349 : goto finish_dub;
2367 : }
2368 : }
2369 :
2370 : //----------------------------------
2371 : //
2372 : // DIGIT
2373 : // first non-significant digit
2374 : // to the right of decimal
2375 : //
2376 2080 : do_num4:
2377 : {
2378 2080 : if(BOOST_JSON_UNLIKELY(! cs))
2379 : {
2380 64 : if(BOOST_JSON_UNLIKELY(
2381 : ! h_.on_number_part(
2382 : {begin, cs.used(begin)}, ec_)))
2383 6 : return fail(cs.begin());
2384 :
2385 : BOOST_IF_CONSTEXPR( precise_parsing )
2386 4 : num_buf_.append( begin, cs.used(begin) );
2387 52 : return maybe_suspend(
2388 52 : cs.begin(), state::num4, num);
2389 : }
2390 2016 : char const c = *cs;
2391 2016 : if(BOOST_JSON_LIKELY(
2392 : //static_cast<unsigned char>(c - '0') < 10))
2393 : c >= '0' && c <= '9'))
2394 : {
2395 1949 : ++cs;
2396 : }
2397 : else
2398 : {
2399 : // digit required
2400 : BOOST_STATIC_CONSTEXPR source_location loc
2401 : = BOOST_CURRENT_LOCATION;
2402 67 : return fail(cs.begin(), error::syntax, &loc);
2403 : }
2404 : }
2405 :
2406 : //----------------------------------
2407 : //
2408 : // 1*DIGIT
2409 : // non-significant digits
2410 : // to the right of decimal
2411 : //
2412 2013470 : do_num5:
2413 37889832 : for(;;)
2414 : {
2415 39903302 : if(BOOST_JSON_UNLIKELY(! cs))
2416 : {
2417 6112 : if(BOOST_JSON_UNLIKELY(more_))
2418 : {
2419 4577 : if(BOOST_JSON_UNLIKELY(
2420 : ! h_.on_number_part(
2421 : {begin, cs.used(begin)}, ec_)))
2422 20 : return fail(cs.begin());
2423 :
2424 : BOOST_IF_CONSTEXPR( precise_parsing )
2425 178 : num_buf_.append( begin, cs.used(begin) );
2426 4537 : return suspend(cs.begin(), state::num5, num);
2427 : }
2428 1535 : goto finish_dub;
2429 : }
2430 39897190 : char const c = *cs;
2431 39897190 : if(BOOST_JSON_LIKELY(
2432 : c >= '0' && c <= '9'))
2433 : {
2434 37889832 : ++cs;
2435 : }
2436 2007358 : else if((c | 32) == 'e')
2437 : {
2438 2003236 : ++cs;
2439 2003236 : goto do_exp1;
2440 : }
2441 : else
2442 : {
2443 4122 : goto finish_dub;
2444 : }
2445 : }
2446 :
2447 : //----------------------------------
2448 : //
2449 : // [.eE]
2450 : //
2451 2055290 : do_num6:
2452 : {
2453 2055290 : if(BOOST_JSON_UNLIKELY(! cs))
2454 : {
2455 798 : if(BOOST_JSON_UNLIKELY(more_))
2456 : {
2457 751 : if(BOOST_JSON_UNLIKELY(
2458 : ! h_.on_number_part(
2459 : {begin, cs.used(begin)}, ec_)))
2460 42 : return fail(cs.begin());
2461 :
2462 : BOOST_IF_CONSTEXPR( precise_parsing )
2463 98 : num_buf_.append( begin, cs.used(begin) );
2464 667 : return suspend(cs.begin(), state::num6, num);
2465 : }
2466 47 : goto finish_int;
2467 : }
2468 2054492 : char const c = *cs;
2469 2054492 : if(BOOST_JSON_LIKELY(
2470 : c == '.'))
2471 : {
2472 2016097 : ++cs;
2473 : }
2474 38395 : else if((c | 32) == 'e')
2475 : {
2476 9140 : ++cs;
2477 9140 : goto do_exp1;
2478 : }
2479 : else
2480 : {
2481 29255 : goto finish_int;
2482 : }
2483 : }
2484 :
2485 : //----------------------------------
2486 : //
2487 : // DIGIT
2488 : // first significant digit
2489 : // to the right of decimal
2490 : //
2491 2016835 : do_num7:
2492 : {
2493 2016835 : if(BOOST_JSON_UNLIKELY(! cs))
2494 : {
2495 691 : if(BOOST_JSON_UNLIKELY(more_))
2496 : {
2497 687 : if(BOOST_JSON_UNLIKELY(
2498 : ! h_.on_number_part(
2499 : {begin, cs.used(begin)}, ec_)))
2500 35 : return fail(cs.begin());
2501 :
2502 : BOOST_IF_CONSTEXPR( precise_parsing )
2503 96 : num_buf_.append( begin, cs.used(begin) );
2504 617 : return suspend(cs.begin(), state::num7, num);
2505 : }
2506 : // digit required
2507 : BOOST_STATIC_CONSTEXPR source_location loc
2508 : = BOOST_CURRENT_LOCATION;
2509 4 : return fail(cs.begin(), error::syntax, &loc);
2510 : }
2511 2016144 : char const c = *cs;
2512 2016144 : if(BOOST_JSON_UNLIKELY(
2513 : c < '0' || c > '9'))
2514 : {
2515 : // digit required
2516 : BOOST_STATIC_CONSTEXPR source_location loc
2517 : = BOOST_CURRENT_LOCATION;
2518 169 : return fail(cs.begin(), error::syntax, &loc);
2519 : }
2520 : }
2521 :
2522 : //----------------------------------
2523 : //
2524 : // 1*DIGIT
2525 : // significant digits
2526 : // to the right of decimal
2527 : //
2528 2034436 : do_num8:
2529 3277926 : for(;;)
2530 : {
2531 5314862 : if(BOOST_JSON_UNLIKELY(! cs))
2532 : {
2533 12816 : if(BOOST_JSON_UNLIKELY(more_))
2534 : {
2535 11080 : if(BOOST_JSON_UNLIKELY(
2536 : ! h_.on_number_part(
2537 : {begin, cs.used(begin)}, ec_)))
2538 67 : return fail(cs.begin());
2539 :
2540 : BOOST_IF_CONSTEXPR( precise_parsing )
2541 3442 : num_buf_.append( begin, cs.used(begin) );
2542 10945 : return suspend(cs.begin(), state::num8, num);
2543 : }
2544 1736 : goto finish_dub;
2545 : }
2546 5302046 : char const c = *cs;
2547 5302046 : if(BOOST_JSON_LIKELY(
2548 : c >= '0' && c <= '9'))
2549 : {
2550 5284910 : ++cs;
2551 5279817 : if(!no_parsing && BOOST_JSON_LIKELY(
2552 : num.mant <= 9007199254740991)) // 2^53-1
2553 : {
2554 3277926 : if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2555 : {
2556 : BOOST_STATIC_CONSTEXPR source_location loc
2557 : = BOOST_CURRENT_LOCATION;
2558 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2559 : }
2560 3277926 : --num.bias;
2561 3277926 : num.mant = 10 * num.mant + ( c - '0' );
2562 : }
2563 : else
2564 : {
2565 2006984 : goto do_num5;
2566 : }
2567 : }
2568 17136 : else if((c | 32) == 'e')
2569 : {
2570 11133 : ++cs;
2571 11133 : goto do_exp1;
2572 : }
2573 : else
2574 : {
2575 6003 : goto finish_dub;
2576 : }
2577 : }
2578 :
2579 : //----------------------------------
2580 : //
2581 : // *[+-]
2582 : //
2583 2031210 : do_exp1:
2584 2031210 : if(BOOST_JSON_UNLIKELY(! cs))
2585 : {
2586 565 : if(BOOST_JSON_UNLIKELY(
2587 : ! h_.on_number_part(
2588 : {begin, cs.used(begin)}, ec_)))
2589 48 : return fail(cs.begin());
2590 :
2591 : BOOST_IF_CONSTEXPR( precise_parsing )
2592 46 : num_buf_.append( begin, cs.used(begin) );
2593 469 : return maybe_suspend(
2594 469 : cs.begin(), state::exp1, num);
2595 : }
2596 2030645 : if(*cs == '+')
2597 : {
2598 1931 : ++cs;
2599 : }
2600 2028714 : else if(*cs == '-')
2601 : {
2602 1001935 : ++cs;
2603 1001935 : num.frac = true;
2604 : }
2605 :
2606 : //----------------------------------
2607 : //
2608 : // DIGIT
2609 : // first digit of the exponent
2610 : //
2611 1026779 : do_exp2:
2612 : {
2613 2030770 : if(BOOST_JSON_UNLIKELY(! cs))
2614 : {
2615 172 : if(BOOST_JSON_UNLIKELY(more_))
2616 : {
2617 163 : if(BOOST_JSON_UNLIKELY(
2618 : ! h_.on_number_part(
2619 : {begin, cs.used(begin)}, ec_)))
2620 19 : return fail(cs.begin());
2621 :
2622 : BOOST_IF_CONSTEXPR( precise_parsing )
2623 4 : num_buf_.append( begin, cs.used(begin) );
2624 125 : return suspend(cs.begin(), state::exp2, num);
2625 : }
2626 : // digit required
2627 : BOOST_STATIC_CONSTEXPR source_location loc
2628 : = BOOST_CURRENT_LOCATION;
2629 9 : return fail(cs.begin(), error::syntax, &loc);
2630 : }
2631 2030598 : char const c = *cs;
2632 2030598 : if(BOOST_JSON_UNLIKELY(
2633 : c < '0' || c > '9'))
2634 : {
2635 : // digit required
2636 : BOOST_STATIC_CONSTEXPR source_location loc
2637 : = BOOST_CURRENT_LOCATION;
2638 508 : return fail(cs.begin(), error::syntax, &loc);
2639 : }
2640 2030090 : ++cs;
2641 2030090 : num.exp = c - '0';
2642 : }
2643 :
2644 : //----------------------------------
2645 : //
2646 : // 1*DIGIT
2647 : // subsequent digits in the exponent
2648 : //
2649 2042113 : do_exp3:
2650 5466102 : for(;;)
2651 : {
2652 7508215 : if(BOOST_JSON_UNLIKELY(! cs))
2653 : {
2654 2020530 : if(BOOST_JSON_UNLIKELY(more_))
2655 : {
2656 12177 : if(BOOST_JSON_UNLIKELY(
2657 : ! h_.on_number_part(
2658 : {begin, cs.used(begin)}, ec_)))
2659 77 : return fail(cs.begin());
2660 :
2661 : BOOST_IF_CONSTEXPR( precise_parsing )
2662 2873 : num_buf_.append( begin, cs.used(begin) );
2663 12023 : return suspend(cs.begin(), state::exp3, num);
2664 : }
2665 : }
2666 : else
2667 : {
2668 5487685 : char const c = *cs;
2669 5487685 : if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2670 : {
2671 5466102 : if(BOOST_JSON_UNLIKELY(
2672 : // 2147483647 INT_MAX
2673 : num.exp > 214748364 ||
2674 : (num.exp == 214748364 && c > '7')
2675 : ))
2676 3855 : num.exp = INT_MAX;
2677 : else BOOST_IF_CONSTEXPR( !no_parsing )
2678 4921395 : num.exp = 10 * num.exp + ( c - '0' );
2679 :
2680 5466102 : ++cs;
2681 5466102 : continue;
2682 : }
2683 : }
2684 2029936 : BOOST_ASSERT(num.exp >= 0);
2685 2029936 : if ( num.frac )
2686 : {
2687 1001799 : if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2688 : {
2689 : // if exponent overflowed, bias is a very large negative
2690 : // number, and mantissa isn't zero, then we cannot parse the
2691 : // number correctly
2692 91 : if(BOOST_JSON_UNLIKELY(
2693 : (num.exp == INT_MAX) &&
2694 : (num.bias < 0) &&
2695 : (num.exp + num.bias < 308) &&
2696 : num.mant ))
2697 : {
2698 : BOOST_STATIC_CONSTEXPR source_location loc
2699 : = BOOST_CURRENT_LOCATION;
2700 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2701 : }
2702 :
2703 91 : num.bias = 0;
2704 91 : num.exp = INT_MAX;
2705 : }
2706 : }
2707 1028137 : else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2708 : {
2709 : // if exponent overflowed, bias is a very large positive number,
2710 : // and mantissa isn't zero, then we cannot parse the
2711 : // number correctly
2712 0 : if(BOOST_JSON_UNLIKELY(
2713 : (num.exp == INT_MAX) &&
2714 : (num.bias > 0) &&
2715 : (num.exp - num.bias < 308) &&
2716 : num.mant ))
2717 : {
2718 : BOOST_STATIC_CONSTEXPR source_location loc
2719 : = BOOST_CURRENT_LOCATION;
2720 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2721 : }
2722 :
2723 0 : num.bias = 0;
2724 0 : num.exp = INT_MAX;
2725 : }
2726 2029936 : goto finish_dub;
2727 : }
2728 :
2729 30361 : finish_int:
2730 28432 : if(negative || (!stack_empty && num.neg))
2731 : {
2732 2531 : if(BOOST_JSON_UNLIKELY(
2733 : ! h_.on_int64(static_cast<
2734 : int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2735 309 : return fail(cs.begin());
2736 1914 : return cs.begin();
2737 : }
2738 27830 : if(num.mant <= INT64_MAX)
2739 : {
2740 27530 : finish_signed:
2741 30805 : if(BOOST_JSON_UNLIKELY(
2742 : ! h_.on_int64(static_cast<
2743 : int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2744 2260 : return fail(cs.begin());
2745 26285 : return cs.begin();
2746 : }
2747 319 : if(BOOST_JSON_UNLIKELY(
2748 : ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2749 33 : return fail(cs.begin());
2750 254 : return cs.begin();
2751 2052261 : finish_dub:
2752 : double d;
2753 2052261 : std::size_t const size = cs.used(begin);
2754 2052261 : BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2755 : BOOST_IF_CONSTEXPR( precise_parsing )
2756 : {
2757 1009310 : char const* data = begin;
2758 1009310 : std::size_t full_size = size;
2759 : // if we previously suspended or if the current input ends with the
2760 : // number, we need to copy the current part of the number to the
2761 : // temporary buffer
2762 1009310 : if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2763 : {
2764 4771 : data = num_buf_.append( begin, size );
2765 4771 : full_size = num_buf_.size();
2766 : }
2767 1009310 : auto const err = detail::charconv::from_chars(
2768 : data, data + full_size, d );
2769 1009310 : BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2770 1009310 : BOOST_ASSERT( err.ptr == data + full_size );
2771 : (void)err;
2772 : }
2773 : else BOOST_IF_CONSTEXPR( no_parsing )
2774 9258 : d = 0;
2775 : else
2776 1033693 : d = detail::dec_to_float(
2777 : num.mant,
2778 531741 : num.bias + (num.frac ?
2779 501952 : -num.exp : num.exp),
2780 1033693 : num.neg);
2781 2052261 : if(BOOST_JSON_UNLIKELY(
2782 : ! h_.on_double(d, {begin, size}, ec_)))
2783 1903 : return fail(cs.begin());
2784 2048455 : return cs.begin();
2785 : }
2786 :
2787 : //----------------------------------------------------------
2788 :
2789 : template<class Handler>
2790 : template<class... Args>
2791 2164579 : basic_parser<Handler>::
2792 : basic_parser(
2793 : parse_options const& opt,
2794 : Args&&... args)
2795 2164571 : : h_(std::forward<Args>(args)...)
2796 2164579 : , opt_(opt)
2797 : {
2798 2164579 : }
2799 :
2800 : //----------------------------------------------------------
2801 :
2802 : template<class Handler>
2803 : void
2804 4153127 : basic_parser<Handler>::
2805 : reset() noexcept
2806 : {
2807 4153127 : ec_ = {};
2808 4153127 : st_.clear();
2809 4153127 : more_ = true;
2810 4153127 : done_ = false;
2811 4153127 : clean_ = true;
2812 4153127 : num_buf_.clear();
2813 4153127 : }
2814 :
2815 : template<class Handler>
2816 : void
2817 16 : basic_parser<Handler>::
2818 : fail(system::error_code ec) noexcept
2819 : {
2820 16 : if(! ec)
2821 : {
2822 : // assign an arbitrary
2823 : // error code to prevent UB
2824 0 : BOOST_JSON_FAIL(ec_, error::incomplete);
2825 : }
2826 : else
2827 : {
2828 16 : ec_ = ec;
2829 : }
2830 16 : done_ = false;
2831 16 : }
2832 :
2833 : //----------------------------------------------------------
2834 :
2835 : template<class Handler>
2836 : std::size_t
2837 2334148 : basic_parser<Handler>::
2838 : write_some(
2839 : bool more,
2840 : char const* data,
2841 : std::size_t size,
2842 : system::error_code& ec)
2843 : {
2844 : // see if we exited via exception
2845 : // on the last call to write_some
2846 2334148 : if(! clean_)
2847 : {
2848 : // prevent UB
2849 1 : if(! ec_)
2850 : {
2851 1 : BOOST_JSON_FAIL(ec_, error::exception);
2852 : }
2853 : }
2854 2334148 : if(ec_)
2855 : {
2856 : // error is sticky
2857 5 : ec = ec_;
2858 5 : return 0;
2859 : }
2860 2334143 : clean_ = false;
2861 2334143 : more_ = more;
2862 2334143 : end_ = data + size;
2863 : const char* p;
2864 2334143 : if(BOOST_JSON_LIKELY(st_.empty()))
2865 : {
2866 : // first time
2867 2164565 : depth_ = opt_.max_depth;
2868 2164565 : if(BOOST_JSON_UNLIKELY(
2869 : ! h_.on_document_begin(ec_)))
2870 : {
2871 7889 : ec = ec_;
2872 7889 : return 0;
2873 : }
2874 2148786 : p = parse_document(data, std::true_type());
2875 : }
2876 : else
2877 : {
2878 169578 : p = parse_document(data, std::false_type());
2879 : }
2880 :
2881 2299265 : if(BOOST_JSON_LIKELY(p != sentinel()))
2882 : {
2883 2099051 : BOOST_ASSERT(! ec_);
2884 2099051 : if(! done_)
2885 : {
2886 2031637 : done_ = true;
2887 2031637 : h_.on_document_end(ec_);
2888 : }
2889 : }
2890 : else
2891 : {
2892 200214 : if(! ec_)
2893 : {
2894 173462 : if(! more_)
2895 : {
2896 572 : BOOST_JSON_FAIL(ec_, error::incomplete);
2897 : }
2898 172890 : else if(! st_.empty())
2899 : {
2900 : // consume as much trailing whitespace in
2901 : // the JSON document as possible, but still
2902 : // consider the parse complete
2903 : state st;
2904 172890 : st_.peek(st);
2905 172890 : if( st == state::doc3 &&
2906 88550 : ! done_)
2907 : {
2908 70723 : done_ = true;
2909 70723 : h_.on_document_end(ec_);
2910 : }
2911 : }
2912 : }
2913 198570 : p = end_;
2914 : }
2915 2293661 : ec = ec_;
2916 2293661 : clean_ = true;
2917 2293661 : return p - data;
2918 : }
2919 :
2920 : template<class Handler>
2921 : std::size_t
2922 1 : basic_parser<Handler>::
2923 : write_some(
2924 : bool more,
2925 : char const* data,
2926 : std::size_t size,
2927 : std::error_code& ec)
2928 : {
2929 1 : system::error_code jec;
2930 1 : std::size_t const result = write_some(more, data, size, jec);
2931 1 : ec = jec;
2932 1 : return result;
2933 : }
2934 :
2935 : #endif
2936 :
2937 : } // namespace json
2938 : } // namespace boost
2939 :
2940 : #ifdef _MSC_VER
2941 : #pragma warning(pop)
2942 : #endif
2943 :
2944 : #endif
|