basic_parser_impl.hpp

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