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