basic_parser_impl.hpp

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