GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: basic_parser_impl.hpp
Date: 2025-12-23 17:20:53
Exec Total Coverage
Lines: 1253 1275 98.3%
Functions: 1531 4324 35.4%
Branches: 1041 1266 82.2%

Line Branch Exec Source
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 4253760 operator()( mp11::mp_size_t<N> ) const
205 {
206 8496638 return parser->parse_number(
207 4253760 p,
208 std::integral_constant<bool, StackEmpty_>(),
209 std::integral_constant<char, First_>(),
210 std::integral_constant<
211 4242880 number_precision, static_cast<number_precision>(N)>() );
212 }
213 };
214
215 //----------------------------------------------------------
216
217 template<class Handler>
218 void
219 275010 basic_parser<Handler>::
220 reserve()
221 {
222
2/2
✓ Branch 1 taken 37619 times.
✓ Branch 2 taken 173315 times.
275010 if(BOOST_JSON_LIKELY(
223 ! st_.empty()))
224 58636 return;
225 // Reserve the largest stack we need,
226 // to avoid reallocation during suspend.
227 432748 st_.reserve(
228 sizeof(state) + // document parsing state
229 (sizeof(state) +
230 216374 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 5929271 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 5929271 const char*>(this) + 1;
252 }
253
254 template<class Handler>
255 bool
256 2697371 basic_parser<Handler>::
257 incomplete(
258 const detail::const_stream_wrapper& cs)
259 {
260 2697371 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 95877 basic_parser<Handler>::
288 suspend_or_fail(
289 state st,
290 std::size_t n)
291 {
292
6/6
✓ Branch 1 taken 36108 times.
✓ Branch 2 taken 20117 times.
✓ Branch 3 taken 35911 times.
✓ Branch 4 taken 197 times.
✓ Branch 5 taken 35911 times.
✓ Branch 6 taken 20314 times.
95877 if(BOOST_JSON_LIKELY(
293 ! ec_ && more_))
294 {
295 // suspend
296 55259 reserve();
297 55259 st_.push_unchecked(n);
298 55259 st_.push_unchecked(st);
299 }
300 95877 return sentinel();
301 }
302
303
304 template<class Handler>
305 const char*
306 38010 basic_parser<Handler>::
307 fail(const char* p) noexcept
308 {
309
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 19005 times.
38010 BOOST_ASSERT( p != sentinel() );
310 38010 end_ = p;
311 38010 return sentinel();
312 }
313
314 template<class Handler>
315 const char*
316 15522 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.
15522 BOOST_ASSERT( p != sentinel() );
323 15522 end_ = p;
324 15522 ec_.assign(ev, loc);
325 15522 return sentinel();
326 }
327
328 template<class Handler>
329 const char*
330 22517 basic_parser<Handler>::
331 maybe_suspend(
332 const char* p,
333 state st)
334 {
335
2/2
✓ Branch 1 taken 9529 times.
✓ Branch 2 taken 1965 times.
22517 if( p != sentinel() )
336 18626 end_ = p;
337
2/2
✓ Branch 0 taken 11232 times.
✓ Branch 1 taken 262 times.
22517 if(BOOST_JSON_LIKELY(more_))
338 {
339 // suspend
340 22012 reserve();
341 22012 st_.push_unchecked(st);
342 }
343 22517 return sentinel();
344 }
345
346 template<class Handler>
347 const char*
348 59544 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 38336 times.
59544 BOOST_ASSERT( p != sentinel() );
355 59544 end_ = p;
356
2/2
✓ Branch 0 taken 37936 times.
✓ Branch 1 taken 400 times.
59544 if(BOOST_JSON_LIKELY(more_))
357 {
358 // suspend
359 58750 reserve();
360 58750 st_.push_unchecked(n);
361 58750 st_.push_unchecked(st);
362 }
363 59544 return sentinel();
364 }
365
366 template<class Handler>
367 const char*
368 1736 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.
1736 BOOST_ASSERT( p != sentinel() );
375 1736 end_ = p;
376
1/2
✓ Branch 0 taken 1123 times.
✗ Branch 1 not taken.
1736 if(BOOST_JSON_LIKELY(more_))
377 {
378 // suspend
379 1736 num_ = num;
380 1736 reserve();
381 1736 st_.push_unchecked(st);;
382 }
383 1736 return sentinel();
384 }
385
386 template<class Handler>
387 const char*
388 95545 basic_parser<Handler>::
389 suspend(
390 const char* p,
391 state st)
392 {
393
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 88676 times.
95545 BOOST_ASSERT( p != sentinel() );
394 95545 end_ = p;
395 // suspend
396 95545 reserve();
397 95545 st_.push_unchecked(st);
398 95545 return sentinel();
399 }
400
401 template<class Handler>
402 const char*
403 41708 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 36056 times.
41708 BOOST_ASSERT( p != sentinel() );
410 41708 end_ = p;
411 // suspend
412 41708 num_ = num;
413 41708 reserve();
414 41708 st_.push_unchecked(st);
415 41708 return sentinel();
416 }
417
418 template<class Handler>
419 template<
420 bool StackEmpty_/*,
421 bool Terminal_*/>
422 const char*
423 43684 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 43684 detail::const_stream_wrapper cs(p, end_);
429 43684 const char* start = cs.begin();
430 std::size_t remain;
431
6/6
✓ Branch 1 taken 8021 times.
✓ Branch 2 taken 13821 times.
✓ Branch 4 taken 3607 times.
✓ Branch 5 taken 4414 times.
✓ Branch 6 taken 3607 times.
✓ Branch 7 taken 18235 times.
43684 if(! stack_empty && ! st_.empty())
432 {
433 state st;
434
1/1
✓ Branch 1 taken 3607 times.
7214 st_.pop(st);
435
4/5
✗ Branch 0 not taken.
✓ Branch 1 taken 539 times.
✓ Branch 2 taken 2414 times.
✓ Branch 3 taken 438 times.
✓ Branch 4 taken 216 times.
7214 switch(st)
436 {
437 default: BOOST_JSON_UNREACHABLE();
438 1078 case state::com1: goto do_com1;
439 4828 case state::com2: goto do_com2;
440 876 case state::com3: goto do_com3;
441 432 case state::com4: goto do_com4;
442 }
443 }
444
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 18235 times.
36470 BOOST_ASSERT(*cs == '/');
445 36470 ++cs;
446 37548 do_com1:
447
2/2
✓ Branch 1 taken 556 times.
✓ Branch 2 taken 18218 times.
37548 if(BOOST_JSON_UNLIKELY(! cs))
448
1/1
✓ Branch 2 taken 556 times.
1112 return maybe_suspend(cs.begin(), state::com1);
449
3/3
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 10529 times.
✓ Branch 3 taken 7684 times.
36436 switch(*cs)
450 {
451 10 default:
452 {
453 BOOST_STATIC_CONSTEXPR source_location loc
454 = BOOST_CURRENT_LOCATION;
455 10 return fail(cs.begin(), error::syntax, &loc);
456 }
457 21058 case '/':
458 21058 ++cs;
459 25886 do_com2:
460 // KRYSTIAN TODO: this is a mess, we have to fix this
461 25886 remain = cs.remain();
462
2/2
✓ Branch 0 taken 12513 times.
✓ Branch 1 taken 430 times.
51772 cs = remain ? static_cast<const char*>(
463 25886 std::memchr(cs.begin(), '\n', remain)) : sentinel();
464
2/2
✓ Branch 1 taken 2233 times.
✓ Branch 2 taken 10710 times.
25886 if(! cs.begin())
465 4466 cs = sentinel();
466
2/2
✓ Branch 1 taken 2663 times.
✓ Branch 2 taken 10280 times.
25886 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 2498 times.
✓ Branch 2 taken 39 times.
✓ Branch 3 taken 126 times.
5326 if(terminal && ! more_)
472 {
473
3/6
✗ Branch 1 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 7 not taken.
✓ Branch 3 taken 6 times.
✗ Branch 5 not taken.
✓ Branch 4 taken 26 times.
78 if(BOOST_JSON_UNLIKELY(! h_.on_comment(
474 {start, cs.remain(start)}, ec_)))
475 4 return fail(cs.end());
476 70 return cs.end();
477 }
478
3/6
✗ Branch 1 not taken.
✓ Branch 6 taken 482 times.
✗ Branch 7 not taken.
✓ Branch 3 taken 577 times.
✗ Branch 5 not taken.
✓ Branch 4 taken 1467 times.
5248 if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479 {start, cs.remain(start)}, ec_)))
480 190 return fail(cs.end());
481
2/2
✓ Branch 0 taken 106 times.
✓ Branch 1 taken 2328 times.
4868 if(terminal)
482
1/1
✓ Branch 2 taken 106 times.
212 return suspend(cs.end(), state::com2);
483
1/1
✓ Branch 2 taken 2328 times.
4656 return maybe_suspend(cs.end(), state::com2);
484 }
485 20560 break;
486 3368 case '*':
487 do
488 {
489 18736 ++cs;
490 19612 do_com3:
491 // KRYSTIAN TODO: this is a mess, we have to fix this
492 19612 remain = cs.remain();
493
2/2
✓ Branch 0 taken 9545 times.
✓ Branch 1 taken 261 times.
39224 cs = remain ? static_cast<const char*>(
494 19612 std::memchr(cs.begin(), '*', remain)) : sentinel();
495
2/2
✓ Branch 1 taken 242 times.
✓ Branch 2 taken 9564 times.
19612 if(! cs.begin())
496 484 cs = sentinel();
497 // stopped inside a c comment
498
2/2
✓ Branch 1 taken 503 times.
✓ Branch 2 taken 9303 times.
19612 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
499 {
500
3/6
✗ Branch 1 not taken.
✓ Branch 6 taken 193 times.
✗ Branch 7 not taken.
✓ Branch 3 taken 223 times.
✗ Branch 5 not taken.
✓ Branch 4 taken 56 times.
1006 if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
501 {start, cs.remain(start)}, ec_)))
502 60 return fail(cs.end());
503
1/1
✓ Branch 2 taken 443 times.
886 return maybe_suspend(cs.end(), state::com3);
504 }
505 // found a asterisk, check if the next char is a slash
506 18606 ++cs;
507 19038 do_com4:
508
2/2
✓ Branch 1 taken 259 times.
✓ Branch 2 taken 9260 times.
19038 if(BOOST_JSON_UNLIKELY(! cs))
509 {
510
3/6
✗ Branch 1 not taken.
✓ Branch 6 taken 104 times.
✗ Branch 7 not taken.
✓ Branch 3 taken 122 times.
✗ Branch 5 not taken.
✓ Branch 4 taken 14 times.
518 if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511 {start, cs.used(start)}, ec_)))
512 36 return fail(cs.begin());
513
1/1
✓ Branch 2 taken 223 times.
446 return maybe_suspend(cs.begin(), state::com4);
514 }
515 }
516
2/2
✓ Branch 1 taken 1684 times.
✓ Branch 2 taken 7576 times.
18520 while(*cs != '/');
517 }
518 35712 ++cs;
519
3/6
✗ Branch 1 not taken.
✓ Branch 6 taken 7687 times.
✗ Branch 7 not taken.
✓ Branch 3 taken 8651 times.
✗ Branch 5 not taken.
✓ Branch 4 taken 544 times.
35712 if(BOOST_JSON_UNLIKELY(! h_.on_comment(
520 {start, cs.used(start)}, ec_)))
521 1928 return fail(cs.begin());
522 31856 return cs.begin();
523 }
524
525 template<class Handler>
526 template<bool StackEmpty_>
527 const char*
528 4637364 basic_parser<Handler>::
529 parse_document(const char* p,
530 std::integral_constant<bool, StackEmpty_> stack_empty)
531 {
532 4637364 detail::const_stream_wrapper cs(p, end_);
533
5/6
✓ Branch 1 taken 169836 times.
✓ Branch 2 taken 2148846 times.
✓ Branch 4 taken 169836 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 169836 times.
✓ Branch 7 taken 2148846 times.
4637364 if(! stack_empty && ! st_.empty())
534 {
535 state st;
536 339672 st_.peek(st);
537
4/4
✓ Branch 0 taken 83752 times.
✓ Branch 1 taken 601 times.
✓ Branch 2 taken 85263 times.
✓ Branch 3 taken 220 times.
339672 switch(st)
538 {
539 167504 default: goto do_doc2;
540 1202 case state::doc1:
541
1/1
✓ Branch 1 taken 601 times.
1202 st_.pop(st);
542 1202 goto do_doc1;
543 170526 case state::doc3:
544
1/1
✓ Branch 1 taken 85263 times.
170526 st_.pop(st);
545 170526 goto do_doc3;
546 440 case state::com1: case state::com2:
547 case state::com3: case state::com4:
548 440 goto do_doc4;
549 }
550 }
551 4297692 do_doc1:
552 4298894 cs = detail::count_whitespace(cs.begin(), cs.end());
553
2/2
✓ Branch 1 taken 633 times.
✓ Branch 2 taken 2148814 times.
4298894 if(BOOST_JSON_UNLIKELY(! cs))
554
1/1
✓ Branch 2 taken 633 times.
1266 return maybe_suspend(cs.begin(), state::doc1);
555 4297628 do_doc2:
556 4465132 switch(+opt_.allow_comments |
557 4465132 (opt_.allow_trailing_commas << 1) |
558
8/8
✓ Branch 0 taken 2208676 times.
✓ Branch 1 taken 13759 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.
4465132 (opt_.allow_invalid_utf8 << 2))
559 {
560 // no extensions
561 4417352 default:
562
1/1
✓ Branch 4 taken 2193516 times.
4417352 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563 4387036 break;
564 // comments
565 27518 case 1:
566
1/1
✓ Branch 4 taken 11496 times.
27518 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567 22992 break;
568 // trailing
569 13420 case 2:
570
1/1
✓ Branch 4 taken 5117 times.
13420 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571 10234 break;
572 // comments & trailing
573 1522 case 3:
574
1/1
✓ Branch 4 taken 761 times.
1522 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575 1522 break;
576 // skip validation
577 1520 case 4:
578
1/1
✓ Branch 4 taken 760 times.
1520 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579 1520 break;
580 // comments & skip validation
581 1520 case 5:
582
1/1
✓ Branch 4 taken 760 times.
1520 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583 1520 break;
584 // trailing & skip validation
585 1520 case 6:
586
1/1
✓ Branch 4 taken 760 times.
1520 cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587 1520 break;
588 // comments & trailing & skip validation
589 760 case 7:
590
1/1
✓ Branch 4 taken 380 times.
760 cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591 760 break;
592 }
593
2/2
✓ Branch 1 taken 110955 times.
✓ Branch 2 taken 2102597 times.
4427104 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594 // the appropriate state has already been pushed into stack
595 221910 return sentinel();
596 4205194 do_doc3:
597 4376384 cs = detail::count_whitespace(cs.begin(), cs.end());
598
2/2
✓ Branch 1 taken 2185594 times.
✓ Branch 2 taken 2598 times.
4376384 if(BOOST_JSON_UNLIKELY(! cs))
599 {
600
2/2
✓ Branch 0 taken 88570 times.
✓ Branch 1 taken 2097024 times.
4371188 if(more_)
601
1/1
✓ Branch 2 taken 88570 times.
177140 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.
5196 else if(opt_.allow_comments && *cs == '/')
604 {
605 1072 do_doc4:
606
1/1
✓ Branch 3 taken 671 times.
1512 cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
2/2
✓ Branch 1 taken 339 times.
✓ Branch 2 taken 332 times.
1342 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608 678 return sentinel();
609 664 goto do_doc3;
610 }
611 4198172 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 4700646 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 126947 times.
✓ Branch 2 taken 2223376 times.
✓ Branch 4 taken 24770 times.
✓ Branch 5 taken 102177 times.
✓ Branch 6 taken 2248146 times.
✓ Branch 7 taken 102177 times.
4700646 if(stack_empty || st_.empty())
630 {
631 4496292 loop:
632
14/14
✓ Branch 0 taken 22753 times.
✓ Branch 1 taken 25178 times.
✓ Branch 2 taken 2041773 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 47660 times.
✓ Branch 9 taken 20632 times.
✓ Branch 10 taken 74142 times.
✓ Branch 11 taken 6130 times.
✓ Branch 12 taken 12 times.
✓ Branch 13 taken 1105 times.
4506124 switch(*p)
633 {
634 45506 case '0':
635 45506 return mp11::mp_with_index<3>(
636
1/1
✓ Branch 1 taken 22092 times.
45506 static_cast<unsigned char>(opt_.numbers),
637 44184 parse_number_helper<true, '0'>{ this, p });
638 50356 case '-':
639 50356 return mp11::mp_with_index<3>(
640
1/1
✓ Branch 1 taken 24066 times.
50356 static_cast<unsigned char>(opt_.numbers),
641 48132 parse_number_helper<true, '-'>{ this, p });
642 4083546 case '1': case '2': case '3':
643 case '4': case '5': case '6':
644 case '7': case '8': case '9':
645 4083546 return mp11::mp_with_index<3>(
646
1/1
✓ Branch 1 taken 2038928 times.
4083546 static_cast<unsigned char>(opt_.numbers),
647 4077858 parse_number_helper<true, '+'>{ this, p });
648 22758 case 'n':
649 22758 return parse_literal( p, detail::literals_c<detail::literals::null>() );
650 1328 case 't':
651 1328 return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652 1444 case 'f':
653 1444 return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654 1362 case 'I':
655
2/2
✓ Branch 0 taken 24 times.
✓ Branch 1 taken 657 times.
1362 if( !opt_.allow_infinity_and_nan )
656 {
657 BOOST_STATIC_CONSTEXPR source_location loc
658 = BOOST_CURRENT_LOCATION;
659 48 return fail(p, error::syntax, &loc);
660 }
661 1314 return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662 462 case 'N':
663
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 201 times.
462 if( !opt_.allow_infinity_and_nan )
664 {
665 BOOST_STATIC_CONSTEXPR source_location loc
666 = BOOST_CURRENT_LOCATION;
667 60 return fail(p, error::syntax, &loc);
668 }
669 402 return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670 95320 case '"':
671 95320 return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672 41264 case '[':
673 41264 return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674 148284 case '{':
675 148284 return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676 12260 case '/':
677
2/2
✓ Branch 1 taken 284 times.
✓ Branch 2 taken 5846 times.
12260 if(! allow_comments)
678 {
679 BOOST_STATIC_CONSTEXPR source_location loc
680 = BOOST_CURRENT_LOCATION;
681 568 return fail(p, error::syntax, &loc);
682 }
683
1/1
✓ Branch 2 taken 5610 times.
11692 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 596 times.
✓ Branch 2 taken 5014 times.
11220 if(BOOST_JSON_UNLIKELY(p == sentinel()))
688 1192 return maybe_suspend(p, state::val2);
689 BOOST_FALLTHROUGH;
690 case ' ':
691 case '\t':
692 case '\n':
693 case '\r':
694 10052 p = detail::count_whitespace(p, end_);
695
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 4916 times.
10052 if(BOOST_JSON_UNLIKELY(p == end_))
696 220 return maybe_suspend(p, state::val1);
697 9832 goto loop;
698 2210 default:
699 {
700 BOOST_STATIC_CONSTEXPR source_location loc
701 = BOOST_CURRENT_LOCATION;
702 2210 return fail(p, error::syntax, &loc);
703 }
704 }
705 }
706 204354 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 204354 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 204354 st_.peek(st);
724
8/9
✗ Branch 0 not taken.
✓ Branch 1 taken 1924 times.
✓ Branch 2 taken 20316 times.
✓ Branch 3 taken 5754 times.
✓ Branch 4 taken 35119 times.
✓ Branch 5 taken 37176 times.
✓ Branch 6 taken 108 times.
✓ Branch 7 taken 1708 times.
✓ Branch 8 taken 72 times.
204354 switch(st)
725 {
726 default: BOOST_JSON_UNREACHABLE();
727 3848 case state::lit1:
728
1/1
✓ Branch 1 taken 1698 times.
3848 return parse_literal(p, detail::literals_c<detail::literals::resume>() );
729
730 40632 case state::str1: case state::str2:
731 case state::str8:
732
1/1
✓ Branch 1 taken 18133 times.
40632 return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733
734 11508 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 4408 times.
11508 return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738
739 70238 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 29032 times.
70238 return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746
747 74352 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 74352 return mp11::mp_with_index<3>(
754
1/1
✓ Branch 1 taken 36353 times.
74352 static_cast<unsigned char>(opt_.numbers),
755 72706 parse_number_helper<false, 0>{ this, p });
756
757 // KRYSTIAN NOTE: these are special cases
758 216 case state::val1:
759 {
760
1/1
✓ Branch 1 taken 108 times.
216 st_.pop(st);
761
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 108 times.
216 BOOST_ASSERT(st_.empty());
762 216 p = detail::count_whitespace(p, end_);
763
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 108 times.
216 if(BOOST_JSON_UNLIKELY(p == end_))
764 return maybe_suspend(p, state::val1);
765
1/1
✓ Branch 1 taken 82 times.
216 return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
766 }
767
768 3416 case state::val2:
769 {
770
1/1
✓ Branch 1 taken 1708 times.
3416 st_.pop(st);
771
1/1
✓ Branch 2 taken 1690 times.
3416 p = parse_comment(p, std::false_type(), std::false_type());
772
2/2
✓ Branch 1 taken 1369 times.
✓ Branch 2 taken 321 times.
3380 if(BOOST_JSON_UNLIKELY(p == sentinel()))
773
1/1
✓ Branch 1 taken 1369 times.
2738 return maybe_suspend(p, state::val2);
774
2/2
✓ Branch 0 taken 82 times.
✓ Branch 1 taken 239 times.
642 if(BOOST_JSON_UNLIKELY( p == end_ ))
775
1/1
✓ Branch 1 taken 82 times.
164 return maybe_suspend(p, state::val3);
776
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 239 times.
478 BOOST_ASSERT(st_.empty());
777
1/1
✓ Branch 1 taken 187 times.
478 return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
778 }
779
780 144 case state::val3:
781 {
782
1/1
✓ Branch 1 taken 72 times.
144 st_.pop(st);
783
1/1
✓ Branch 1 taken 72 times.
144 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 33126 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 33126 detail::const_stream_wrapper cs(p, end_);
800 BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801 {
802 27264 constexpr std::size_t index = literal_index(Literal::value);
803 27264 constexpr char const* literal = detail::literal_strings[index];
804 27264 constexpr std::size_t sz = detail::literal_sizes[index];
805
806
2/2
✓ Branch 1 taken 11982 times.
✓ Branch 2 taken 1650 times.
27264 if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807 {
808 23964 int const cmp = std::memcmp(cs.begin(), literal, sz);
809
2/2
✓ Branch 0 taken 197 times.
✓ Branch 1 taken 11785 times.
23964 if( cmp != 0 )
810 {
811 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812 394 return fail(cs.begin(), error::syntax, &loc);
813 }
814
815 BOOST_IF_CONSTEXPR( Literal::value == L::null )
816 {
817
3/5
✓ Branch 1 taken 10007 times.
✓ Branch 3 taken 3 times.
✓ Branch 4 taken 9846 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
21574 if(BOOST_JSON_UNLIKELY(
818 ! h_.on_null(ec_)))
819 322 return fail(cs.begin());
820 }
821 else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822 {
823
3/5
✓ Branch 1 taken 199 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 185 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
768 if(BOOST_JSON_UNLIKELY(
824 ! h_.on_bool(true, ec_)))
825 28 return fail(cs.begin());
826 }
827 else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828 {
829
2/5
✓ Branch 1 taken 266 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 253 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
812 if(BOOST_JSON_UNLIKELY(
830 ! h_.on_bool(false, ec_)))
831 26 return fail(cs.begin());
832 }
833 else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834 {
835
2/6
✓ Branch 3 taken 43 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 30 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
206 if(BOOST_JSON_UNLIKELY(
836 ! h_.on_double(
837 std::numeric_limits<double>::infinity(),
838 string_view(literal, sz),
839 ec_)))
840 26 return fail(cs.begin());
841 }
842 else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843 {
844
2/6
✓ Branch 3 taken 5 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 4 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
18 if(BOOST_JSON_UNLIKELY(
845 ! h_.on_double(
846 -std::numeric_limits<double>::infinity(),
847 string_view(literal, sz),
848 ec_)))
849 2 return fail(cs.begin());
850 }
851 else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852 {
853
2/6
✓ Branch 3 taken 40 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
192 if(BOOST_JSON_UNLIKELY(
854 ! h_.on_double(
855 std::numeric_limits<double>::quiet_NaN(),
856 string_view(literal, sz),
857 ec_)))
858 24 return fail(cs.begin());
859 }
860 else
861 {
862 BOOST_JSON_UNREACHABLE();
863 }
864
865 22722 cs += sz;
866 22722 return cs.begin();
867 }
868
869 3300 offset = 0;
870 3300 cur_lit = index;
871 }
872 else
873 {
874 state st;
875
1/1
✓ Branch 1 taken 2931 times.
5862 st_.pop(st);
876
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2931 times.
5862 BOOST_ASSERT( st == state::lit1 );
877
878 5862 cur_lit = cur_lit_;
879 5862 offset = lit_offset_;
880 }
881
882 9162 std::size_t const lit_size = detail::literal_sizes[cur_lit];
883 9162 std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884 9162 int cmp = 0;
885
2/2
✓ Branch 1 taken 4580 times.
✓ Branch 2 taken 1 times.
9162 if(BOOST_JSON_LIKELY( cs.begin() ))
886 9160 cmp = std::memcmp(
887 9160 cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
2/2
✓ Branch 0 taken 699 times.
✓ Branch 1 taken 3882 times.
9162 if( cmp != 0 )
889 {
890 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891 1398 return fail(cs.begin(), error::syntax, &loc);
892 }
893
894
2/2
✓ Branch 0 taken 1990 times.
✓ Branch 1 taken 1892 times.
7764 if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895 {
896
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1990 times.
3980 BOOST_ASSERT( cur_lit < 256 );
897 3980 cur_lit_ = static_cast<unsigned char>( cur_lit );
898
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1990 times.
3980 BOOST_ASSERT( offset + size < 256 );
899 3980 lit_offset_ = static_cast<unsigned char>( offset + size );
900
1/1
✓ Branch 2 taken 1990 times.
3980 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.
3784 switch( static_cast<L>(cur_lit) )
904 {
905 944 case L::null:
906
3/5
✓ Branch 1 taken 253 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 192 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
944 if(BOOST_JSON_UNLIKELY(
907 ! h_.on_null(ec_)))
908 122 return fail(cs.begin());
909 702 break;
910 304 case L::true_:
911
3/5
✓ Branch 1 taken 89 times.
✓ Branch 3 taken 1 times.
✓ Branch 4 taken 67 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
304 if(BOOST_JSON_UNLIKELY(
912 ! h_.on_bool(true, ec_)))
913 44 return fail(cs.begin());
914 218 break;
915 396 case L::false_:
916
2/5
✓ Branch 1 taken 114 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 86 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
396 if(BOOST_JSON_UNLIKELY(
917 ! h_.on_bool(false, ec_)))
918 56 return fail(cs.begin());
919 284 break;
920 616 case L::infinity:
921
2/6
✓ Branch 3 taken 161 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 112 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
616 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 98 return fail(cs.begin());
929 420 break;
930 1372 case L::neg_infinity:
931
2/6
✓ Branch 3 taken 359 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 257 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
1372 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 204 return fail(cs.begin());
939 964 break;
940 152 case L::nan:
941
2/6
✓ Branch 3 taken 40 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 28 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
152 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 24 return fail(cs.begin());
949 104 break;
950 default: BOOST_JSON_UNREACHABLE();
951 }
952
953 2692 cs += size;
954 2692 return cs.begin();
955 }
956
957 //----------------------------------------------------------
958
959 template<class Handler>
960 template<bool StackEmpty_, bool IsKey_>
961 const char*
962 323002 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 323002 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 39765 times.
✓ Branch 2 taken 121736 times.
✓ Branch 4 taken 32974 times.
✓ Branch 5 taken 6791 times.
✓ Branch 6 taken 32974 times.
✓ Branch 7 taken 128527 times.
323002 if(! stack_empty && ! st_.empty())
974 {
975 state st;
976
1/1
✓ Branch 1 taken 32974 times.
65948 st_.pop(st);
977
1/1
✓ Branch 1 taken 32974 times.
65948 st_.pop(total);
978
3/4
✗ Branch 0 not taken.
✓ Branch 1 taken 3149 times.
✓ Branch 2 taken 1861 times.
✓ Branch 3 taken 27964 times.
65948 switch(st)
979 {
980 default: BOOST_JSON_UNREACHABLE();
981 6298 case state::str2: goto do_str2;
982 3722 case state::str8: goto do_str8;
983 55928 case state::str1: break;
984 }
985 }
986 else
987 {
988
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 128527 times.
257054 BOOST_ASSERT(*cs == '\x22'); // '"'
989 257054 ++cs;
990 257054 total = 0;
991 }
992
993 329966 do_str1:
994 329966 start = cs.begin();
995
2/2
✓ Branch 0 taken 2177 times.
✓ Branch 1 taken 162806 times.
659932 cs = allow_bad_utf8?
996 4354 detail::count_valid<true>(cs.begin(), cs.end()):
997 325612 detail::count_valid<false>(cs.begin(), cs.end());
998 329966 size = cs.used(start);
999
2/2
✓ Branch 1 taken 94056 times.
✓ Branch 2 taken 70927 times.
329966 if(is_key)
1000 {
1001
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 46745 times.
93490 BOOST_ASSERT(total <= Handler::max_key_size);
1002
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 94053 times.
188112 if(BOOST_JSON_UNLIKELY(size >
1003 Handler::max_key_size - total))
1004 {
1005 BOOST_STATIC_CONSTEXPR source_location loc
1006 = BOOST_CURRENT_LOCATION;
1007 6 return fail(cs.begin(), error::key_too_large, &loc);
1008 }
1009 }
1010 else
1011 {
1012
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 35465 times.
70930 BOOST_ASSERT(total <= Handler::max_string_size);
1013
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 70924 times.
141854 if(BOOST_JSON_UNLIKELY(size >
1014 Handler::max_string_size - total))
1015 {
1016 BOOST_STATIC_CONSTEXPR source_location loc
1017 = BOOST_CURRENT_LOCATION;
1018 6 return fail(cs.begin(), error::string_too_large, &loc);
1019 }
1020 }
1021 329954 total += size;
1022
2/2
✓ Branch 1 taken 30298 times.
✓ Branch 2 taken 134679 times.
329954 if(BOOST_JSON_UNLIKELY(! cs))
1023 {
1024 // call handler if the string isn't empty
1025
2/2
✓ Branch 0 taken 27123 times.
✓ Branch 1 taken 3175 times.
60596 if(BOOST_JSON_LIKELY(size))
1026 {
1027 {
1028
2/2
✓ Branch 1 taken 11306 times.
✓ Branch 2 taken 15817 times.
54246 bool r = is_key?
1029
1/2
✓ Branch 2 taken 8117 times.
✗ Branch 1 not taken.
24828 h_.on_key_part( {start, size}, total, ec_ ):
1030
1/2
✓ Branch 2 taken 8662 times.
✗ Branch 1 not taken.
32086 h_.on_string_part( {start, size}, total, ec_ );
1031
1032
2/2
✓ Branch 0 taken 1110 times.
✓ Branch 1 taken 24905 times.
52030 if(BOOST_JSON_UNLIKELY(!r))
1033 {
1034 2220 return fail(cs.begin());
1035 }
1036 }
1037 }
1038
1/1
✓ Branch 2 taken 28080 times.
56160 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 119611 times.
269358 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.
30136 if((*cs & 0x80) && !allow_bad_utf8)
1047 {
1048 6924 seq_.save(cs.begin(), cs.remain());
1049
2/2
✓ Branch 1 taken 1557 times.
✓ Branch 2 taken 1905 times.
6924 if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050 {
1051 BOOST_STATIC_CONSTEXPR source_location loc
1052 = BOOST_CURRENT_LOCATION;
1053 3114 return fail(cs.begin(), error::syntax, &loc);
1054 }
1055
2/2
✓ Branch 0 taken 245 times.
✓ Branch 1 taken 1660 times.
3810 if(BOOST_JSON_LIKELY(size))
1056 {
1057
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 245 times.
490 bool const r = is_key?
1058
0/2
✗ Branch 2 not taken.
✗ Branch 1 not taken.
44 h_.on_key_part( {start, size}, total, ec_ ):
1059
0/2
✗ Branch 2 not taken.
✗ Branch 1 not taken.
490 h_.on_string_part( {start, size}, total, ec_ );
1060
2/2
✓ Branch 0 taken 22 times.
✓ Branch 1 taken 201 times.
446 if(BOOST_JSON_UNLIKELY( !r ))
1061 44 return fail( cs.begin() );
1062 }
1063
1/1
✓ Branch 2 taken 1861 times.
3722 return maybe_suspend(cs.end(), state::str8, total);
1064 }
1065
2/2
✓ Branch 1 taken 11497 times.
✓ Branch 2 taken 109 times.
23212 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.
22994 if(BOOST_JSON_LIKELY(size))
1069 {
1070
2/2
✓ Branch 1 taken 742 times.
✓ Branch 2 taken 3508 times.
8500 bool const r = is_key?
1071
1/2
✓ Branch 2 taken 3 times.
✗ Branch 1 not taken.
2452 h_.on_key_part( {start, size}, total, ec_ ):
1072
1/2
✓ Branch 2 taken 89 times.
✗ Branch 1 not taken.
7108 h_.on_string_part( {start, size}, total, ec_ );
1073
2/2
✓ Branch 0 taken 484 times.
✓ Branch 1 taken 3282 times.
7532 if(BOOST_JSON_UNLIKELY( !r ))
1074 968 return fail( cs.begin() );
1075 }
1076 14494 do_str2:
1077
1/1
✓ Branch 3 taken 12716 times.
27356 cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
2/2
✓ Branch 1 taken 5473 times.
✓ Branch 2 taken 7243 times.
25432 if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
1/1
✓ Branch 1 taken 5473 times.
10946 return suspend_or_fail(state::str2, total);
1080
1081 14486 goto do_str1;
1082 }
1083 // illegal control
1084 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085 218 return fail(cs.begin(), error::syntax, &loc);
1086 }
1087
1088 {
1089
2/2
✓ Branch 1 taken 80177 times.
✓ Branch 2 taken 39434 times.
239222 bool r = is_key?
1090
1/2
✓ Branch 2 taken 38473 times.
✗ Branch 1 not taken.
169102 h_.on_key( {start, size}, total, ec_ ):
1091
1/2
✓ Branch 2 taken 26288 times.
✗ Branch 1 not taken.
84138 h_.on_string( {start, size}, total, ec_ );
1092
1093
2/2
✓ Branch 0 taken 4318 times.
✓ Branch 1 taken 110919 times.
230474 if(BOOST_JSON_UNLIKELY(!r))
1094 {
1095 8636 return fail(cs.begin());
1096 }
1097 }
1098
1099 221838 ++cs;
1100 221838 return cs.begin();
1101
1102 3722 do_str8:
1103 3722 uint8_t needed = seq_.needed();
1104
1/2
✗ Branch 3 not taken.
✓ Branch 4 taken 1861 times.
3722 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.
3722 if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107 {
1108 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109 420 return fail(cs.begin(), error::syntax, &loc);
1110 }
1111 {
1112
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1651 times.
3302 bool const r = is_key?
1113
0/2
✗ Branch 4 not taken.
✗ Branch 1 not taken.
402 h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114
1/2
✓ Branch 4 taken 629 times.
✗ Branch 1 not taken.
3302 h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115
2/2
✓ Branch 0 taken 201 times.
✓ Branch 1 taken 1249 times.
2900 if(BOOST_JSON_UNLIKELY( !r ))
1116 402 return fail( cs.begin() );
1117 }
1118 2498 cs += needed;
1119 2498 goto do_str1;
1120 }
1121
1122 template<class Handler>
1123 template<bool StackEmpty_>
1124 const char*
1125 27356 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 27356 constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1134
2/2
✓ Branch 0 taken 835 times.
✓ Branch 1 taken 12843 times.
27356 auto const ev_too_large = is_key?
1135 error::key_too_large : error::string_too_large;
1136 27356 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 27356 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 27356 detail::clipped_const_stream cs(p, end_);
1161 27356 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.
27356 if(! stack_empty && ! st_.empty())
1164 {
1165 state st;
1166
1/1
✓ Branch 1 taken 3149 times.
6298 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.
6298 switch(st)
1168 {
1169 default: BOOST_JSON_UNREACHABLE();
1170 1056 case state::str3: goto do_str3;
1171 784 case state::str4: goto do_str4;
1172 780 case state::str5: goto do_str5;
1173 778 case state::str6: goto do_str6;
1174 772 case state::str7: goto do_str7;
1175 464 case state::sur1: goto do_sur1;
1176 376 case state::sur2: goto do_sur2;
1177 328 case state::sur3: goto do_sur3;
1178 324 case state::sur4: goto do_sur4;
1179 320 case state::sur5: goto do_sur5;
1180 316 case state::sur6: goto do_sur6;
1181 }
1182 }
1183
1184 7562 while(true)
1185 {
1186
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14310 times.
28620 BOOST_ASSERT( temp.capacity() );
1187
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 14310 times.
28620 BOOST_ASSERT(*cs == '\\');
1188 28620 ++cs;
1189 30338 do_str3:
1190
2/2
✓ Branch 1 taken 561 times.
✓ Branch 2 taken 14813 times.
30748 if(BOOST_JSON_UNLIKELY(! cs))
1191 {
1192
2/2
✓ Branch 1 taken 100 times.
✓ Branch 2 taken 461 times.
1122 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.
200 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 200 total += temp.size();
1203 {
1204 182 bool r = is_key
1205
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 100 times.
✗ Branch 4 not taken.
✗ Branch 3 not taken.
200 ? h_.on_key_part(temp.get(), total, ec_)
1206
0/2
✗ Branch 2 not taken.
✗ Branch 1 not taken.
200 : h_.on_string_part(temp.get(), total, ec_);
1207
1208
2/2
✓ Branch 0 taken 9 times.
✓ Branch 1 taken 82 times.
182 if(BOOST_JSON_UNLIKELY(!r))
1209 {
1210 18 return fail(cs.begin());
1211 }
1212 }
1213 164 temp.clear();
1214 }
1215 1086 cs.clip(temp.max_size());
1216
1/2
✓ Branch 1 taken 543 times.
✗ Branch 2 not taken.
1086 if(BOOST_JSON_UNLIKELY(! cs))
1217
1/1
✓ Branch 2 taken 543 times.
1086 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.
29626 switch(*cs)
1220 {
1221 382 default:
1222 {
1223 BOOST_STATIC_CONSTEXPR source_location loc
1224 = BOOST_CURRENT_LOCATION;
1225 382 return fail(cs.begin(), error::syntax, &loc);
1226 }
1227 530 case '\x22': // '"'
1228 530 temp.push_back('\x22');
1229 530 ++cs;
1230 530 break;
1231 356 case '\\':
1232 356 temp.push_back('\\');
1233 356 ++cs;
1234 356 break;
1235 192 case '/':
1236 192 temp.push_back('/');
1237 192 ++cs;
1238 192 break;
1239 224 case 'b':
1240 224 temp.push_back('\x08');
1241 224 ++cs;
1242 224 break;
1243 216 case 'f':
1244 216 temp.push_back('\x0c');
1245 216 ++cs;
1246 216 break;
1247 3526 case 'n':
1248 3526 temp.push_back('\x0a');
1249 3526 ++cs;
1250 3526 break;
1251 292 case 'r':
1252 292 temp.push_back('\x0d');
1253 292 ++cs;
1254 292 break;
1255 532 case 't':
1256 532 temp.push_back('\x09');
1257 532 ++cs;
1258 532 break;
1259 23376 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.
23376 if(BOOST_JSON_LIKELY(cs.remain() > 10))
1265 {
1266 // KRYSTIAN TODO: this could be done
1267 // with fewer instructions
1268 22788 digit = detail::load_little_endian<4>(
1269 11394 cs.begin() + 1);
1270 11394 int d4 = detail::hex_digit(static_cast<
1271 11394 unsigned char>(digit >> 24));
1272 11394 int d3 = detail::hex_digit(static_cast<
1273 11394 unsigned char>(digit >> 16));
1274 11394 int d2 = detail::hex_digit(static_cast<
1275 11394 unsigned char>(digit >> 8));
1276 11394 int d1 = detail::hex_digit(static_cast<
1277 unsigned char>(digit));
1278
2/2
✓ Branch 0 taken 60 times.
✓ Branch 1 taken 5637 times.
11394 if(BOOST_JSON_UNLIKELY(
1279 (d1 | d2 | d3 | d4) == -1))
1280 {
1281
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 15 times.
120 if(d1 != -1)
1282 90 ++cs;
1283
2/2
✓ Branch 0 taken 30 times.
✓ Branch 1 taken 30 times.
120 if(d2 != -1)
1284 60 ++cs;
1285
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 45 times.
120 if(d3 != -1)
1286 30 ++cs;
1287 BOOST_STATIC_CONSTEXPR source_location loc
1288 = BOOST_CURRENT_LOCATION;
1289 120 return fail(cs.begin(), error::expected_hex_digit, &loc);
1290 }
1291 // 32 bit unicode scalar value
1292 11274 unsigned u1 =
1293 11274 (d1 << 12) + (d2 << 8) +
1294 11274 (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.
11274 if(BOOST_JSON_LIKELY(
1300 u1 < 0xd800 || u1 > 0xdfff))
1301 {
1302 2680 cs += 5;
1303 2680 temp.append_utf8(u1);
1304 2680 break;
1305 }
1306
2/2
✓ Branch 0 taken 707 times.
✓ Branch 1 taken 3590 times.
8594 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.
1414 if(!allow_bad_utf16)
1311 {
1312 BOOST_STATIC_CONSTEXPR source_location loc
1313 = BOOST_CURRENT_LOCATION;
1314 244 return fail(cs.begin(), error::illegal_leading_surrogate,
1315 244 &loc);
1316 }
1317 // Otherwise, append the Unicode replacement character
1318 else
1319 {
1320 1170 cs += 5;
1321 1170 temp.append_utf8(urc);
1322 1170 break;
1323 }
1324 }
1325 7180 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.
7180 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.
312 if(!allow_bad_utf16)
1334 {
1335 BOOST_STATIC_CONSTEXPR source_location loc
1336 = BOOST_CURRENT_LOCATION;
1337 30 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 282 temp.append_utf8(urc);
1344 282 break;
1345 }
1346 }
1347 6868 ++cs;
1348
2/2
✓ Branch 1 taken 220 times.
✓ Branch 2 taken 3214 times.
6868 if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1349 {
1350
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 205 times.
440 if (!allow_bad_utf16)
1351 {
1352 BOOST_STATIC_CONSTEXPR source_location loc
1353 = BOOST_CURRENT_LOCATION;
1354 30 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 410 temp.append_utf8(urc);
1361 410 goto do_str3;
1362 }
1363 }
1364 6428 ++cs;
1365 6428 digit = detail::load_little_endian<4>(cs.begin());
1366 6428 d4 = detail::hex_digit(static_cast<
1367 6428 unsigned char>(digit >> 24));
1368 6428 d3 = detail::hex_digit(static_cast<
1369 6428 unsigned char>(digit >> 16));
1370 6428 d2 = detail::hex_digit(static_cast<
1371 6428 unsigned char>(digit >> 8));
1372 6428 d1 = detail::hex_digit(static_cast<
1373 unsigned char>(digit));
1374
2/2
✓ Branch 0 taken 90 times.
✓ Branch 1 taken 3124 times.
6428 if(BOOST_JSON_UNLIKELY(
1375 (d1 | d2 | d3 | d4) == -1))
1376 {
1377
2/2
✓ Branch 0 taken 75 times.
✓ Branch 1 taken 15 times.
180 if(d1 != -1)
1378 150 ++cs;
1379
2/2
✓ Branch 0 taken 45 times.
✓ Branch 1 taken 45 times.
180 if(d2 != -1)
1380 90 ++cs;
1381
2/2
✓ Branch 0 taken 15 times.
✓ Branch 1 taken 75 times.
180 if(d3 != -1)
1382 30 ++cs;
1383 BOOST_STATIC_CONSTEXPR source_location loc
1384 = BOOST_CURRENT_LOCATION;
1385 180 return fail(cs.begin(), error::expected_hex_digit, &loc);
1386 }
1387 6248 unsigned u2 =
1388 6248 (d1 << 12) + (d2 << 8) +
1389 6248 (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.
6248 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.
2706 if(!allow_bad_utf16)
1397 {
1398 BOOST_STATIC_CONSTEXPR source_location loc
1399 = BOOST_CURRENT_LOCATION;
1400 272 return fail(cs.begin(), error::illegal_trailing_surrogate,
1401 272 &loc);
1402 }
1403 // Append the replacement character for the
1404 // first leading surrogate.
1405 2434 cs += 4;
1406 2434 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.
2434 if (u2 < 0xd800 || u2 > 0xdbff)
1411 {
1412 1048 temp.append_utf8(u2);
1413 1048 break;
1414 }
1415 // If it is a valid leading surrogate
1416 else
1417 {
1418 1386 u1_ = u2;
1419 1386 goto do_sur1;
1420 }
1421 }
1422 3542 cs += 4;
1423 // Calculate the Unicode code point from the surrogate pair and
1424 // append the UTF-8 representation.
1425 3542 unsigned cp =
1426 3542 ((u1 - 0xd800) << 10) +
1427 ((u2 - 0xdc00)) +
1428 0x10000;
1429 // utf-16 surrogate pair
1430 3542 temp.append_utf8(cp);
1431 3542 break;
1432 }
1433 // flush
1434
2/2
✓ Branch 1 taken 1722 times.
✓ Branch 2 taken 4269 times.
11982 if(BOOST_JSON_LIKELY(! temp.empty()))
1435 {
1436
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 3 times.
6 BOOST_ASSERT(total <= max_size);
1437
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1722 times.
3444 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 3444 total += temp.size();
1445 {
1446 3164 bool r = is_key
1447
1/4
✗ Branch 0 not taken.
✓ Branch 1 taken 1722 times.
✗ Branch 4 not taken.
✗ Branch 3 not taken.
3444 ? h_.on_key_part(temp.get(), total, ec_)
1448
1/2
✓ Branch 2 taken 3 times.
✗ Branch 1 not taken.
3444 : h_.on_string_part(temp.get(), total, ec_);
1449
1450
2/2
✓ Branch 0 taken 140 times.
✓ Branch 1 taken 1442 times.
3164 if(BOOST_JSON_UNLIKELY(!r))
1451 {
1452 280 return fail(cs.begin());
1453 }
1454 }
1455 2884 temp.clear();
1456 2884 cs.clip(temp.max_size());
1457 }
1458 11422 ++cs;
1459 // utf-16 escape
1460 12206 do_str4:
1461
2/2
✓ Branch 1 taken 392 times.
✓ Branch 2 taken 5711 times.
12206 if(BOOST_JSON_UNLIKELY(! cs))
1462
1/1
✓ Branch 2 taken 392 times.
784 return maybe_suspend(cs.begin(), state::str4);
1463 11422 digit = detail::hex_digit(*cs);
1464
2/2
✓ Branch 0 taken 50 times.
✓ Branch 1 taken 5661 times.
11422 if(BOOST_JSON_UNLIKELY(digit == -1))
1465 {
1466 BOOST_STATIC_CONSTEXPR source_location loc
1467 = BOOST_CURRENT_LOCATION;
1468 100 return fail(cs.begin(), error::expected_hex_digit, &loc);
1469 }
1470 11322 ++cs;
1471 11322 u1_ = digit << 12;
1472 12102 do_str5:
1473
2/2
✓ Branch 1 taken 390 times.
✓ Branch 2 taken 5661 times.
12102 if(BOOST_JSON_UNLIKELY(! cs))
1474
1/1
✓ Branch 2 taken 390 times.
780 return maybe_suspend(cs.begin(), state::str5);
1475 11322 digit = detail::hex_digit(*cs);
1476
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 5641 times.
11322 if(BOOST_JSON_UNLIKELY(digit == -1))
1477 {
1478 BOOST_STATIC_CONSTEXPR source_location loc
1479 = BOOST_CURRENT_LOCATION;
1480 40 return fail(cs.begin(), error::expected_hex_digit, &loc);
1481 }
1482 11282 ++cs;
1483 11282 u1_ += digit << 8;
1484 12060 do_str6:
1485
2/2
✓ Branch 1 taken 389 times.
✓ Branch 2 taken 5641 times.
12060 if(BOOST_JSON_UNLIKELY(! cs))
1486
1/1
✓ Branch 2 taken 389 times.
778 return maybe_suspend(cs.begin(), state::str6);
1487 11282 digit = detail::hex_digit(*cs);
1488
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 5621 times.
11282 if(BOOST_JSON_UNLIKELY(digit == -1))
1489 {
1490 BOOST_STATIC_CONSTEXPR source_location loc
1491 = BOOST_CURRENT_LOCATION;
1492 40 return fail(cs.begin(), error::expected_hex_digit, &loc);
1493 }
1494 11242 ++cs;
1495 11242 u1_ += digit << 4;
1496 12014 do_str7:
1497
2/2
✓ Branch 1 taken 386 times.
✓ Branch 2 taken 5621 times.
12014 if(BOOST_JSON_UNLIKELY(! cs))
1498
1/1
✓ Branch 2 taken 386 times.
772 return maybe_suspend(cs.begin(), state::str7);
1499 11242 digit = detail::hex_digit(*cs);
1500
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 5586 times.
11242 if(BOOST_JSON_UNLIKELY(digit == -1))
1501 {
1502 BOOST_STATIC_CONSTEXPR source_location loc
1503 = BOOST_CURRENT_LOCATION;
1504 70 return fail(cs.begin(), error::expected_hex_digit, &loc);
1505 }
1506 11172 ++cs;
1507 11172 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.
11172 if(BOOST_JSON_LIKELY(
1509 u1_ < 0xd800 || u1_ > 0xdfff))
1510 {
1511
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1434 times.
2868 BOOST_ASSERT(temp.empty());
1512 // utf-8 codepoint
1513 2868 temp.append_utf8(u1_);
1514 2868 break;
1515 }
1516
2/2
✓ Branch 0 taken 1585 times.
✓ Branch 1 taken 2567 times.
8304 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.
3170 if(!allow_bad_utf16)
1521 {
1522 BOOST_STATIC_CONSTEXPR source_location loc
1523 = BOOST_CURRENT_LOCATION;
1524 418 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.
2752 BOOST_ASSERT(temp.empty());
1530 2752 temp.append_utf8(urc);
1531 2752 break;
1532 }
1533 }
1534 5134 do_sur1:
1535
2/2
✓ Branch 1 taken 232 times.
✓ Branch 2 taken 3560 times.
7584 if(BOOST_JSON_UNLIKELY(! cs))
1536
1/1
✓ Branch 2 taken 232 times.
464 return maybe_suspend(cs.begin(), state::sur1);
1537
2/2
✓ Branch 1 taken 952 times.
✓ Branch 2 taken 2608 times.
7120 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.
1904 if(!allow_bad_utf16)
1542 {
1543 BOOST_STATIC_CONSTEXPR source_location loc
1544 = BOOST_CURRENT_LOCATION;
1545 298 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 1606 temp.append_utf8(urc);
1552 1606 break;
1553 }
1554 }
1555 5216 ++cs;
1556 5592 do_sur2:
1557
2/2
✓ Branch 1 taken 188 times.
✓ Branch 2 taken 2608 times.
5592 if(BOOST_JSON_UNLIKELY(! cs))
1558
1/1
✓ Branch 2 taken 188 times.
376 return maybe_suspend(cs.begin(), state::sur2);
1559
2/2
✓ Branch 1 taken 396 times.
✓ Branch 2 taken 2212 times.
5216 if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1560 {
1561
2/2
✓ Branch 0 taken 65 times.
✓ Branch 1 taken 331 times.
792 if (!allow_bad_utf16)
1562 {
1563 BOOST_STATIC_CONSTEXPR source_location loc
1564 = BOOST_CURRENT_LOCATION;
1565 130 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 662 temp.append_utf8(urc);
1572 662 goto do_str3;
1573 }
1574 }
1575 4424 ++cs;
1576 4752 do_sur3:
1577
2/2
✓ Branch 1 taken 164 times.
✓ Branch 2 taken 2212 times.
4752 if(BOOST_JSON_UNLIKELY(! cs))
1578
1/1
✓ Branch 2 taken 164 times.
328 return maybe_suspend(cs.begin(), state::sur3);
1579 4424 digit = detail::hex_digit(*cs);
1580
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2177 times.
4424 if(BOOST_JSON_UNLIKELY(digit == -1))
1581 {
1582 BOOST_STATIC_CONSTEXPR source_location loc
1583 = BOOST_CURRENT_LOCATION;
1584 70 return fail(cs.begin(), error::expected_hex_digit, &loc);
1585 }
1586 4354 ++cs;
1587 4354 u2_ = digit << 12;
1588 4678 do_sur4:
1589
2/2
✓ Branch 1 taken 162 times.
✓ Branch 2 taken 2177 times.
4678 if(BOOST_JSON_UNLIKELY(! cs))
1590
1/1
✓ Branch 2 taken 162 times.
324 return maybe_suspend(cs.begin(), state::sur4);
1591 4354 digit = detail::hex_digit(*cs);
1592
2/2
✓ Branch 0 taken 35 times.
✓ Branch 1 taken 2142 times.
4354 if(BOOST_JSON_UNLIKELY(digit == -1))
1593 {
1594 BOOST_STATIC_CONSTEXPR source_location loc
1595 = BOOST_CURRENT_LOCATION;
1596 70 return fail(cs.begin(), error::expected_hex_digit, &loc);
1597 }
1598 4284 ++cs;
1599 4284 u2_ += digit << 8;
1600 4604 do_sur5:
1601
2/2
✓ Branch 1 taken 160 times.
✓ Branch 2 taken 2142 times.
4604 if(BOOST_JSON_UNLIKELY(! cs))
1602
1/1
✓ Branch 2 taken 160 times.
320 return maybe_suspend(cs.begin(), state::sur5);
1603 4284 digit = detail::hex_digit(*cs);
1604
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2122 times.
4284 if(BOOST_JSON_UNLIKELY(digit == -1))
1605 {
1606 BOOST_STATIC_CONSTEXPR source_location loc
1607 = BOOST_CURRENT_LOCATION;
1608 40 return fail(cs.begin(), error::expected_hex_digit, &loc);
1609 }
1610 4244 ++cs;
1611 4244 u2_ += digit << 4;
1612 4560 do_sur6:
1613
2/2
✓ Branch 1 taken 158 times.
✓ Branch 2 taken 2122 times.
4560 if(BOOST_JSON_UNLIKELY(! cs))
1614
1/1
✓ Branch 2 taken 158 times.
316 return maybe_suspend(cs.begin(), state::sur6);
1615 4244 digit = detail::hex_digit(*cs);
1616
2/2
✓ Branch 0 taken 20 times.
✓ Branch 1 taken 2102 times.
4244 if(BOOST_JSON_UNLIKELY(digit == -1))
1617 {
1618 BOOST_STATIC_CONSTEXPR source_location loc
1619 = BOOST_CURRENT_LOCATION;
1620 40 return fail(cs.begin(), error::expected_hex_digit, &loc);
1621 }
1622 4204 ++cs;
1623 4204 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.
4204 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.
1160 if(!allow_bad_utf16)
1631 {
1632 BOOST_STATIC_CONSTEXPR source_location loc
1633 = BOOST_CURRENT_LOCATION;
1634 120 return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1635 }
1636 // Append the replacement character for the
1637 // first leading surrogate.
1638 1040 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.
1040 if (u2_ < 0xd800 || u2_ > 0xdbff)
1643 {
1644 440 temp.append_utf8(u2_);
1645 440 break;
1646 }
1647 // If it is a valid leading surrogate
1648 else
1649 {
1650 600 u1_ = u2_;
1651 600 goto do_sur1;
1652 }
1653 }
1654 // Calculate the Unicode code point from the surrogate pair and
1655 // append the UTF-8 representation.
1656 3044 unsigned cp =
1657 3044 ((u1_ - 0xd800) << 10) +
1658 3044 ((u2_ - 0xdc00)) +
1659 0x10000;
1660 // utf-16 surrogate pair
1661 3044 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.
25300 if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1666 17738 break;
1667 }
1668
1669
1/2
✓ Branch 1 taken 8869 times.
✗ Branch 2 not taken.
17738 if(BOOST_JSON_LIKELY( temp.size() ))
1670 {
1671
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 433 times.
866 BOOST_ASSERT(total <= max_size);
1672
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 8869 times.
17738 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 17738 total += temp.size();
1680 16112 bool const r = is_key
1681
3/4
✓ Branch 0 taken 717 times.
✓ Branch 1 taken 8152 times.
✓ Branch 4 taken 5 times.
✗ Branch 3 not taken.
17738 ? h_.on_key_part(temp.get(), total, ec_)
1682
1/2
✓ Branch 2 taken 428 times.
✗ Branch 1 not taken.
16304 : h_.on_string_part(temp.get(), total, ec_);
1683
2/2
✓ Branch 0 taken 813 times.
✓ Branch 1 taken 7243 times.
16112 if(BOOST_JSON_UNLIKELY( !r ))
1684 1626 return fail( cs.begin() );
1685 }
1686
1687 14486 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 218522 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 218522 detail::const_stream_wrapper cs(p, end_);
1708 std::size_t size;
1709
5/6
✓ Branch 1 taken 35119 times.
✓ Branch 2 taken 74142 times.
✓ Branch 4 taken 35119 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 35119 times.
✓ Branch 7 taken 74142 times.
218522 if(! stack_empty && ! st_.empty())
1710 {
1711 // resume
1712 state st;
1713
1/1
✓ Branch 1 taken 35119 times.
70238 st_.pop(st);
1714
1/1
✓ Branch 1 taken 35119 times.
70238 st_.pop(size);
1715
11/12
✗ Branch 0 not taken.
✓ Branch 1 taken 1597 times.
✓ Branch 2 taken 235 times.
✓ Branch 3 taken 12658 times.
✓ Branch 4 taken 1696 times.
✓ Branch 5 taken 251 times.
✓ Branch 6 taken 1597 times.
✓ Branch 7 taken 15474 times.
✓ Branch 8 taken 432 times.
✓ Branch 9 taken 664 times.
✓ Branch 10 taken 181 times.
✓ Branch 11 taken 334 times.
70238 switch(st)
1716 {
1717 default: BOOST_JSON_UNREACHABLE();
1718 3194 case state::obj1: goto do_obj1;
1719 470 case state::obj2: goto do_obj2;
1720 25316 case state::obj3: goto do_obj3;
1721 3392 case state::obj4: goto do_obj4;
1722 502 case state::obj5: goto do_obj5;
1723 3194 case state::obj6: goto do_obj6;
1724 30948 case state::obj7: goto do_obj7;
1725 864 case state::obj8: goto do_obj8;
1726 1328 case state::obj9: goto do_obj9;
1727 362 case state::obj10: goto do_obj10;
1728 668 case state::obj11: goto do_obj11;
1729 }
1730 }
1731
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 74142 times.
148284 BOOST_ASSERT(*cs == '{');
1732 148284 size = 0;
1733
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 74139 times.
148284 if(BOOST_JSON_UNLIKELY(! depth_))
1734 {
1735 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1736 6 return fail(cs.begin(), error::too_deep, &loc);
1737 }
1738 148278 --depth_;
1739
5/5
✓ Branch 1 taken 19074 times.
✓ Branch 3 taken 2 times.
✓ Branch 4 taken 17033 times.
✓ Branch 5 taken 1 times.
✓ Branch 2 taken 34953 times.
148278 if(BOOST_JSON_UNLIKELY(
1740 ! h_.on_object_begin(ec_)))
1741 4080 return fail(cs.begin());
1742 140122 ++cs;
1743 // object:
1744 // '{' *ws '}'
1745 // '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1746 147258 do_obj1:
1747 147258 cs = detail::count_whitespace(cs.begin(), cs.end());
1748
2/2
✓ Branch 1 taken 1631 times.
✓ Branch 2 taken 71998 times.
147258 if(BOOST_JSON_UNLIKELY(! cs))
1749
1/1
✓ Branch 2 taken 1631 times.
3262 return maybe_suspend(cs.begin(), state::obj1, size);
1750
2/2
✓ Branch 1 taken 69099 times.
✓ Branch 2 taken 2899 times.
143996 if(BOOST_JSON_LIKELY(*cs != '}'))
1751 {
1752
2/2
✓ Branch 1 taken 2411 times.
✓ Branch 2 taken 66688 times.
138198 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.
4822 if(allow_comments && *cs == '/')
1755 {
1756 4278 do_obj2:
1757
1/1
✓ Branch 3 taken 2290 times.
4748 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1758
2/2
✓ Branch 1 taken 319 times.
✓ Branch 2 taken 1971 times.
4580 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1759
1/1
✓ Branch 1 taken 319 times.
638 return suspend_or_fail(state::obj2, size);
1760 3942 goto do_obj1;
1761 }
1762 BOOST_STATIC_CONSTEXPR source_location loc
1763 = BOOST_CURRENT_LOCATION;
1764 544 return fail(cs.begin(), error::syntax, &loc);
1765 }
1766 133376 loop:
1767
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 80867 times.
161736 if(BOOST_JSON_UNLIKELY(++size >
1768 Handler::max_object_size))
1769 {
1770 BOOST_STATIC_CONSTEXPR source_location loc
1771 = BOOST_CURRENT_LOCATION;
1772 2 return fail(cs.begin(), error::object_too_large, &loc);
1773 }
1774 161734 do_obj3:
1775
1/1
✓ Branch 2 taken 90569 times.
187050 cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1776
2/2
✓ Branch 1 taken 15602 times.
✓ Branch 2 taken 74967 times.
181138 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1777
1/1
✓ Branch 1 taken 15602 times.
31204 return suspend_or_fail(state::obj3, size);
1778 149934 do_obj4:
1779 158268 cs = detail::count_whitespace(cs.begin(), cs.end());
1780
2/2
✓ Branch 1 taken 1711 times.
✓ Branch 2 taken 77423 times.
158268 if(BOOST_JSON_UNLIKELY(! cs))
1781
1/1
✓ Branch 2 taken 1711 times.
3422 return maybe_suspend(cs.begin(), state::obj4, size);
1782
2/2
✓ Branch 1 taken 2925 times.
✓ Branch 2 taken 74498 times.
154846 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.
5850 if(allow_comments && *cs == '/')
1785 {
1786 5558 do_obj5:
1787
1/1
✓ Branch 3 taken 2876 times.
6060 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1788
2/2
✓ Branch 1 taken 405 times.
✓ Branch 2 taken 2471 times.
5752 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1789
1/1
✓ Branch 1 taken 405 times.
810 return suspend_or_fail(state::obj5, size);
1790 4942 goto do_obj4;
1791 }
1792 BOOST_STATIC_CONSTEXPR source_location loc
1793 = BOOST_CURRENT_LOCATION;
1794 292 return fail(cs.begin(), error::syntax, &loc);
1795 }
1796 148996 ++cs;
1797 152190 do_obj6:
1798 152190 cs = detail::count_whitespace(cs.begin(), cs.end());
1799
2/2
✓ Branch 1 taken 1627 times.
✓ Branch 2 taken 74468 times.
152190 if(BOOST_JSON_UNLIKELY(! cs))
1800
1/1
✓ Branch 2 taken 1627 times.
3254 return maybe_suspend(cs.begin(), state::obj6, size);
1801 148936 do_obj7:
1802
1/1
✓ Branch 2 taken 82593 times.
179884 cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1803
2/2
✓ Branch 1 taken 23619 times.
✓ Branch 2 taken 58974 times.
165186 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1804
1/1
✓ Branch 1 taken 23619 times.
47238 return suspend_or_fail(state::obj7, size);
1805 117948 do_obj8:
1806 122484 cs = detail::count_whitespace(cs.begin(), cs.end());
1807
2/2
✓ Branch 1 taken 447 times.
✓ Branch 2 taken 60795 times.
122484 if(BOOST_JSON_UNLIKELY(! cs))
1808
1/1
✓ Branch 2 taken 447 times.
894 return maybe_suspend(cs.begin(), state::obj8, size);
1809
2/2
✓ Branch 1 taken 17820 times.
✓ Branch 2 taken 42975 times.
121590 if(BOOST_JSON_LIKELY(*cs == ','))
1810 {
1811 35640 ++cs;
1812 39478 do_obj9:
1813 39478 cs = detail::count_whitespace(cs.begin(), cs.end());
1814
2/2
✓ Branch 1 taken 694 times.
✓ Branch 2 taken 19045 times.
39478 if(BOOST_JSON_UNLIKELY(! cs))
1815
1/1
✓ Branch 2 taken 694 times.
1388 return maybe_suspend(cs.begin(), state::obj9, size);
1816
1817 // loop for next element
1818
2/2
✓ Branch 1 taken 14180 times.
✓ Branch 2 taken 4865 times.
38090 if(BOOST_JSON_LIKELY(*cs == '\x22'))
1819 28360 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.
9730 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.
3288 if(allow_comments && *cs == '/')
1823 {
1824 2866 do_obj10:
1825
1/1
✓ Branch 3 taken 1525 times.
3228 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1826
2/2
✓ Branch 1 taken 270 times.
✓ Branch 2 taken 1255 times.
3050 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1827
1/1
✓ Branch 1 taken 270 times.
540 return suspend_or_fail(state::obj10, size);
1828 2510 goto do_obj9;
1829 }
1830 BOOST_STATIC_CONSTEXPR source_location loc
1831 = BOOST_CURRENT_LOCATION;
1832 422 return fail(cs.begin(), error::syntax, &loc);
1833 }
1834 }
1835
2/2
✓ Branch 1 taken 2325 times.
✓ Branch 2 taken 40650 times.
85950 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.
4650 if(allow_comments && *cs == '/')
1838 {
1839 4344 do_obj11:
1840
1/1
✓ Branch 3 taken 2338 times.
5012 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1841
2/2
✓ Branch 1 taken 502 times.
✓ Branch 2 taken 1836 times.
4676 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1842
1/1
✓ Branch 1 taken 502 times.
1004 return suspend_or_fail(state::obj11, size);
1843 3672 goto do_obj8;
1844 }
1845 BOOST_STATIC_CONSTEXPR source_location loc
1846 = BOOST_CURRENT_LOCATION;
1847 306 return fail(cs.begin(), error::syntax, &loc);
1848 }
1849 // got closing brace, fall through
1850 }
1851
3/5
✓ Branch 1 taken 40603 times.
✗ Branch 3 not taken.
✓ Branch 4 taken 39100 times.
✓ Branch 5 taken 1 times.
✗ Branch 2 not taken.
93540 if(BOOST_JSON_UNLIKELY(
1852 ! h_.on_object_end(size, ec_)))
1853 3004 return fail(cs.begin());
1854 87454 ++depth_;
1855 87454 ++cs;
1856 87454 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 52772 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 52772 detail::const_stream_wrapper cs(p, end_);
1877 std::size_t size;
1878
5/6
✓ Branch 1 taken 5754 times.
✓ Branch 2 taken 20632 times.
✓ Branch 4 taken 5754 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 5754 times.
✓ Branch 7 taken 20632 times.
52772 if(! stack_empty && ! st_.empty())
1879 {
1880 // resume
1881 state st;
1882
1/1
✓ Branch 1 taken 5754 times.
11508 st_.pop(st);
1883
1/1
✓ Branch 1 taken 5754 times.
11508 st_.pop(size);
1884
6/7
✗ Branch 0 not taken.
✓ Branch 1 taken 1054 times.
✓ Branch 2 taken 384 times.
✓ Branch 3 taken 2951 times.
✓ Branch 4 taken 396 times.
✓ Branch 5 taken 675 times.
✓ Branch 6 taken 294 times.
11508 switch(st)
1885 {
1886 default: BOOST_JSON_UNREACHABLE();
1887 2108 case state::arr1: goto do_arr1;
1888 768 case state::arr2: goto do_arr2;
1889 5902 case state::arr3: goto do_arr3;
1890 792 case state::arr4: goto do_arr4;
1891 1350 case state::arr5: goto do_arr5;
1892 588 case state::arr6: goto do_arr6;
1893 }
1894 }
1895
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 20632 times.
41264 BOOST_ASSERT(*cs == '[');
1896 41264 size = 0;
1897
2/2
✓ Branch 0 taken 34 times.
✓ Branch 1 taken 20598 times.
41264 if(BOOST_JSON_UNLIKELY(! depth_))
1898 {
1899 BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1900 68 return fail(cs.begin(), error::too_deep, &loc);
1901 }
1902 41196 --depth_;
1903
4/5
✓ Branch 1 taken 6579 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 5767 times.
✗ Branch 5 not taken.
✓ Branch 2 taken 2136 times.
41196 if(BOOST_JSON_UNLIKELY(
1904 ! h_.on_array_begin(ec_)))
1905 1624 return fail(cs.begin());
1906 37960 ++cs;
1907 // array:
1908 // '[' *ws ']'
1909 // '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1910 43134 do_arr1:
1911 43134 cs = detail::count_whitespace(cs.begin(), cs.end());
1912
2/2
✓ Branch 1 taken 1075 times.
✓ Branch 2 taken 20492 times.
43134 if(BOOST_JSON_UNLIKELY(! cs))
1913
1/1
✓ Branch 2 taken 1075 times.
2150 return maybe_suspend(cs.begin(), state::arr1, size);
1914
2/2
✓ Branch 1 taken 18744 times.
✓ Branch 2 taken 1748 times.
40984 if(BOOST_JSON_LIKELY(*cs != ']'))
1915 {
1916 37488 loop:
1917
6/6
✓ Branch 1 taken 7772 times.
✓ Branch 2 taken 18463 times.
✓ Branch 4 taken 1789 times.
✓ Branch 5 taken 5983 times.
✓ Branch 6 taken 1789 times.
✓ Branch 7 taken 24446 times.
52470 if(allow_comments && *cs == '/')
1918 {
1919 3578 do_arr2:
1920
1/1
✓ Branch 3 taken 2045 times.
4346 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1921
2/2
✓ Branch 1 taken 512 times.
✓ Branch 2 taken 1533 times.
4090 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1922
1/1
✓ Branch 1 taken 512 times.
1024 return suspend_or_fail(state::arr2, size);
1923 3066 goto do_arr1;
1924 }
1925
2/2
✓ Branch 0 taken 1 times.
✓ Branch 1 taken 24445 times.
48892 if(BOOST_JSON_UNLIKELY(++size >
1926 Handler::max_array_size))
1927 {
1928 BOOST_STATIC_CONSTEXPR source_location loc
1929 = BOOST_CURRENT_LOCATION;
1930 2 return fail(cs.begin(), error::array_too_large, &loc);
1931 }
1932 48890 do_arr3:
1933 // array is not empty, value required
1934
1/1
✓ Branch 2 taken 24765 times.
54792 cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1935
2/2
✓ Branch 1 taken 9065 times.
✓ Branch 2 taken 15700 times.
49530 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1936
1/1
✓ Branch 1 taken 9065 times.
18130 return suspend_or_fail(state::arr3, size);
1937 31400 do_arr4:
1938 34652 cs = detail::count_whitespace(cs.begin(), cs.end());
1939
2/2
✓ Branch 1 taken 505 times.
✓ Branch 2 taken 16821 times.
34652 if(BOOST_JSON_UNLIKELY(! cs))
1940
1/1
✓ Branch 2 taken 505 times.
1010 return maybe_suspend(cs.begin(), state::arr4, size);
1941
2/2
✓ Branch 1 taken 9204 times.
✓ Branch 2 taken 7617 times.
33642 if(BOOST_JSON_LIKELY(*cs == ','))
1942 {
1943 18408 ++cs;
1944 19758 do_arr5:
1945 19758 cs = detail::count_whitespace(cs.begin(), cs.end());
1946
2/2
✓ Branch 1 taken 705 times.
✓ Branch 2 taken 9174 times.
19758 if(BOOST_JSON_UNLIKELY(! cs))
1947
1/1
✓ Branch 2 taken 705 times.
1410 return maybe_suspend(cs.begin(), state::arr5, size);
1948 // loop for next element
1949
6/6
✓ Branch 0 taken 2580 times.
✓ Branch 1 taken 6594 times.
✓ Branch 3 taken 897 times.
✓ Branch 4 taken 1683 times.
✓ Branch 5 taken 7491 times.
✓ Branch 6 taken 1683 times.
18348 if(! allow_trailing || *cs != ']')
1950 14982 goto loop;
1951 }
1952
2/2
✓ Branch 1 taken 1969 times.
✓ Branch 2 taken 5648 times.
15234 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.
3938 if(allow_comments && *cs == '/')
1955 {
1956 3082 do_arr6:
1957
1/1
✓ Branch 3 taken 1688 times.
3670 cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1958
2/2
✓ Branch 1 taken 458 times.
✓ Branch 2 taken 1230 times.
3376 if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1959
1/1
✓ Branch 1 taken 458 times.
916 return suspend_or_fail(state::arr6, size);
1960 2460 goto do_arr4;
1961 }
1962 BOOST_STATIC_CONSTEXPR source_location loc
1963 = BOOST_CURRENT_LOCATION;
1964 856 return fail(cs.begin(), error::syntax, &loc);
1965 }
1966 // got closing bracket; fall through
1967 }
1968
3/5
✓ Branch 1 taken 4672 times.
✓ Branch 3 taken 6 times.
✓ Branch 4 taken 4125 times.
✗ Branch 5 not taken.
✗ Branch 2 not taken.
18158 if(BOOST_JSON_UNLIKELY(
1969 ! h_.on_array_end(size, ec_)))
1970 1094 return fail(cs.begin());
1971 15906 ++depth_;
1972 15906 ++cs;
1973 15906 return cs.begin();
1974 }
1975
1976 //----------------------------------------------------------
1977
1978 template<class Handler>
1979 template<bool StackEmpty_, char First_, number_precision Numbers_>
1980 const char*
1981 4253760 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 4253760 constexpr bool precise_parsing = mode == number_precision::precise;
1988 4253760 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 4253760 bool const negative = first == '-';
1995 4253760 bool const zero_first = first == '0';
1996 4253760 bool const nonzero_first = first == '+';
1997 4253760 detail::const_stream_wrapper cs(p, end_);
1998 number num;
1999 4253760 const char* begin = cs.begin();
2000
5/6
✓ Branch 1 taken 37176 times.
✓ Branch 2 taken 2089704 times.
✗ Branch 4 not taken.
✓ Branch 5 taken 37176 times.
✓ Branch 6 taken 2089704 times.
✓ Branch 7 taken 37176 times.
4253760 if(stack_empty || st_.empty())
2001 {
2002 4179408 num.bias = 0;
2003 4179408 num.exp = 0;
2004 4179408 num.frac = false;
2005 4179408 num_buf_.clear();
2006
2007 //----------------------------------
2008 //
2009 // '-'
2010 // leading minus sign
2011 //
2012
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2089704 times.
4179408 BOOST_ASSERT(cs);
2013 if(negative)
2014 50356 ++cs;
2015
2016 4179408 num.neg = negative;
2017 4179408 num.frac = false;
2018 4179408 num.exp = 0;
2019 4179408 num.bias = 0;
2020
2021 // fast path
2022
2/2
✓ Branch 1 taken 2028504 times.
✓ Branch 2 taken 61200 times.
4179408 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.
19976 if( nonzero_first ||
2027 19976 (negative && *cs != '0') )
2028 {
2029 4014634 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.
4014634 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.
3672 if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033 {
2034
1/1
✓ Branch 1 taken 8 times.
18 return parse_literal(
2035 p - 1,
2036 16 detail::literals_c<detail::literals::neg_infinity>());
2037 }
2038
2039
2/2
✓ Branch 0 taken 2 times.
✓ Branch 1 taken 1825 times.
3654 if( ! nonzero_first && n1 == 0 )
2040 {
2041 // digit required
2042 BOOST_STATIC_CONSTEXPR source_location loc
2043 = BOOST_CURRENT_LOCATION;
2044 4 return fail(cs.begin(), error::syntax, &loc);
2045 }
2046
2047 BOOST_IF_CONSTEXPR( !no_parsing )
2048 4012916 num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049 else
2050 1696 num.mant = 0;
2051
2052 4014612 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.
4014612 if( n1 == 16 )
2057 {
2058 4002848 goto do_num2;
2059 }
2060 }
2061 else
2062 {
2063 // 0. floating-point or 0e integer
2064 42374 num.mant = 0;
2065 42374 n1 = 0;
2066 42374 ++cs;
2067 }
2068
2069 {
2070 54138 const char c = *cs;
2071
2/2
✓ Branch 0 taken 9870 times.
✓ Branch 1 taken 17199 times.
54138 if(c != '.')
2072 {
2073
2/2
✓ Branch 0 taken 6576 times.
✓ Branch 1 taken 3294 times.
19740 if((c | 32) == 'e')
2074 {
2075 13152 ++cs;
2076 13152 goto do_exp1;
2077 }
2078 BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079 38 num.mant = ~num.mant + 1;
2080 6588 goto finish_signed;
2081 }
2082 }
2083
2084 // floating-point number
2085
2086 34398 ++cs;
2087
2088 34398 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.
34398 BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
2/2
✓ Branch 0 taken 3 times.
✓ Branch 1 taken 17196 times.
34398 if( n2 == 0 )
2092 {
2093 // digit required
2094 BOOST_STATIC_CONSTEXPR source_location loc
2095 = BOOST_CURRENT_LOCATION;
2096 6 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.
34392 if( n1 + n2 >= 19 )
2101 {
2102 244 goto do_num7;
2103 }
2104
2105 BOOST_IF_CONSTEXPR( !no_parsing )
2106 25710 num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 17074 times.
34148 BOOST_ASSERT(num.bias == 0);
2109
2110 34148 num.bias -= n2;
2111
2112 34148 cs += n2;
2113
2114 34148 char ch = *cs;
2115
2116
2/2
✓ Branch 0 taken 110 times.
✓ Branch 1 taken 16964 times.
34148 if( (ch | 32) == 'e' )
2117 {
2118 220 ++cs;
2119 220 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.
33928 else if( ch >= '0' && ch <= '9' )
2122 {
2123 20034 goto do_num8;
2124 }
2125
2126 13894 goto finish_dub;
2127 }
2128 }
2129 else
2130 {
2131 74352 num = num_;
2132 state st;
2133
1/1
✓ Branch 1 taken 37176 times.
74352 st_.pop(st);
2134
11/12
✗ Branch 0 not taken.
✓ Branch 1 taken 602 times.
✓ Branch 2 taken 6340 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.
74352 switch(st)
2135 {
2136 default: BOOST_JSON_UNREACHABLE();
2137 1204 case state::num1: goto do_num1;
2138 12680 case state::num2: goto do_num2;
2139 1604 case state::num3: goto do_num3;
2140 104 case state::num4: goto do_num4;
2141 9074 case state::num5: goto do_num5;
2142 1332 case state::num6: goto do_num6;
2143 1232 case state::num7: goto do_num7;
2144 21888 case state::num8: goto do_num8;
2145 938 case state::exp1: goto do_exp1;
2146 250 case state::exp2: goto do_exp2;
2147 24046 case state::exp3: goto do_exp3;
2148 }
2149 }
2150
2151 //----------------------------------
2152 //
2153 // DIGIT
2154 // first digit
2155 //
2156 123604 do_num1:
2157 31584 if(zero_first || nonzero_first ||
2158
2/2
✓ Branch 1 taken 15070 times.
✓ Branch 2 taken 722 times.
31584 BOOST_JSON_LIKELY(cs))
2159 {
2160 122160 char const c = *cs;
2161 if(zero_first)
2162 {
2163 19436 ++cs;
2164 19436 num.mant = 0;
2165 19436 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.
30140 else if(nonzero_first || BOOST_JSON_LIKELY(
2168 c >= '1' && c <= '9'))
2169 {
2170 85080 ++cs;
2171 85080 num.mant = c - '0';
2172 }
2173
2/2
✓ Branch 0 taken 7627 times.
✓ Branch 1 taken 1195 times.
17644 else if(BOOST_JSON_UNLIKELY(
2174 c == '0'))
2175 {
2176 15254 ++cs;
2177 15254 num.mant = 0;
2178 15254 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.
2390 else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181 {
2182
1/1
✓ Branch 1 taken 1007 times.
2014 st_.push(state::lit1);
2183 2014 cur_lit_ = literal_index(detail::literals::neg_infinity);
2184 2014 lit_offset_ = 1;
2185
1/1
✓ Branch 2 taken 961 times.
2014 return parse_literal(
2186 1922 cs.begin(), detail::literals_c<detail::literals::resume>() );
2187 }
2188 else
2189 {
2190 BOOST_STATIC_CONSTEXPR source_location loc
2191 = BOOST_CURRENT_LOCATION;
2192 376 return fail(cs.begin(), error::syntax, &loc);
2193 }
2194 }
2195 else
2196 {
2197
3/6
✓ Branch 3 taken 215 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 155 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 303 times.
1444 if(BOOST_JSON_UNLIKELY(
2198 ! h_.on_number_part(
2199 {begin, cs.used(begin)}, ec_)))
2200 120 return fail(cs.begin());
2201
2202 BOOST_IF_CONSTEXPR( precise_parsing )
2203
1/1
✓ Branch 2 taken 64 times.
128 num_buf_.append( begin, cs.used(begin) );
2204
1/1
✓ Branch 2 taken 602 times.
1204 return maybe_suspend(
2205 1204 cs.begin(), state::num1, num);
2206 }
2207
2208 //----------------------------------
2209 //
2210 // 1*DIGIT
2211 // significant digits left of decimal
2212 //
2213 4100608 do_num2:
2214
6/6
✓ Branch 1 taken 6576 times.
✓ Branch 2 taken 2037469 times.
✓ Branch 3 taken 1567 times.
✓ Branch 4 taken 5009 times.
✓ Branch 5 taken 1567 times.
✓ Branch 6 taken 2042478 times.
4088090 if(negative || (!stack_empty && num.neg))
2215 {
2216 44800 for(;;)
2217 {
2218
2/2
✓ Branch 1 taken 1921 times.
✓ Branch 2 taken 28305 times.
60452 if(BOOST_JSON_UNLIKELY(! cs))
2219 {
2220
2/2
✓ Branch 0 taken 1469 times.
✓ Branch 1 taken 452 times.
3842 if(BOOST_JSON_UNLIKELY(more_))
2221 {
2222
3/6
✓ Branch 3 taken 397 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 328 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 796 times.
2938 if(BOOST_JSON_UNLIKELY(
2223 ! h_.on_number_part(
2224 {begin, cs.used(begin)}, ec_)))
2225 138 return fail(cs.begin());
2226
2227 BOOST_IF_CONSTEXPR( precise_parsing )
2228
1/1
✓ Branch 2 taken 32 times.
64 num_buf_.append( begin, cs.used(begin) );
2229
1/1
✓ Branch 2 taken 1331 times.
2662 return suspend(cs.begin(), state::num2, num);
2230 }
2231 904 goto finish_int;
2232 }
2233 56610 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.
56610 if(BOOST_JSON_LIKELY(
2235 c >= '0' && c <= '9'))
2236 {
2237 46446 ++cs;
2238 // 9223372036854775808 INT64_MIN
2239
2/2
✓ Branch 0 taken 22508 times.
✓ Branch 1 taken 715 times.
46446 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.
45016 num.mant == 922337203685477580 && c > '8'))
2241 break;
2242 BOOST_IF_CONSTEXPR( !no_parsing )
2243 44282 num.mant = 10 * num.mant + ( c - '0' );
2244 44800 continue;
2245 }
2246 10164 goto do_num6; // [.eE]
2247 }
2248 }
2249 else
2250 {
2251 13770088 for(;;)
2252 {
2253
2/2
✓ Branch 1 taken 6428 times.
✓ Branch 2 taken 8921094 times.
17855044 if(BOOST_JSON_UNLIKELY(! cs))
2254 {
2255
2/2
✓ Branch 0 taken 5815 times.
✓ Branch 1 taken 613 times.
12856 if(BOOST_JSON_UNLIKELY(more_))
2256 {
2257
4/6
✓ Branch 3 taken 2197 times.
✓ Branch 5 taken 6 times.
✓ Branch 6 taken 1791 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 1790 times.
11630 if(BOOST_JSON_UNLIKELY(
2258 ! h_.on_number_part(
2259 {begin, cs.used(begin)}, ec_)))
2260 812 return fail(cs.begin());
2261
2262 BOOST_IF_CONSTEXPR( precise_parsing )
2263
1/1
✓ Branch 2 taken 174 times.
348 num_buf_.append( begin, cs.used(begin) );
2264
1/1
✓ Branch 2 taken 5009 times.
10018 return suspend(cs.begin(), state::num2, num);
2265 }
2266 1226 goto finish_int;
2267 }
2268 17842188 char const c = *cs;
2269
6/6
✓ Branch 0 taken 6898097 times.
✓ Branch 1 taken 2022997 times.
✓ Branch 2 taken 6888869 times.
✓ Branch 3 taken 9228 times.
✓ Branch 4 taken 6888869 times.
✓ Branch 5 taken 2032225 times.
17842188 if(BOOST_JSON_LIKELY(
2270 c >= '0' && c <= '9'))
2271 {
2272 13777738 ++cs;
2273 // 18446744073709551615 UINT64_MAX
2274
2/2
✓ Branch 0 taken 6885466 times.
✓ Branch 1 taken 3403 times.
13777738 if( num.mant > 1844674407370955161 || (
2275
4/4
✓ Branch 0 taken 680 times.
✓ Branch 1 taken 6884786 times.
✓ Branch 2 taken 258 times.
✓ Branch 3 taken 422 times.
13770932 num.mant == 1844674407370955161 && c > '5'))
2276 break;
2277 BOOST_IF_CONSTEXPR( !no_parsing )
2278 13758892 num.mant = 10 * num.mant + ( c - '0' );
2279 }
2280 else
2281 {
2282 4064450 goto do_num6; // [.eE]
2283 }
2284 }
2285 }
2286 9296 ++num.bias;
2287
2288 //----------------------------------
2289 //
2290 // 1*DIGIT
2291 // non-significant digits left of decimal
2292 //
2293 10900 do_num3:
2294 23116 for(;;)
2295 {
2296
2/2
✓ Branch 1 taken 1527 times.
✓ Branch 2 taken 15481 times.
34016 if(BOOST_JSON_UNLIKELY(! cs))
2297 {
2298
2/2
✓ Branch 0 taken 894 times.
✓ Branch 1 taken 633 times.
3054 if(BOOST_JSON_UNLIKELY(more_))
2299 {
2300
3/6
✓ Branch 3 taken 181 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 135 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 539 times.
1788 if(BOOST_JSON_UNLIKELY(
2301 ! h_.on_number_part(
2302 {begin, cs.used(begin)}, ec_)))
2303 92 return fail(cs.begin());
2304
2305 BOOST_IF_CONSTEXPR( precise_parsing )
2306
1/1
✓ Branch 2 taken 12 times.
24 num_buf_.append( begin, cs.used(begin) );
2307
1/1
✓ Branch 2 taken 802 times.
1604 return suspend(cs.begin(), state::num3, num);
2308 }
2309 1266 goto finish_dub;
2310 }
2311 30962 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.
30962 if(BOOST_JSON_UNLIKELY(
2313 c >= '0' && c <= '9'))
2314 {
2315
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 11558 times.
23116 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 23116 ++cs;
2322 23116 ++num.bias;
2323 }
2324
2/2
✓ Branch 0 taken 2028 times.
✓ Branch 1 taken 1895 times.
7846 else if(BOOST_JSON_LIKELY(
2325 c == '.'))
2326 {
2327 4056 ++cs;
2328 4056 break;
2329 }
2330
2/2
✓ Branch 0 taken 546 times.
✓ Branch 1 taken 1349 times.
3790 else if((c | 32) == 'e')
2331 {
2332 1092 ++cs;
2333 1092 goto do_exp1;
2334 }
2335 else
2336 {
2337 2698 goto finish_dub;
2338 }
2339 }
2340
2341 //----------------------------------
2342 //
2343 // DIGIT
2344 // first non-significant digit
2345 // to the right of decimal
2346 //
2347 4160 do_num4:
2348 {
2349
2/2
✓ Branch 1 taken 64 times.
✓ Branch 2 taken 2016 times.
4160 if(BOOST_JSON_UNLIKELY(! cs))
2350 {
2351
3/6
✓ Branch 3 taken 22 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 16 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 20 times.
128 if(BOOST_JSON_UNLIKELY(
2352 ! h_.on_number_part(
2353 {begin, cs.used(begin)}, ec_)))
2354 12 return fail(cs.begin());
2355
2356 BOOST_IF_CONSTEXPR( precise_parsing )
2357
1/1
✓ Branch 2 taken 4 times.
8 num_buf_.append( begin, cs.used(begin) );
2358
1/1
✓ Branch 2 taken 52 times.
104 return maybe_suspend(
2359 104 cs.begin(), state::num4, num);
2360 }
2361 4032 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.
4032 if(BOOST_JSON_LIKELY(
2363 //static_cast<unsigned char>(c - '0') < 10))
2364 c >= '0' && c <= '9'))
2365 {
2366 3898 ++cs;
2367 }
2368 else
2369 {
2370 // digit required
2371 BOOST_STATIC_CONSTEXPR source_location loc
2372 = BOOST_CURRENT_LOCATION;
2373 134 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 4026940 do_num5:
2384 75779664 for(;;)
2385 {
2386
2/2
✓ Branch 1 taken 6112 times.
✓ Branch 2 taken 39897190 times.
79806604 if(BOOST_JSON_UNLIKELY(! cs))
2387 {
2388
2/2
✓ Branch 0 taken 4577 times.
✓ Branch 1 taken 1535 times.
12224 if(BOOST_JSON_UNLIKELY(more_))
2389 {
2390
3/6
✓ Branch 3 taken 94 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 74 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 4403 times.
9154 if(BOOST_JSON_UNLIKELY(
2391 ! h_.on_number_part(
2392 {begin, cs.used(begin)}, ec_)))
2393 40 return fail(cs.begin());
2394
2395 BOOST_IF_CONSTEXPR( precise_parsing )
2396
1/1
✓ Branch 2 taken 178 times.
356 num_buf_.append( begin, cs.used(begin) );
2397
1/1
✓ Branch 2 taken 4537 times.
9074 return suspend(cs.begin(), state::num5, num);
2398 }
2399 3070 goto finish_dub;
2400 }
2401 79794380 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.
79794380 if(BOOST_JSON_LIKELY(
2403 c >= '0' && c <= '9'))
2404 {
2405 75779664 ++cs;
2406 }
2407
2/2
✓ Branch 0 taken 2003236 times.
✓ Branch 1 taken 4122 times.
4014716 else if((c | 32) == 'e')
2408 {
2409 4006472 ++cs;
2410 4006472 goto do_exp1;
2411 }
2412 else
2413 {
2414 8244 goto finish_dub;
2415 }
2416 }
2417
2418 //----------------------------------
2419 //
2420 // [.eE]
2421 //
2422 4110636 do_num6:
2423 {
2424
2/2
✓ Branch 1 taken 798 times.
✓ Branch 2 taken 2054520 times.
4110636 if(BOOST_JSON_UNLIKELY(! cs))
2425 {
2426
2/2
✓ Branch 0 taken 751 times.
✓ Branch 1 taken 47 times.
1596 if(BOOST_JSON_UNLIKELY(more_))
2427 {
2428
3/6
✓ Branch 3 taken 161 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 119 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 431 times.
1502 if(BOOST_JSON_UNLIKELY(
2429 ! h_.on_number_part(
2430 {begin, cs.used(begin)}, ec_)))
2431 84 return fail(cs.begin());
2432
2433 BOOST_IF_CONSTEXPR( precise_parsing )
2434
1/1
✓ Branch 2 taken 98 times.
196 num_buf_.append( begin, cs.used(begin) );
2435
1/1
✓ Branch 2 taken 667 times.
1334 return suspend(cs.begin(), state::num6, num);
2436 }
2437 94 goto finish_int;
2438 }
2439 4109040 char const c = *cs;
2440
2/2
✓ Branch 0 taken 2016097 times.
✓ Branch 1 taken 38423 times.
4109040 if(BOOST_JSON_LIKELY(
2441 c == '.'))
2442 {
2443 4032194 ++cs;
2444 }
2445
2/2
✓ Branch 0 taken 9140 times.
✓ Branch 1 taken 29283 times.
76846 else if((c | 32) == 'e')
2446 {
2447 18280 ++cs;
2448 18280 goto do_exp1;
2449 }
2450 else
2451 {
2452 58566 goto finish_int;
2453 }
2454 }
2455
2456 //----------------------------------
2457 //
2458 // DIGIT
2459 // first significant digit
2460 // to the right of decimal
2461 //
2462 4033670 do_num7:
2463 {
2464
2/2
✓ Branch 1 taken 691 times.
✓ Branch 2 taken 2016144 times.
4033670 if(BOOST_JSON_UNLIKELY(! cs))
2465 {
2466
2/2
✓ Branch 0 taken 687 times.
✓ Branch 1 taken 4 times.
1382 if(BOOST_JSON_UNLIKELY(more_))
2467 {
2468
3/6
✓ Branch 3 taken 144 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 109 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 412 times.
1374 if(BOOST_JSON_UNLIKELY(
2469 ! h_.on_number_part(
2470 {begin, cs.used(begin)}, ec_)))
2471 70 return fail(cs.begin());
2472
2473 BOOST_IF_CONSTEXPR( precise_parsing )
2474
1/1
✓ Branch 2 taken 96 times.
192 num_buf_.append( begin, cs.used(begin) );
2475
1/1
✓ Branch 2 taken 617 times.
1234 return suspend(cs.begin(), state::num7, num);
2476 }
2477 // digit required
2478 BOOST_STATIC_CONSTEXPR source_location loc
2479 = BOOST_CURRENT_LOCATION;
2480 8 return fail(cs.begin(), error::syntax, &loc);
2481 }
2482 4032288 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.
4032288 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 338 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 4068872 do_num8:
2500 6555852 for(;;)
2501 {
2502
2/2
✓ Branch 1 taken 12816 times.
✓ Branch 2 taken 5302046 times.
10629724 if(BOOST_JSON_UNLIKELY(! cs))
2503 {
2504
2/2
✓ Branch 0 taken 11080 times.
✓ Branch 1 taken 1736 times.
25632 if(BOOST_JSON_UNLIKELY(more_))
2505 {
2506
3/6
✓ Branch 3 taken 341 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 274 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 10478 times.
22160 if(BOOST_JSON_UNLIKELY(
2507 ! h_.on_number_part(
2508 {begin, cs.used(begin)}, ec_)))
2509 134 return fail(cs.begin());
2510
2511 BOOST_IF_CONSTEXPR( precise_parsing )
2512
1/1
✓ Branch 2 taken 3441 times.
6884 num_buf_.append( begin, cs.used(begin) );
2513
1/1
✓ Branch 2 taken 10945 times.
21890 return suspend(cs.begin(), state::num8, num);
2514 }
2515 3472 goto finish_dub;
2516 }
2517 10604092 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.
10604092 if(BOOST_JSON_LIKELY(
2519 c >= '0' && c <= '9'))
2520 {
2521 10569820 ++cs;
2522
2/2
✓ Branch 0 taken 3277926 times.
✓ Branch 1 taken 2001891 times.
10559634 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.
6555852 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 6555852 --num.bias;
2532 6555852 num.mant = 10 * num.mant + ( c - '0' );
2533 }
2534 else
2535 {
2536 4013968 goto do_num5;
2537 }
2538 }
2539
2/2
✓ Branch 0 taken 11133 times.
✓ Branch 1 taken 6003 times.
34272 else if((c | 32) == 'e')
2540 {
2541 22266 ++cs;
2542 22266 goto do_exp1;
2543 }
2544 else
2545 {
2546 12006 goto finish_dub;
2547 }
2548 }
2549
2550 //----------------------------------
2551 //
2552 // *[+-]
2553 //
2554 4062420 do_exp1:
2555
2/2
✓ Branch 1 taken 565 times.
✓ Branch 2 taken 2030645 times.
4062420 if(BOOST_JSON_UNLIKELY(! cs))
2556 {
2557
3/6
✓ Branch 3 taken 196 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 148 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 187 times.
1130 if(BOOST_JSON_UNLIKELY(
2558 ! h_.on_number_part(
2559 {begin, cs.used(begin)}, ec_)))
2560 96 return fail(cs.begin());
2561
2562 BOOST_IF_CONSTEXPR( precise_parsing )
2563
1/1
✓ Branch 2 taken 46 times.
92 num_buf_.append( begin, cs.used(begin) );
2564
1/1
✓ Branch 2 taken 469 times.
938 return maybe_suspend(
2565 938 cs.begin(), state::exp1, num);
2566 }
2567
2/2
✓ Branch 1 taken 1931 times.
✓ Branch 2 taken 2028714 times.
4061290 if(*cs == '+')
2568 {
2569 3862 ++cs;
2570 }
2571
2/2
✓ Branch 1 taken 1026779 times.
✓ Branch 2 taken 1001935 times.
4057428 else if(*cs == '-')
2572 {
2573 2003870 ++cs;
2574 2003870 num.frac = true;
2575 }
2576
2577 //----------------------------------
2578 //
2579 // DIGIT
2580 // first digit of the exponent
2581 //
2582 2053558 do_exp2:
2583 {
2584
2/2
✓ Branch 1 taken 172 times.
✓ Branch 2 taken 2030598 times.
4061540 if(BOOST_JSON_UNLIKELY(! cs))
2585 {
2586
2/2
✓ Branch 0 taken 163 times.
✓ Branch 1 taken 9 times.
344 if(BOOST_JSON_UNLIKELY(more_))
2587 {
2588
3/6
✓ Branch 3 taken 75 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 56 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 16 times.
326 if(BOOST_JSON_UNLIKELY(
2589 ! h_.on_number_part(
2590 {begin, cs.used(begin)}, ec_)))
2591 38 return fail(cs.begin());
2592
2593 BOOST_IF_CONSTEXPR( precise_parsing )
2594
1/1
✓ Branch 2 taken 4 times.
8 num_buf_.append( begin, cs.used(begin) );
2595
1/1
✓ Branch 2 taken 125 times.
250 return suspend(cs.begin(), state::exp2, num);
2596 }
2597 // digit required
2598 BOOST_STATIC_CONSTEXPR source_location loc
2599 = BOOST_CURRENT_LOCATION;
2600 18 return fail(cs.begin(), error::syntax, &loc);
2601 }
2602 4061196 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.
4061196 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 1016 return fail(cs.begin(), error::syntax, &loc);
2610 }
2611 4060180 ++cs;
2612 4060180 num.exp = c - '0';
2613 }
2614
2615 //----------------------------------
2616 //
2617 // 1*DIGIT
2618 // subsequent digits in the exponent
2619 //
2620 4084226 do_exp3:
2621 10932204 for(;;)
2622 {
2623
2/2
✓ Branch 1 taken 2020530 times.
✓ Branch 2 taken 5487685 times.
15016430 if(BOOST_JSON_UNLIKELY(! cs))
2624 {
2625
2/2
✓ Branch 0 taken 12177 times.
✓ Branch 1 taken 2008353 times.
4041060 if(BOOST_JSON_UNLIKELY(more_))
2626 {
2627
3/6
✓ Branch 3 taken 329 times.
✗ Branch 5 not taken.
✓ Branch 6 taken 252 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 11540 times.
24354 if(BOOST_JSON_UNLIKELY(
2628 ! h_.on_number_part(
2629 {begin, cs.used(begin)}, ec_)))
2630 154 return fail(cs.begin());
2631
2632 BOOST_IF_CONSTEXPR( precise_parsing )
2633
1/1
✓ Branch 2 taken 2873 times.
5746 num_buf_.append( begin, cs.used(begin) );
2634
1/1
✓ Branch 2 taken 12023 times.
24046 return suspend(cs.begin(), state::exp3, num);
2635 }
2636 }
2637 else
2638 {
2639 10975370 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.
10975370 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.
10932204 if(BOOST_JSON_UNLIKELY(
2643 // 2147483647 INT_MAX
2644 num.exp > 214748364 ||
2645 (num.exp == 214748364 && c > '7')
2646 ))
2647 7710 num.exp = INT_MAX;
2648 else BOOST_IF_CONSTEXPR( !no_parsing )
2649 9842790 num.exp = 10 * num.exp + ( c - '0' );
2650
2651 10932204 ++cs;
2652 10932204 continue;
2653 }
2654 }
2655
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 2029936 times.
4059872 BOOST_ASSERT(num.exp >= 0);
2656
2/2
✓ Branch 0 taken 1001799 times.
✓ Branch 1 taken 1028137 times.
4059872 if ( num.frac )
2657 {
2658
2/2
✓ Branch 0 taken 91 times.
✓ Branch 1 taken 1001708 times.
2003598 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.
182 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 182 num.bias = 0;
2675 182 num.exp = INT_MAX;
2676 }
2677 }
2678
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1028137 times.
2056274 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 4059872 goto finish_dub;
2698 }
2699
2700 60790 finish_int:
2701
6/6
✓ Branch 1 taken 2894 times.
✓ Branch 2 taken 25571 times.
✓ Branch 3 taken 602 times.
✓ Branch 4 taken 2292 times.
✓ Branch 5 taken 602 times.
✓ Branch 6 taken 27863 times.
56930 if(negative || (!stack_empty && num.neg))
2702 {
2703
3/6
✓ Branch 3 taken 1497 times.
✓ Branch 5 taken 2 times.
✓ Branch 6 taken 1187 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
5064 if(BOOST_JSON_UNLIKELY(
2704 ! h_.on_int64(static_cast<
2705 int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706 620 return fail(cs.begin());
2707 3828 return cs.begin();
2708 }
2709
2/2
✓ Branch 0 taken 27542 times.
✓ Branch 1 taken 321 times.
55726 if(num.mant <= INT64_MAX)
2710 {
2711 55122 finish_signed:
2712
4/6
✓ Branch 3 taken 17877 times.
✓ Branch 5 taken 7 times.
✓ Branch 6 taken 15610 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✓ Branch 4 taken 1 times.
61672 if(BOOST_JSON_UNLIKELY(
2713 ! h_.on_int64(static_cast<
2714 int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715 4534 return fail(cs.begin());
2716 52618 return cs.begin();
2717 }
2718
3/6
✓ Branch 3 taken 224 times.
✓ Branch 5 taken 3 times.
✓ Branch 6 taken 189 times.
✗ Branch 1 not taken.
✗ Branch 7 not taken.
✗ Branch 4 not taken.
642 if(BOOST_JSON_UNLIKELY(
2719 ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720 70 return fail(cs.begin());
2721 508 return cs.begin();
2722 4104522 finish_dub:
2723 double d;
2724 4104522 std::size_t const size = cs.used(begin);
2725
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 1042951 times.
4104522 BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726 BOOST_IF_CONSTEXPR( precise_parsing )
2727 {
2728 2018620 char const* data = begin;
2729 2018620 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.
2018620 if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734 {
2735
1/1
✓ Branch 1 taken 4771 times.
9542 data = num_buf_.append( begin, size );
2736 9542 full_size = num_buf_.size();
2737 }
2738 2018620 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.
2018620 BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
1/2
✗ Branch 0 not taken.
✓ Branch 1 taken 1009310 times.
2018620 BOOST_ASSERT( err.ptr == data + full_size );
2742 (void)err;
2743 }
2744 else BOOST_IF_CONSTEXPR( no_parsing )
2745 18516 d = 0;
2746 else
2747 2067386 d = detail::dec_to_float(
2748 num.mant,
2749 1063482 num.bias + (num.frac ?
2750 1003904 -num.exp : num.exp),
2751
2/2
✓ Branch 0 taken 501952 times.
✓ Branch 1 taken 531741 times.
2067386 num.neg);
2752
2/6
✗ Branch 4 not taken.
✓ Branch 5 taken 2043759 times.
✗ Branch 1 not taken.
✗ Branch 6 not taken.
✓ Branch 2 taken 2039799 times.
✗ Branch 3 not taken.
4104522 if(BOOST_JSON_UNLIKELY(
2753 ! h_.on_double(d, {begin, size}, ec_)))
2754 3806 return fail(cs.begin());
2755 4096910 return cs.begin();
2756 }
2757
2758 //----------------------------------------------------------
2759
2760 template<class Handler>
2761 template<class... Args>
2762 4329277 basic_parser<Handler>::
2763 basic_parser(
2764 parse_options const& opt,
2765 Args&&... args)
2766
1/1
✓ Branch 2 taken 23 times.
4329261 : h_(std::forward<Args>(args)...)
2767 4329277 , opt_(opt)
2768 {
2769 4329277 }
2770
2771 //----------------------------------------------------------
2772
2773 template<class Handler>
2774 void
2775 4153129 basic_parser<Handler>::
2776 reset() noexcept
2777 {
2778 4153129 ec_ = {};
2779 4153129 st_.clear();
2780 4153129 more_ = true;
2781 4153129 done_ = false;
2782 4153129 clean_ = true;
2783 4153129 num_buf_.clear();
2784 4153129 }
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 2458495 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 times.
✓ Branch 1 taken 2331155 times.
2458495 if(! clean_)
2818 {
2819 // prevent UB
2820
1/2
✓ Branch 1 taken 1 times.
✗ Branch 2 not taken.
2 if(! ec_)
2821 {
2822 2 BOOST_JSON_FAIL(ec_, error::exception);
2823 }
2824 }
2825
2/2
✓ Branch 1 taken 5 times.
✓ Branch 2 taken 2331151 times.
2458495 if(ec_)
2826 {
2827 // error is sticky
2828 7 ec = ec_;
2829 7 return 0;
2830 }
2831 2458488 clean_ = false;
2832 2458488 more_ = more;
2833 2458488 end_ = data + size;
2834 const char* p;
2835
2/2
✓ Branch 1 taken 2164070 times.
✓ Branch 2 taken 167081 times.
2458488 if(BOOST_JSON_LIKELY(st_.empty()))
2836 {
2837 // first time
2838 2251820 depth_ = opt_.max_depth;
2839
3/3
✓ Branch 2 taken 2148290 times.
✓ Branch 3 taken 1 times.
✓ Branch 1 taken 7889 times.
2251820 if(BOOST_JSON_UNLIKELY(
2840 ! h_.on_document_begin(ec_)))
2841 {
2842 15778 ec = ec_;
2843 15778 return 0;
2844 }
2845 2220262 p = parse_document(data, std::true_type());
2846 }
2847 else
2848 {
2849 206668 p = parse_document(data, std::false_type());
2850 }
2851
2852
2/2
✓ Branch 1 taken 2098579 times.
✓ Branch 2 taken 197694 times.
2388874 if(BOOST_JSON_LIKELY(p != sentinel()))
2853 {
2854
1/2
✗ Branch 1 not taken.
✓ Branch 2 taken 2098579 times.
2120986 BOOST_ASSERT(! ec_);
2855
2/2
✓ Branch 0 taken 2031361 times.
✓ Branch 1 taken 67218 times.
2120986 if(! done_)
2856 {
2857 2050263 done_ = true;
2858 2050263 h_.on_document_end(ec_);
2859 }
2860 }
2861 else
2862 {
2863
2/2
✓ Branch 1 taken 170965 times.
✓ Branch 2 taken 26729 times.
267888 if(! ec_)
2864 {
2865
2/2
✓ Branch 0 taken 572 times.
✓ Branch 1 taken 170393 times.
214404 if(! more_)
2866 {
2867 1119 BOOST_JSON_FAIL(ec_, error::incomplete);
2868 }
2869
1/2
✓ Branch 1 taken 170393 times.
✗ Branch 2 not taken.
213285 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 213285 st_.peek(st);
2876
2/2
✓ Branch 0 taken 88354 times.
✓ Branch 1 taken 82039 times.
213285 if( st == state::doc3 &&
2877
2/2
✓ Branch 0 taken 70527 times.
✓ Branch 1 taken 17827 times.
95163 ! done_)
2878 {
2879 77336 done_ = true;
2880
1/1
✓ Branch 1 taken 1645 times.
77336 h_.on_document_end(ec_);
2881 }
2882 }
2883 }
2884 264600 p = end_;
2885 }
2886 2377666 ec = ec_;
2887 2377666 clean_ = true;
2888 2377666 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 times.
1 std::size_t const result = write_some(more, data, size, jec);
2902
1/1
✓ Branch 1 taken 1 times.
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