GCC Code Coverage Report


Directory: libs/json/include/boost/json/
File: basic_parser_impl.hpp
Date: 2025-12-23 17:22:01
Exec Total Coverage
Lines: 1259 1283 98.1%
Functions: 1385 3904 35.5%
Branches: 1036 1264 82.0%

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