TLA 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 HIT 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 2126888 : operator()( mp11::mp_size_t<N> ) const
205 : {
206 4248335 : return parser->parse_number(
207 2126888 : p,
208 : std::integral_constant<bool, StackEmpty_>(),
209 : std::integral_constant<char, First_>(),
210 : std::integral_constant<
211 2121448 : number_precision, static_cast<number_precision>(N)>() );
212 : }
213 : };
214 :
215 : //----------------------------------------------------------
216 :
217 : template<class Handler>
218 : void
219 210572 : basic_parser<Handler>::
220 : reserve()
221 : {
222 210572 : if(BOOST_JSON_LIKELY(
223 : ! st_.empty()))
224 37469 : return;
225 : // Reserve the largest stack we need,
226 : // to avoid reallocation during suspend.
227 346206 : st_.reserve(
228 : sizeof(state) + // document parsing state
229 : (sizeof(state) +
230 173103 : 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 5341073 : 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 5341073 : const char*>(this) + 1;
252 : }
253 :
254 : template<class Handler>
255 : bool
256 2459881 : basic_parser<Handler>::
257 : incomplete(
258 : const detail::const_stream_wrapper& cs)
259 : {
260 2459881 : 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 56176 : basic_parser<Handler>::
288 : suspend_or_fail(
289 : state st,
290 : std::size_t n)
291 : {
292 56176 : if(BOOST_JSON_LIKELY(
293 : ! ec_ && more_))
294 : {
295 : // suspend
296 35861 : reserve();
297 35861 : st_.push_unchecked(n);
298 35861 : st_.push_unchecked(st);
299 : }
300 56176 : 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 7774 : basic_parser<Handler>::
317 : fail(
318 : const char* p,
319 : error ev,
320 : source_location const* loc) noexcept
321 : {
322 7774 : BOOST_ASSERT( p != sentinel() );
323 7774 : end_ = p;
324 7774 : ec_.assign(ev, loc);
325 7774 : return sentinel();
326 : }
327 :
328 : template<class Handler>
329 : const char*
330 11289 : basic_parser<Handler>::
331 : maybe_suspend(
332 : const char* p,
333 : state st)
334 : {
335 11289 : if( p != sentinel() )
336 9424 : end_ = p;
337 11289 : if(BOOST_JSON_LIKELY(more_))
338 : {
339 : // suspend
340 11027 : reserve();
341 11027 : st_.push_unchecked(st);
342 : }
343 11289 : return sentinel();
344 : }
345 :
346 : template<class Handler>
347 : const char*
348 38234 : basic_parser<Handler>::
349 : maybe_suspend(
350 : const char* p,
351 : state st,
352 : std::size_t n)
353 : {
354 38234 : BOOST_ASSERT( p != sentinel() );
355 38234 : end_ = p;
356 38234 : if(BOOST_JSON_LIKELY(more_))
357 : {
358 : // suspend
359 37833 : reserve();
360 37833 : st_.push_unchecked(n);
361 37833 : st_.push_unchecked(st);
362 : }
363 38234 : 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 88657 : basic_parser<Handler>::
389 : suspend(
390 : const char* p,
391 : state st)
392 : {
393 88657 : BOOST_ASSERT( p != sentinel() );
394 88657 : end_ = p;
395 : // suspend
396 88657 : reserve();
397 88657 : st_.push_unchecked(st);
398 88657 : return sentinel();
399 : }
400 :
401 : template<class Handler>
402 : const char*
403 36071 : basic_parser<Handler>::
404 : suspend(
405 : const char* p,
406 : state st,
407 : const number& num)
408 : {
409 36071 : BOOST_ASSERT( p != sentinel() );
410 36071 : end_ = p;
411 : // suspend
412 36071 : num_ = num;
413 36071 : reserve();
414 36071 : st_.push_unchecked(st);
415 36071 : return sentinel();
416 : }
417 :
418 : template<class Handler>
419 : template<
420 : bool StackEmpty_/*,
421 : bool Terminal_*/>
422 : const char*
423 21737 : 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 21737 : detail::const_stream_wrapper cs(p, end_);
429 21737 : const char* start = cs.begin();
430 : std::size_t remain;
431 21737 : if(! stack_empty && ! st_.empty())
432 : {
433 : state st;
434 3507 : st_.pop(st);
435 3507 : switch(st)
436 : {
437 MIS 0 : default: BOOST_JSON_UNREACHABLE();
438 HIT 534 : case state::com1: goto do_com1;
439 2319 : 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 18230 : BOOST_ASSERT(*cs == '/');
445 18230 : ++cs;
446 18764 : do_com1:
447 18764 : if(BOOST_JSON_UNLIKELY(! cs))
448 551 : return maybe_suspend(cs.begin(), state::com1);
449 18213 : 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 10524 : case '/':
458 10524 : ++cs;
459 12843 : do_com2:
460 : // KRYSTIAN TODO: this is a mess, we have to fix this
461 12843 : remain = cs.remain();
462 25686 : cs = remain ? static_cast<const char*>(
463 12843 : std::memchr(cs.begin(), '\n', remain)) : sentinel();
464 12843 : if(! cs.begin())
465 2143 : cs = sentinel();
466 12843 : 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 2568 : 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 2529 : if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479 : {start, cs.remain(start)}, ec_)))
480 95 : return fail(cs.end());
481 2339 : if(terminal)
482 106 : return suspend(cs.end(), state::com2);
483 2233 : return maybe_suspend(cs.end(), state::com2);
484 : }
485 10275 : 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 17851 : ++cs;
519 17851 : if(BOOST_JSON_UNLIKELY(! h_.on_comment(
520 : {start, cs.used(start)}, ec_)))
521 964 : return fail(cs.begin());
522 15923 : return cs.begin();
523 : }
524 :
525 : template<class Handler>
526 : template<bool StackEmpty_>
527 : const char*
528 2318439 : basic_parser<Handler>::
529 : parse_document(const char* p,
530 : std::integral_constant<bool, StackEmpty_> stack_empty)
531 : {
532 2318439 : detail::const_stream_wrapper cs(p, end_);
533 2318439 : if(! stack_empty && ! st_.empty())
534 : {
535 : state st;
536 169624 : st_.peek(st);
537 169624 : switch(st)
538 : {
539 83559 : default: goto do_doc2;
540 601 : case state::doc1:
541 601 : st_.pop(st);
542 601 : goto do_doc1;
543 85244 : case state::doc3:
544 85244 : st_.pop(st);
545 85244 : 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 2148815 : do_doc1:
552 2149416 : cs = detail::count_whitespace(cs.begin(), cs.end());
553 2149416 : if(BOOST_JSON_UNLIKELY(! cs))
554 633 : return maybe_suspend(cs.begin(), state::doc1);
555 2148783 : do_doc2:
556 2232342 : switch(+opt_.allow_comments |
557 2232342 : (opt_.allow_trailing_commas << 1) |
558 2232342 : (opt_.allow_invalid_utf8 << 2))
559 : {
560 : // no extensions
561 2208660 : default:
562 2208660 : cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563 2193502 : break;
564 : // comments
565 13551 : case 1:
566 13551 : cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567 11288 : 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 2213328 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594 : // the appropriate state has already been pushed into stack
595 110765 : return sentinel();
596 2102563 : do_doc3:
597 2188139 : cs = detail::count_whitespace(cs.begin(), cs.end());
598 2188139 : if(BOOST_JSON_UNLIKELY(! cs))
599 : {
600 2185541 : if(more_)
601 88551 : 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 2099052 : 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 2349972 : 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 2349972 : if(stack_empty || st_.empty())
630 : {
631 2248027 : loop:
632 2252943 : 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 2041766 : case '1': case '2': case '3':
643 : case '4': case '5': case '6':
644 : case '7': case '8': case '9':
645 2041766 : return mp11::mp_with_index<3>(
646 2041766 : static_cast<unsigned char>(opt_.numbers),
647 2038922 : parse_number_helper<true, '+'>{ this, p });
648 11380 : case 'n':
649 11380 : 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 47577 : case '"':
671 47577 : return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672 20618 : case '[':
673 20618 : return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674 74131 : case '{':
675 74131 : return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676 6125 : case '/':
677 6125 : 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 5841 : 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 5605 : if(BOOST_JSON_UNLIKELY(p == sentinel()))
688 591 : 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 101945 : 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 101945 : 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 101945 : st_.peek(st);
724 101945 : switch(st)
725 : {
726 MIS 0 : default: BOOST_JSON_UNREACHABLE();
727 HIT 1924 : case state::lit1:
728 1924 : return parse_literal(p, detail::literals_c<detail::literals::resume>() );
729 :
730 20259 : case state::str1: case state::str2:
731 : case state::str8:
732 20259 : return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733 :
734 5730 : case state::arr1: case state::arr2:
735 : case state::arr3: case state::arr4:
736 : case state::arr5: case state::arr6:
737 5730 : return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738 :
739 35058 : 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 35058 : return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746 :
747 37191 : 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 37191 : return mp11::mp_with_index<3>(
754 37191 : static_cast<unsigned char>(opt_.numbers),
755 36368 : 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 MIS 0 : return maybe_suspend(p, state::val1);
765 HIT 108 : return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
766 : }
767 :
768 1608 : case state::val2:
769 : {
770 1608 : st_.pop(st);
771 1608 : p = parse_comment(p, std::false_type(), std::false_type());
772 1590 : if(BOOST_JSON_UNLIKELY(p == sentinel()))
773 1274 : return maybe_suspend(p, state::val2);
774 316 : if(BOOST_JSON_UNLIKELY( p == end_ ))
775 77 : 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 67 : case state::val3:
781 : {
782 67 : st_.pop(st);
783 67 : 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 16564 : 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 16564 : detail::const_stream_wrapper cs(p, end_);
800 : BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801 : {
802 13633 : constexpr std::size_t index = literal_index(Literal::value);
803 13633 : constexpr char const* literal = detail::literal_strings[index];
804 13633 : constexpr std::size_t sz = detail::literal_sizes[index];
805 :
806 13633 : if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807 : {
808 11983 : int const cmp = std::memcmp(cs.begin(), literal, sz);
809 11983 : 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 10788 : 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 11362 : cs += sz;
866 11362 : 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 MIS 0 : default: BOOST_JSON_UNREACHABLE();
951 : }
952 :
953 HIT 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 161311 : 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 161311 : detail::const_stream_wrapper cs(p, end_);
970 : std::size_t total;
971 : char const* start;
972 : std::size_t size;
973 161311 : if(! stack_empty && ! st_.empty())
974 : {
975 : state st;
976 32906 : st_.pop(st);
977 32906 : st_.pop(total);
978 32906 : switch(st)
979 : {
980 MIS 0 : default: BOOST_JSON_UNREACHABLE();
981 HIT 3149 : case state::str2: goto do_str2;
982 1864 : case state::str8: goto do_str8;
983 27893 : case state::str1: break;
984 : }
985 : }
986 : else
987 : {
988 128405 : BOOST_ASSERT(*cs == '\x22'); // '"'
989 128405 : ++cs;
990 128405 : total = 0;
991 : }
992 :
993 164791 : do_str1:
994 164791 : start = cs.begin();
995 329582 : cs = allow_bad_utf8?
996 2177 : detail::count_valid<true>(cs.begin(), cs.end()):
997 162614 : detail::count_valid<false>(cs.begin(), cs.end());
998 164791 : size = cs.used(start);
999 164791 : if(is_key)
1000 : {
1001 46694 : BOOST_ASSERT(total <= Handler::max_key_size);
1002 94005 : 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 35324 : BOOST_ASSERT(total <= Handler::max_string_size);
1013 70786 : 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 164785 : total += size;
1022 164785 : if(BOOST_JSON_UNLIKELY(! cs))
1023 : {
1024 : // call handler if the string isn't empty
1025 30227 : if(BOOST_JSON_LIKELY(size))
1026 : {
1027 : {
1028 27066 : bool r = is_key?
1029 12404 : h_.on_key_part( {start, size}, total, ec_ ):
1030 15996 : h_.on_string_part( {start, size}, total, ec_ );
1031 :
1032 25958 : if(BOOST_JSON_UNLIKELY(!r))
1033 : {
1034 1110 : return fail(cs.begin());
1035 : }
1036 : }
1037 : }
1038 28009 : 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 134558 : if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044 : {
1045 : // sequence is invalid or incomplete
1046 15071 : if((*cs & 0x80) && !allow_bad_utf8)
1047 : {
1048 3465 : seq_.save(cs.begin(), cs.remain());
1049 3465 : 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 1908 : 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 1864 : 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 119487 : bool r = is_key?
1090 84511 : h_.on_key( {start, size}, total, ec_ ):
1091 41985 : h_.on_string( {start, size}, total, ec_ );
1092 :
1093 115113 : if(BOOST_JSON_UNLIKELY(!r))
1094 : {
1095 4318 : return fail(cs.begin());
1096 : }
1097 : }
1098 :
1099 110795 : ++cs;
1100 110795 : return cs.begin();
1101 :
1102 1864 : do_str8:
1103 1864 : uint8_t needed = seq_.needed();
1104 1864 : if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105 MIS 0 : return maybe_suspend(cs.end(), state::str8, total);
1106 HIT 1864 : 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 1654 : std::size_t const n = seq_.length();
1113 : bool r;
1114 1654 : if(is_key)
1115 : {
1116 2 : BOOST_ASSERT(total <= Handler::max_key_size);
1117 2 : if(BOOST_JSON_UNLIKELY(n >
1118 : Handler::max_key_size - total))
1119 : {
1120 : BOOST_STATIC_CONSTEXPR source_location loc
1121 : = BOOST_CURRENT_LOCATION;
1122 1 : return fail(cs.begin(), error::key_too_large, &loc);
1123 : }
1124 1 : total += n;
1125 1 : r = h_.on_key_part( {seq_.data(), n}, total, ec_ );
1126 : }
1127 : else
1128 : {
1129 1 : BOOST_ASSERT(total <= Handler::max_string_size);
1130 1652 : if(BOOST_JSON_UNLIKELY(n >
1131 : Handler::max_string_size - total))
1132 : {
1133 : BOOST_STATIC_CONSTEXPR source_location loc
1134 : = BOOST_CURRENT_LOCATION;
1135 1 : return fail(cs.begin(), error::string_too_large, &loc);
1136 : }
1137 1651 : total += n;
1138 1651 : r = h_.on_string_part( {seq_.data(), n}, total, ec_ );
1139 : }
1140 1451 : if(BOOST_JSON_UNLIKELY( !r ))
1141 201 : return fail( cs.begin() );
1142 : }
1143 1250 : cs += needed;
1144 1250 : goto do_str1;
1145 : }
1146 :
1147 : template<class Handler>
1148 : template<bool StackEmpty_>
1149 : const char*
1150 13678 : basic_parser<Handler>::
1151 : parse_escaped(
1152 : const char* p,
1153 : std::size_t& total,
1154 : std::integral_constant<bool, StackEmpty_> stack_empty,
1155 : bool is_key,
1156 : bool allow_bad_utf16)
1157 : {
1158 13678 : constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1159 13678 : auto const ev_too_large = is_key?
1160 : error::key_too_large : error::string_too_large;
1161 13678 : auto const max_size = is_key?
1162 : Handler::max_key_size : Handler::max_string_size;
1163 : int digit;
1164 :
1165 : //---------------------------------------------------------------
1166 : //
1167 : // To handle escapes, a local temporary buffer accumulates
1168 : // the unescaped result. The algorithm attempts to fill the
1169 : // buffer to capacity before invoking the handler.
1170 : // In some cases the temporary buffer needs to be flushed
1171 : // before it is full:
1172 : // * When the closing double quote is seen
1173 : // * When there in no more input (and more is expected later)
1174 : // A goal of the algorithm is to call the handler as few times
1175 : // as possible. Thus, when the first escape is encountered,
1176 : // the algorithm attempts to fill the temporary buffer first.
1177 : //
1178 13678 : detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1179 :
1180 : // Unescaped JSON is never larger than its escaped version.
1181 : // To efficiently process only what will fit in the temporary buffer,
1182 : // the size of the input stream is temporarily "clipped" to the size
1183 : // of the temporary buffer.
1184 : // handle escaped character
1185 13678 : detail::clipped_const_stream cs(p, end_);
1186 13678 : cs.clip(temp.max_size());
1187 :
1188 13678 : if(! stack_empty && ! st_.empty())
1189 : {
1190 : state st;
1191 3149 : st_.pop(st);
1192 3149 : switch(st)
1193 : {
1194 MIS 0 : default: BOOST_JSON_UNREACHABLE();
1195 HIT 528 : case state::str3: goto do_str3;
1196 392 : case state::str4: goto do_str4;
1197 390 : case state::str5: goto do_str5;
1198 389 : case state::str6: goto do_str6;
1199 386 : case state::str7: goto do_str7;
1200 232 : case state::sur1: goto do_sur1;
1201 188 : case state::sur2: goto do_sur2;
1202 164 : case state::sur3: goto do_sur3;
1203 162 : case state::sur4: goto do_sur4;
1204 160 : case state::sur5: goto do_sur5;
1205 158 : case state::sur6: goto do_sur6;
1206 : }
1207 : }
1208 :
1209 3781 : while(true)
1210 : {
1211 14310 : BOOST_ASSERT( temp.capacity() );
1212 14310 : BOOST_ASSERT(*cs == '\\');
1213 14310 : ++cs;
1214 15169 : do_str3:
1215 15374 : if(BOOST_JSON_UNLIKELY(! cs))
1216 : {
1217 561 : if(BOOST_JSON_LIKELY(! temp.empty()))
1218 : {
1219 MIS 0 : BOOST_ASSERT(total <= max_size);
1220 HIT 100 : if(BOOST_JSON_UNLIKELY(
1221 : temp.size() > max_size - total))
1222 : {
1223 : BOOST_STATIC_CONSTEXPR source_location loc
1224 : = BOOST_CURRENT_LOCATION;
1225 MIS 0 : return fail(cs.begin(), ev_too_large, &loc);
1226 : }
1227 HIT 100 : total += temp.size();
1228 : {
1229 91 : bool r = is_key
1230 100 : ? h_.on_key_part(temp.get(), total, ec_)
1231 100 : : h_.on_string_part(temp.get(), total, ec_);
1232 :
1233 91 : if(BOOST_JSON_UNLIKELY(!r))
1234 : {
1235 9 : return fail(cs.begin());
1236 : }
1237 : }
1238 82 : temp.clear();
1239 : }
1240 543 : cs.clip(temp.max_size());
1241 543 : if(BOOST_JSON_UNLIKELY(! cs))
1242 543 : return maybe_suspend(cs.begin(), state::str3);
1243 : }
1244 14813 : switch(*cs)
1245 : {
1246 191 : default:
1247 : {
1248 : BOOST_STATIC_CONSTEXPR source_location loc
1249 : = BOOST_CURRENT_LOCATION;
1250 191 : return fail(cs.begin(), error::syntax, &loc);
1251 : }
1252 265 : case '\x22': // '"'
1253 265 : temp.push_back('\x22');
1254 265 : ++cs;
1255 265 : break;
1256 178 : case '\\':
1257 178 : temp.push_back('\\');
1258 178 : ++cs;
1259 178 : break;
1260 96 : case '/':
1261 96 : temp.push_back('/');
1262 96 : ++cs;
1263 96 : break;
1264 112 : case 'b':
1265 112 : temp.push_back('\x08');
1266 112 : ++cs;
1267 112 : break;
1268 108 : case 'f':
1269 108 : temp.push_back('\x0c');
1270 108 : ++cs;
1271 108 : break;
1272 1763 : case 'n':
1273 1763 : temp.push_back('\x0a');
1274 1763 : ++cs;
1275 1763 : break;
1276 146 : case 'r':
1277 146 : temp.push_back('\x0d');
1278 146 : ++cs;
1279 146 : break;
1280 266 : case 't':
1281 266 : temp.push_back('\x09');
1282 266 : ++cs;
1283 266 : break;
1284 11688 : case 'u':
1285 : // utf16 escape
1286 : //
1287 : // fast path only when the buffer
1288 : // is large enough for 2 surrogates
1289 11688 : if(BOOST_JSON_LIKELY(cs.remain() > 10))
1290 : {
1291 : // KRYSTIAN TODO: this could be done
1292 : // with fewer instructions
1293 11394 : digit = detail::load_little_endian<4>(
1294 5697 : cs.begin() + 1);
1295 5697 : int d4 = detail::hex_digit(static_cast<
1296 5697 : unsigned char>(digit >> 24));
1297 5697 : int d3 = detail::hex_digit(static_cast<
1298 5697 : unsigned char>(digit >> 16));
1299 5697 : int d2 = detail::hex_digit(static_cast<
1300 5697 : unsigned char>(digit >> 8));
1301 5697 : int d1 = detail::hex_digit(static_cast<
1302 : unsigned char>(digit));
1303 5697 : if(BOOST_JSON_UNLIKELY(
1304 : (d1 | d2 | d3 | d4) == -1))
1305 : {
1306 60 : if(d1 != -1)
1307 45 : ++cs;
1308 60 : if(d2 != -1)
1309 30 : ++cs;
1310 60 : if(d3 != -1)
1311 15 : ++cs;
1312 : BOOST_STATIC_CONSTEXPR source_location loc
1313 : = BOOST_CURRENT_LOCATION;
1314 60 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1315 : }
1316 : // 32 bit unicode scalar value
1317 5637 : unsigned u1 =
1318 5637 : (d1 << 12) + (d2 << 8) +
1319 5637 : (d3 << 4) + d4;
1320 : // valid unicode scalar values are
1321 : // [0, D7FF] and [E000, 10FFFF]
1322 : // values within this range are valid utf-8
1323 : // code points and invalid leading surrogates.
1324 5637 : if(BOOST_JSON_LIKELY(
1325 : u1 < 0xd800 || u1 > 0xdfff))
1326 : {
1327 1340 : cs += 5;
1328 1340 : temp.append_utf8(u1);
1329 1340 : break;
1330 : }
1331 4297 : if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1332 : {
1333 : // If it's an illegal leading surrogate and
1334 : // the parser does not allow it, return an error.
1335 707 : if(!allow_bad_utf16)
1336 : {
1337 : BOOST_STATIC_CONSTEXPR source_location loc
1338 : = BOOST_CURRENT_LOCATION;
1339 122 : return fail(cs.begin(), error::illegal_leading_surrogate,
1340 122 : &loc);
1341 : }
1342 : // Otherwise, append the Unicode replacement character
1343 : else
1344 : {
1345 585 : cs += 5;
1346 585 : temp.append_utf8(urc);
1347 585 : break;
1348 : }
1349 : }
1350 3590 : cs += 5;
1351 : // KRYSTIAN TODO: this can be a two byte load
1352 : // and a single comparison. We lose error information,
1353 : // but it's faster.
1354 3590 : if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1355 : {
1356 : // If the next character is not a backslash and
1357 : // the parser does not allow it, return a syntax error.
1358 156 : if(!allow_bad_utf16)
1359 : {
1360 : BOOST_STATIC_CONSTEXPR source_location loc
1361 : = BOOST_CURRENT_LOCATION;
1362 15 : return fail(cs.begin(), error::syntax, &loc);
1363 : }
1364 : // Otherwise, append the Unicode replacement character since
1365 : // the first code point is a valid leading surrogate
1366 : else
1367 : {
1368 141 : temp.append_utf8(urc);
1369 141 : break;
1370 : }
1371 : }
1372 3434 : ++cs;
1373 3434 : if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1374 : {
1375 220 : if (!allow_bad_utf16)
1376 : {
1377 : BOOST_STATIC_CONSTEXPR source_location loc
1378 : = BOOST_CURRENT_LOCATION;
1379 15 : return fail(cs.begin(), error::syntax, &loc);
1380 : }
1381 : // Otherwise, append the Unicode replacement character since
1382 : // the first code point is a valid leading surrogate
1383 : else
1384 : {
1385 205 : temp.append_utf8(urc);
1386 205 : goto do_str3;
1387 : }
1388 : }
1389 3214 : ++cs;
1390 3214 : digit = detail::load_little_endian<4>(cs.begin());
1391 3214 : d4 = detail::hex_digit(static_cast<
1392 3214 : unsigned char>(digit >> 24));
1393 3214 : d3 = detail::hex_digit(static_cast<
1394 3214 : unsigned char>(digit >> 16));
1395 3214 : d2 = detail::hex_digit(static_cast<
1396 3214 : unsigned char>(digit >> 8));
1397 3214 : d1 = detail::hex_digit(static_cast<
1398 : unsigned char>(digit));
1399 3214 : if(BOOST_JSON_UNLIKELY(
1400 : (d1 | d2 | d3 | d4) == -1))
1401 : {
1402 90 : if(d1 != -1)
1403 75 : ++cs;
1404 90 : if(d2 != -1)
1405 45 : ++cs;
1406 90 : if(d3 != -1)
1407 15 : ++cs;
1408 : BOOST_STATIC_CONSTEXPR source_location loc
1409 : = BOOST_CURRENT_LOCATION;
1410 90 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1411 : }
1412 3124 : unsigned u2 =
1413 3124 : (d1 << 12) + (d2 << 8) +
1414 3124 : (d3 << 4) + d4;
1415 : // Check if the second code point is a valid trailing surrogate.
1416 : // Valid trailing surrogates are [DC00, DFFF]
1417 3124 : if(BOOST_JSON_UNLIKELY(
1418 : u2 < 0xdc00 || u2 > 0xdfff))
1419 : {
1420 : // If not valid and the parser does not allow it, return an error.
1421 1353 : if(!allow_bad_utf16)
1422 : {
1423 : BOOST_STATIC_CONSTEXPR source_location loc
1424 : = BOOST_CURRENT_LOCATION;
1425 136 : return fail(cs.begin(), error::illegal_trailing_surrogate,
1426 136 : &loc);
1427 : }
1428 : // Append the replacement character for the
1429 : // first leading surrogate.
1430 1217 : cs += 4;
1431 1217 : temp.append_utf8(urc);
1432 : // Check if the second code point is a
1433 : // valid unicode scalar value (invalid leading
1434 : // or trailing surrogate)
1435 1217 : if (u2 < 0xd800 || u2 > 0xdbff)
1436 : {
1437 524 : temp.append_utf8(u2);
1438 524 : break;
1439 : }
1440 : // If it is a valid leading surrogate
1441 : else
1442 : {
1443 693 : u1_ = u2;
1444 693 : goto do_sur1;
1445 : }
1446 : }
1447 1771 : cs += 4;
1448 : // Calculate the Unicode code point from the surrogate pair and
1449 : // append the UTF-8 representation.
1450 1771 : unsigned cp =
1451 1771 : ((u1 - 0xd800) << 10) +
1452 : ((u2 - 0xdc00)) +
1453 : 0x10000;
1454 : // utf-16 surrogate pair
1455 1771 : temp.append_utf8(cp);
1456 1771 : break;
1457 : }
1458 : // flush
1459 5991 : if(BOOST_JSON_LIKELY(! temp.empty()))
1460 : {
1461 3 : BOOST_ASSERT(total <= max_size);
1462 1722 : if(BOOST_JSON_UNLIKELY(
1463 : temp.size() > max_size - total))
1464 : {
1465 : BOOST_STATIC_CONSTEXPR source_location loc
1466 : = BOOST_CURRENT_LOCATION;
1467 MIS 0 : return fail(cs.begin(), ev_too_large, &loc);
1468 : }
1469 HIT 1722 : total += temp.size();
1470 : {
1471 1582 : bool r = is_key
1472 1722 : ? h_.on_key_part(temp.get(), total, ec_)
1473 1722 : : h_.on_string_part(temp.get(), total, ec_);
1474 :
1475 1582 : if(BOOST_JSON_UNLIKELY(!r))
1476 : {
1477 140 : return fail(cs.begin());
1478 : }
1479 : }
1480 1442 : temp.clear();
1481 1442 : cs.clip(temp.max_size());
1482 : }
1483 5711 : ++cs;
1484 : // utf-16 escape
1485 6103 : do_str4:
1486 6103 : if(BOOST_JSON_UNLIKELY(! cs))
1487 392 : return maybe_suspend(cs.begin(), state::str4);
1488 5711 : digit = detail::hex_digit(*cs);
1489 5711 : if(BOOST_JSON_UNLIKELY(digit == -1))
1490 : {
1491 : BOOST_STATIC_CONSTEXPR source_location loc
1492 : = BOOST_CURRENT_LOCATION;
1493 50 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1494 : }
1495 5661 : ++cs;
1496 5661 : u1_ = digit << 12;
1497 6051 : do_str5:
1498 6051 : if(BOOST_JSON_UNLIKELY(! cs))
1499 390 : return maybe_suspend(cs.begin(), state::str5);
1500 5661 : digit = detail::hex_digit(*cs);
1501 5661 : if(BOOST_JSON_UNLIKELY(digit == -1))
1502 : {
1503 : BOOST_STATIC_CONSTEXPR source_location loc
1504 : = BOOST_CURRENT_LOCATION;
1505 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1506 : }
1507 5641 : ++cs;
1508 5641 : u1_ += digit << 8;
1509 6030 : do_str6:
1510 6030 : if(BOOST_JSON_UNLIKELY(! cs))
1511 389 : return maybe_suspend(cs.begin(), state::str6);
1512 5641 : digit = detail::hex_digit(*cs);
1513 5641 : if(BOOST_JSON_UNLIKELY(digit == -1))
1514 : {
1515 : BOOST_STATIC_CONSTEXPR source_location loc
1516 : = BOOST_CURRENT_LOCATION;
1517 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1518 : }
1519 5621 : ++cs;
1520 5621 : u1_ += digit << 4;
1521 6007 : do_str7:
1522 6007 : if(BOOST_JSON_UNLIKELY(! cs))
1523 386 : return maybe_suspend(cs.begin(), state::str7);
1524 5621 : digit = detail::hex_digit(*cs);
1525 5621 : if(BOOST_JSON_UNLIKELY(digit == -1))
1526 : {
1527 : BOOST_STATIC_CONSTEXPR source_location loc
1528 : = BOOST_CURRENT_LOCATION;
1529 35 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1530 : }
1531 5586 : ++cs;
1532 5586 : u1_ += digit;
1533 5586 : if(BOOST_JSON_LIKELY(
1534 : u1_ < 0xd800 || u1_ > 0xdfff))
1535 : {
1536 1434 : BOOST_ASSERT(temp.empty());
1537 : // utf-8 codepoint
1538 1434 : temp.append_utf8(u1_);
1539 1434 : break;
1540 : }
1541 4152 : if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1542 : {
1543 : // If it's an illegal leading surrogate and
1544 : // the parser does not allow it, return an error.
1545 1585 : if(!allow_bad_utf16)
1546 : {
1547 : BOOST_STATIC_CONSTEXPR source_location loc
1548 : = BOOST_CURRENT_LOCATION;
1549 209 : return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1550 : }
1551 : // Otherwise, append the Unicode replacement character
1552 : else
1553 : {
1554 1376 : BOOST_ASSERT(temp.empty());
1555 1376 : temp.append_utf8(urc);
1556 1376 : break;
1557 : }
1558 : }
1559 2567 : do_sur1:
1560 3792 : if(BOOST_JSON_UNLIKELY(! cs))
1561 232 : return maybe_suspend(cs.begin(), state::sur1);
1562 3560 : if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1563 : {
1564 : // If the next character is not a backslash and
1565 : // the parser does not allow it, return a syntax error.
1566 952 : if(!allow_bad_utf16)
1567 : {
1568 : BOOST_STATIC_CONSTEXPR source_location loc
1569 : = BOOST_CURRENT_LOCATION;
1570 149 : return fail(cs.begin(), error::syntax, &loc);
1571 : }
1572 : // Otherwise, append the Unicode replacement character since
1573 : // the first code point is a valid leading surrogate
1574 : else
1575 : {
1576 803 : temp.append_utf8(urc);
1577 803 : break;
1578 : }
1579 : }
1580 2608 : ++cs;
1581 2796 : do_sur2:
1582 2796 : if(BOOST_JSON_UNLIKELY(! cs))
1583 188 : return maybe_suspend(cs.begin(), state::sur2);
1584 2608 : if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1585 : {
1586 396 : if (!allow_bad_utf16)
1587 : {
1588 : BOOST_STATIC_CONSTEXPR source_location loc
1589 : = BOOST_CURRENT_LOCATION;
1590 65 : return fail(cs.begin(), error::syntax, &loc);
1591 : }
1592 : // Otherwise, append the Unicode replacement character since
1593 : // the first code point is a valid leading surrogate
1594 : else
1595 : {
1596 331 : temp.append_utf8(urc);
1597 331 : goto do_str3;
1598 : }
1599 : }
1600 2212 : ++cs;
1601 2376 : do_sur3:
1602 2376 : if(BOOST_JSON_UNLIKELY(! cs))
1603 164 : return maybe_suspend(cs.begin(), state::sur3);
1604 2212 : digit = detail::hex_digit(*cs);
1605 2212 : if(BOOST_JSON_UNLIKELY(digit == -1))
1606 : {
1607 : BOOST_STATIC_CONSTEXPR source_location loc
1608 : = BOOST_CURRENT_LOCATION;
1609 35 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1610 : }
1611 2177 : ++cs;
1612 2177 : u2_ = digit << 12;
1613 2339 : do_sur4:
1614 2339 : if(BOOST_JSON_UNLIKELY(! cs))
1615 162 : return maybe_suspend(cs.begin(), state::sur4);
1616 2177 : digit = detail::hex_digit(*cs);
1617 2177 : if(BOOST_JSON_UNLIKELY(digit == -1))
1618 : {
1619 : BOOST_STATIC_CONSTEXPR source_location loc
1620 : = BOOST_CURRENT_LOCATION;
1621 35 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1622 : }
1623 2142 : ++cs;
1624 2142 : u2_ += digit << 8;
1625 2302 : do_sur5:
1626 2302 : if(BOOST_JSON_UNLIKELY(! cs))
1627 160 : return maybe_suspend(cs.begin(), state::sur5);
1628 2142 : digit = detail::hex_digit(*cs);
1629 2142 : if(BOOST_JSON_UNLIKELY(digit == -1))
1630 : {
1631 : BOOST_STATIC_CONSTEXPR source_location loc
1632 : = BOOST_CURRENT_LOCATION;
1633 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1634 : }
1635 2122 : ++cs;
1636 2122 : u2_ += digit << 4;
1637 2280 : do_sur6:
1638 2280 : if(BOOST_JSON_UNLIKELY(! cs))
1639 158 : return maybe_suspend(cs.begin(), state::sur6);
1640 2122 : digit = detail::hex_digit(*cs);
1641 2122 : if(BOOST_JSON_UNLIKELY(digit == -1))
1642 : {
1643 : BOOST_STATIC_CONSTEXPR source_location loc
1644 : = BOOST_CURRENT_LOCATION;
1645 20 : return fail(cs.begin(), error::expected_hex_digit, &loc);
1646 : }
1647 2102 : ++cs;
1648 2102 : u2_ += digit;
1649 : // Check if the second code point is a valid trailing surrogate.
1650 : // Valid trailing surrogates are [DC00, DFFF]
1651 2102 : if(BOOST_JSON_UNLIKELY(
1652 : u2_ < 0xdc00 || u2_ > 0xdfff))
1653 : {
1654 : // If not valid and the parser does not allow it, return an error.
1655 580 : if(!allow_bad_utf16)
1656 : {
1657 : BOOST_STATIC_CONSTEXPR source_location loc
1658 : = BOOST_CURRENT_LOCATION;
1659 60 : return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1660 : }
1661 : // Append the replacement character for the
1662 : // first leading surrogate.
1663 520 : temp.append_utf8(urc);
1664 : // Check if the second code point is a
1665 : // valid unicode scalar value (invalid leading
1666 : // or trailing surrogate)
1667 520 : if (u2_ < 0xd800 || u2_ > 0xdbff)
1668 : {
1669 220 : temp.append_utf8(u2_);
1670 220 : break;
1671 : }
1672 : // If it is a valid leading surrogate
1673 : else
1674 : {
1675 300 : u1_ = u2_;
1676 300 : goto do_sur1;
1677 : }
1678 : }
1679 : // Calculate the Unicode code point from the surrogate pair and
1680 : // append the UTF-8 representation.
1681 1522 : unsigned cp =
1682 1522 : ((u1_ - 0xd800) << 10) +
1683 1522 : ((u2_ - 0xdc00)) +
1684 : 0x10000;
1685 : // utf-16 surrogate pair
1686 1522 : temp.append_utf8(cp);
1687 : }
1688 :
1689 : // flush
1690 12650 : if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1691 8869 : break;
1692 : }
1693 :
1694 8869 : if(BOOST_JSON_LIKELY( temp.size() ))
1695 : {
1696 433 : BOOST_ASSERT(total <= max_size);
1697 8869 : if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1698 : {
1699 : BOOST_STATIC_CONSTEXPR source_location loc
1700 : = BOOST_CURRENT_LOCATION;
1701 MIS 0 : return fail(cs.begin(), ev_too_large, &loc);
1702 : }
1703 :
1704 HIT 8869 : total += temp.size();
1705 8056 : bool const r = is_key
1706 8869 : ? h_.on_key_part(temp.get(), total, ec_)
1707 8152 : : h_.on_string_part(temp.get(), total, ec_);
1708 8056 : if(BOOST_JSON_UNLIKELY( !r ))
1709 813 : return fail( cs.begin() );
1710 : }
1711 :
1712 7243 : return cs.begin();
1713 : }
1714 :
1715 : //----------------------------------------------------------
1716 :
1717 : template<class Handler>
1718 : template<
1719 : bool StackEmpty_,
1720 : bool AllowComments_/*,
1721 : bool AllowTrailing_,
1722 : bool AllowBadUTF8_*/>
1723 : const char*
1724 109189 : basic_parser<Handler>::
1725 : parse_object(const char* p,
1726 : std::integral_constant<bool, StackEmpty_> stack_empty,
1727 : std::integral_constant<bool, AllowComments_> allow_comments,
1728 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1729 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1730 : bool allow_bad_utf16)
1731 : {
1732 109189 : detail::const_stream_wrapper cs(p, end_);
1733 : std::size_t size;
1734 109189 : if(! stack_empty && ! st_.empty())
1735 : {
1736 : // resume
1737 : state st;
1738 35058 : st_.pop(st);
1739 35058 : st_.pop(size);
1740 35058 : switch(st)
1741 : {
1742 MIS 0 : default: BOOST_JSON_UNREACHABLE();
1743 HIT 1595 : case state::obj1: goto do_obj1;
1744 235 : case state::obj2: goto do_obj2;
1745 12647 : case state::obj3: goto do_obj3;
1746 1690 : case state::obj4: goto do_obj4;
1747 251 : case state::obj5: goto do_obj5;
1748 1591 : case state::obj6: goto do_obj6;
1749 15448 : case state::obj7: goto do_obj7;
1750 426 : case state::obj8: goto do_obj8;
1751 660 : case state::obj9: goto do_obj9;
1752 181 : case state::obj10: goto do_obj10;
1753 334 : case state::obj11: goto do_obj11;
1754 : }
1755 : }
1756 74131 : BOOST_ASSERT(*cs == '{');
1757 74131 : size = 0;
1758 74131 : if(BOOST_JSON_UNLIKELY(! depth_))
1759 : {
1760 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1761 3 : return fail(cs.begin(), error::too_deep, &loc);
1762 : }
1763 74128 : --depth_;
1764 74128 : if(BOOST_JSON_UNLIKELY(
1765 : ! h_.on_object_begin(ec_)))
1766 2040 : return fail(cs.begin());
1767 70050 : ++cs;
1768 : // object:
1769 : // '{' *ws '}'
1770 : // '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1771 73616 : do_obj1:
1772 73616 : cs = detail::count_whitespace(cs.begin(), cs.end());
1773 73616 : if(BOOST_JSON_UNLIKELY(! cs))
1774 1629 : return maybe_suspend(cs.begin(), state::obj1, size);
1775 71987 : if(BOOST_JSON_LIKELY(*cs != '}'))
1776 : {
1777 69088 : if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1778 : {
1779 2411 : if(allow_comments && *cs == '/')
1780 : {
1781 2139 : do_obj2:
1782 2374 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1783 2290 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1784 319 : return suspend_or_fail(state::obj2, size);
1785 1971 : goto do_obj1;
1786 : }
1787 : BOOST_STATIC_CONSTEXPR source_location loc
1788 : = BOOST_CURRENT_LOCATION;
1789 272 : return fail(cs.begin(), error::syntax, &loc);
1790 : }
1791 66677 : loop:
1792 80829 : if(BOOST_JSON_UNLIKELY(++size >
1793 : Handler::max_object_size))
1794 : {
1795 : BOOST_STATIC_CONSTEXPR source_location loc
1796 : = BOOST_CURRENT_LOCATION;
1797 1 : return fail(cs.begin(), error::object_too_large, &loc);
1798 : }
1799 80828 : do_obj3:
1800 93475 : cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1801 90519 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1802 15592 : return suspend_or_fail(state::obj3, size);
1803 74927 : do_obj4:
1804 79088 : cs = detail::count_whitespace(cs.begin(), cs.end());
1805 79088 : if(BOOST_JSON_UNLIKELY(! cs))
1806 1705 : return maybe_suspend(cs.begin(), state::obj4, size);
1807 77383 : if(BOOST_JSON_UNLIKELY(*cs != ':'))
1808 : {
1809 2925 : if(allow_comments && *cs == '/')
1810 : {
1811 2779 : do_obj5:
1812 3030 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1813 2876 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1814 405 : return suspend_or_fail(state::obj5, size);
1815 2471 : goto do_obj4;
1816 : }
1817 : BOOST_STATIC_CONSTEXPR source_location loc
1818 : = BOOST_CURRENT_LOCATION;
1819 146 : return fail(cs.begin(), error::syntax, &loc);
1820 : }
1821 74458 : ++cs;
1822 76049 : do_obj6:
1823 76049 : cs = detail::count_whitespace(cs.begin(), cs.end());
1824 76049 : if(BOOST_JSON_UNLIKELY(! cs))
1825 1622 : return maybe_suspend(cs.begin(), state::obj6, size);
1826 74427 : do_obj7:
1827 89875 : cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1828 82526 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1829 23593 : return suspend_or_fail(state::obj7, size);
1830 58933 : do_obj8:
1831 61195 : cs = detail::count_whitespace(cs.begin(), cs.end());
1832 61195 : if(BOOST_JSON_UNLIKELY(! cs))
1833 441 : return maybe_suspend(cs.begin(), state::obj8, size);
1834 60754 : if(BOOST_JSON_LIKELY(*cs == ','))
1835 : {
1836 17792 : ++cs;
1837 19707 : do_obj9:
1838 19707 : cs = detail::count_whitespace(cs.begin(), cs.end());
1839 19707 : if(BOOST_JSON_UNLIKELY(! cs))
1840 690 : return maybe_suspend(cs.begin(), state::obj9, size);
1841 :
1842 : // loop for next element
1843 19017 : if(BOOST_JSON_LIKELY(*cs == '\x22'))
1844 14152 : goto loop;
1845 4865 : if(! allow_trailing || *cs != '}')
1846 : {
1847 1644 : if(allow_comments && *cs == '/')
1848 : {
1849 1433 : do_obj10:
1850 1614 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1851 1525 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1852 270 : return suspend_or_fail(state::obj10, size);
1853 1255 : goto do_obj9;
1854 : }
1855 : BOOST_STATIC_CONSTEXPR source_location loc
1856 : = BOOST_CURRENT_LOCATION;
1857 211 : return fail(cs.begin(), error::syntax, &loc);
1858 : }
1859 : }
1860 42962 : else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1861 : {
1862 2325 : if(allow_comments && *cs == '/')
1863 : {
1864 2172 : do_obj11:
1865 2506 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1866 2338 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1867 502 : return suspend_or_fail(state::obj11, size);
1868 1836 : goto do_obj8;
1869 : }
1870 : BOOST_STATIC_CONSTEXPR source_location loc
1871 : = BOOST_CURRENT_LOCATION;
1872 153 : return fail(cs.begin(), error::syntax, &loc);
1873 : }
1874 : // got closing brace, fall through
1875 : }
1876 46757 : if(BOOST_JSON_UNLIKELY(
1877 : ! h_.on_object_end(size, ec_)))
1878 1502 : return fail(cs.begin());
1879 43714 : ++depth_;
1880 43714 : ++cs;
1881 43714 : return cs.begin();
1882 : }
1883 :
1884 : //----------------------------------------------------------
1885 :
1886 : template<class Handler>
1887 : template<
1888 : bool StackEmpty_,
1889 : bool AllowComments_/*,
1890 : bool AllowTrailing_,
1891 : bool AllowBadUTF8_*/>
1892 : const char*
1893 26348 : basic_parser<Handler>::
1894 : parse_array(const char* p,
1895 : std::integral_constant<bool, StackEmpty_> stack_empty,
1896 : std::integral_constant<bool, AllowComments_> allow_comments,
1897 : /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1898 : /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1899 : bool allow_bad_utf16)
1900 : {
1901 26348 : detail::const_stream_wrapper cs(p, end_);
1902 : std::size_t size;
1903 26348 : if(! stack_empty && ! st_.empty())
1904 : {
1905 : // resume
1906 : state st;
1907 5730 : st_.pop(st);
1908 5730 : st_.pop(size);
1909 5730 : switch(st)
1910 : {
1911 MIS 0 : default: BOOST_JSON_UNREACHABLE();
1912 HIT 1052 : case state::arr1: goto do_arr1;
1913 384 : case state::arr2: goto do_arr2;
1914 2938 : case state::arr3: goto do_arr3;
1915 391 : case state::arr4: goto do_arr4;
1916 671 : case state::arr5: goto do_arr5;
1917 294 : case state::arr6: goto do_arr6;
1918 : }
1919 : }
1920 20618 : BOOST_ASSERT(*cs == '[');
1921 20618 : size = 0;
1922 20618 : if(BOOST_JSON_UNLIKELY(! depth_))
1923 : {
1924 : BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1925 34 : return fail(cs.begin(), error::too_deep, &loc);
1926 : }
1927 20584 : --depth_;
1928 20584 : if(BOOST_JSON_UNLIKELY(
1929 : ! h_.on_array_begin(ec_)))
1930 812 : return fail(cs.begin());
1931 18966 : ++cs;
1932 : // array:
1933 : // '[' *ws ']'
1934 : // '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1935 21551 : do_arr1:
1936 21551 : cs = detail::count_whitespace(cs.begin(), cs.end());
1937 21551 : if(BOOST_JSON_UNLIKELY(! cs))
1938 1073 : return maybe_suspend(cs.begin(), state::arr1, size);
1939 20478 : if(BOOST_JSON_LIKELY(*cs != ']'))
1940 : {
1941 18730 : loop:
1942 26193 : if(allow_comments && *cs == '/')
1943 : {
1944 1789 : do_arr2:
1945 2173 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1946 2045 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1947 512 : return suspend_or_fail(state::arr2, size);
1948 1533 : goto do_arr1;
1949 : }
1950 24404 : if(BOOST_JSON_UNLIKELY(++size >
1951 : Handler::max_array_size))
1952 : {
1953 : BOOST_STATIC_CONSTEXPR source_location loc
1954 : = BOOST_CURRENT_LOCATION;
1955 1 : return fail(cs.begin(), error::array_too_large, &loc);
1956 : }
1957 24403 : do_arr3:
1958 : // array is not empty, value required
1959 27341 : cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1960 24710 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1961 9052 : return suspend_or_fail(state::arr3, size);
1962 15658 : do_arr4:
1963 17279 : cs = detail::count_whitespace(cs.begin(), cs.end());
1964 17279 : if(BOOST_JSON_UNLIKELY(! cs))
1965 500 : return maybe_suspend(cs.begin(), state::arr4, size);
1966 16779 : if(BOOST_JSON_LIKELY(*cs == ','))
1967 : {
1968 9176 : ++cs;
1969 9847 : do_arr5:
1970 9847 : cs = detail::count_whitespace(cs.begin(), cs.end());
1971 9847 : if(BOOST_JSON_UNLIKELY(! cs))
1972 701 : return maybe_suspend(cs.begin(), state::arr5, size);
1973 : // loop for next element
1974 9146 : if(! allow_trailing || *cs != ']')
1975 7463 : goto loop;
1976 : }
1977 7603 : else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1978 : {
1979 1969 : if(allow_comments && *cs == '/')
1980 : {
1981 1541 : do_arr6:
1982 1835 : cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1983 1688 : if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1984 458 : return suspend_or_fail(state::arr6, size);
1985 1230 : goto do_arr4;
1986 : }
1987 : BOOST_STATIC_CONSTEXPR source_location loc
1988 : = BOOST_CURRENT_LOCATION;
1989 428 : return fail(cs.begin(), error::syntax, &loc);
1990 : }
1991 : // got closing bracket; fall through
1992 : }
1993 9065 : if(BOOST_JSON_UNLIKELY(
1994 : ! h_.on_array_end(size, ec_)))
1995 547 : return fail(cs.begin());
1996 7939 : ++depth_;
1997 7939 : ++cs;
1998 7939 : return cs.begin();
1999 : }
2000 :
2001 : //----------------------------------------------------------
2002 :
2003 : template<class Handler>
2004 : template<bool StackEmpty_, char First_, number_precision Numbers_>
2005 : const char*
2006 2126888 : basic_parser<Handler>::
2007 : parse_number(const char* p,
2008 : std::integral_constant<bool, StackEmpty_> stack_empty,
2009 : std::integral_constant<char, First_> first,
2010 : std::integral_constant<number_precision, Numbers_> mode)
2011 : {
2012 2126888 : constexpr bool precise_parsing = mode == number_precision::precise;
2013 2126888 : constexpr bool no_parsing = mode == number_precision::none;
2014 :
2015 : // only one of these will be true if we are not resuming
2016 : // if negative then !zero_first && !nonzero_first
2017 : // if zero_first then !nonzero_first && !negative
2018 : // if nonzero_first then !zero_first && !negative
2019 2126888 : bool const negative = first == '-';
2020 2126888 : bool const zero_first = first == '0';
2021 2126888 : bool const nonzero_first = first == '+';
2022 2126888 : detail::const_stream_wrapper cs(p, end_);
2023 : number num;
2024 2126888 : const char* begin = cs.begin();
2025 2126888 : if(stack_empty || st_.empty())
2026 : {
2027 2089697 : num.bias = 0;
2028 2089697 : num.exp = 0;
2029 2089697 : num.frac = false;
2030 2089697 : num_buf_.clear();
2031 :
2032 : //----------------------------------
2033 : //
2034 : // '-'
2035 : // leading minus sign
2036 : //
2037 2089697 : BOOST_ASSERT(cs);
2038 : if(negative)
2039 25178 : ++cs;
2040 :
2041 2089697 : num.neg = negative;
2042 2089697 : num.frac = false;
2043 2089697 : num.exp = 0;
2044 2089697 : num.bias = 0;
2045 :
2046 : // fast path
2047 2089697 : if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048 : {
2049 : int n1;
2050 :
2051 9989 : if( nonzero_first ||
2052 9989 : (negative && *cs != '0') )
2053 : {
2054 2007318 : n1 = detail::count_digits( cs.begin() );
2055 2007318 : BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056 :
2057 1837 : if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058 : {
2059 9 : return parse_literal(
2060 : p - 1,
2061 8 : detail::literals_c<detail::literals::neg_infinity>());
2062 : }
2063 :
2064 1828 : if( ! nonzero_first && n1 == 0 )
2065 : {
2066 : // digit required
2067 : BOOST_STATIC_CONSTEXPR source_location loc
2068 : = BOOST_CURRENT_LOCATION;
2069 2 : return fail(cs.begin(), error::syntax, &loc);
2070 : }
2071 :
2072 : BOOST_IF_CONSTEXPR( !no_parsing )
2073 2006459 : num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074 : else
2075 848 : num.mant = 0;
2076 :
2077 2007307 : cs += n1;
2078 :
2079 : // integer or floating-point with
2080 : // >= 16 leading digits
2081 2007307 : if( n1 == 16 )
2082 : {
2083 2001424 : goto do_num2;
2084 : }
2085 : }
2086 : else
2087 : {
2088 : // 0. floating-point or 0e integer
2089 21187 : num.mant = 0;
2090 21187 : n1 = 0;
2091 21187 : ++cs;
2092 : }
2093 :
2094 : {
2095 27070 : const char c = *cs;
2096 27070 : if(c != '.')
2097 : {
2098 9871 : if((c | 32) == 'e')
2099 : {
2100 6576 : ++cs;
2101 6576 : goto do_exp1;
2102 : }
2103 : BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104 20 : num.mant = ~num.mant + 1;
2105 3295 : goto finish_signed;
2106 : }
2107 : }
2108 :
2109 : // floating-point number
2110 :
2111 17199 : ++cs;
2112 :
2113 17199 : int n2 = detail::count_digits( cs.begin() );
2114 17199 : BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115 :
2116 17199 : if( n2 == 0 )
2117 : {
2118 : // digit required
2119 : BOOST_STATIC_CONSTEXPR source_location loc
2120 : = BOOST_CURRENT_LOCATION;
2121 3 : return fail(cs.begin(), error::syntax, &loc);
2122 : }
2123 :
2124 : // floating-point mantissa overflow
2125 17196 : if( n1 + n2 >= 19 )
2126 : {
2127 122 : goto do_num7;
2128 : }
2129 :
2130 : BOOST_IF_CONSTEXPR( !no_parsing )
2131 12855 : num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132 :
2133 17074 : BOOST_ASSERT(num.bias == 0);
2134 :
2135 17074 : num.bias -= n2;
2136 :
2137 17074 : cs += n2;
2138 :
2139 17074 : char ch = *cs;
2140 :
2141 17074 : if( (ch | 32) == 'e' )
2142 : {
2143 110 : ++cs;
2144 110 : goto do_exp1;
2145 : }
2146 16964 : else if( ch >= '0' && ch <= '9' )
2147 : {
2148 10017 : goto do_num8;
2149 : }
2150 :
2151 6947 : goto finish_dub;
2152 : }
2153 : }
2154 : else
2155 : {
2156 37191 : num = num_;
2157 : state st;
2158 37191 : st_.pop(st);
2159 37191 : switch(st)
2160 : {
2161 MIS 0 : default: BOOST_JSON_UNREACHABLE();
2162 HIT 602 : case state::num1: goto do_num1;
2163 6338 : case state::num2: goto do_num2;
2164 802 : case state::num3: goto do_num3;
2165 52 : case state::num4: goto do_num4;
2166 4537 : case state::num5: goto do_num5;
2167 666 : case state::num6: goto do_num6;
2168 616 : case state::num7: goto do_num7;
2169 10944 : case state::num8: goto do_num8;
2170 469 : case state::exp1: goto do_exp1;
2171 133 : case state::exp2: goto do_exp2;
2172 12032 : case state::exp3: goto do_exp3;
2173 : }
2174 : }
2175 :
2176 : //----------------------------------
2177 : //
2178 : // DIGIT
2179 : // first digit
2180 : //
2181 61794 : do_num1:
2182 15791 : if(zero_first || nonzero_first ||
2183 15791 : BOOST_JSON_LIKELY(cs))
2184 : {
2185 61072 : char const c = *cs;
2186 : if(zero_first)
2187 : {
2188 9718 : ++cs;
2189 9718 : num.mant = 0;
2190 9718 : goto do_num6;
2191 : }
2192 15069 : else if(nonzero_first || BOOST_JSON_LIKELY(
2193 : c >= '1' && c <= '9'))
2194 : {
2195 42532 : ++cs;
2196 42532 : num.mant = c - '0';
2197 : }
2198 8822 : else if(BOOST_JSON_UNLIKELY(
2199 : c == '0'))
2200 : {
2201 7627 : ++cs;
2202 7627 : num.mant = 0;
2203 7627 : goto do_num6;
2204 : }
2205 1195 : else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206 : {
2207 1007 : st_.push(state::lit1);
2208 1007 : cur_lit_ = literal_index(detail::literals::neg_infinity);
2209 1007 : lit_offset_ = 1;
2210 1007 : return parse_literal(
2211 961 : cs.begin(), detail::literals_c<detail::literals::resume>() );
2212 : }
2213 : else
2214 : {
2215 : BOOST_STATIC_CONSTEXPR source_location loc
2216 : = BOOST_CURRENT_LOCATION;
2217 188 : return fail(cs.begin(), error::syntax, &loc);
2218 : }
2219 : }
2220 : else
2221 : {
2222 722 : if(BOOST_JSON_UNLIKELY(
2223 : ! h_.on_number_part(
2224 : {begin, cs.used(begin)}, ec_)))
2225 60 : return fail(cs.begin());
2226 :
2227 : BOOST_IF_CONSTEXPR( precise_parsing )
2228 64 : num_buf_.append( begin, cs.used(begin) );
2229 602 : return maybe_suspend(
2230 602 : cs.begin(), state::num1, num);
2231 : }
2232 :
2233 : //----------------------------------
2234 : //
2235 : // 1*DIGIT
2236 : // significant digits left of decimal
2237 : //
2238 2050294 : do_num2:
2239 2044036 : if(negative || (!stack_empty && num.neg))
2240 : {
2241 22400 : for(;;)
2242 : {
2243 30225 : if(BOOST_JSON_UNLIKELY(! cs))
2244 : {
2245 1921 : if(BOOST_JSON_UNLIKELY(more_))
2246 : {
2247 1469 : if(BOOST_JSON_UNLIKELY(
2248 : ! h_.on_number_part(
2249 : {begin, cs.used(begin)}, ec_)))
2250 69 : return fail(cs.begin());
2251 :
2252 : BOOST_IF_CONSTEXPR( precise_parsing )
2253 32 : num_buf_.append( begin, cs.used(begin) );
2254 1331 : return suspend(cs.begin(), state::num2, num);
2255 : }
2256 452 : goto finish_int;
2257 : }
2258 28304 : char const c = *cs;
2259 28304 : if(BOOST_JSON_LIKELY(
2260 : c >= '0' && c <= '9'))
2261 : {
2262 23223 : ++cs;
2263 : // 9223372036854775808 INT64_MIN
2264 23223 : if( num.mant > 922337203685477580 || (
2265 22508 : num.mant == 922337203685477580 && c > '8'))
2266 : break;
2267 : BOOST_IF_CONSTEXPR( !no_parsing )
2268 22141 : num.mant = 10 * num.mant + ( c - '0' );
2269 22400 : continue;
2270 : }
2271 5081 : goto do_num6; // [.eE]
2272 : }
2273 : }
2274 : else
2275 : {
2276 6885037 : for(;;)
2277 : {
2278 8927506 : if(BOOST_JSON_UNLIKELY(! cs))
2279 : {
2280 6426 : if(BOOST_JSON_UNLIKELY(more_))
2281 : {
2282 5813 : if(BOOST_JSON_UNLIKELY(
2283 : ! h_.on_number_part(
2284 : {begin, cs.used(begin)}, ec_)))
2285 406 : return fail(cs.begin());
2286 :
2287 : BOOST_IF_CONSTEXPR( precise_parsing )
2288 174 : num_buf_.append( begin, cs.used(begin) );
2289 5007 : return suspend(cs.begin(), state::num2, num);
2290 : }
2291 613 : goto finish_int;
2292 : }
2293 8921080 : char const c = *cs;
2294 8921080 : if(BOOST_JSON_LIKELY(
2295 : c >= '0' && c <= '9'))
2296 : {
2297 6888862 : ++cs;
2298 : // 18446744073709551615 UINT64_MAX
2299 6888862 : if( num.mant > 1844674407370955161 || (
2300 6885459 : num.mant == 1844674407370955161 && c > '5'))
2301 : break;
2302 : BOOST_IF_CONSTEXPR( !no_parsing )
2303 6879439 : num.mant = 10 * num.mant + ( c - '0' );
2304 : }
2305 : else
2306 : {
2307 2032218 : goto do_num6; // [.eE]
2308 : }
2309 : }
2310 : }
2311 4648 : ++num.bias;
2312 :
2313 : //----------------------------------
2314 : //
2315 : // 1*DIGIT
2316 : // non-significant digits left of decimal
2317 : //
2318 5450 : do_num3:
2319 11558 : for(;;)
2320 : {
2321 17008 : if(BOOST_JSON_UNLIKELY(! cs))
2322 : {
2323 1527 : if(BOOST_JSON_UNLIKELY(more_))
2324 : {
2325 894 : if(BOOST_JSON_UNLIKELY(
2326 : ! h_.on_number_part(
2327 : {begin, cs.used(begin)}, ec_)))
2328 46 : return fail(cs.begin());
2329 :
2330 : BOOST_IF_CONSTEXPR( precise_parsing )
2331 12 : num_buf_.append( begin, cs.used(begin) );
2332 802 : return suspend(cs.begin(), state::num3, num);
2333 : }
2334 633 : goto finish_dub;
2335 : }
2336 15481 : char const c = *cs;
2337 15481 : if(BOOST_JSON_UNLIKELY(
2338 : c >= '0' && c <= '9'))
2339 : {
2340 11558 : if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341 : {
2342 : BOOST_STATIC_CONSTEXPR source_location loc
2343 : = BOOST_CURRENT_LOCATION;
2344 MIS 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2345 : }
2346 HIT 11558 : ++cs;
2347 11558 : ++num.bias;
2348 : }
2349 3923 : else if(BOOST_JSON_LIKELY(
2350 : c == '.'))
2351 : {
2352 2028 : ++cs;
2353 2028 : break;
2354 : }
2355 1895 : else if((c | 32) == 'e')
2356 : {
2357 546 : ++cs;
2358 546 : goto do_exp1;
2359 : }
2360 : else
2361 : {
2362 1349 : goto finish_dub;
2363 : }
2364 : }
2365 :
2366 : //----------------------------------
2367 : //
2368 : // DIGIT
2369 : // first non-significant digit
2370 : // to the right of decimal
2371 : //
2372 2080 : do_num4:
2373 : {
2374 2080 : if(BOOST_JSON_UNLIKELY(! cs))
2375 : {
2376 64 : if(BOOST_JSON_UNLIKELY(
2377 : ! h_.on_number_part(
2378 : {begin, cs.used(begin)}, ec_)))
2379 6 : return fail(cs.begin());
2380 :
2381 : BOOST_IF_CONSTEXPR( precise_parsing )
2382 4 : num_buf_.append( begin, cs.used(begin) );
2383 52 : return maybe_suspend(
2384 52 : cs.begin(), state::num4, num);
2385 : }
2386 2016 : char const c = *cs;
2387 2016 : if(BOOST_JSON_LIKELY(
2388 : //static_cast<unsigned char>(c - '0') < 10))
2389 : c >= '0' && c <= '9'))
2390 : {
2391 1949 : ++cs;
2392 : }
2393 : else
2394 : {
2395 : // digit required
2396 : BOOST_STATIC_CONSTEXPR source_location loc
2397 : = BOOST_CURRENT_LOCATION;
2398 67 : return fail(cs.begin(), error::syntax, &loc);
2399 : }
2400 : }
2401 :
2402 : //----------------------------------
2403 : //
2404 : // 1*DIGIT
2405 : // non-significant digits
2406 : // to the right of decimal
2407 : //
2408 2013470 : do_num5:
2409 37889832 : for(;;)
2410 : {
2411 39903302 : if(BOOST_JSON_UNLIKELY(! cs))
2412 : {
2413 6112 : if(BOOST_JSON_UNLIKELY(more_))
2414 : {
2415 4577 : if(BOOST_JSON_UNLIKELY(
2416 : ! h_.on_number_part(
2417 : {begin, cs.used(begin)}, ec_)))
2418 20 : return fail(cs.begin());
2419 :
2420 : BOOST_IF_CONSTEXPR( precise_parsing )
2421 178 : num_buf_.append( begin, cs.used(begin) );
2422 4537 : return suspend(cs.begin(), state::num5, num);
2423 : }
2424 1535 : goto finish_dub;
2425 : }
2426 39897190 : char const c = *cs;
2427 39897190 : if(BOOST_JSON_LIKELY(
2428 : c >= '0' && c <= '9'))
2429 : {
2430 37889832 : ++cs;
2431 : }
2432 2007358 : else if((c | 32) == 'e')
2433 : {
2434 2003236 : ++cs;
2435 2003236 : goto do_exp1;
2436 : }
2437 : else
2438 : {
2439 4122 : goto finish_dub;
2440 : }
2441 : }
2442 :
2443 : //----------------------------------
2444 : //
2445 : // [.eE]
2446 : //
2447 2055310 : do_num6:
2448 : {
2449 2055310 : if(BOOST_JSON_UNLIKELY(! cs))
2450 : {
2451 798 : if(BOOST_JSON_UNLIKELY(more_))
2452 : {
2453 751 : if(BOOST_JSON_UNLIKELY(
2454 : ! h_.on_number_part(
2455 : {begin, cs.used(begin)}, ec_)))
2456 42 : return fail(cs.begin());
2457 :
2458 : BOOST_IF_CONSTEXPR( precise_parsing )
2459 98 : num_buf_.append( begin, cs.used(begin) );
2460 667 : return suspend(cs.begin(), state::num6, num);
2461 : }
2462 47 : goto finish_int;
2463 : }
2464 2054512 : char const c = *cs;
2465 2054512 : if(BOOST_JSON_LIKELY(
2466 : c == '.'))
2467 : {
2468 2016097 : ++cs;
2469 : }
2470 38415 : else if((c | 32) == 'e')
2471 : {
2472 9140 : ++cs;
2473 9140 : goto do_exp1;
2474 : }
2475 : else
2476 : {
2477 29275 : goto finish_int;
2478 : }
2479 : }
2480 :
2481 : //----------------------------------
2482 : //
2483 : // DIGIT
2484 : // first significant digit
2485 : // to the right of decimal
2486 : //
2487 2016835 : do_num7:
2488 : {
2489 2016835 : if(BOOST_JSON_UNLIKELY(! cs))
2490 : {
2491 691 : if(BOOST_JSON_UNLIKELY(more_))
2492 : {
2493 687 : if(BOOST_JSON_UNLIKELY(
2494 : ! h_.on_number_part(
2495 : {begin, cs.used(begin)}, ec_)))
2496 35 : return fail(cs.begin());
2497 :
2498 : BOOST_IF_CONSTEXPR( precise_parsing )
2499 96 : num_buf_.append( begin, cs.used(begin) );
2500 617 : return suspend(cs.begin(), state::num7, num);
2501 : }
2502 : // digit required
2503 : BOOST_STATIC_CONSTEXPR source_location loc
2504 : = BOOST_CURRENT_LOCATION;
2505 4 : return fail(cs.begin(), error::syntax, &loc);
2506 : }
2507 2016144 : char const c = *cs;
2508 2016144 : if(BOOST_JSON_UNLIKELY(
2509 : c < '0' || c > '9'))
2510 : {
2511 : // digit required
2512 : BOOST_STATIC_CONSTEXPR source_location loc
2513 : = BOOST_CURRENT_LOCATION;
2514 169 : return fail(cs.begin(), error::syntax, &loc);
2515 : }
2516 : }
2517 :
2518 : //----------------------------------
2519 : //
2520 : // 1*DIGIT
2521 : // significant digits
2522 : // to the right of decimal
2523 : //
2524 2034436 : do_num8:
2525 3277926 : for(;;)
2526 : {
2527 5314862 : if(BOOST_JSON_UNLIKELY(! cs))
2528 : {
2529 12816 : if(BOOST_JSON_UNLIKELY(more_))
2530 : {
2531 11080 : if(BOOST_JSON_UNLIKELY(
2532 : ! h_.on_number_part(
2533 : {begin, cs.used(begin)}, ec_)))
2534 67 : return fail(cs.begin());
2535 :
2536 : BOOST_IF_CONSTEXPR( precise_parsing )
2537 3442 : num_buf_.append( begin, cs.used(begin) );
2538 10945 : return suspend(cs.begin(), state::num8, num);
2539 : }
2540 1736 : goto finish_dub;
2541 : }
2542 5302046 : char const c = *cs;
2543 5302046 : if(BOOST_JSON_LIKELY(
2544 : c >= '0' && c <= '9'))
2545 : {
2546 5284910 : ++cs;
2547 5279817 : if(!no_parsing && BOOST_JSON_LIKELY(
2548 : num.mant <= 9007199254740991)) // 2^53-1
2549 : {
2550 3277926 : if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551 : {
2552 : BOOST_STATIC_CONSTEXPR source_location loc
2553 : = BOOST_CURRENT_LOCATION;
2554 MIS 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2555 : }
2556 HIT 3277926 : --num.bias;
2557 3277926 : num.mant = 10 * num.mant + ( c - '0' );
2558 : }
2559 : else
2560 : {
2561 2006984 : goto do_num5;
2562 : }
2563 : }
2564 17136 : else if((c | 32) == 'e')
2565 : {
2566 11133 : ++cs;
2567 11133 : goto do_exp1;
2568 : }
2569 : else
2570 : {
2571 6003 : goto finish_dub;
2572 : }
2573 : }
2574 :
2575 : //----------------------------------
2576 : //
2577 : // *[+-]
2578 : //
2579 2031210 : do_exp1:
2580 2031210 : if(BOOST_JSON_UNLIKELY(! cs))
2581 : {
2582 565 : if(BOOST_JSON_UNLIKELY(
2583 : ! h_.on_number_part(
2584 : {begin, cs.used(begin)}, ec_)))
2585 48 : return fail(cs.begin());
2586 :
2587 : BOOST_IF_CONSTEXPR( precise_parsing )
2588 46 : num_buf_.append( begin, cs.used(begin) );
2589 469 : return maybe_suspend(
2590 469 : cs.begin(), state::exp1, num);
2591 : }
2592 2030645 : if(*cs == '+')
2593 : {
2594 2150 : ++cs;
2595 : }
2596 2028495 : else if(*cs == '-')
2597 : {
2598 1001935 : ++cs;
2599 1001935 : num.frac = true;
2600 : }
2601 :
2602 : //----------------------------------
2603 : //
2604 : // DIGIT
2605 : // first digit of the exponent
2606 : //
2607 1026560 : do_exp2:
2608 : {
2609 2030778 : if(BOOST_JSON_UNLIKELY(! cs))
2610 : {
2611 180 : if(BOOST_JSON_UNLIKELY(more_))
2612 : {
2613 171 : if(BOOST_JSON_UNLIKELY(
2614 : ! h_.on_number_part(
2615 : {begin, cs.used(begin)}, ec_)))
2616 19 : return fail(cs.begin());
2617 :
2618 : BOOST_IF_CONSTEXPR( precise_parsing )
2619 4 : num_buf_.append( begin, cs.used(begin) );
2620 133 : return suspend(cs.begin(), state::exp2, num);
2621 : }
2622 : // digit required
2623 : BOOST_STATIC_CONSTEXPR source_location loc
2624 : = BOOST_CURRENT_LOCATION;
2625 9 : return fail(cs.begin(), error::syntax, &loc);
2626 : }
2627 2030598 : char const c = *cs;
2628 2030598 : if(BOOST_JSON_UNLIKELY(
2629 : c < '0' || c > '9'))
2630 : {
2631 : // digit required
2632 : BOOST_STATIC_CONSTEXPR source_location loc
2633 : = BOOST_CURRENT_LOCATION;
2634 508 : return fail(cs.begin(), error::syntax, &loc);
2635 : }
2636 2030090 : ++cs;
2637 2030090 : num.exp = c - '0';
2638 : }
2639 :
2640 : //----------------------------------
2641 : //
2642 : // 1*DIGIT
2643 : // subsequent digits in the exponent
2644 : //
2645 2042122 : do_exp3:
2646 5466310 : for(;;)
2647 : {
2648 7508432 : if(BOOST_JSON_UNLIKELY(! cs))
2649 : {
2650 2020539 : if(BOOST_JSON_UNLIKELY(more_))
2651 : {
2652 12186 : if(BOOST_JSON_UNLIKELY(
2653 : ! h_.on_number_part(
2654 : {begin, cs.used(begin)}, ec_)))
2655 77 : return fail(cs.begin());
2656 :
2657 : BOOST_IF_CONSTEXPR( precise_parsing )
2658 2873 : num_buf_.append( begin, cs.used(begin) );
2659 12032 : return suspend(cs.begin(), state::exp3, num);
2660 : }
2661 : }
2662 : else
2663 : {
2664 5487893 : char const c = *cs;
2665 5487893 : if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666 : {
2667 5466310 : if(BOOST_JSON_UNLIKELY(
2668 : // 2147483647 INT_MAX
2669 : num.exp > 214748364 ||
2670 : (num.exp == 214748364 && c > '7')
2671 : ))
2672 3855 : num.exp = INT_MAX;
2673 : else BOOST_IF_CONSTEXPR( !no_parsing )
2674 4921603 : num.exp = 10 * num.exp + ( c - '0' );
2675 :
2676 5466310 : ++cs;
2677 5466310 : continue;
2678 : }
2679 : }
2680 2029936 : BOOST_ASSERT(num.exp >= 0);
2681 2029936 : if ( num.frac )
2682 : {
2683 1001799 : if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684 : {
2685 : // if exponent overflowed, bias is a very large negative
2686 : // number, and mantissa isn't zero, then we cannot parse the
2687 : // number correctly
2688 91 : if(BOOST_JSON_UNLIKELY(
2689 : (num.exp == INT_MAX) &&
2690 : (num.bias < 0) &&
2691 : (num.exp + num.bias < 308) &&
2692 : num.mant ))
2693 : {
2694 : BOOST_STATIC_CONSTEXPR source_location loc
2695 : = BOOST_CURRENT_LOCATION;
2696 MIS 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2697 : }
2698 :
2699 HIT 91 : num.bias = 0;
2700 91 : num.exp = INT_MAX;
2701 : }
2702 : }
2703 1028137 : else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704 : {
2705 : // if exponent overflowed, bias is a very large positive number,
2706 : // and mantissa isn't zero, then we cannot parse the
2707 : // number correctly
2708 MIS 0 : if(BOOST_JSON_UNLIKELY(
2709 : (num.exp == INT_MAX) &&
2710 : (num.bias > 0) &&
2711 : (num.exp - num.bias < 308) &&
2712 : num.mant ))
2713 : {
2714 : BOOST_STATIC_CONSTEXPR source_location loc
2715 : = BOOST_CURRENT_LOCATION;
2716 0 : return fail(cs.begin(), error::exponent_overflow, &loc);
2717 : }
2718 :
2719 0 : num.bias = 0;
2720 0 : num.exp = INT_MAX;
2721 : }
2722 HIT 2029936 : goto finish_dub;
2723 : }
2724 :
2725 30387 : finish_int:
2726 28458 : if(negative || (!stack_empty && num.neg))
2727 : {
2728 2531 : if(BOOST_JSON_UNLIKELY(
2729 : ! h_.on_int64(static_cast<
2730 : int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731 310 : return fail(cs.begin());
2732 1913 : return cs.begin();
2733 : }
2734 27856 : if(num.mant <= INT64_MAX)
2735 : {
2736 27555 : finish_signed:
2737 30830 : if(BOOST_JSON_UNLIKELY(
2738 : ! h_.on_int64(static_cast<
2739 : int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740 2267 : return fail(cs.begin());
2741 26303 : return cs.begin();
2742 : }
2743 321 : if(BOOST_JSON_UNLIKELY(
2744 : ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745 35 : return fail(cs.begin());
2746 254 : return cs.begin();
2747 2052261 : finish_dub:
2748 : double d;
2749 2052261 : std::size_t const size = cs.used(begin);
2750 2052261 : BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751 : BOOST_IF_CONSTEXPR( precise_parsing )
2752 : {
2753 1009310 : char const* data = begin;
2754 1009310 : std::size_t full_size = size;
2755 : // if we previously suspended or if the current input ends with the
2756 : // number, we need to copy the current part of the number to the
2757 : // temporary buffer
2758 1009310 : if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759 : {
2760 4771 : data = num_buf_.append( begin, size );
2761 4771 : full_size = num_buf_.size();
2762 : }
2763 1009310 : auto const err = detail::charconv::from_chars(
2764 : data, data + full_size, d );
2765 1009310 : BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766 1009310 : BOOST_ASSERT( err.ptr == data + full_size );
2767 : (void)err;
2768 : }
2769 : else BOOST_IF_CONSTEXPR( no_parsing )
2770 9258 : d = 0;
2771 : else
2772 1033693 : d = detail::dec_to_float(
2773 : num.mant,
2774 531741 : num.bias + (num.frac ?
2775 501952 : -num.exp : num.exp),
2776 1033693 : num.neg);
2777 2052261 : if(BOOST_JSON_UNLIKELY(
2778 : ! h_.on_double(d, {begin, size}, ec_)))
2779 1903 : return fail(cs.begin());
2780 2048455 : return cs.begin();
2781 : }
2782 :
2783 : //----------------------------------------------------------
2784 :
2785 : template<class Handler>
2786 : template<class... Args>
2787 2164608 : basic_parser<Handler>::
2788 : basic_parser(
2789 : parse_options const& opt,
2790 : Args&&... args)
2791 2164600 : : h_(std::forward<Args>(args)...)
2792 2164608 : , opt_(opt)
2793 : {
2794 2164608 : }
2795 :
2796 : //----------------------------------------------------------
2797 :
2798 : template<class Handler>
2799 : void
2800 4153132 : basic_parser<Handler>::
2801 : reset() noexcept
2802 : {
2803 4153132 : ec_ = {};
2804 4153132 : st_.clear();
2805 4153132 : more_ = true;
2806 4153132 : done_ = false;
2807 4153132 : clean_ = true;
2808 4153132 : num_buf_.clear();
2809 4153132 : }
2810 :
2811 : template<class Handler>
2812 : void
2813 16 : basic_parser<Handler>::
2814 : fail(system::error_code ec) noexcept
2815 : {
2816 16 : if(! ec)
2817 : {
2818 : // assign an arbitrary
2819 : // error code to prevent UB
2820 MIS 0 : BOOST_JSON_FAIL(ec_, error::incomplete);
2821 : }
2822 : else
2823 : {
2824 HIT 16 : ec_ = ec;
2825 : }
2826 16 : done_ = false;
2827 16 : }
2828 :
2829 : //----------------------------------------------------------
2830 :
2831 : template<class Handler>
2832 : std::size_t
2833 2334223 : basic_parser<Handler>::
2834 : write_some(
2835 : bool more,
2836 : char const* data,
2837 : std::size_t size,
2838 : system::error_code& ec)
2839 : {
2840 : // see if we exited via exception
2841 : // on the last call to write_some
2842 2334223 : if(! clean_)
2843 : {
2844 : // prevent UB
2845 1 : if(! ec_)
2846 : {
2847 1 : BOOST_JSON_FAIL(ec_, error::exception);
2848 : }
2849 : }
2850 2334223 : if(ec_)
2851 : {
2852 : // error is sticky
2853 5 : ec = ec_;
2854 5 : return 0;
2855 : }
2856 2334218 : clean_ = false;
2857 2334218 : more_ = more;
2858 2334218 : end_ = data + size;
2859 : const char* p;
2860 2334218 : if(BOOST_JSON_LIKELY(st_.empty()))
2861 : {
2862 : // first time
2863 2164594 : depth_ = opt_.max_depth;
2864 2164594 : if(BOOST_JSON_UNLIKELY(
2865 : ! h_.on_document_begin(ec_)))
2866 : {
2867 7889 : ec = ec_;
2868 7889 : return 0;
2869 : }
2870 2148815 : p = parse_document(data, std::true_type());
2871 : }
2872 : else
2873 : {
2874 169624 : p = parse_document(data, std::false_type());
2875 : }
2876 :
2877 2299340 : if(BOOST_JSON_LIKELY(p != sentinel()))
2878 : {
2879 2099052 : BOOST_ASSERT(! ec_);
2880 2099052 : if(! done_)
2881 : {
2882 2031637 : done_ = true;
2883 2031637 : h_.on_document_end(ec_);
2884 : }
2885 : }
2886 : else
2887 : {
2888 200288 : if(! ec_)
2889 : {
2890 173509 : if(! more_)
2891 : {
2892 573 : BOOST_JSON_FAIL(ec_, error::incomplete);
2893 : }
2894 172936 : else if(! st_.empty())
2895 : {
2896 : // consume as much trailing whitespace in
2897 : // the JSON document as possible, but still
2898 : // consider the parse complete
2899 : state st;
2900 172936 : st_.peek(st);
2901 172936 : if( st == state::doc3 &&
2902 88551 : ! done_)
2903 : {
2904 70724 : done_ = true;
2905 70724 : h_.on_document_end(ec_);
2906 : }
2907 : }
2908 : }
2909 198644 : p = end_;
2910 : }
2911 2293736 : ec = ec_;
2912 2293736 : clean_ = true;
2913 2293736 : return p - data;
2914 : }
2915 :
2916 : template<class Handler>
2917 : std::size_t
2918 1 : basic_parser<Handler>::
2919 : write_some(
2920 : bool more,
2921 : char const* data,
2922 : std::size_t size,
2923 : std::error_code& ec)
2924 : {
2925 1 : system::error_code jec;
2926 1 : std::size_t const result = write_some(more, data, size, jec);
2927 1 : ec = jec;
2928 1 : return result;
2929 : }
2930 :
2931 : #endif
2932 :
2933 : } // namespace json
2934 : } // namespace boost
2935 :
2936 : #ifdef _MSC_VER
2937 : #pragma warning(pop)
2938 : #endif
2939 :
2940 : #endif
|