Coverage Report

Created: 2024-02-11 06:17

/src/boost/boost/json/basic_parser_impl.hpp
Line
Count
Source (jump to first uncovered line)
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
pow10(int exp) noexcept
55
5.55M
{
56
5.55M
    static double const tab[618] = {
57
5.55M
                        1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
58
59
5.55M
        1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
60
5.55M
        1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
61
5.55M
        1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
62
5.55M
        1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
63
5.55M
        1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
64
5.55M
        1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
65
5.55M
        1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
66
5.55M
        1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
67
5.55M
        1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
68
5.55M
        1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
69
70
5.55M
        1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
71
5.55M
        1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
72
5.55M
        1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
73
5.55M
        1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
74
5.55M
        1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
75
5.55M
        1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
76
5.55M
        1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
77
5.55M
        1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
78
5.55M
        1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
79
5.55M
        1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
80
81
5.55M
        1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
82
5.55M
        1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
83
5.55M
        1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
84
5.55M
        1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
85
5.55M
        1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
86
5.55M
        1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
87
5.55M
        1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
88
5.55M
        1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
89
5.55M
        1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
90
5.55M
        1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
91
92
5.55M
        1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
93
5.55M
        1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
94
5.55M
        1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
95
5.55M
        1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
96
5.55M
        1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
97
5.55M
        1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
98
5.55M
        1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
99
5.55M
        1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
100
5.55M
        1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
101
5.55M
        1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
102
103
5.55M
        1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
104
5.55M
        1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
105
5.55M
        1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
106
5.55M
        1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
107
5.55M
        1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
108
5.55M
        1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
109
5.55M
        1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
110
5.55M
        1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
111
5.55M
        1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
112
5.55M
        1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
113
114
5.55M
        1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
115
5.55M
        1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
116
5.55M
        1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
117
5.55M
        1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
118
5.55M
        1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
119
5.55M
        1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
120
5.55M
        1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
121
5.55M
        1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
122
5.55M
        1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
123
5.55M
        1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
124
125
5.55M
        1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
126
127
5.55M
    if( exp > 308 )
128
42.6k
    {
129
42.6k
        return std::numeric_limits<double>::infinity();
130
42.6k
    }
131
5.51M
    else if( exp < -308 )
132
9.07k
    {
133
        // due to the way pow10 is used by dec_to_float,
134
        // we can afford to return 0.0 here
135
9.07k
        return 0.0;
136
9.07k
    }
137
5.50M
    else
138
5.50M
    {
139
5.50M
        exp += 308;
140
5.50M
        BOOST_ASSERT(exp >= 0 && exp < 618);
141
5.50M
        return tab[exp];
142
5.50M
    }
143
5.55M
}
144
145
inline
146
double
147
dec_to_float(
148
    std::uint64_t m,
149
    std::int32_t e,
150
    bool neg) noexcept
151
5.57M
{
152
    // convert to double explicitly to silence warnings
153
5.57M
    double x = static_cast<double>(m);
154
5.57M
    if(neg)
155
30.2k
        x = -x;
156
157
5.57M
    if(e < -305)
158
11.0k
    {
159
11.0k
        x *= 1e-305 ;
160
11.0k
        e += 305;
161
11.0k
    }
162
163
5.57M
    if(e >= -22 && e < 0)
164
43.3k
        return x / pow10(-e);
165
166
5.52M
    return x * pow10(e);
167
5.57M
}
168
169
inline
170
bool
171
is_control(char c) noexcept
172
57.3M
{
173
57.3M
    return static_cast<unsigned char>(c) < 32;
174
57.3M
}
175
176
inline
177
int
178
hex_digit(unsigned char c) noexcept
179
12.5M
{
180
    // by Peter Dimov
181
12.5M
    if( c >= '0' && c <= '9' )
182
6.98M
        return c - '0';
183
5.53M
    c &= ~0x20;
184
5.53M
    if( c >= 'A' && c <= 'F' )
185
5.52M
        return 10 + c - 'A';
186
1.28k
    return -1;
187
5.53M
}
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
    operator()( mp11::mp_size_t<N> ) const
215
10.6M
    {
216
10.6M
        return parser->parse_number(
217
10.6M
            p,
218
10.6M
            std::integral_constant<bool, StackEmpty_>(),
219
10.6M
            std::integral_constant<char, First_>(),
220
10.6M
            std::integral_constant<
221
10.6M
                number_precision, static_cast<number_precision>(N)>() );
222
10.6M
    }
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)48>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
215
228k
    {
216
228k
        return parser->parse_number(
217
228k
            p,
218
228k
            std::integral_constant<bool, StackEmpty_>(),
219
228k
            std::integral_constant<char, First_>(),
220
228k
            std::integral_constant<
221
228k
                number_precision, static_cast<number_precision>(N)>() );
222
228k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)48>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)48>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)45>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
215
37.1k
    {
216
37.1k
        return parser->parse_number(
217
37.1k
            p,
218
37.1k
            std::integral_constant<bool, StackEmpty_>(),
219
37.1k
            std::integral_constant<char, First_>(),
220
37.1k
            std::integral_constant<
221
37.1k
                number_precision, static_cast<number_precision>(N)>() );
222
37.1k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)45>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)45>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)43>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
215
10.3M
    {
216
10.3M
        return parser->parse_number(
217
10.3M
            p,
218
10.3M
            std::integral_constant<bool, StackEmpty_>(),
219
10.3M
            std::integral_constant<char, First_>(),
220
10.3M
            std::integral_constant<
221
10.3M
                number_precision, static_cast<number_precision>(N)>() );
222
10.3M
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)43>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<true, (char)43>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<false, (char)0>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
215
3.18k
    {
216
3.18k
        return parser->parse_number(
217
3.18k
            p,
218
3.18k
            std::integral_constant<bool, StackEmpty_>(),
219
3.18k
            std::integral_constant<char, First_>(),
220
3.18k
            std::integral_constant<
221
3.18k
                number_precision, static_cast<number_precision>(N)>() );
222
3.18k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<false, (char)0>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number_helper<false, (char)0>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
223
};
224
225
//----------------------------------------------------------
226
227
template<class Handler>
228
void
229
basic_parser<Handler>::
230
reserve()
231
9.51k
{
232
9.51k
    if(BOOST_JSON_LIKELY(
233
9.51k
        ! st_.empty()))
234
2.25k
        return;
235
    // Reserve the largest stack we need,
236
    // to avoid reallocation during suspend.
237
7.26k
    st_.reserve(
238
7.26k
        sizeof(state) + // document parsing state
239
7.26k
        (sizeof(state) +
240
7.26k
            sizeof(std::size_t)) * depth() + // array and object state + size
241
7.26k
        sizeof(state) + // value parsing state
242
7.26k
        sizeof(std::size_t) + // string size
243
7.26k
        sizeof(state)); // comment state
244
7.26k
}
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
basic_parser<Handler>::
256
sentinel()
257
11.9M
{
258
    // the "+1" ensures that the returned pointer is unique even if
259
    // the given input buffer borders on this object
260
11.9M
    return reinterpret_cast<
261
11.9M
        const char*>(this) + 1;
262
11.9M
}
263
264
template<class Handler>
265
bool
266
basic_parser<Handler>::
267
incomplete(
268
    const detail::const_stream_wrapper& cs)
269
11.8M
{
270
11.8M
    return cs.begin() == sentinel();
271
11.8M
}
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
basic_parser<Handler>::
298
suspend_or_fail(
299
    state st,
300
    std::size_t n)
301
8.01k
{
302
8.01k
    if(BOOST_JSON_LIKELY(
303
8.01k
        ! ec_ && more_))
304
2.19k
    {
305
        // suspend
306
2.19k
        reserve();
307
2.19k
        st_.push_unchecked(n);
308
2.19k
        st_.push_unchecked(st);
309
2.19k
    }
310
8.01k
    return sentinel();
311
8.01k
}
312
313
314
template<class Handler>
315
const char*
316
basic_parser<Handler>::
317
fail(const char* p) noexcept
318
0
{
319
0
    BOOST_ASSERT( p != sentinel() );
320
0
    end_ = p;
321
0
    return sentinel();
322
0
}
323
324
template<class Handler>
325
const char*
326
basic_parser<Handler>::
327
fail(
328
    const char* p,
329
    error ev,
330
    source_location const* loc) noexcept
331
4.79k
{
332
4.79k
    BOOST_ASSERT( p != sentinel() );
333
4.79k
    end_ = p;
334
4.79k
    ec_.assign(ev, loc);
335
4.79k
    return sentinel();
336
4.79k
}
337
338
template<class Handler>
339
const char*
340
basic_parser<Handler>::
341
maybe_suspend(
342
    const char* p,
343
    state st)
344
701
{
345
701
    if( p != sentinel() )
346
575
        end_ = p;
347
701
    if(BOOST_JSON_LIKELY(more_))
348
327
    {
349
        // suspend
350
327
        reserve();
351
327
        st_.push_unchecked(st);
352
327
    }
353
701
    return sentinel();
354
701
}
355
356
template<class Handler>
357
const char*
358
basic_parser<Handler>::
359
maybe_suspend(
360
    const char* p,
361
    state st,
362
    std::size_t n)
363
5.83k
{
364
5.83k
    BOOST_ASSERT( p != sentinel() );
365
5.83k
    end_ = p;
366
5.83k
    if(BOOST_JSON_LIKELY(more_))
367
1.76k
    {
368
        // suspend
369
1.76k
        reserve();
370
1.76k
        st_.push_unchecked(n);
371
1.76k
        st_.push_unchecked(st);
372
1.76k
    }
373
5.83k
    return sentinel();
374
5.83k
}
375
376
template<class Handler>
377
const char*
378
basic_parser<Handler>::
379
maybe_suspend(
380
    const char* p,
381
    state st,
382
    const number& num)
383
339
{
384
339
    BOOST_ASSERT( p != sentinel() );
385
339
    end_ = p;
386
339
    if(BOOST_JSON_LIKELY(more_))
387
113
    {
388
        // suspend
389
113
        num_ = num;
390
113
        reserve();
391
113
        st_.push_unchecked(st);;
392
113
    }
393
339
    return sentinel();
394
339
}
395
396
template<class Handler>
397
const char*
398
basic_parser<Handler>::
399
suspend(
400
    const char* p,
401
    state st)
402
2.04k
{
403
2.04k
    BOOST_ASSERT( p != sentinel() );
404
2.04k
    end_ = p;
405
    // suspend
406
2.04k
    reserve();
407
2.04k
    st_.push_unchecked(st);
408
2.04k
    return sentinel();
409
2.04k
}
410
411
template<class Handler>
412
const char*
413
basic_parser<Handler>::
414
suspend(
415
    const char* p,
416
    state st,
417
    const number& num)
418
3.07k
{
419
3.07k
    BOOST_ASSERT( p != sentinel() );
420
3.07k
    end_ = p;
421
    // suspend
422
3.07k
    num_ = num;
423
3.07k
    reserve();
424
3.07k
    st_.push_unchecked(st);
425
3.07k
    return sentinel();
426
3.07k
}
427
428
template<class Handler>
429
template<
430
    bool StackEmpty_/*,
431
    bool Terminal_*/>
432
const char*
433
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
5.28k
{
438
5.28k
    detail::const_stream_wrapper cs(p, end_);
439
5.28k
    const char* start = cs.begin();
440
5.28k
    std::size_t remain;
441
5.28k
    if(! stack_empty && ! st_.empty())
442
118
    {
443
118
        state st;
444
118
        st_.pop(st);
445
118
        switch(st)
446
118
        {
447
0
            default: BOOST_JSON_UNREACHABLE();
448
63
            case state::com1: goto do_com1;
449
19
            case state::com2: goto do_com2;
450
32
            case state::com3: goto do_com3;
451
4
            case state::com4: goto do_com4;
452
118
        }
453
118
    }
454
5.16k
    BOOST_ASSERT(*cs == '/');
455
5.16k
    ++cs;
456
5.22k
do_com1:
457
5.22k
    if(BOOST_JSON_UNLIKELY(! cs))
458
126
        return maybe_suspend(cs.begin(), state::com1);
459
5.10k
    switch(*cs)
460
5.10k
    {
461
23
    default:
462
23
        {
463
23
            BOOST_STATIC_CONSTEXPR source_location loc
464
23
                = BOOST_CURRENT_LOCATION;
465
23
            return fail(cs.begin(), error::syntax, &loc);
466
0
        }
467
4.71k
    case '/':
468
4.71k
        ++cs;
469
4.73k
do_com2:
470
        // KRYSTIAN TODO: this is a mess, we have to fix this
471
4.73k
        remain = cs.remain();
472
4.73k
        cs = remain ? static_cast<const char*>(
473
4.70k
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
474
4.73k
        if(! cs.begin())
475
9
            cs = sentinel();
476
4.73k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
477
38
        {
478
            // if the doc does not terminate
479
            // with a newline, treat it as the
480
            // end of the comment
481
38
            if(terminal && ! more_)
482
1
            {
483
1
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
484
1
                    {start, cs.remain(start)}, ec_)))
485
0
                    return fail(cs.end());
486
1
                return cs.end();
487
1
            }
488
37
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
489
37
                {start, cs.remain(start)}, ec_)))
490
0
                return fail(cs.end());
491
37
            if(terminal)
492
1
                return suspend(cs.end(), state::com2);
493
36
            return maybe_suspend(cs.end(), state::com2);
494
37
        }
495
4.69k
        break;
496
4.69k
    case '*':
497
365
        do
498
1.51k
        {
499
1.51k
            ++cs;
500
1.54k
do_com3:
501
            // KRYSTIAN TODO: this is a mess, we have to fix this
502
1.54k
            remain = cs.remain();
503
1.54k
            cs = remain ? static_cast<const char*>(
504
1.49k
                std::memchr(cs.begin(), '*', remain)) : sentinel();
505
1.54k
            if(! cs.begin())
506
17
                cs = sentinel();
507
            // stopped inside a c comment
508
1.54k
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
509
64
            {
510
64
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
64
                    {start, cs.remain(start)}, ec_)))
512
0
                    return fail(cs.end());
513
64
                return maybe_suspend(cs.end(), state::com3);
514
64
            }
515
            // found a asterisk, check if the next char is a slash
516
1.48k
            ++cs;
517
1.48k
do_com4:
518
1.48k
            if(BOOST_JSON_UNLIKELY(! cs))
519
8
            {
520
8
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
521
8
                    {start, cs.used(start)}, ec_)))
522
0
                    return fail(cs.begin());
523
8
                return maybe_suspend(cs.begin(), state::com4);
524
8
            }
525
1.48k
        }
526
1.47k
        while(*cs != '/');
527
5.10k
    }
528
5.02k
    ++cs;
529
5.02k
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
530
5.02k
        {start, cs.used(start)}, ec_)))
531
0
        return fail(cs.begin());
532
5.02k
    return cs.begin();
533
5.02k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_comment<true>(char const*, std::__1::integral_constant<bool, true>, bool)
Line
Count
Source
437
5.16k
{
438
5.16k
    detail::const_stream_wrapper cs(p, end_);
439
5.16k
    const char* start = cs.begin();
440
5.16k
    std::size_t remain;
441
5.16k
    if(! stack_empty && ! st_.empty())
442
0
    {
443
0
        state st;
444
0
        st_.pop(st);
445
0
        switch(st)
446
0
        {
447
0
            default: BOOST_JSON_UNREACHABLE();
448
0
            case state::com1: goto do_com1;
449
0
            case state::com2: goto do_com2;
450
0
            case state::com3: goto do_com3;
451
0
            case state::com4: goto do_com4;
452
0
        }
453
0
    }
454
5.16k
    BOOST_ASSERT(*cs == '/');
455
5.16k
    ++cs;
456
5.16k
do_com1:
457
5.16k
    if(BOOST_JSON_UNLIKELY(! cs))
458
63
        return maybe_suspend(cs.begin(), state::com1);
459
5.10k
    switch(*cs)
460
5.10k
    {
461
23
    default:
462
23
        {
463
23
            BOOST_STATIC_CONSTEXPR source_location loc
464
23
                = BOOST_CURRENT_LOCATION;
465
23
            return fail(cs.begin(), error::syntax, &loc);
466
0
        }
467
4.71k
    case '/':
468
4.71k
        ++cs;
469
4.71k
do_com2:
470
        // KRYSTIAN TODO: this is a mess, we have to fix this
471
4.71k
        remain = cs.remain();
472
4.71k
        cs = remain ? static_cast<const char*>(
473
4.70k
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
474
4.71k
        if(! cs.begin())
475
9
            cs = sentinel();
476
4.71k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
477
19
        {
478
            // if the doc does not terminate
479
            // with a newline, treat it as the
480
            // end of the comment
481
19
            if(terminal && ! more_)
482
0
            {
483
0
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
484
0
                    {start, cs.remain(start)}, ec_)))
485
0
                    return fail(cs.end());
486
0
                return cs.end();
487
0
            }
488
19
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
489
19
                {start, cs.remain(start)}, ec_)))
490
0
                return fail(cs.end());
491
19
            if(terminal)
492
1
                return suspend(cs.end(), state::com2);
493
18
            return maybe_suspend(cs.end(), state::com2);
494
19
        }
495
4.69k
        break;
496
4.69k
    case '*':
497
365
        do
498
1.51k
        {
499
1.51k
            ++cs;
500
1.51k
do_com3:
501
            // KRYSTIAN TODO: this is a mess, we have to fix this
502
1.51k
            remain = cs.remain();
503
1.51k
            cs = remain ? static_cast<const char*>(
504
1.49k
                std::memchr(cs.begin(), '*', remain)) : sentinel();
505
1.51k
            if(! cs.begin())
506
17
                cs = sentinel();
507
            // stopped inside a c comment
508
1.51k
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
509
32
            {
510
32
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
32
                    {start, cs.remain(start)}, ec_)))
512
0
                    return fail(cs.end());
513
32
                return maybe_suspend(cs.end(), state::com3);
514
32
            }
515
            // found a asterisk, check if the next char is a slash
516
1.48k
            ++cs;
517
1.48k
do_com4:
518
1.48k
            if(BOOST_JSON_UNLIKELY(! cs))
519
4
            {
520
4
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
521
4
                    {start, cs.used(start)}, ec_)))
522
0
                    return fail(cs.begin());
523
4
                return maybe_suspend(cs.begin(), state::com4);
524
4
            }
525
1.48k
        }
526
1.47k
        while(*cs != '/');
527
5.10k
    }
528
5.02k
    ++cs;
529
5.02k
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
530
5.02k
        {start, cs.used(start)}, ec_)))
531
0
        return fail(cs.begin());
532
5.02k
    return cs.begin();
533
5.02k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_comment<false>(char const*, std::__1::integral_constant<bool, false>, bool)
Line
Count
Source
437
118
{
438
118
    detail::const_stream_wrapper cs(p, end_);
439
118
    const char* start = cs.begin();
440
118
    std::size_t remain;
441
118
    if(! stack_empty && ! st_.empty())
442
118
    {
443
118
        state st;
444
118
        st_.pop(st);
445
118
        switch(st)
446
118
        {
447
0
            default: BOOST_JSON_UNREACHABLE();
448
63
            case state::com1: goto do_com1;
449
19
            case state::com2: goto do_com2;
450
32
            case state::com3: goto do_com3;
451
4
            case state::com4: goto do_com4;
452
118
        }
453
118
    }
454
0
    BOOST_ASSERT(*cs == '/');
455
0
    ++cs;
456
63
do_com1:
457
63
    if(BOOST_JSON_UNLIKELY(! cs))
458
63
        return maybe_suspend(cs.begin(), state::com1);
459
0
    switch(*cs)
460
0
    {
461
0
    default:
462
0
        {
463
0
            BOOST_STATIC_CONSTEXPR source_location loc
464
0
                = BOOST_CURRENT_LOCATION;
465
0
            return fail(cs.begin(), error::syntax, &loc);
466
0
        }
467
0
    case '/':
468
0
        ++cs;
469
19
do_com2:
470
        // KRYSTIAN TODO: this is a mess, we have to fix this
471
19
        remain = cs.remain();
472
19
        cs = remain ? static_cast<const char*>(
473
19
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
474
19
        if(! cs.begin())
475
0
            cs = sentinel();
476
19
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
477
19
        {
478
            // if the doc does not terminate
479
            // with a newline, treat it as the
480
            // end of the comment
481
19
            if(terminal && ! more_)
482
1
            {
483
1
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
484
1
                    {start, cs.remain(start)}, ec_)))
485
0
                    return fail(cs.end());
486
1
                return cs.end();
487
1
            }
488
18
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
489
18
                {start, cs.remain(start)}, ec_)))
490
0
                return fail(cs.end());
491
18
            if(terminal)
492
0
                return suspend(cs.end(), state::com2);
493
18
            return maybe_suspend(cs.end(), state::com2);
494
18
        }
495
0
        break;
496
0
    case '*':
497
0
        do
498
0
        {
499
0
            ++cs;
500
32
do_com3:
501
            // KRYSTIAN TODO: this is a mess, we have to fix this
502
32
            remain = cs.remain();
503
32
            cs = remain ? static_cast<const char*>(
504
32
                std::memchr(cs.begin(), '*', remain)) : sentinel();
505
32
            if(! cs.begin())
506
0
                cs = sentinel();
507
            // stopped inside a c comment
508
32
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
509
32
            {
510
32
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
32
                    {start, cs.remain(start)}, ec_)))
512
0
                    return fail(cs.end());
513
32
                return maybe_suspend(cs.end(), state::com3);
514
32
            }
515
            // found a asterisk, check if the next char is a slash
516
0
            ++cs;
517
4
do_com4:
518
4
            if(BOOST_JSON_UNLIKELY(! cs))
519
4
            {
520
4
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
521
4
                    {start, cs.used(start)}, ec_)))
522
0
                    return fail(cs.begin());
523
4
                return maybe_suspend(cs.begin(), state::com4);
524
4
            }
525
4
        }
526
0
        while(*cs != '/');
527
0
    }
528
0
    ++cs;
529
0
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
530
0
        {start, cs.used(start)}, ec_)))
531
0
        return fail(cs.begin());
532
0
    return cs.begin();
533
0
}
534
535
template<class Handler>
536
template<bool StackEmpty_>
537
const char*
538
basic_parser<Handler>::
539
parse_document(const char* p,
540
    std::integral_constant<bool, StackEmpty_> stack_empty)
541
25.3k
{
542
25.3k
    detail::const_stream_wrapper cs(p, end_);
543
25.3k
    if(! stack_empty && ! st_.empty())
544
7.25k
    {
545
7.25k
        state st;
546
7.25k
        st_.peek(st);
547
7.25k
        switch(st)
548
7.25k
        {
549
5.14k
        default: goto do_doc2;
550
5.14k
        case state::doc1:
551
49
                 st_.pop(st);
552
49
                 goto do_doc1;
553
2.04k
        case state::doc3:
554
2.04k
                 st_.pop(st);
555
2.04k
                 goto do_doc3;
556
13
        case state::com1: case state::com2:
557
15
        case state::com3: case state::com4:
558
15
                 goto do_doc4;
559
7.25k
        }
560
7.25k
    }
561
18.1k
do_doc1:
562
18.1k
    cs = detail::count_whitespace(cs.begin(), cs.end());
563
18.1k
    if(BOOST_JSON_UNLIKELY(! cs))
564
122
        return maybe_suspend(cs.begin(), state::doc1);
565
23.2k
do_doc2:
566
23.2k
    switch(+opt_.allow_comments |
567
23.2k
        (opt_.allow_trailing_commas << 1) |
568
23.2k
        (opt_.allow_invalid_utf8 << 2))
569
23.2k
    {
570
    // no extensions
571
9.20k
    default:
572
9.20k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type());
573
9.20k
        break;
574
    // comments
575
1.64k
    case 1:
576
1.64k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type());
577
1.64k
        break;
578
    // trailing
579
1.41k
    case 2:
580
1.41k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type());
581
1.41k
        break;
582
    // comments & trailing
583
2.27k
    case 3:
584
2.27k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type());
585
2.27k
        break;
586
    // skip validation
587
1.18k
    case 4:
588
1.18k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type());
589
1.18k
        break;
590
    // comments & skip validation
591
1.91k
    case 5:
592
1.91k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type());
593
1.91k
        break;
594
    // trailing & skip validation
595
2.82k
    case 6:
596
2.82k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type());
597
2.82k
        break;
598
    // comments & trailing & skip validation
599
2.73k
    case 7:
600
2.73k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type());
601
2.73k
        break;
602
23.2k
    }
603
23.0k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
604
        // the appropriate state has already been pushed into stack
605
14.4k
        return sentinel();
606
11.2k
do_doc3:
607
11.2k
    cs = detail::count_whitespace(cs.begin(), cs.end());
608
11.2k
    if(BOOST_JSON_UNLIKELY(! cs))
609
9.01k
    {
610
9.01k
        if(more_)
611
2.04k
            return suspend(cs.begin(), state::doc3);
612
9.01k
    }
613
2.27k
    else if(opt_.allow_comments && *cs == '/')
614
636
    {
615
651
do_doc4:
616
651
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
617
651
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
618
31
            return sentinel();
619
620
        goto do_doc3;
620
651
    }
621
8.61k
    return cs.begin();
622
11.2k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_document<true>(char const*, std::__1::integral_constant<bool, true>)
Line
Count
Source
541
18.1k
{
542
18.1k
    detail::const_stream_wrapper cs(p, end_);
543
18.1k
    if(! stack_empty && ! st_.empty())
544
0
    {
545
0
        state st;
546
0
        st_.peek(st);
547
0
        switch(st)
548
0
        {
549
0
        default: goto do_doc2;
550
0
        case state::doc1:
551
0
                 st_.pop(st);
552
0
                 goto do_doc1;
553
0
        case state::doc3:
554
0
                 st_.pop(st);
555
0
                 goto do_doc3;
556
0
        case state::com1: case state::com2:
557
0
        case state::com3: case state::com4:
558
0
                 goto do_doc4;
559
0
        }
560
0
    }
561
18.1k
do_doc1:
562
18.1k
    cs = detail::count_whitespace(cs.begin(), cs.end());
563
18.1k
    if(BOOST_JSON_UNLIKELY(! cs))
564
73
        return maybe_suspend(cs.begin(), state::doc1);
565
18.0k
do_doc2:
566
18.0k
    switch(+opt_.allow_comments |
567
18.0k
        (opt_.allow_trailing_commas << 1) |
568
18.0k
        (opt_.allow_invalid_utf8 << 2))
569
18.0k
    {
570
    // no extensions
571
8.43k
    default:
572
8.43k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type());
573
8.43k
        break;
574
    // comments
575
1.06k
    case 1:
576
1.06k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type());
577
1.06k
        break;
578
    // trailing
579
949
    case 2:
580
949
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type());
581
949
        break;
582
    // comments & trailing
583
1.55k
    case 3:
584
1.55k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type());
585
1.55k
        break;
586
    // skip validation
587
763
    case 4:
588
763
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type());
589
763
        break;
590
    // comments & skip validation
591
1.32k
    case 5:
592
1.32k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type());
593
1.32k
        break;
594
    // trailing & skip validation
595
2.03k
    case 6:
596
2.03k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type());
597
2.03k
        break;
598
    // comments & trailing & skip validation
599
1.92k
    case 7:
600
1.92k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type());
601
1.92k
        break;
602
18.0k
    }
603
17.9k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
604
        // the appropriate state has already been pushed into stack
605
11.9k
        return sentinel();
606
6.64k
do_doc3:
607
6.64k
    cs = detail::count_whitespace(cs.begin(), cs.end());
608
6.64k
    if(BOOST_JSON_UNLIKELY(! cs))
609
4.37k
    {
610
4.37k
        if(more_)
611
2.04k
            return suspend(cs.begin(), state::doc3);
612
4.37k
    }
613
2.27k
    else if(opt_.allow_comments && *cs == '/')
614
636
    {
615
636
do_doc4:
616
636
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
617
636
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
618
17
            return sentinel();
619
619
        goto do_doc3;
620
636
    }
621
3.97k
    return cs.begin();
622
6.64k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_document<false>(char const*, std::__1::integral_constant<bool, false>)
Line
Count
Source
541
7.25k
{
542
7.25k
    detail::const_stream_wrapper cs(p, end_);
543
7.25k
    if(! stack_empty && ! st_.empty())
544
7.25k
    {
545
7.25k
        state st;
546
7.25k
        st_.peek(st);
547
7.25k
        switch(st)
548
7.25k
        {
549
5.14k
        default: goto do_doc2;
550
5.14k
        case state::doc1:
551
49
                 st_.pop(st);
552
49
                 goto do_doc1;
553
2.04k
        case state::doc3:
554
2.04k
                 st_.pop(st);
555
2.04k
                 goto do_doc3;
556
13
        case state::com1: case state::com2:
557
15
        case state::com3: case state::com4:
558
15
                 goto do_doc4;
559
7.25k
        }
560
7.25k
    }
561
49
do_doc1:
562
49
    cs = detail::count_whitespace(cs.begin(), cs.end());
563
49
    if(BOOST_JSON_UNLIKELY(! cs))
564
49
        return maybe_suspend(cs.begin(), state::doc1);
565
5.14k
do_doc2:
566
5.14k
    switch(+opt_.allow_comments |
567
5.14k
        (opt_.allow_trailing_commas << 1) |
568
5.14k
        (opt_.allow_invalid_utf8 << 2))
569
5.14k
    {
570
    // no extensions
571
764
    default:
572
764
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type());
573
764
        break;
574
    // comments
575
580
    case 1:
576
580
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type());
577
580
        break;
578
    // trailing
579
468
    case 2:
580
468
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type());
581
468
        break;
582
    // comments & trailing
583
721
    case 3:
584
721
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type());
585
721
        break;
586
    // skip validation
587
421
    case 4:
588
421
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type());
589
421
        break;
590
    // comments & skip validation
591
598
    case 5:
592
598
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type());
593
598
        break;
594
    // trailing & skip validation
595
781
    case 6:
596
781
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type());
597
781
        break;
598
    // comments & trailing & skip validation
599
813
    case 7:
600
813
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type());
601
813
        break;
602
5.14k
    }
603
5.11k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
604
        // the appropriate state has already been pushed into stack
605
2.51k
        return sentinel();
606
4.64k
do_doc3:
607
4.64k
    cs = detail::count_whitespace(cs.begin(), cs.end());
608
4.64k
    if(BOOST_JSON_UNLIKELY(! cs))
609
4.64k
    {
610
4.64k
        if(more_)
611
0
            return suspend(cs.begin(), state::doc3);
612
4.64k
    }
613
0
    else if(opt_.allow_comments && *cs == '/')
614
0
    {
615
15
do_doc4:
616
15
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
617
15
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
618
14
            return sentinel();
619
1
        goto do_doc3;
620
15
    }
621
4.64k
    return cs.begin();
622
4.64k
}
623
624
template<class Handler>
625
template<
626
    bool StackEmpty_,
627
    bool AllowComments_/*,
628
    bool AllowTrailing_,
629
    bool AllowBadUTF8_*/>
630
const char*
631
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
10.8M
{
638
10.8M
    if(stack_empty || st_.empty())
639
10.8M
    {
640
10.8M
loop:
641
10.8M
        switch(*p)
642
10.8M
        {
643
228k
        case '0':
644
228k
            return mp11::mp_with_index<3>(
645
228k
                static_cast<unsigned char>(opt_.numbers),
646
228k
                parse_number_helper<true, '0'>{ this, p });
647
37.1k
        case '-':
648
37.1k
            return mp11::mp_with_index<3>(
649
37.1k
                static_cast<unsigned char>(opt_.numbers),
650
37.1k
                parse_number_helper<true, '-'>{ this, p });
651
6.07M
        case '1': case '2': case '3':
652
6.57M
        case '4': case '5': case '6':
653
10.3M
        case '7': case '8': case '9':
654
10.3M
            return mp11::mp_with_index<3>(
655
10.3M
                static_cast<unsigned char>(opt_.numbers),
656
10.3M
                parse_number_helper<true, '+'>{ this, p });
657
13.7k
        case 'n':
658
13.7k
            return parse_literal( p, mp11::mp_int<detail::null_literal>() );
659
22.5k
        case 't':
660
22.5k
            return parse_literal( p, mp11::mp_int<detail::true_literal>() );
661
21.7k
        case 'f':
662
21.7k
            return parse_literal( p, mp11::mp_int<detail::false_literal>() );
663
5
        case 'I':
664
5
            if( !opt_.allow_infinity_and_nan )
665
5
            {
666
5
                BOOST_STATIC_CONSTEXPR source_location loc
667
5
                    = BOOST_CURRENT_LOCATION;
668
5
                return fail(p, error::syntax, &loc);
669
5
            }
670
0
            return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
671
6
        case 'N':
672
6
            if( !opt_.allow_infinity_and_nan )
673
6
            {
674
6
                BOOST_STATIC_CONSTEXPR source_location loc
675
6
                    = BOOST_CURRENT_LOCATION;
676
6
                return fail(p, error::syntax, &loc);
677
6
            }
678
0
            return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
679
82.4k
        case '"':
680
82.4k
            return parse_unescaped(p, std::true_type(), std::false_type(), allow_bad_utf8);
681
20.2k
        case '[':
682
20.2k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
683
22.4k
        case '{':
684
22.4k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
685
1.50k
        case '/':
686
1.50k
            if(! allow_comments)
687
3
            {
688
3
                BOOST_STATIC_CONSTEXPR source_location loc
689
3
                    = BOOST_CURRENT_LOCATION;
690
3
                return fail(p, error::syntax, &loc);
691
3
            }
692
1.50k
            p = parse_comment(p, stack_empty, std::false_type());
693
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
694
            // can add an overload, change the existing one to take a pointer,
695
            // or just leave it as is
696
1.50k
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
697
67
                return maybe_suspend(p, state::val2);
698
            // intentional fallthrough
699
1.43k
        case ' ':
700
1.43k
        case '\t':
701
1.43k
        case '\n':
702
1.43k
        case '\r':
703
1.43k
            p = detail::count_whitespace(p, end_);
704
1.43k
            if(BOOST_JSON_UNLIKELY(p == end_))
705
41
                return maybe_suspend(p, state::val1);
706
1.39k
            goto loop;
707
1.39k
        default:
708
658
            {
709
658
                BOOST_STATIC_CONSTEXPR source_location loc
710
658
                    = BOOST_CURRENT_LOCATION;
711
658
                return fail(p, error::syntax, &loc);
712
1.43k
            }
713
10.8M
        }
714
10.8M
    }
715
7.07k
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8);
716
10.8M
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_value<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
637
6.08M
{
638
6.08M
    if(stack_empty || st_.empty())
639
6.08M
    {
640
6.08M
loop:
641
6.08M
        switch(*p)
642
6.08M
        {
643
187k
        case '0':
644
187k
            return mp11::mp_with_index<3>(
645
187k
                static_cast<unsigned char>(opt_.numbers),
646
187k
                parse_number_helper<true, '0'>{ this, p });
647
28.6k
        case '-':
648
28.6k
            return mp11::mp_with_index<3>(
649
28.6k
                static_cast<unsigned char>(opt_.numbers),
650
28.6k
                parse_number_helper<true, '-'>{ this, p });
651
2.83M
        case '1': case '2': case '3':
652
3.28M
        case '4': case '5': case '6':
653
5.72M
        case '7': case '8': case '9':
654
5.72M
            return mp11::mp_with_index<3>(
655
5.72M
                static_cast<unsigned char>(opt_.numbers),
656
5.72M
                parse_number_helper<true, '+'>{ this, p });
657
8.52k
        case 'n':
658
8.52k
            return parse_literal( p, mp11::mp_int<detail::null_literal>() );
659
15.7k
        case 't':
660
15.7k
            return parse_literal( p, mp11::mp_int<detail::true_literal>() );
661
19.5k
        case 'f':
662
19.5k
            return parse_literal( p, mp11::mp_int<detail::false_literal>() );
663
3
        case 'I':
664
3
            if( !opt_.allow_infinity_and_nan )
665
3
            {
666
3
                BOOST_STATIC_CONSTEXPR source_location loc
667
3
                    = BOOST_CURRENT_LOCATION;
668
3
                return fail(p, error::syntax, &loc);
669
3
            }
670
0
            return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
671
4
        case 'N':
672
4
            if( !opt_.allow_infinity_and_nan )
673
4
            {
674
4
                BOOST_STATIC_CONSTEXPR source_location loc
675
4
                    = BOOST_CURRENT_LOCATION;
676
4
                return fail(p, error::syntax, &loc);
677
4
            }
678
0
            return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
679
71.2k
        case '"':
680
71.2k
            return parse_unescaped(p, std::true_type(), std::false_type(), allow_bad_utf8);
681
12.0k
        case '[':
682
12.0k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
683
15.5k
        case '{':
684
15.5k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
685
3
        case '/':
686
3
            if(! allow_comments)
687
3
            {
688
3
                BOOST_STATIC_CONSTEXPR source_location loc
689
3
                    = BOOST_CURRENT_LOCATION;
690
3
                return fail(p, error::syntax, &loc);
691
3
            }
692
0
            p = parse_comment(p, stack_empty, std::false_type());
693
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
694
            // can add an overload, change the existing one to take a pointer,
695
            // or just leave it as is
696
0
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
697
0
                return maybe_suspend(p, state::val2);
698
            // intentional fallthrough
699
0
        case ' ':
700
0
        case '\t':
701
0
        case '\n':
702
0
        case '\r':
703
0
            p = detail::count_whitespace(p, end_);
704
0
            if(BOOST_JSON_UNLIKELY(p == end_))
705
0
                return maybe_suspend(p, state::val1);
706
0
            goto loop;
707
410
        default:
708
410
            {
709
410
                BOOST_STATIC_CONSTEXPR source_location loc
710
410
                    = BOOST_CURRENT_LOCATION;
711
410
                return fail(p, error::syntax, &loc);
712
0
            }
713
6.08M
        }
714
6.08M
    }
715
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8);
716
6.08M
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_value<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
637
4.74M
{
638
4.74M
    if(stack_empty || st_.empty())
639
4.74M
    {
640
4.74M
loop:
641
4.74M
        switch(*p)
642
4.74M
        {
643
41.2k
        case '0':
644
41.2k
            return mp11::mp_with_index<3>(
645
41.2k
                static_cast<unsigned char>(opt_.numbers),
646
41.2k
                parse_number_helper<true, '0'>{ this, p });
647
8.50k
        case '-':
648
8.50k
            return mp11::mp_with_index<3>(
649
8.50k
                static_cast<unsigned char>(opt_.numbers),
650
8.50k
                parse_number_helper<true, '-'>{ this, p });
651
3.23M
        case '1': case '2': case '3':
652
3.28M
        case '4': case '5': case '6':
653
4.65M
        case '7': case '8': case '9':
654
4.65M
            return mp11::mp_with_index<3>(
655
4.65M
                static_cast<unsigned char>(opt_.numbers),
656
4.65M
                parse_number_helper<true, '+'>{ this, p });
657
5.26k
        case 'n':
658
5.26k
            return parse_literal( p, mp11::mp_int<detail::null_literal>() );
659
6.85k
        case 't':
660
6.85k
            return parse_literal( p, mp11::mp_int<detail::true_literal>() );
661
2.18k
        case 'f':
662
2.18k
            return parse_literal( p, mp11::mp_int<detail::false_literal>() );
663
2
        case 'I':
664
2
            if( !opt_.allow_infinity_and_nan )
665
2
            {
666
2
                BOOST_STATIC_CONSTEXPR source_location loc
667
2
                    = BOOST_CURRENT_LOCATION;
668
2
                return fail(p, error::syntax, &loc);
669
2
            }
670
0
            return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
671
2
        case 'N':
672
2
            if( !opt_.allow_infinity_and_nan )
673
2
            {
674
2
                BOOST_STATIC_CONSTEXPR source_location loc
675
2
                    = BOOST_CURRENT_LOCATION;
676
2
                return fail(p, error::syntax, &loc);
677
2
            }
678
0
            return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
679
11.1k
        case '"':
680
11.1k
            return parse_unescaped(p, std::true_type(), std::false_type(), allow_bad_utf8);
681
8.17k
        case '[':
682
8.17k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
683
6.91k
        case '{':
684
6.91k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
685
1.50k
        case '/':
686
1.50k
            if(! allow_comments)
687
0
            {
688
0
                BOOST_STATIC_CONSTEXPR source_location loc
689
0
                    = BOOST_CURRENT_LOCATION;
690
0
                return fail(p, error::syntax, &loc);
691
0
            }
692
1.50k
            p = parse_comment(p, stack_empty, std::false_type());
693
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
694
            // can add an overload, change the existing one to take a pointer,
695
            // or just leave it as is
696
1.50k
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
697
67
                return maybe_suspend(p, state::val2);
698
            // intentional fallthrough
699
1.43k
        case ' ':
700
1.43k
        case '\t':
701
1.43k
        case '\n':
702
1.43k
        case '\r':
703
1.43k
            p = detail::count_whitespace(p, end_);
704
1.43k
            if(BOOST_JSON_UNLIKELY(p == end_))
705
41
                return maybe_suspend(p, state::val1);
706
1.39k
            goto loop;
707
1.39k
        default:
708
248
            {
709
248
                BOOST_STATIC_CONSTEXPR source_location loc
710
248
                    = BOOST_CURRENT_LOCATION;
711
248
                return fail(p, error::syntax, &loc);
712
1.43k
            }
713
4.74M
        }
714
4.74M
    }
715
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8);
716
4.74M
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_value<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
637
3.30k
{
638
3.30k
    if(stack_empty || st_.empty())
639
0
    {
640
0
loop:
641
0
        switch(*p)
642
0
        {
643
0
        case '0':
644
0
            return mp11::mp_with_index<3>(
645
0
                static_cast<unsigned char>(opt_.numbers),
646
0
                parse_number_helper<true, '0'>{ this, p });
647
0
        case '-':
648
0
            return mp11::mp_with_index<3>(
649
0
                static_cast<unsigned char>(opt_.numbers),
650
0
                parse_number_helper<true, '-'>{ this, p });
651
0
        case '1': case '2': case '3':
652
0
        case '4': case '5': case '6':
653
0
        case '7': case '8': case '9':
654
0
            return mp11::mp_with_index<3>(
655
0
                static_cast<unsigned char>(opt_.numbers),
656
0
                parse_number_helper<true, '+'>{ this, p });
657
0
        case 'n':
658
0
            return parse_literal( p, mp11::mp_int<detail::null_literal>() );
659
0
        case 't':
660
0
            return parse_literal( p, mp11::mp_int<detail::true_literal>() );
661
0
        case 'f':
662
0
            return parse_literal( p, mp11::mp_int<detail::false_literal>() );
663
0
        case 'I':
664
0
            if( !opt_.allow_infinity_and_nan )
665
0
            {
666
0
                BOOST_STATIC_CONSTEXPR source_location loc
667
0
                    = BOOST_CURRENT_LOCATION;
668
0
                return fail(p, error::syntax, &loc);
669
0
            }
670
0
            return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
671
0
        case 'N':
672
0
            if( !opt_.allow_infinity_and_nan )
673
0
            {
674
0
                BOOST_STATIC_CONSTEXPR source_location loc
675
0
                    = BOOST_CURRENT_LOCATION;
676
0
                return fail(p, error::syntax, &loc);
677
0
            }
678
0
            return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
679
0
        case '"':
680
0
            return parse_unescaped(p, std::true_type(), std::false_type(), allow_bad_utf8);
681
0
        case '[':
682
0
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
683
0
        case '{':
684
0
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
685
0
        case '/':
686
0
            if(! allow_comments)
687
0
            {
688
0
                BOOST_STATIC_CONSTEXPR source_location loc
689
0
                    = BOOST_CURRENT_LOCATION;
690
0
                return fail(p, error::syntax, &loc);
691
0
            }
692
0
            p = parse_comment(p, stack_empty, std::false_type());
693
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
694
            // can add an overload, change the existing one to take a pointer,
695
            // or just leave it as is
696
0
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
697
0
                return maybe_suspend(p, state::val2);
698
            // intentional fallthrough
699
0
        case ' ':
700
0
        case '\t':
701
0
        case '\n':
702
0
        case '\r':
703
0
            p = detail::count_whitespace(p, end_);
704
0
            if(BOOST_JSON_UNLIKELY(p == end_))
705
0
                return maybe_suspend(p, state::val1);
706
0
            goto loop;
707
0
        default:
708
0
            {
709
0
                BOOST_STATIC_CONSTEXPR source_location loc
710
0
                    = BOOST_CURRENT_LOCATION;
711
0
                return fail(p, error::syntax, &loc);
712
0
            }
713
0
        }
714
0
    }
715
3.30k
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8);
716
3.30k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_value<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
637
3.77k
{
638
3.77k
    if(stack_empty || st_.empty())
639
0
    {
640
0
loop:
641
0
        switch(*p)
642
0
        {
643
0
        case '0':
644
0
            return mp11::mp_with_index<3>(
645
0
                static_cast<unsigned char>(opt_.numbers),
646
0
                parse_number_helper<true, '0'>{ this, p });
647
0
        case '-':
648
0
            return mp11::mp_with_index<3>(
649
0
                static_cast<unsigned char>(opt_.numbers),
650
0
                parse_number_helper<true, '-'>{ this, p });
651
0
        case '1': case '2': case '3':
652
0
        case '4': case '5': case '6':
653
0
        case '7': case '8': case '9':
654
0
            return mp11::mp_with_index<3>(
655
0
                static_cast<unsigned char>(opt_.numbers),
656
0
                parse_number_helper<true, '+'>{ this, p });
657
0
        case 'n':
658
0
            return parse_literal( p, mp11::mp_int<detail::null_literal>() );
659
0
        case 't':
660
0
            return parse_literal( p, mp11::mp_int<detail::true_literal>() );
661
0
        case 'f':
662
0
            return parse_literal( p, mp11::mp_int<detail::false_literal>() );
663
0
        case 'I':
664
0
            if( !opt_.allow_infinity_and_nan )
665
0
            {
666
0
                BOOST_STATIC_CONSTEXPR source_location loc
667
0
                    = BOOST_CURRENT_LOCATION;
668
0
                return fail(p, error::syntax, &loc);
669
0
            }
670
0
            return parse_literal( p, mp11::mp_int<detail::infinity_literal>() );
671
0
        case 'N':
672
0
            if( !opt_.allow_infinity_and_nan )
673
0
            {
674
0
                BOOST_STATIC_CONSTEXPR source_location loc
675
0
                    = BOOST_CURRENT_LOCATION;
676
0
                return fail(p, error::syntax, &loc);
677
0
            }
678
0
            return parse_literal( p, mp11::mp_int<detail::nan_literal>() );
679
0
        case '"':
680
0
            return parse_unescaped(p, std::true_type(), std::false_type(), allow_bad_utf8);
681
0
        case '[':
682
0
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
683
0
        case '{':
684
0
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
685
0
        case '/':
686
0
            if(! allow_comments)
687
0
            {
688
0
                BOOST_STATIC_CONSTEXPR source_location loc
689
0
                    = BOOST_CURRENT_LOCATION;
690
0
                return fail(p, error::syntax, &loc);
691
0
            }
692
0
            p = parse_comment(p, stack_empty, std::false_type());
693
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
694
            // can add an overload, change the existing one to take a pointer,
695
            // or just leave it as is
696
0
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
697
0
                return maybe_suspend(p, state::val2);
698
            // intentional fallthrough
699
0
        case ' ':
700
0
        case '\t':
701
0
        case '\n':
702
0
        case '\r':
703
0
            p = detail::count_whitespace(p, end_);
704
0
            if(BOOST_JSON_UNLIKELY(p == end_))
705
0
                return maybe_suspend(p, state::val1);
706
0
            goto loop;
707
0
        default:
708
0
            {
709
0
                BOOST_STATIC_CONSTEXPR source_location loc
710
0
                    = BOOST_CURRENT_LOCATION;
711
0
                return fail(p, error::syntax, &loc);
712
0
            }
713
0
        }
714
0
    }
715
3.77k
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8);
716
3.77k
}
717
718
template<class Handler>
719
template<
720
    bool AllowComments_/*,
721
    bool AllowTrailing_,
722
    bool AllowBadUTF8_*/>
723
const char*
724
basic_parser<Handler>::
725
resume_value(const char* p,
726
    std::integral_constant<bool, AllowComments_> allow_comments,
727
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
728
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8)
729
7.07k
{
730
7.07k
    state st;
731
7.07k
    st_.peek(st);
732
7.07k
    switch(st)
733
7.07k
    {
734
0
    default: BOOST_JSON_UNREACHABLE();
735
53
    case state::lit1:
736
53
        return parse_literal(p,  mp11::mp_int<detail::resume_literal>() );
737
738
155
    case state::str1:
739
155
        return parse_unescaped(p, std::false_type(), std::false_type(), allow_bad_utf8);
740
741
350
    case state::str2: case state::str3:
742
383
    case state::str4: case state::str5:
743
414
    case state::str6: case state::str7:
744
476
    case state::str8:
745
489
    case state::sur1: case state::sur2:
746
503
    case state::sur3: case state::sur4:
747
521
    case state::sur5: case state::sur6:
748
521
        return parse_escaped(p, 0, std::false_type(), std::false_type(), allow_bad_utf8);
749
750
102
    case state::arr1: case state::arr2:
751
1.63k
    case state::arr3: case state::arr4:
752
1.77k
    case state::arr5: case state::arr6:
753
1.77k
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
754
755
88
    case state::obj1: case state::obj2:
756
420
    case state::obj3: case state::obj4:
757
484
    case state::obj5: case state::obj6:
758
1.20k
    case state::obj7: case state::obj8:
759
1.27k
    case state::obj9: case state::obj10:
760
1.28k
    case state::obj11:
761
1.28k
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
762
763
837
    case state::num1: case state::num2:
764
926
    case state::num3: case state::num4:
765
1.06k
    case state::num5: case state::num6:
766
2.12k
    case state::num7: case state::num8:
767
2.24k
    case state::exp1: case state::exp2:
768
3.18k
    case state::exp3:
769
3.18k
        return mp11::mp_with_index<3>(
770
3.18k
            static_cast<unsigned char>(opt_.numbers),
771
3.18k
            parse_number_helper<false, 0>{ this, p });
772
773
    // KRYSTIAN NOTE: these are special cases
774
41
    case state::val1:
775
41
    {
776
41
        st_.pop(st);
777
41
        BOOST_ASSERT(st_.empty());
778
41
        p = detail::count_whitespace(p, end_);
779
41
        if(BOOST_JSON_UNLIKELY(p == end_))
780
41
            return maybe_suspend(p, state::val1);
781
0
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
782
41
    }
783
784
59
    case state::val2:
785
59
    {
786
59
        st_.pop(st);
787
59
        p = parse_comment(p, std::false_type(), std::false_type());
788
59
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
789
59
            return maybe_suspend(p, state::val2);
790
0
        if(BOOST_JSON_UNLIKELY( p == end_ ))
791
0
            return maybe_suspend(p, state::val3);
792
0
        BOOST_ASSERT(st_.empty());
793
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
794
0
    }
795
796
0
    case state::val3:
797
0
    {
798
0
        st_.pop(st);
799
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
800
0
    }
801
7.07k
    }
802
7.07k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::resume_value<false>(char const*, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
729
3.30k
{
730
3.30k
    state st;
731
3.30k
    st_.peek(st);
732
3.30k
    switch(st)
733
3.30k
    {
734
0
    default: BOOST_JSON_UNREACHABLE();
735
26
    case state::lit1:
736
26
        return parse_literal(p,  mp11::mp_int<detail::resume_literal>() );
737
738
68
    case state::str1:
739
68
        return parse_unescaped(p, std::false_type(), std::false_type(), allow_bad_utf8);
740
741
171
    case state::str2: case state::str3:
742
185
    case state::str4: case state::str5:
743
203
    case state::str6: case state::str7:
744
233
    case state::str8:
745
239
    case state::sur1: case state::sur2:
746
242
    case state::sur3: case state::sur4:
747
251
    case state::sur5: case state::sur6:
748
251
        return parse_escaped(p, 0, std::false_type(), std::false_type(), allow_bad_utf8);
749
750
39
    case state::arr1: case state::arr2:
751
746
    case state::arr3: case state::arr4:
752
818
    case state::arr5: case state::arr6:
753
818
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
754
755
38
    case state::obj1: case state::obj2:
756
207
    case state::obj3: case state::obj4:
757
235
    case state::obj5: case state::obj6:
758
550
    case state::obj7: case state::obj8:
759
577
    case state::obj9: case state::obj10:
760
577
    case state::obj11:
761
577
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
762
763
433
    case state::num1: case state::num2:
764
481
    case state::num3: case state::num4:
765
557
    case state::num5: case state::num6:
766
1.02k
    case state::num7: case state::num8:
767
1.08k
    case state::exp1: case state::exp2:
768
1.56k
    case state::exp3:
769
1.56k
        return mp11::mp_with_index<3>(
770
1.56k
            static_cast<unsigned char>(opt_.numbers),
771
1.56k
            parse_number_helper<false, 0>{ this, p });
772
773
    // KRYSTIAN NOTE: these are special cases
774
0
    case state::val1:
775
0
    {
776
0
        st_.pop(st);
777
0
        BOOST_ASSERT(st_.empty());
778
0
        p = detail::count_whitespace(p, end_);
779
0
        if(BOOST_JSON_UNLIKELY(p == end_))
780
0
            return maybe_suspend(p, state::val1);
781
0
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
782
0
    }
783
784
0
    case state::val2:
785
0
    {
786
0
        st_.pop(st);
787
0
        p = parse_comment(p, std::false_type(), std::false_type());
788
0
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
789
0
            return maybe_suspend(p, state::val2);
790
0
        if(BOOST_JSON_UNLIKELY( p == end_ ))
791
0
            return maybe_suspend(p, state::val3);
792
0
        BOOST_ASSERT(st_.empty());
793
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
794
0
    }
795
796
0
    case state::val3:
797
0
    {
798
0
        st_.pop(st);
799
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
800
0
    }
801
3.30k
    }
802
3.30k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::resume_value<true>(char const*, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
729
3.77k
{
730
3.77k
    state st;
731
3.77k
    st_.peek(st);
732
3.77k
    switch(st)
733
3.77k
    {
734
0
    default: BOOST_JSON_UNREACHABLE();
735
27
    case state::lit1:
736
27
        return parse_literal(p,  mp11::mp_int<detail::resume_literal>() );
737
738
87
    case state::str1:
739
87
        return parse_unescaped(p, std::false_type(), std::false_type(), allow_bad_utf8);
740
741
179
    case state::str2: case state::str3:
742
198
    case state::str4: case state::str5:
743
211
    case state::str6: case state::str7:
744
243
    case state::str8:
745
250
    case state::sur1: case state::sur2:
746
261
    case state::sur3: case state::sur4:
747
270
    case state::sur5: case state::sur6:
748
270
        return parse_escaped(p, 0, std::false_type(), std::false_type(), allow_bad_utf8);
749
750
63
    case state::arr1: case state::arr2:
751
884
    case state::arr3: case state::arr4:
752
959
    case state::arr5: case state::arr6:
753
959
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
754
755
50
    case state::obj1: case state::obj2:
756
213
    case state::obj3: case state::obj4:
757
249
    case state::obj5: case state::obj6:
758
653
    case state::obj7: case state::obj8:
759
699
    case state::obj9: case state::obj10:
760
704
    case state::obj11:
761
704
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8);
762
763
404
    case state::num1: case state::num2:
764
445
    case state::num3: case state::num4:
765
510
    case state::num5: case state::num6:
766
1.09k
    case state::num7: case state::num8:
767
1.15k
    case state::exp1: case state::exp2:
768
1.62k
    case state::exp3:
769
1.62k
        return mp11::mp_with_index<3>(
770
1.62k
            static_cast<unsigned char>(opt_.numbers),
771
1.62k
            parse_number_helper<false, 0>{ this, p });
772
773
    // KRYSTIAN NOTE: these are special cases
774
41
    case state::val1:
775
41
    {
776
41
        st_.pop(st);
777
41
        BOOST_ASSERT(st_.empty());
778
41
        p = detail::count_whitespace(p, end_);
779
41
        if(BOOST_JSON_UNLIKELY(p == end_))
780
41
            return maybe_suspend(p, state::val1);
781
0
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8);
782
41
    }
783
784
59
    case state::val2:
785
59
    {
786
59
        st_.pop(st);
787
59
        p = parse_comment(p, std::false_type(), std::false_type());
788
59
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
789
59
            return maybe_suspend(p, state::val2);
790
0
        if(BOOST_JSON_UNLIKELY( p == end_ ))
791
0
            return maybe_suspend(p, state::val3);
792
0
        BOOST_ASSERT(st_.empty());
793
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
794
0
    }
795
796
0
    case state::val3:
797
0
    {
798
0
        st_.pop(st);
799
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8);
800
0
    }
801
3.77k
    }
802
3.77k
}
803
804
template<class Handler>
805
template<int Literal>
806
const char*
807
basic_parser<Handler>::
808
parse_literal(const char* p,
809
    std::integral_constant<int, Literal> literal)
810
58.1k
{
811
58.1k
    constexpr char const* literals[] = {
812
58.1k
        "null",
813
58.1k
        "true",
814
58.1k
        "false",
815
58.1k
        "Infinity",
816
58.1k
        "-Infinity",
817
58.1k
        "NaN",
818
58.1k
    };
819
820
58.1k
    constexpr std::size_t literal_sizes[] = {
821
58.1k
        4,
822
58.1k
        4,
823
58.1k
        5,
824
58.1k
        8,
825
58.1k
        9,
826
58.1k
        3,
827
58.1k
    };
828
829
58.1k
    std::size_t cur_lit;
830
58.1k
    std::size_t offset;
831
832
58.1k
    detail::const_stream_wrapper cs(p, end_);
833
58.1k
    BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
834
58.1k
    {
835
58.1k
        BOOST_ASSERT( literal >= 0 );
836
58.1k
        if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
837
57.8k
        {
838
57.8k
            int const cmp = std::memcmp(
839
57.8k
                cs.begin(), literals[literal], literal_sizes[literal] );
840
57.8k
            if( cmp != 0 )
841
124
            {
842
124
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
843
124
                return fail(cs.begin(), error::syntax, &loc);
844
124
            }
845
846
57.6k
            BOOST_IF_CONSTEXPR( literal == detail::null_literal )
847
13.6k
            {
848
13.6k
                if(BOOST_JSON_UNLIKELY(
849
13.6k
                    ! h_.on_null(ec_)))
850
0
                    return fail(cs.begin());
851
13.6k
            }
852
44.0k
            else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
853
22.4k
            {
854
22.4k
                if(BOOST_JSON_UNLIKELY(
855
22.4k
                    ! h_.on_bool(true, ec_)))
856
0
                    return fail(cs.begin());
857
22.4k
            }
858
21.6k
            else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
859
21.6k
            {
860
21.6k
                if(BOOST_JSON_UNLIKELY(
861
21.6k
                    ! h_.on_bool(false, ec_)))
862
0
                    return fail(cs.begin());
863
21.6k
            }
864
0
            else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
865
0
            {
866
0
                if(BOOST_JSON_UNLIKELY(
867
0
                    ! h_.on_double(
868
0
                        std::numeric_limits<double>::infinity(),
869
0
                        string_view(
870
0
                            literals[detail::infinity_literal],
871
0
                            literal_sizes[detail::infinity_literal]),
872
0
                        ec_)))
873
0
                    return fail(cs.begin());
874
0
            }
875
0
            else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
876
0
            {
877
0
                if(BOOST_JSON_UNLIKELY(
878
0
                    ! h_.on_double(
879
0
                        -std::numeric_limits<double>::infinity(),
880
0
                        string_view(
881
0
                            literals[detail::neg_infinity_literal],
882
0
                            literal_sizes[detail::neg_infinity_literal]),
883
0
                        ec_)))
884
0
                    return fail(cs.begin());
885
0
            }
886
0
            else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
887
0
            {
888
0
                if(BOOST_JSON_UNLIKELY(
889
0
                    ! h_.on_double(
890
0
                        std::numeric_limits<double>::quiet_NaN(),
891
0
                        string_view(
892
0
                            literals[detail::nan_literal],
893
0
                            literal_sizes[detail::nan_literal]),
894
0
                        ec_)))
895
0
                    return fail(cs.begin());
896
0
            }
897
0
            else
898
0
            {
899
0
                BOOST_JSON_UNREACHABLE();
900
0
            }
901
902
57.6k
            cs += literal_sizes[literal];
903
57.6k
            return cs.begin();
904
57.6k
        }
905
906
329
        offset = 0;
907
329
        cur_lit = literal;
908
329
    }
909
53
    else
910
53
    {
911
53
        state st;
912
53
        st_.pop(st);
913
53
        BOOST_ASSERT( st == state::lit1 );
914
915
53
        cur_lit = cur_lit_;
916
53
        offset = lit_offset_;
917
53
    }
918
919
382
    std::size_t const size = (std::min)(
920
382
        literal_sizes[cur_lit] - offset, cs.remain() );
921
382
    int cmp = 0;
922
382
    if(BOOST_JSON_LIKELY( cs.begin() ))
923
329
        cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
924
382
    if( cmp != 0 )
925
245
    {
926
245
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
927
245
        return fail(cs.begin(), error::syntax, &loc);
928
245
    }
929
930
137
    if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
931
137
    {
932
137
        BOOST_ASSERT( cur_lit < 256 );
933
137
        cur_lit_ = static_cast<unsigned char>( cur_lit );
934
137
        BOOST_ASSERT( offset + size < 256 );
935
137
        lit_offset_ = static_cast<unsigned char>( offset + size );
936
137
        return maybe_suspend(cs.begin() + size, state::lit1);
937
137
    }
938
939
0
    switch( cur_lit )
940
0
    {
941
0
    case detail::null_literal:
942
0
        if(BOOST_JSON_UNLIKELY(
943
0
            ! h_.on_null(ec_)))
944
0
            return fail(cs.begin());
945
0
        break;
946
0
    case detail::true_literal:
947
0
        if(BOOST_JSON_UNLIKELY(
948
0
            ! h_.on_bool(true, ec_)))
949
0
            return fail(cs.begin());
950
0
        break;
951
0
    case detail::false_literal:
952
0
        if(BOOST_JSON_UNLIKELY(
953
0
            ! h_.on_bool(false, ec_)))
954
0
            return fail(cs.begin());
955
0
        break;
956
0
    case detail::infinity_literal:
957
0
        if(BOOST_JSON_UNLIKELY(
958
0
            ! h_.on_double(
959
0
                std::numeric_limits<double>::infinity(),
960
0
                string_view(
961
0
                    literals[detail::infinity_literal],
962
0
                    literal_sizes[detail::infinity_literal]),
963
0
                ec_)))
964
0
            return fail(cs.begin());
965
0
        break;
966
0
    case detail::neg_infinity_literal:
967
0
        if(BOOST_JSON_UNLIKELY(
968
0
            ! h_.on_double(
969
0
                -std::numeric_limits<double>::infinity(),
970
0
                string_view(
971
0
                    literals[detail::neg_infinity_literal],
972
0
                    literal_sizes[detail::neg_infinity_literal]),
973
0
                ec_)))
974
0
            return fail(cs.begin());
975
0
        break;
976
0
    case detail::nan_literal:
977
0
        if(BOOST_JSON_UNLIKELY(
978
0
            ! h_.on_double(
979
0
                std::numeric_limits<double>::quiet_NaN(),
980
0
                string_view(
981
0
                    literals[detail::nan_literal],
982
0
                    literal_sizes[detail::nan_literal]),
983
0
                ec_)))
984
0
            return fail(cs.begin());
985
0
        break;
986
0
    default: BOOST_JSON_UNREACHABLE();
987
0
    }
988
989
0
    cs += size;
990
0
    return cs.begin();
991
0
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<4>(char const*, std::__1::integral_constant<int, 4>)
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<-1>(char const*, std::__1::integral_constant<int, -1>)
Line
Count
Source
810
53
{
811
53
    constexpr char const* literals[] = {
812
53
        "null",
813
53
        "true",
814
53
        "false",
815
53
        "Infinity",
816
53
        "-Infinity",
817
53
        "NaN",
818
53
    };
819
820
53
    constexpr std::size_t literal_sizes[] = {
821
53
        4,
822
53
        4,
823
53
        5,
824
53
        8,
825
53
        9,
826
53
        3,
827
53
    };
828
829
53
    std::size_t cur_lit;
830
53
    std::size_t offset;
831
832
53
    detail::const_stream_wrapper cs(p, end_);
833
53
    BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
834
0
    {
835
0
        BOOST_ASSERT( literal >= 0 );
836
0
        if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
837
0
        {
838
0
            int const cmp = std::memcmp(
839
0
                cs.begin(), literals[literal], literal_sizes[literal] );
840
0
            if( cmp != 0 )
841
0
            {
842
0
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
843
0
                return fail(cs.begin(), error::syntax, &loc);
844
0
            }
845
846
0
            BOOST_IF_CONSTEXPR( literal == detail::null_literal )
847
0
            {
848
0
                if(BOOST_JSON_UNLIKELY(
849
0
                    ! h_.on_null(ec_)))
850
0
                    return fail(cs.begin());
851
0
            }
852
0
            else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
853
0
            {
854
0
                if(BOOST_JSON_UNLIKELY(
855
0
                    ! h_.on_bool(true, ec_)))
856
0
                    return fail(cs.begin());
857
0
            }
858
0
            else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
859
0
            {
860
0
                if(BOOST_JSON_UNLIKELY(
861
0
                    ! h_.on_bool(false, ec_)))
862
0
                    return fail(cs.begin());
863
0
            }
864
0
            else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
865
0
            {
866
0
                if(BOOST_JSON_UNLIKELY(
867
0
                    ! h_.on_double(
868
0
                        std::numeric_limits<double>::infinity(),
869
0
                        string_view(
870
0
                            literals[detail::infinity_literal],
871
0
                            literal_sizes[detail::infinity_literal]),
872
0
                        ec_)))
873
0
                    return fail(cs.begin());
874
0
            }
875
0
            else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
876
0
            {
877
0
                if(BOOST_JSON_UNLIKELY(
878
0
                    ! h_.on_double(
879
0
                        -std::numeric_limits<double>::infinity(),
880
0
                        string_view(
881
0
                            literals[detail::neg_infinity_literal],
882
0
                            literal_sizes[detail::neg_infinity_literal]),
883
0
                        ec_)))
884
0
                    return fail(cs.begin());
885
0
            }
886
0
            else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
887
0
            {
888
0
                if(BOOST_JSON_UNLIKELY(
889
0
                    ! h_.on_double(
890
0
                        std::numeric_limits<double>::quiet_NaN(),
891
0
                        string_view(
892
0
                            literals[detail::nan_literal],
893
0
                            literal_sizes[detail::nan_literal]),
894
0
                        ec_)))
895
0
                    return fail(cs.begin());
896
0
            }
897
0
            else
898
0
            {
899
0
                BOOST_JSON_UNREACHABLE();
900
0
            }
901
902
0
            cs += literal_sizes[literal];
903
0
            return cs.begin();
904
0
        }
905
906
0
        offset = 0;
907
0
        cur_lit = literal;
908
0
    }
909
53
    else
910
53
    {
911
53
        state st;
912
53
        st_.pop(st);
913
53
        BOOST_ASSERT( st == state::lit1 );
914
915
53
        cur_lit = cur_lit_;
916
53
        offset = lit_offset_;
917
53
    }
918
919
53
    std::size_t const size = (std::min)(
920
53
        literal_sizes[cur_lit] - offset, cs.remain() );
921
53
    int cmp = 0;
922
53
    if(BOOST_JSON_LIKELY( cs.begin() ))
923
0
        cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
924
53
    if( cmp != 0 )
925
0
    {
926
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
927
0
        return fail(cs.begin(), error::syntax, &loc);
928
0
    }
929
930
53
    if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
931
53
    {
932
53
        BOOST_ASSERT( cur_lit < 256 );
933
53
        cur_lit_ = static_cast<unsigned char>( cur_lit );
934
53
        BOOST_ASSERT( offset + size < 256 );
935
53
        lit_offset_ = static_cast<unsigned char>( offset + size );
936
53
        return maybe_suspend(cs.begin() + size, state::lit1);
937
53
    }
938
939
0
    switch( cur_lit )
940
0
    {
941
0
    case detail::null_literal:
942
0
        if(BOOST_JSON_UNLIKELY(
943
0
            ! h_.on_null(ec_)))
944
0
            return fail(cs.begin());
945
0
        break;
946
0
    case detail::true_literal:
947
0
        if(BOOST_JSON_UNLIKELY(
948
0
            ! h_.on_bool(true, ec_)))
949
0
            return fail(cs.begin());
950
0
        break;
951
0
    case detail::false_literal:
952
0
        if(BOOST_JSON_UNLIKELY(
953
0
            ! h_.on_bool(false, ec_)))
954
0
            return fail(cs.begin());
955
0
        break;
956
0
    case detail::infinity_literal:
957
0
        if(BOOST_JSON_UNLIKELY(
958
0
            ! h_.on_double(
959
0
                std::numeric_limits<double>::infinity(),
960
0
                string_view(
961
0
                    literals[detail::infinity_literal],
962
0
                    literal_sizes[detail::infinity_literal]),
963
0
                ec_)))
964
0
            return fail(cs.begin());
965
0
        break;
966
0
    case detail::neg_infinity_literal:
967
0
        if(BOOST_JSON_UNLIKELY(
968
0
            ! h_.on_double(
969
0
                -std::numeric_limits<double>::infinity(),
970
0
                string_view(
971
0
                    literals[detail::neg_infinity_literal],
972
0
                    literal_sizes[detail::neg_infinity_literal]),
973
0
                ec_)))
974
0
            return fail(cs.begin());
975
0
        break;
976
0
    case detail::nan_literal:
977
0
        if(BOOST_JSON_UNLIKELY(
978
0
            ! h_.on_double(
979
0
                std::numeric_limits<double>::quiet_NaN(),
980
0
                string_view(
981
0
                    literals[detail::nan_literal],
982
0
                    literal_sizes[detail::nan_literal]),
983
0
                ec_)))
984
0
            return fail(cs.begin());
985
0
        break;
986
0
    default: BOOST_JSON_UNREACHABLE();
987
0
    }
988
989
0
    cs += size;
990
0
    return cs.begin();
991
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<0>(char const*, std::__1::integral_constant<int, 0>)
Line
Count
Source
810
13.7k
{
811
13.7k
    constexpr char const* literals[] = {
812
13.7k
        "null",
813
13.7k
        "true",
814
13.7k
        "false",
815
13.7k
        "Infinity",
816
13.7k
        "-Infinity",
817
13.7k
        "NaN",
818
13.7k
    };
819
820
13.7k
    constexpr std::size_t literal_sizes[] = {
821
13.7k
        4,
822
13.7k
        4,
823
13.7k
        5,
824
13.7k
        8,
825
13.7k
        9,
826
13.7k
        3,
827
13.7k
    };
828
829
13.7k
    std::size_t cur_lit;
830
13.7k
    std::size_t offset;
831
832
13.7k
    detail::const_stream_wrapper cs(p, end_);
833
13.7k
    BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
834
13.7k
    {
835
13.7k
        BOOST_ASSERT( literal >= 0 );
836
13.7k
        if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
837
13.6k
        {
838
13.6k
            int const cmp = std::memcmp(
839
13.6k
                cs.begin(), literals[literal], literal_sizes[literal] );
840
13.6k
            if( cmp != 0 )
841
35
            {
842
35
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
843
35
                return fail(cs.begin(), error::syntax, &loc);
844
35
            }
845
846
13.6k
            BOOST_IF_CONSTEXPR( literal == detail::null_literal )
847
13.6k
            {
848
13.6k
                if(BOOST_JSON_UNLIKELY(
849
13.6k
                    ! h_.on_null(ec_)))
850
0
                    return fail(cs.begin());
851
13.6k
            }
852
0
            else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
853
0
            {
854
0
                if(BOOST_JSON_UNLIKELY(
855
0
                    ! h_.on_bool(true, ec_)))
856
0
                    return fail(cs.begin());
857
0
            }
858
0
            else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
859
0
            {
860
0
                if(BOOST_JSON_UNLIKELY(
861
0
                    ! h_.on_bool(false, ec_)))
862
0
                    return fail(cs.begin());
863
0
            }
864
0
            else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
865
0
            {
866
0
                if(BOOST_JSON_UNLIKELY(
867
0
                    ! h_.on_double(
868
0
                        std::numeric_limits<double>::infinity(),
869
0
                        string_view(
870
0
                            literals[detail::infinity_literal],
871
0
                            literal_sizes[detail::infinity_literal]),
872
0
                        ec_)))
873
0
                    return fail(cs.begin());
874
0
            }
875
0
            else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
876
0
            {
877
0
                if(BOOST_JSON_UNLIKELY(
878
0
                    ! h_.on_double(
879
0
                        -std::numeric_limits<double>::infinity(),
880
0
                        string_view(
881
0
                            literals[detail::neg_infinity_literal],
882
0
                            literal_sizes[detail::neg_infinity_literal]),
883
0
                        ec_)))
884
0
                    return fail(cs.begin());
885
0
            }
886
0
            else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
887
0
            {
888
0
                if(BOOST_JSON_UNLIKELY(
889
0
                    ! h_.on_double(
890
0
                        std::numeric_limits<double>::quiet_NaN(),
891
0
                        string_view(
892
0
                            literals[detail::nan_literal],
893
0
                            literal_sizes[detail::nan_literal]),
894
0
                        ec_)))
895
0
                    return fail(cs.begin());
896
0
            }
897
0
            else
898
0
            {
899
0
                BOOST_JSON_UNREACHABLE();
900
0
            }
901
902
13.6k
            cs += literal_sizes[literal];
903
13.6k
            return cs.begin();
904
13.6k
        }
905
906
106
        offset = 0;
907
106
        cur_lit = literal;
908
106
    }
909
0
    else
910
0
    {
911
0
        state st;
912
0
        st_.pop(st);
913
0
        BOOST_ASSERT( st == state::lit1 );
914
915
0
        cur_lit = cur_lit_;
916
0
        offset = lit_offset_;
917
0
    }
918
919
106
    std::size_t const size = (std::min)(
920
106
        literal_sizes[cur_lit] - offset, cs.remain() );
921
106
    int cmp = 0;
922
106
    if(BOOST_JSON_LIKELY( cs.begin() ))
923
106
        cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
924
106
    if( cmp != 0 )
925
79
    {
926
79
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
927
79
        return fail(cs.begin(), error::syntax, &loc);
928
79
    }
929
930
27
    if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
931
27
    {
932
27
        BOOST_ASSERT( cur_lit < 256 );
933
27
        cur_lit_ = static_cast<unsigned char>( cur_lit );
934
27
        BOOST_ASSERT( offset + size < 256 );
935
27
        lit_offset_ = static_cast<unsigned char>( offset + size );
936
27
        return maybe_suspend(cs.begin() + size, state::lit1);
937
27
    }
938
939
0
    switch( cur_lit )
940
0
    {
941
0
    case detail::null_literal:
942
0
        if(BOOST_JSON_UNLIKELY(
943
0
            ! h_.on_null(ec_)))
944
0
            return fail(cs.begin());
945
0
        break;
946
0
    case detail::true_literal:
947
0
        if(BOOST_JSON_UNLIKELY(
948
0
            ! h_.on_bool(true, ec_)))
949
0
            return fail(cs.begin());
950
0
        break;
951
0
    case detail::false_literal:
952
0
        if(BOOST_JSON_UNLIKELY(
953
0
            ! h_.on_bool(false, ec_)))
954
0
            return fail(cs.begin());
955
0
        break;
956
0
    case detail::infinity_literal:
957
0
        if(BOOST_JSON_UNLIKELY(
958
0
            ! h_.on_double(
959
0
                std::numeric_limits<double>::infinity(),
960
0
                string_view(
961
0
                    literals[detail::infinity_literal],
962
0
                    literal_sizes[detail::infinity_literal]),
963
0
                ec_)))
964
0
            return fail(cs.begin());
965
0
        break;
966
0
    case detail::neg_infinity_literal:
967
0
        if(BOOST_JSON_UNLIKELY(
968
0
            ! h_.on_double(
969
0
                -std::numeric_limits<double>::infinity(),
970
0
                string_view(
971
0
                    literals[detail::neg_infinity_literal],
972
0
                    literal_sizes[detail::neg_infinity_literal]),
973
0
                ec_)))
974
0
            return fail(cs.begin());
975
0
        break;
976
0
    case detail::nan_literal:
977
0
        if(BOOST_JSON_UNLIKELY(
978
0
            ! h_.on_double(
979
0
                std::numeric_limits<double>::quiet_NaN(),
980
0
                string_view(
981
0
                    literals[detail::nan_literal],
982
0
                    literal_sizes[detail::nan_literal]),
983
0
                ec_)))
984
0
            return fail(cs.begin());
985
0
        break;
986
0
    default: BOOST_JSON_UNREACHABLE();
987
0
    }
988
989
0
    cs += size;
990
0
    return cs.begin();
991
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<1>(char const*, std::__1::integral_constant<int, 1>)
Line
Count
Source
810
22.5k
{
811
22.5k
    constexpr char const* literals[] = {
812
22.5k
        "null",
813
22.5k
        "true",
814
22.5k
        "false",
815
22.5k
        "Infinity",
816
22.5k
        "-Infinity",
817
22.5k
        "NaN",
818
22.5k
    };
819
820
22.5k
    constexpr std::size_t literal_sizes[] = {
821
22.5k
        4,
822
22.5k
        4,
823
22.5k
        5,
824
22.5k
        8,
825
22.5k
        9,
826
22.5k
        3,
827
22.5k
    };
828
829
22.5k
    std::size_t cur_lit;
830
22.5k
    std::size_t offset;
831
832
22.5k
    detail::const_stream_wrapper cs(p, end_);
833
22.5k
    BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
834
22.5k
    {
835
22.5k
        BOOST_ASSERT( literal >= 0 );
836
22.5k
        if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
837
22.4k
        {
838
22.4k
            int const cmp = std::memcmp(
839
22.4k
                cs.begin(), literals[literal], literal_sizes[literal] );
840
22.4k
            if( cmp != 0 )
841
37
            {
842
37
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
843
37
                return fail(cs.begin(), error::syntax, &loc);
844
37
            }
845
846
22.4k
            BOOST_IF_CONSTEXPR( literal == detail::null_literal )
847
0
            {
848
0
                if(BOOST_JSON_UNLIKELY(
849
0
                    ! h_.on_null(ec_)))
850
0
                    return fail(cs.begin());
851
0
            }
852
22.4k
            else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
853
22.4k
            {
854
22.4k
                if(BOOST_JSON_UNLIKELY(
855
22.4k
                    ! h_.on_bool(true, ec_)))
856
0
                    return fail(cs.begin());
857
22.4k
            }
858
0
            else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
859
0
            {
860
0
                if(BOOST_JSON_UNLIKELY(
861
0
                    ! h_.on_bool(false, ec_)))
862
0
                    return fail(cs.begin());
863
0
            }
864
0
            else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
865
0
            {
866
0
                if(BOOST_JSON_UNLIKELY(
867
0
                    ! h_.on_double(
868
0
                        std::numeric_limits<double>::infinity(),
869
0
                        string_view(
870
0
                            literals[detail::infinity_literal],
871
0
                            literal_sizes[detail::infinity_literal]),
872
0
                        ec_)))
873
0
                    return fail(cs.begin());
874
0
            }
875
0
            else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
876
0
            {
877
0
                if(BOOST_JSON_UNLIKELY(
878
0
                    ! h_.on_double(
879
0
                        -std::numeric_limits<double>::infinity(),
880
0
                        string_view(
881
0
                            literals[detail::neg_infinity_literal],
882
0
                            literal_sizes[detail::neg_infinity_literal]),
883
0
                        ec_)))
884
0
                    return fail(cs.begin());
885
0
            }
886
0
            else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
887
0
            {
888
0
                if(BOOST_JSON_UNLIKELY(
889
0
                    ! h_.on_double(
890
0
                        std::numeric_limits<double>::quiet_NaN(),
891
0
                        string_view(
892
0
                            literals[detail::nan_literal],
893
0
                            literal_sizes[detail::nan_literal]),
894
0
                        ec_)))
895
0
                    return fail(cs.begin());
896
0
            }
897
0
            else
898
0
            {
899
0
                BOOST_JSON_UNREACHABLE();
900
0
            }
901
902
22.4k
            cs += literal_sizes[literal];
903
22.4k
            return cs.begin();
904
22.4k
        }
905
906
106
        offset = 0;
907
106
        cur_lit = literal;
908
106
    }
909
0
    else
910
0
    {
911
0
        state st;
912
0
        st_.pop(st);
913
0
        BOOST_ASSERT( st == state::lit1 );
914
915
0
        cur_lit = cur_lit_;
916
0
        offset = lit_offset_;
917
0
    }
918
919
106
    std::size_t const size = (std::min)(
920
106
        literal_sizes[cur_lit] - offset, cs.remain() );
921
106
    int cmp = 0;
922
106
    if(BOOST_JSON_LIKELY( cs.begin() ))
923
106
        cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
924
106
    if( cmp != 0 )
925
78
    {
926
78
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
927
78
        return fail(cs.begin(), error::syntax, &loc);
928
78
    }
929
930
28
    if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
931
28
    {
932
28
        BOOST_ASSERT( cur_lit < 256 );
933
28
        cur_lit_ = static_cast<unsigned char>( cur_lit );
934
28
        BOOST_ASSERT( offset + size < 256 );
935
28
        lit_offset_ = static_cast<unsigned char>( offset + size );
936
28
        return maybe_suspend(cs.begin() + size, state::lit1);
937
28
    }
938
939
0
    switch( cur_lit )
940
0
    {
941
0
    case detail::null_literal:
942
0
        if(BOOST_JSON_UNLIKELY(
943
0
            ! h_.on_null(ec_)))
944
0
            return fail(cs.begin());
945
0
        break;
946
0
    case detail::true_literal:
947
0
        if(BOOST_JSON_UNLIKELY(
948
0
            ! h_.on_bool(true, ec_)))
949
0
            return fail(cs.begin());
950
0
        break;
951
0
    case detail::false_literal:
952
0
        if(BOOST_JSON_UNLIKELY(
953
0
            ! h_.on_bool(false, ec_)))
954
0
            return fail(cs.begin());
955
0
        break;
956
0
    case detail::infinity_literal:
957
0
        if(BOOST_JSON_UNLIKELY(
958
0
            ! h_.on_double(
959
0
                std::numeric_limits<double>::infinity(),
960
0
                string_view(
961
0
                    literals[detail::infinity_literal],
962
0
                    literal_sizes[detail::infinity_literal]),
963
0
                ec_)))
964
0
            return fail(cs.begin());
965
0
        break;
966
0
    case detail::neg_infinity_literal:
967
0
        if(BOOST_JSON_UNLIKELY(
968
0
            ! h_.on_double(
969
0
                -std::numeric_limits<double>::infinity(),
970
0
                string_view(
971
0
                    literals[detail::neg_infinity_literal],
972
0
                    literal_sizes[detail::neg_infinity_literal]),
973
0
                ec_)))
974
0
            return fail(cs.begin());
975
0
        break;
976
0
    case detail::nan_literal:
977
0
        if(BOOST_JSON_UNLIKELY(
978
0
            ! h_.on_double(
979
0
                std::numeric_limits<double>::quiet_NaN(),
980
0
                string_view(
981
0
                    literals[detail::nan_literal],
982
0
                    literal_sizes[detail::nan_literal]),
983
0
                ec_)))
984
0
            return fail(cs.begin());
985
0
        break;
986
0
    default: BOOST_JSON_UNREACHABLE();
987
0
    }
988
989
0
    cs += size;
990
0
    return cs.begin();
991
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<2>(char const*, std::__1::integral_constant<int, 2>)
Line
Count
Source
810
21.7k
{
811
21.7k
    constexpr char const* literals[] = {
812
21.7k
        "null",
813
21.7k
        "true",
814
21.7k
        "false",
815
21.7k
        "Infinity",
816
21.7k
        "-Infinity",
817
21.7k
        "NaN",
818
21.7k
    };
819
820
21.7k
    constexpr std::size_t literal_sizes[] = {
821
21.7k
        4,
822
21.7k
        4,
823
21.7k
        5,
824
21.7k
        8,
825
21.7k
        9,
826
21.7k
        3,
827
21.7k
    };
828
829
21.7k
    std::size_t cur_lit;
830
21.7k
    std::size_t offset;
831
832
21.7k
    detail::const_stream_wrapper cs(p, end_);
833
21.7k
    BOOST_IF_CONSTEXPR( literal != detail::resume_literal )
834
21.7k
    {
835
21.7k
        BOOST_ASSERT( literal >= 0 );
836
21.7k
        if(BOOST_JSON_LIKELY( cs.remain() >= literal_sizes[literal] ))
837
21.6k
        {
838
21.6k
            int const cmp = std::memcmp(
839
21.6k
                cs.begin(), literals[literal], literal_sizes[literal] );
840
21.6k
            if( cmp != 0 )
841
52
            {
842
52
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
843
52
                return fail(cs.begin(), error::syntax, &loc);
844
52
            }
845
846
21.6k
            BOOST_IF_CONSTEXPR( literal == detail::null_literal )
847
0
            {
848
0
                if(BOOST_JSON_UNLIKELY(
849
0
                    ! h_.on_null(ec_)))
850
0
                    return fail(cs.begin());
851
0
            }
852
21.6k
            else BOOST_IF_CONSTEXPR( literal == detail::true_literal )
853
0
            {
854
0
                if(BOOST_JSON_UNLIKELY(
855
0
                    ! h_.on_bool(true, ec_)))
856
0
                    return fail(cs.begin());
857
0
            }
858
21.6k
            else BOOST_IF_CONSTEXPR( literal == detail::false_literal )
859
21.6k
            {
860
21.6k
                if(BOOST_JSON_UNLIKELY(
861
21.6k
                    ! h_.on_bool(false, ec_)))
862
0
                    return fail(cs.begin());
863
21.6k
            }
864
0
            else BOOST_IF_CONSTEXPR( literal == detail::infinity_literal )
865
0
            {
866
0
                if(BOOST_JSON_UNLIKELY(
867
0
                    ! h_.on_double(
868
0
                        std::numeric_limits<double>::infinity(),
869
0
                        string_view(
870
0
                            literals[detail::infinity_literal],
871
0
                            literal_sizes[detail::infinity_literal]),
872
0
                        ec_)))
873
0
                    return fail(cs.begin());
874
0
            }
875
0
            else BOOST_IF_CONSTEXPR( literal == detail::neg_infinity_literal )
876
0
            {
877
0
                if(BOOST_JSON_UNLIKELY(
878
0
                    ! h_.on_double(
879
0
                        -std::numeric_limits<double>::infinity(),
880
0
                        string_view(
881
0
                            literals[detail::neg_infinity_literal],
882
0
                            literal_sizes[detail::neg_infinity_literal]),
883
0
                        ec_)))
884
0
                    return fail(cs.begin());
885
0
            }
886
0
            else BOOST_IF_CONSTEXPR( literal == detail::nan_literal )
887
0
            {
888
0
                if(BOOST_JSON_UNLIKELY(
889
0
                    ! h_.on_double(
890
0
                        std::numeric_limits<double>::quiet_NaN(),
891
0
                        string_view(
892
0
                            literals[detail::nan_literal],
893
0
                            literal_sizes[detail::nan_literal]),
894
0
                        ec_)))
895
0
                    return fail(cs.begin());
896
0
            }
897
0
            else
898
0
            {
899
0
                BOOST_JSON_UNREACHABLE();
900
0
            }
901
902
21.6k
            cs += literal_sizes[literal];
903
21.6k
            return cs.begin();
904
21.6k
        }
905
906
117
        offset = 0;
907
117
        cur_lit = literal;
908
117
    }
909
0
    else
910
0
    {
911
0
        state st;
912
0
        st_.pop(st);
913
0
        BOOST_ASSERT( st == state::lit1 );
914
915
0
        cur_lit = cur_lit_;
916
0
        offset = lit_offset_;
917
0
    }
918
919
117
    std::size_t const size = (std::min)(
920
117
        literal_sizes[cur_lit] - offset, cs.remain() );
921
117
    int cmp = 0;
922
117
    if(BOOST_JSON_LIKELY( cs.begin() ))
923
117
        cmp = std::memcmp( cs.begin(), literals[cur_lit] + offset, size );
924
117
    if( cmp != 0 )
925
88
    {
926
88
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
927
88
        return fail(cs.begin(), error::syntax, &loc);
928
88
    }
929
930
29
    if(BOOST_JSON_UNLIKELY( offset + size < literal_sizes[cur_lit] ))
931
29
    {
932
29
        BOOST_ASSERT( cur_lit < 256 );
933
29
        cur_lit_ = static_cast<unsigned char>( cur_lit );
934
29
        BOOST_ASSERT( offset + size < 256 );
935
29
        lit_offset_ = static_cast<unsigned char>( offset + size );
936
29
        return maybe_suspend(cs.begin() + size, state::lit1);
937
29
    }
938
939
0
    switch( cur_lit )
940
0
    {
941
0
    case detail::null_literal:
942
0
        if(BOOST_JSON_UNLIKELY(
943
0
            ! h_.on_null(ec_)))
944
0
            return fail(cs.begin());
945
0
        break;
946
0
    case detail::true_literal:
947
0
        if(BOOST_JSON_UNLIKELY(
948
0
            ! h_.on_bool(true, ec_)))
949
0
            return fail(cs.begin());
950
0
        break;
951
0
    case detail::false_literal:
952
0
        if(BOOST_JSON_UNLIKELY(
953
0
            ! h_.on_bool(false, ec_)))
954
0
            return fail(cs.begin());
955
0
        break;
956
0
    case detail::infinity_literal:
957
0
        if(BOOST_JSON_UNLIKELY(
958
0
            ! h_.on_double(
959
0
                std::numeric_limits<double>::infinity(),
960
0
                string_view(
961
0
                    literals[detail::infinity_literal],
962
0
                    literal_sizes[detail::infinity_literal]),
963
0
                ec_)))
964
0
            return fail(cs.begin());
965
0
        break;
966
0
    case detail::neg_infinity_literal:
967
0
        if(BOOST_JSON_UNLIKELY(
968
0
            ! h_.on_double(
969
0
                -std::numeric_limits<double>::infinity(),
970
0
                string_view(
971
0
                    literals[detail::neg_infinity_literal],
972
0
                    literal_sizes[detail::neg_infinity_literal]),
973
0
                ec_)))
974
0
            return fail(cs.begin());
975
0
        break;
976
0
    case detail::nan_literal:
977
0
        if(BOOST_JSON_UNLIKELY(
978
0
            ! h_.on_double(
979
0
                std::numeric_limits<double>::quiet_NaN(),
980
0
                string_view(
981
0
                    literals[detail::nan_literal],
982
0
                    literal_sizes[detail::nan_literal]),
983
0
                ec_)))
984
0
            return fail(cs.begin());
985
0
        break;
986
0
    default: BOOST_JSON_UNREACHABLE();
987
0
    }
988
989
0
    cs += size;
990
0
    return cs.begin();
991
0
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<3>(char const*, std::__1::integral_constant<int, 3>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<5>(char const*, std::__1::integral_constant<int, 5>)
992
993
//----------------------------------------------------------
994
995
template<class Handler>
996
template<
997
    bool StackEmpty_,
998
    bool IsKey_/*,
999
    bool AllowBadUTF8_*/>
1000
const char*
1001
basic_parser<Handler>::
1002
parse_string(const char* p,
1003
    std::integral_constant<bool, StackEmpty_> stack_empty,
1004
    std::integral_constant<bool, IsKey_> is_key,
1005
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8)
1006
991k
{
1007
991k
    if(! stack_empty && ! st_.empty())
1008
223
    {
1009
223
        state st;
1010
223
        st_.peek(st);
1011
223
        switch(st)
1012
223
        {
1013
0
        default: BOOST_JSON_UNREACHABLE();
1014
139
        case state::str1:
1015
139
            return parse_unescaped(p, stack_empty, is_key, allow_bad_utf8);
1016
1017
57
        case state::str2: case state::str3:
1018
58
        case state::str4: case state::str5:
1019
61
        case state::str6: case state::str7:
1020
78
        case state::str8:
1021
79
        case state::sur1: case state::sur2:
1022
79
        case state::sur3: case state::sur4:
1023
84
        case state::sur5: case state::sur6:
1024
84
            return parse_escaped(p, 0, stack_empty, is_key, allow_bad_utf8);
1025
223
        }
1026
223
    }
1027
1028
991k
    return parse_unescaped(p, std::true_type(), is_key, allow_bad_utf8);
1029
991k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_string<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool)
Line
Count
Source
1006
991k
{
1007
991k
    if(! stack_empty && ! st_.empty())
1008
0
    {
1009
0
        state st;
1010
0
        st_.peek(st);
1011
0
        switch(st)
1012
0
        {
1013
0
        default: BOOST_JSON_UNREACHABLE();
1014
0
        case state::str1:
1015
0
            return parse_unescaped(p, stack_empty, is_key, allow_bad_utf8);
1016
1017
0
        case state::str2: case state::str3:
1018
0
        case state::str4: case state::str5:
1019
0
        case state::str6: case state::str7:
1020
0
        case state::str8:
1021
0
        case state::sur1: case state::sur2:
1022
0
        case state::sur3: case state::sur4:
1023
0
        case state::sur5: case state::sur6:
1024
0
            return parse_escaped(p, 0, stack_empty, is_key, allow_bad_utf8);
1025
0
        }
1026
0
    }
1027
1028
991k
    return parse_unescaped(p, std::true_type(), is_key, allow_bad_utf8);
1029
991k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_string<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool)
Line
Count
Source
1006
223
{
1007
223
    if(! stack_empty && ! st_.empty())
1008
223
    {
1009
223
        state st;
1010
223
        st_.peek(st);
1011
223
        switch(st)
1012
223
        {
1013
0
        default: BOOST_JSON_UNREACHABLE();
1014
139
        case state::str1:
1015
139
            return parse_unescaped(p, stack_empty, is_key, allow_bad_utf8);
1016
1017
57
        case state::str2: case state::str3:
1018
58
        case state::str4: case state::str5:
1019
61
        case state::str6: case state::str7:
1020
78
        case state::str8:
1021
79
        case state::sur1: case state::sur2:
1022
79
        case state::sur3: case state::sur4:
1023
84
        case state::sur5: case state::sur6:
1024
84
            return parse_escaped(p, 0, stack_empty, is_key, allow_bad_utf8);
1025
223
        }
1026
223
    }
1027
1028
0
    return parse_unescaped(p, std::true_type(), is_key, allow_bad_utf8);
1029
223
}
1030
1031
template<class Handler>
1032
template<
1033
    bool StackEmpty_,
1034
    bool IsKey_/*,
1035
    bool AllowBadUTF8_*/>
1036
const char*
1037
basic_parser<Handler>::
1038
parse_unescaped(const char* p,
1039
    std::integral_constant<bool, StackEmpty_> stack_empty,
1040
    std::integral_constant<bool, IsKey_> is_key,
1041
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8)
1042
1.07M
{
1043
1.07M
    detail::const_stream_wrapper cs(p, end_);
1044
1.07M
    std::size_t total;
1045
1.07M
    if(stack_empty || st_.empty())
1046
1.07M
    {
1047
1.07M
        BOOST_ASSERT(*cs == '\x22'); // '"'
1048
1.07M
        ++cs;
1049
1.07M
        total = 0;
1050
1.07M
    }
1051
294
    else
1052
294
    {
1053
294
        state st;
1054
294
        st_.pop(st);
1055
294
        st_.pop(total);
1056
294
    }
1057
1.07M
    char const* start = cs.begin();
1058
1.07M
    cs = allow_bad_utf8?
1059
190k
        detail::count_valid<true>(cs.begin(), cs.end()):
1060
1.07M
        detail::count_valid<false>(cs.begin(), cs.end());
1061
1.07M
    std::size_t size = cs.used(start);
1062
1.07M
    if(is_key)
1063
991k
    {
1064
991k
        BOOST_ASSERT(total <= Handler::max_key_size);
1065
991k
        if(BOOST_JSON_UNLIKELY(size >
1066
991k
            Handler::max_key_size - total))
1067
0
        {
1068
0
            BOOST_STATIC_CONSTEXPR source_location loc
1069
0
                = BOOST_CURRENT_LOCATION;
1070
0
            return fail(cs.begin(), error::key_too_large, &loc);
1071
0
        }
1072
991k
    }
1073
82.5k
    else
1074
82.5k
    {
1075
82.5k
        BOOST_ASSERT(total <= Handler::max_string_size);
1076
82.5k
        if(BOOST_JSON_UNLIKELY(size >
1077
82.5k
            Handler::max_string_size - total))
1078
0
        {
1079
0
            BOOST_STATIC_CONSTEXPR source_location loc
1080
0
                = BOOST_CURRENT_LOCATION;
1081
0
            return fail(cs.begin(), error::string_too_large, &loc);
1082
0
        }
1083
82.5k
    }
1084
1.07M
    total += size;
1085
1.07M
    if(BOOST_JSON_UNLIKELY(! cs))
1086
860
    {
1087
        // call handler if the string isn't empty
1088
860
        if(BOOST_JSON_LIKELY(size))
1089
479
        {
1090
479
            {
1091
479
                bool r = is_key?
1092
203
                    h_.on_key_part( {start, size}, total, ec_ ):
1093
479
                    h_.on_string_part( {start, size}, total, ec_ );
1094
1095
479
                if(BOOST_JSON_UNLIKELY(!r))
1096
0
                {
1097
0
                    return fail(cs.begin());
1098
0
                }
1099
479
            }
1100
479
        }
1101
860
        return maybe_suspend(cs.begin(), state::str1, total);
1102
860
    }
1103
    // at this point all valid characters have been skipped, so any remaining
1104
    // if there are any more characters, they are either escaped, or incomplete
1105
    // utf8, or invalid utf8
1106
1.07M
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1107
47.1k
    {
1108
        // sequence is invalid or incomplete
1109
47.1k
        if((*cs & 0x80) && !allow_bad_utf8)
1110
555
        {
1111
555
            seq_.save(cs.begin(), cs.remain());
1112
555
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1113
454
            {
1114
454
                BOOST_STATIC_CONSTEXPR source_location loc
1115
454
                    = BOOST_CURRENT_LOCATION;
1116
454
                return fail(cs.begin(), error::syntax, &loc);
1117
454
            }
1118
101
            if(BOOST_JSON_LIKELY(size))
1119
73
            {
1120
73
                {
1121
73
                    bool r = is_key?
1122
30
                        h_.on_key_part( {start, size}, total, ec_ ):
1123
73
                        h_.on_string_part( {start, size}, total, ec_ );
1124
1125
73
                    if(BOOST_JSON_UNLIKELY(!r))
1126
0
                    {
1127
0
                        return fail(cs.begin());
1128
0
                    }
1129
73
                }
1130
73
            }
1131
101
            return maybe_suspend(cs.end(), state::str8, total);
1132
101
        }
1133
46.6k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1134
46.5k
        {
1135
            // flush unescaped run from input
1136
46.5k
            if(BOOST_JSON_LIKELY(size))
1137
22.5k
            {
1138
22.5k
                {
1139
22.5k
                    bool r = is_key?
1140
3.58k
                        h_.on_key_part( {start, size}, total, ec_ ):
1141
22.5k
                        h_.on_string_part( {start, size}, total, ec_ );
1142
1143
22.5k
                    if(BOOST_JSON_UNLIKELY(!r))
1144
0
                    {
1145
0
                        return fail(cs.begin());
1146
0
                    }
1147
22.5k
                }
1148
22.5k
            }
1149
46.5k
            return parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf8);
1150
46.5k
        }
1151
        // illegal control
1152
83
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1153
83
        return fail(cs.begin(), error::syntax, &loc);
1154
47.1k
    }
1155
1156
1.02M
    {
1157
1.02M
        bool r = is_key?
1158
985k
            h_.on_key( {start, size}, total, ec_ ):
1159
1.02M
            h_.on_string( {start, size}, total, ec_ );
1160
1161
1.02M
        if(BOOST_JSON_UNLIKELY(!r))
1162
0
        {
1163
0
            return fail(cs.begin());
1164
0
        }
1165
1.02M
    }
1166
1167
1.02M
    ++cs;
1168
1.02M
    return cs.begin();
1169
1.02M
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_unescaped<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool)
Line
Count
Source
1042
82.4k
{
1043
82.4k
    detail::const_stream_wrapper cs(p, end_);
1044
82.4k
    std::size_t total;
1045
82.4k
    if(stack_empty || st_.empty())
1046
82.4k
    {
1047
82.4k
        BOOST_ASSERT(*cs == '\x22'); // '"'
1048
82.4k
        ++cs;
1049
82.4k
        total = 0;
1050
82.4k
    }
1051
0
    else
1052
0
    {
1053
0
        state st;
1054
0
        st_.pop(st);
1055
0
        st_.pop(total);
1056
0
    }
1057
82.4k
    char const* start = cs.begin();
1058
82.4k
    cs = allow_bad_utf8?
1059
32.7k
        detail::count_valid<true>(cs.begin(), cs.end()):
1060
82.4k
        detail::count_valid<false>(cs.begin(), cs.end());
1061
82.4k
    std::size_t size = cs.used(start);
1062
82.4k
    if(is_key)
1063
0
    {
1064
0
        BOOST_ASSERT(total <= Handler::max_key_size);
1065
0
        if(BOOST_JSON_UNLIKELY(size >
1066
0
            Handler::max_key_size - total))
1067
0
        {
1068
0
            BOOST_STATIC_CONSTEXPR source_location loc
1069
0
                = BOOST_CURRENT_LOCATION;
1070
0
            return fail(cs.begin(), error::key_too_large, &loc);
1071
0
        }
1072
0
    }
1073
82.4k
    else
1074
82.4k
    {
1075
82.4k
        BOOST_ASSERT(total <= Handler::max_string_size);
1076
82.4k
        if(BOOST_JSON_UNLIKELY(size >
1077
82.4k
            Handler::max_string_size - total))
1078
0
        {
1079
0
            BOOST_STATIC_CONSTEXPR source_location loc
1080
0
                = BOOST_CURRENT_LOCATION;
1081
0
            return fail(cs.begin(), error::string_too_large, &loc);
1082
0
        }
1083
82.4k
    }
1084
82.4k
    total += size;
1085
82.4k
    if(BOOST_JSON_UNLIKELY(! cs))
1086
313
    {
1087
        // call handler if the string isn't empty
1088
313
        if(BOOST_JSON_LIKELY(size))
1089
276
        {
1090
276
            {
1091
276
                bool r = is_key?
1092
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1093
276
                    h_.on_string_part( {start, size}, total, ec_ );
1094
1095
276
                if(BOOST_JSON_UNLIKELY(!r))
1096
0
                {
1097
0
                    return fail(cs.begin());
1098
0
                }
1099
276
            }
1100
276
        }
1101
313
        return maybe_suspend(cs.begin(), state::str1, total);
1102
313
    }
1103
    // at this point all valid characters have been skipped, so any remaining
1104
    // if there are any more characters, they are either escaped, or incomplete
1105
    // utf8, or invalid utf8
1106
82.1k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1107
41.5k
    {
1108
        // sequence is invalid or incomplete
1109
41.5k
        if((*cs & 0x80) && !allow_bad_utf8)
1110
294
        {
1111
294
            seq_.save(cs.begin(), cs.remain());
1112
294
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1113
235
            {
1114
235
                BOOST_STATIC_CONSTEXPR source_location loc
1115
235
                    = BOOST_CURRENT_LOCATION;
1116
235
                return fail(cs.begin(), error::syntax, &loc);
1117
235
            }
1118
59
            if(BOOST_JSON_LIKELY(size))
1119
43
            {
1120
43
                {
1121
43
                    bool r = is_key?
1122
0
                        h_.on_key_part( {start, size}, total, ec_ ):
1123
43
                        h_.on_string_part( {start, size}, total, ec_ );
1124
1125
43
                    if(BOOST_JSON_UNLIKELY(!r))
1126
0
                    {
1127
0
                        return fail(cs.begin());
1128
0
                    }
1129
43
                }
1130
43
            }
1131
59
            return maybe_suspend(cs.end(), state::str8, total);
1132
59
        }
1133
41.2k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1134
41.2k
        {
1135
            // flush unescaped run from input
1136
41.2k
            if(BOOST_JSON_LIKELY(size))
1137
18.9k
            {
1138
18.9k
                {
1139
18.9k
                    bool r = is_key?
1140
0
                        h_.on_key_part( {start, size}, total, ec_ ):
1141
18.9k
                        h_.on_string_part( {start, size}, total, ec_ );
1142
1143
18.9k
                    if(BOOST_JSON_UNLIKELY(!r))
1144
0
                    {
1145
0
                        return fail(cs.begin());
1146
0
                    }
1147
18.9k
                }
1148
18.9k
            }
1149
41.2k
            return parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf8);
1150
41.2k
        }
1151
        // illegal control
1152
42
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1153
42
        return fail(cs.begin(), error::syntax, &loc);
1154
41.5k
    }
1155
1156
40.5k
    {
1157
40.5k
        bool r = is_key?
1158
0
            h_.on_key( {start, size}, total, ec_ ):
1159
40.5k
            h_.on_string( {start, size}, total, ec_ );
1160
1161
40.5k
        if(BOOST_JSON_UNLIKELY(!r))
1162
0
        {
1163
0
            return fail(cs.begin());
1164
0
        }
1165
40.5k
    }
1166
1167
40.5k
    ++cs;
1168
40.5k
    return cs.begin();
1169
40.5k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_unescaped<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool)
Line
Count
Source
1042
991k
{
1043
991k
    detail::const_stream_wrapper cs(p, end_);
1044
991k
    std::size_t total;
1045
991k
    if(stack_empty || st_.empty())
1046
991k
    {
1047
991k
        BOOST_ASSERT(*cs == '\x22'); // '"'
1048
991k
        ++cs;
1049
991k
        total = 0;
1050
991k
    }
1051
0
    else
1052
0
    {
1053
0
        state st;
1054
0
        st_.pop(st);
1055
0
        st_.pop(total);
1056
0
    }
1057
991k
    char const* start = cs.begin();
1058
991k
    cs = allow_bad_utf8?
1059
157k
        detail::count_valid<true>(cs.begin(), cs.end()):
1060
991k
        detail::count_valid<false>(cs.begin(), cs.end());
1061
991k
    std::size_t size = cs.used(start);
1062
991k
    if(is_key)
1063
991k
    {
1064
991k
        BOOST_ASSERT(total <= Handler::max_key_size);
1065
991k
        if(BOOST_JSON_UNLIKELY(size >
1066
991k
            Handler::max_key_size - total))
1067
0
        {
1068
0
            BOOST_STATIC_CONSTEXPR source_location loc
1069
0
                = BOOST_CURRENT_LOCATION;
1070
0
            return fail(cs.begin(), error::key_too_large, &loc);
1071
0
        }
1072
991k
    }
1073
0
    else
1074
0
    {
1075
0
        BOOST_ASSERT(total <= Handler::max_string_size);
1076
0
        if(BOOST_JSON_UNLIKELY(size >
1077
0
            Handler::max_string_size - total))
1078
0
        {
1079
0
            BOOST_STATIC_CONSTEXPR source_location loc
1080
0
                = BOOST_CURRENT_LOCATION;
1081
0
            return fail(cs.begin(), error::string_too_large, &loc);
1082
0
        }
1083
0
    }
1084
991k
    total += size;
1085
991k
    if(BOOST_JSON_UNLIKELY(! cs))
1086
253
    {
1087
        // call handler if the string isn't empty
1088
253
        if(BOOST_JSON_LIKELY(size))
1089
203
        {
1090
203
            {
1091
203
                bool r = is_key?
1092
203
                    h_.on_key_part( {start, size}, total, ec_ ):
1093
203
                    h_.on_string_part( {start, size}, total, ec_ );
1094
1095
203
                if(BOOST_JSON_UNLIKELY(!r))
1096
0
                {
1097
0
                    return fail(cs.begin());
1098
0
                }
1099
203
            }
1100
203
        }
1101
253
        return maybe_suspend(cs.begin(), state::str1, total);
1102
253
    }
1103
    // at this point all valid characters have been skipped, so any remaining
1104
    // if there are any more characters, they are either escaped, or incomplete
1105
    // utf8, or invalid utf8
1106
991k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1107
5.61k
    {
1108
        // sequence is invalid or incomplete
1109
5.61k
        if((*cs & 0x80) && !allow_bad_utf8)
1110
261
        {
1111
261
            seq_.save(cs.begin(), cs.remain());
1112
261
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1113
219
            {
1114
219
                BOOST_STATIC_CONSTEXPR source_location loc
1115
219
                    = BOOST_CURRENT_LOCATION;
1116
219
                return fail(cs.begin(), error::syntax, &loc);
1117
219
            }
1118
42
            if(BOOST_JSON_LIKELY(size))
1119
30
            {
1120
30
                {
1121
30
                    bool r = is_key?
1122
30
                        h_.on_key_part( {start, size}, total, ec_ ):
1123
30
                        h_.on_string_part( {start, size}, total, ec_ );
1124
1125
30
                    if(BOOST_JSON_UNLIKELY(!r))
1126
0
                    {
1127
0
                        return fail(cs.begin());
1128
0
                    }
1129
30
                }
1130
30
            }
1131
42
            return maybe_suspend(cs.end(), state::str8, total);
1132
42
        }
1133
5.35k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1134
5.30k
        {
1135
            // flush unescaped run from input
1136
5.30k
            if(BOOST_JSON_LIKELY(size))
1137
3.58k
            {
1138
3.58k
                {
1139
3.58k
                    bool r = is_key?
1140
3.58k
                        h_.on_key_part( {start, size}, total, ec_ ):
1141
3.58k
                        h_.on_string_part( {start, size}, total, ec_ );
1142
1143
3.58k
                    if(BOOST_JSON_UNLIKELY(!r))
1144
0
                    {
1145
0
                        return fail(cs.begin());
1146
0
                    }
1147
3.58k
                }
1148
3.58k
            }
1149
5.30k
            return parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf8);
1150
5.30k
        }
1151
        // illegal control
1152
41
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1153
41
        return fail(cs.begin(), error::syntax, &loc);
1154
5.61k
    }
1155
1156
985k
    {
1157
985k
        bool r = is_key?
1158
985k
            h_.on_key( {start, size}, total, ec_ ):
1159
985k
            h_.on_string( {start, size}, total, ec_ );
1160
1161
985k
        if(BOOST_JSON_UNLIKELY(!r))
1162
0
        {
1163
0
            return fail(cs.begin());
1164
0
        }
1165
985k
    }
1166
1167
985k
    ++cs;
1168
985k
    return cs.begin();
1169
985k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_unescaped<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool)
Line
Count
Source
1042
155
{
1043
155
    detail::const_stream_wrapper cs(p, end_);
1044
155
    std::size_t total;
1045
155
    if(stack_empty || st_.empty())
1046
0
    {
1047
0
        BOOST_ASSERT(*cs == '\x22'); // '"'
1048
0
        ++cs;
1049
0
        total = 0;
1050
0
    }
1051
155
    else
1052
155
    {
1053
155
        state st;
1054
155
        st_.pop(st);
1055
155
        st_.pop(total);
1056
155
    }
1057
155
    char const* start = cs.begin();
1058
155
    cs = allow_bad_utf8?
1059
77
        detail::count_valid<true>(cs.begin(), cs.end()):
1060
155
        detail::count_valid<false>(cs.begin(), cs.end());
1061
155
    std::size_t size = cs.used(start);
1062
155
    if(is_key)
1063
0
    {
1064
0
        BOOST_ASSERT(total <= Handler::max_key_size);
1065
0
        if(BOOST_JSON_UNLIKELY(size >
1066
0
            Handler::max_key_size - total))
1067
0
        {
1068
0
            BOOST_STATIC_CONSTEXPR source_location loc
1069
0
                = BOOST_CURRENT_LOCATION;
1070
0
            return fail(cs.begin(), error::key_too_large, &loc);
1071
0
        }
1072
0
    }
1073
155
    else
1074
155
    {
1075
155
        BOOST_ASSERT(total <= Handler::max_string_size);
1076
155
        if(BOOST_JSON_UNLIKELY(size >
1077
155
            Handler::max_string_size - total))
1078
0
        {
1079
0
            BOOST_STATIC_CONSTEXPR source_location loc
1080
0
                = BOOST_CURRENT_LOCATION;
1081
0
            return fail(cs.begin(), error::string_too_large, &loc);
1082
0
        }
1083
155
    }
1084
155
    total += size;
1085
155
    if(BOOST_JSON_UNLIKELY(! cs))
1086
155
    {
1087
        // call handler if the string isn't empty
1088
155
        if(BOOST_JSON_LIKELY(size))
1089
0
        {
1090
0
            {
1091
0
                bool r = is_key?
1092
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1093
0
                    h_.on_string_part( {start, size}, total, ec_ );
1094
1095
0
                if(BOOST_JSON_UNLIKELY(!r))
1096
0
                {
1097
0
                    return fail(cs.begin());
1098
0
                }
1099
0
            }
1100
0
        }
1101
155
        return maybe_suspend(cs.begin(), state::str1, total);
1102
155
    }
1103
    // at this point all valid characters have been skipped, so any remaining
1104
    // if there are any more characters, they are either escaped, or incomplete
1105
    // utf8, or invalid utf8
1106
0
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1107
0
    {
1108
        // sequence is invalid or incomplete
1109
0
        if((*cs & 0x80) && !allow_bad_utf8)
1110
0
        {
1111
0
            seq_.save(cs.begin(), cs.remain());
1112
0
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1113
0
            {
1114
0
                BOOST_STATIC_CONSTEXPR source_location loc
1115
0
                    = BOOST_CURRENT_LOCATION;
1116
0
                return fail(cs.begin(), error::syntax, &loc);
1117
0
            }
1118
0
            if(BOOST_JSON_LIKELY(size))
1119
0
            {
1120
0
                {
1121
0
                    bool r = is_key?
1122
0
                        h_.on_key_part( {start, size}, total, ec_ ):
1123
0
                        h_.on_string_part( {start, size}, total, ec_ );
1124
1125
0
                    if(BOOST_JSON_UNLIKELY(!r))
1126
0
                    {
1127
0
                        return fail(cs.begin());
1128
0
                    }
1129
0
                }
1130
0
            }
1131
0
            return maybe_suspend(cs.end(), state::str8, total);
1132
0
        }
1133
0
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1134
0
        {
1135
            // flush unescaped run from input
1136
0
            if(BOOST_JSON_LIKELY(size))
1137
0
            {
1138
0
                {
1139
0
                    bool r = is_key?
1140
0
                        h_.on_key_part( {start, size}, total, ec_ ):
1141
0
                        h_.on_string_part( {start, size}, total, ec_ );
1142
1143
0
                    if(BOOST_JSON_UNLIKELY(!r))
1144
0
                    {
1145
0
                        return fail(cs.begin());
1146
0
                    }
1147
0
                }
1148
0
            }
1149
0
            return parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf8);
1150
0
        }
1151
        // illegal control
1152
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1153
0
        return fail(cs.begin(), error::syntax, &loc);
1154
0
    }
1155
1156
0
    {
1157
0
        bool r = is_key?
1158
0
            h_.on_key( {start, size}, total, ec_ ):
1159
0
            h_.on_string( {start, size}, total, ec_ );
1160
1161
0
        if(BOOST_JSON_UNLIKELY(!r))
1162
0
        {
1163
0
            return fail(cs.begin());
1164
0
        }
1165
0
    }
1166
1167
0
    ++cs;
1168
0
    return cs.begin();
1169
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_unescaped<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool)
Line
Count
Source
1042
139
{
1043
139
    detail::const_stream_wrapper cs(p, end_);
1044
139
    std::size_t total;
1045
139
    if(stack_empty || st_.empty())
1046
0
    {
1047
0
        BOOST_ASSERT(*cs == '\x22'); // '"'
1048
0
        ++cs;
1049
0
        total = 0;
1050
0
    }
1051
139
    else
1052
139
    {
1053
139
        state st;
1054
139
        st_.pop(st);
1055
139
        st_.pop(total);
1056
139
    }
1057
139
    char const* start = cs.begin();
1058
139
    cs = allow_bad_utf8?
1059
63
        detail::count_valid<true>(cs.begin(), cs.end()):
1060
139
        detail::count_valid<false>(cs.begin(), cs.end());
1061
139
    std::size_t size = cs.used(start);
1062
139
    if(is_key)
1063
139
    {
1064
139
        BOOST_ASSERT(total <= Handler::max_key_size);
1065
139
        if(BOOST_JSON_UNLIKELY(size >
1066
139
            Handler::max_key_size - total))
1067
0
        {
1068
0
            BOOST_STATIC_CONSTEXPR source_location loc
1069
0
                = BOOST_CURRENT_LOCATION;
1070
0
            return fail(cs.begin(), error::key_too_large, &loc);
1071
0
        }
1072
139
    }
1073
0
    else
1074
0
    {
1075
0
        BOOST_ASSERT(total <= Handler::max_string_size);
1076
0
        if(BOOST_JSON_UNLIKELY(size >
1077
0
            Handler::max_string_size - total))
1078
0
        {
1079
0
            BOOST_STATIC_CONSTEXPR source_location loc
1080
0
                = BOOST_CURRENT_LOCATION;
1081
0
            return fail(cs.begin(), error::string_too_large, &loc);
1082
0
        }
1083
0
    }
1084
139
    total += size;
1085
139
    if(BOOST_JSON_UNLIKELY(! cs))
1086
139
    {
1087
        // call handler if the string isn't empty
1088
139
        if(BOOST_JSON_LIKELY(size))
1089
0
        {
1090
0
            {
1091
0
                bool r = is_key?
1092
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1093
0
                    h_.on_string_part( {start, size}, total, ec_ );
1094
1095
0
                if(BOOST_JSON_UNLIKELY(!r))
1096
0
                {
1097
0
                    return fail(cs.begin());
1098
0
                }
1099
0
            }
1100
0
        }
1101
139
        return maybe_suspend(cs.begin(), state::str1, total);
1102
139
    }
1103
    // at this point all valid characters have been skipped, so any remaining
1104
    // if there are any more characters, they are either escaped, or incomplete
1105
    // utf8, or invalid utf8
1106
0
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1107
0
    {
1108
        // sequence is invalid or incomplete
1109
0
        if((*cs & 0x80) && !allow_bad_utf8)
1110
0
        {
1111
0
            seq_.save(cs.begin(), cs.remain());
1112
0
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1113
0
            {
1114
0
                BOOST_STATIC_CONSTEXPR source_location loc
1115
0
                    = BOOST_CURRENT_LOCATION;
1116
0
                return fail(cs.begin(), error::syntax, &loc);
1117
0
            }
1118
0
            if(BOOST_JSON_LIKELY(size))
1119
0
            {
1120
0
                {
1121
0
                    bool r = is_key?
1122
0
                        h_.on_key_part( {start, size}, total, ec_ ):
1123
0
                        h_.on_string_part( {start, size}, total, ec_ );
1124
1125
0
                    if(BOOST_JSON_UNLIKELY(!r))
1126
0
                    {
1127
0
                        return fail(cs.begin());
1128
0
                    }
1129
0
                }
1130
0
            }
1131
0
            return maybe_suspend(cs.end(), state::str8, total);
1132
0
        }
1133
0
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1134
0
        {
1135
            // flush unescaped run from input
1136
0
            if(BOOST_JSON_LIKELY(size))
1137
0
            {
1138
0
                {
1139
0
                    bool r = is_key?
1140
0
                        h_.on_key_part( {start, size}, total, ec_ ):
1141
0
                        h_.on_string_part( {start, size}, total, ec_ );
1142
1143
0
                    if(BOOST_JSON_UNLIKELY(!r))
1144
0
                    {
1145
0
                        return fail(cs.begin());
1146
0
                    }
1147
0
                }
1148
0
            }
1149
0
            return parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf8);
1150
0
        }
1151
        // illegal control
1152
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1153
0
        return fail(cs.begin(), error::syntax, &loc);
1154
0
    }
1155
1156
0
    {
1157
0
        bool r = is_key?
1158
0
            h_.on_key( {start, size}, total, ec_ ):
1159
0
            h_.on_string( {start, size}, total, ec_ );
1160
1161
0
        if(BOOST_JSON_UNLIKELY(!r))
1162
0
        {
1163
0
            return fail(cs.begin());
1164
0
        }
1165
0
    }
1166
1167
0
    ++cs;
1168
0
    return cs.begin();
1169
0
}
1170
1171
template<class Handler>
1172
template<
1173
    bool StackEmpty_/*,
1174
    bool IsKey_,
1175
    bool AllowBadUTF8_*/>
1176
const char*
1177
basic_parser<Handler>::
1178
parse_escaped(
1179
    const char* p,
1180
    std::size_t total,
1181
    std::integral_constant<bool, StackEmpty_> stack_empty,
1182
    /*std::integral_constant<bool, IsKey_>*/ bool is_key,
1183
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8)
1184
47.1k
{
1185
    //---------------------------------------------------------------
1186
    //
1187
    // To handle escapes, a local temporary buffer accumulates
1188
    // the unescaped result. The algorithm attempts to fill the
1189
    // buffer to capacity before invoking the handler.
1190
    // In some cases the temporary buffer needs to be flushed
1191
    // before it is full:
1192
    // * When the closing double quote is seen
1193
    // * When there in no more input (and more is expected later)
1194
    // A goal of the algorithm is to call the handler as few times
1195
    // as possible. Thus, when the first escape is encountered,
1196
    // the algorithm attempts to fill the temporary buffer first.
1197
    //
1198
47.1k
    auto const ev_too_large = is_key?
1199
41.7k
        error::key_too_large : error::string_too_large;
1200
47.1k
    auto const max_size = is_key?
1201
41.7k
        Handler::max_key_size : Handler::max_string_size;
1202
47.1k
    detail::clipped_const_stream cs(p, end_);
1203
47.1k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1204
47.1k
    int digit;
1205
47.1k
    char c;
1206
47.1k
    cs.clip(temp.max_size());
1207
47.1k
    if(! stack_empty && ! st_.empty())
1208
605
    {
1209
605
        state st;
1210
605
        st_.pop(st);
1211
605
        st_.pop(total);
1212
605
        switch(st)
1213
605
        {
1214
0
        default: BOOST_JSON_UNREACHABLE();
1215
292
        case state::str2: goto do_str2;
1216
115
        case state::str3: goto do_str3;
1217
18
        case state::str4: goto do_str4;
1218
16
        case state::str5: goto do_str5;
1219
15
        case state::str6: goto do_str6;
1220
19
        case state::str7: goto do_str7;
1221
79
        case state::str8: goto do_str8;
1222
12
        case state::sur1: goto do_sur1;
1223
2
        case state::sur2: goto do_sur2;
1224
3
        case state::sur3: goto do_sur3;
1225
11
        case state::sur4: goto do_sur4;
1226
7
        case state::sur5: goto do_sur5;
1227
16
        case state::sur6: goto do_sur6;
1228
605
        }
1229
605
    }
1230
    // Unescaped JSON is never larger than its escaped version.
1231
    // To efficiently process only what will fit in the temporary buffer,
1232
    // the size of the input stream is temporarily "clipped" to the size
1233
    // of the temporary buffer.
1234
    // handle escaped character
1235
46.5k
    BOOST_ASSERT(*cs == '\\');
1236
46.5k
    ++cs;
1237
5.36M
do_str3:
1238
5.36M
    if(BOOST_JSON_UNLIKELY(! cs))
1239
1.63k
    {
1240
1.63k
        if(BOOST_JSON_LIKELY(! temp.empty()))
1241
1.42k
        {
1242
1.42k
            BOOST_ASSERT(total <= max_size);
1243
1.42k
            if(BOOST_JSON_UNLIKELY(
1244
1.42k
                temp.size() > max_size - total))
1245
0
            {
1246
0
                BOOST_STATIC_CONSTEXPR source_location loc
1247
0
                    = BOOST_CURRENT_LOCATION;
1248
0
                return fail(cs.begin(), ev_too_large, &loc);
1249
0
            }
1250
1.42k
            total += temp.size();
1251
1.42k
            {
1252
1.42k
                bool r = is_key
1253
1.42k
                    ? h_.on_key_part(temp.get(), total, ec_)
1254
1.42k
                    : h_.on_string_part(temp.get(), total, ec_);
1255
1256
1.42k
                if(BOOST_JSON_UNLIKELY(!r))
1257
0
                {
1258
0
                    return fail(cs.begin());
1259
0
                }
1260
1.42k
            }
1261
1.42k
            temp.clear();
1262
1.42k
        }
1263
1.63k
        cs.clip(temp.max_size());
1264
1.63k
        if(BOOST_JSON_UNLIKELY(! cs))
1265
338
            return maybe_suspend(cs.begin(), state::str3, total);
1266
1.63k
    }
1267
5.36M
    switch(*cs)
1268
5.36M
    {
1269
60
    default:
1270
60
        {
1271
60
            BOOST_STATIC_CONSTEXPR source_location loc
1272
60
                = BOOST_CURRENT_LOCATION;
1273
60
            return fail(cs.begin(), error::syntax, &loc);
1274
0
        }
1275
19.7k
    case '\x22': // '"'
1276
19.7k
        temp.push_back('\x22');
1277
19.7k
        ++cs;
1278
19.7k
        break;
1279
3.27M
    case '\\':
1280
3.27M
        temp.push_back('\\');
1281
3.27M
        ++cs;
1282
3.27M
        break;
1283
3.23k
    case '/':
1284
3.23k
        temp.push_back('/');
1285
3.23k
        ++cs;
1286
3.23k
        break;
1287
8.45k
    case 'b':
1288
8.45k
        temp.push_back('\x08');
1289
8.45k
        ++cs;
1290
8.45k
        break;
1291
48.0k
    case 'f':
1292
48.0k
        temp.push_back('\x0c');
1293
48.0k
        ++cs;
1294
48.0k
        break;
1295
17.1k
    case 'n':
1296
17.1k
        temp.push_back('\x0a');
1297
17.1k
        ++cs;
1298
17.1k
        break;
1299
2.11k
    case 'r':
1300
2.11k
        temp.push_back('\x0d');
1301
2.11k
        ++cs;
1302
2.11k
        break;
1303
1.28k
    case 't':
1304
1.28k
        temp.push_back('\x09');
1305
1.28k
        ++cs;
1306
1.28k
        break;
1307
1.99M
    case 'u':
1308
        // utf16 escape
1309
        //
1310
        // fast path only when the buffer
1311
        // is large enough for 2 surrogates
1312
1.99M
        if(BOOST_JSON_LIKELY(cs.remain() > 10))
1313
1.98M
        {
1314
            // KRYSTIAN TODO: this could be done
1315
            // with fewer instructions
1316
1.98M
            digit = detail::load_little_endian<4>(
1317
1.98M
                cs.begin() + 1);
1318
1.98M
            int d4 = detail::hex_digit(static_cast<
1319
1.98M
                unsigned char>(digit >> 24));
1320
1.98M
            int d3 = detail::hex_digit(static_cast<
1321
1.98M
                unsigned char>(digit >> 16));
1322
1.98M
            int d2 = detail::hex_digit(static_cast<
1323
1.98M
                unsigned char>(digit >> 8));
1324
1.98M
            int d1 = detail::hex_digit(static_cast<
1325
1.98M
                unsigned char>(digit));
1326
1.98M
            if(BOOST_JSON_UNLIKELY(
1327
1.98M
                (d1 | d2 | d3 | d4) == -1))
1328
127
            {
1329
127
                if(d1 != -1)
1330
78
                    ++cs;
1331
127
                if(d2 != -1)
1332
55
                    ++cs;
1333
127
                if(d3 != -1)
1334
44
                    ++cs;
1335
127
                BOOST_STATIC_CONSTEXPR source_location loc
1336
127
                    = BOOST_CURRENT_LOCATION;
1337
127
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1338
127
            }
1339
            // 32 bit unicode scalar value
1340
1.98M
            unsigned const u1 =
1341
1.98M
                (d1 << 12) + (d2 << 8) +
1342
1.98M
                (d3 << 4) + d4;
1343
            // valid unicode scalar values are
1344
            // [0, D7FF] and [E000, 10FFFF]
1345
            // values within this range are valid utf-8
1346
            // code points and invalid leading surrogates.
1347
1.98M
            if(BOOST_JSON_LIKELY(
1348
1.98M
                u1 < 0xd800 || u1 > 0xdfff))
1349
1.79M
            {
1350
1.79M
                cs += 5;
1351
1.79M
                temp.append_utf8(u1);
1352
1.79M
                break;
1353
1.79M
            }
1354
191k
            if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1355
19
            {
1356
19
                BOOST_STATIC_CONSTEXPR source_location loc
1357
19
                    = BOOST_CURRENT_LOCATION;
1358
19
                return fail(cs.begin(), error::illegal_leading_surrogate,
1359
19
                    &loc);
1360
19
            }
1361
191k
            cs += 5;
1362
            // KRYSTIAN TODO: this can be a two byte load
1363
            // and a single comparison. We lose error information,
1364
            // but it's faster.
1365
191k
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1366
24
            {
1367
24
                BOOST_STATIC_CONSTEXPR source_location loc
1368
24
                    = BOOST_CURRENT_LOCATION;
1369
24
                return fail(cs.begin(), error::syntax, &loc);
1370
24
            }
1371
191k
            ++cs;
1372
191k
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1373
23
            {
1374
23
                BOOST_STATIC_CONSTEXPR source_location loc
1375
23
                    = BOOST_CURRENT_LOCATION;
1376
23
                return fail(cs.begin(), error::syntax, &loc);
1377
23
            }
1378
191k
            ++cs;
1379
191k
            digit = detail::load_little_endian<4>(cs.begin());
1380
191k
            d4 = detail::hex_digit(static_cast<
1381
191k
                unsigned char>(digit >> 24));
1382
191k
            d3 = detail::hex_digit(static_cast<
1383
191k
                unsigned char>(digit >> 16));
1384
191k
            d2 = detail::hex_digit(static_cast<
1385
191k
                unsigned char>(digit >> 8));
1386
191k
            d1 = detail::hex_digit(static_cast<
1387
191k
                unsigned char>(digit));
1388
191k
            if(BOOST_JSON_UNLIKELY(
1389
191k
                (d1 | d2 | d3 | d4) == -1))
1390
109
            {
1391
109
                if(d1 != -1)
1392
45
                    ++cs;
1393
109
                if(d2 != -1)
1394
41
                    ++cs;
1395
109
                if(d3 != -1)
1396
41
                    ++cs;
1397
109
                BOOST_STATIC_CONSTEXPR source_location loc
1398
109
                    = BOOST_CURRENT_LOCATION;
1399
109
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1400
109
            }
1401
191k
            unsigned const u2 =
1402
191k
                (d1 << 12) + (d2 << 8) +
1403
191k
                (d3 << 4) + d4;
1404
            // valid trailing surrogates are [DC00, DFFF]
1405
191k
            if(BOOST_JSON_UNLIKELY(
1406
191k
                u2 < 0xdc00 || u2 > 0xdfff))
1407
43
            {
1408
43
                BOOST_STATIC_CONSTEXPR source_location loc
1409
43
                    = BOOST_CURRENT_LOCATION;
1410
43
                return fail(cs.begin(), error::illegal_trailing_surrogate,
1411
43
                    &loc);
1412
43
            }
1413
191k
            cs += 4;
1414
191k
            unsigned cp =
1415
191k
                ((u1 - 0xd800) << 10) +
1416
191k
                ((u2 - 0xdc00)) +
1417
191k
                    0x10000;
1418
            // utf-16 surrogate pair
1419
191k
            temp.append_utf8(cp);
1420
191k
            break;
1421
191k
        }
1422
        // flush
1423
5.68k
        if(BOOST_JSON_LIKELY(! temp.empty()))
1424
5.10k
        {
1425
5.10k
            BOOST_ASSERT(total <= max_size);
1426
5.10k
            if(BOOST_JSON_UNLIKELY(
1427
5.10k
                temp.size() > max_size - total))
1428
0
            {
1429
0
                BOOST_STATIC_CONSTEXPR source_location loc
1430
0
                    = BOOST_CURRENT_LOCATION;
1431
0
                return fail(cs.begin(), ev_too_large, &loc);
1432
0
            }
1433
5.10k
            total += temp.size();
1434
5.10k
            {
1435
5.10k
                bool r = is_key
1436
5.10k
                    ? h_.on_key_part(temp.get(), total, ec_)
1437
5.10k
                    : h_.on_string_part(temp.get(), total, ec_);
1438
1439
5.10k
                if(BOOST_JSON_UNLIKELY(!r))
1440
0
                {
1441
0
                    return fail(cs.begin());
1442
0
                }
1443
5.10k
            }
1444
5.10k
            temp.clear();
1445
5.10k
            cs.clip(temp.max_size());
1446
5.10k
        }
1447
5.68k
        ++cs;
1448
        // utf-16 escape
1449
5.70k
do_str4:
1450
5.70k
        if(BOOST_JSON_UNLIKELY(! cs))
1451
55
            return maybe_suspend(cs.begin(), state::str4, total);
1452
5.64k
        digit = detail::hex_digit(*cs);
1453
5.64k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1454
41
        {
1455
41
            BOOST_STATIC_CONSTEXPR source_location loc
1456
41
                = BOOST_CURRENT_LOCATION;
1457
41
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1458
41
        }
1459
5.60k
        ++cs;
1460
5.60k
        u1_ = digit << 12;
1461
5.62k
do_str5:
1462
5.62k
        if(BOOST_JSON_UNLIKELY(! cs))
1463
56
            return maybe_suspend(cs.begin(), state::str5, total);
1464
5.56k
        digit = detail::hex_digit(*cs);
1465
5.56k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1466
53
        {
1467
53
            BOOST_STATIC_CONSTEXPR source_location loc
1468
53
                = BOOST_CURRENT_LOCATION;
1469
53
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1470
53
        }
1471
5.51k
        ++cs;
1472
5.51k
        u1_ += digit << 8;
1473
5.52k
do_str6:
1474
5.52k
        if(BOOST_JSON_UNLIKELY(! cs))
1475
54
            return maybe_suspend(cs.begin(), state::str6, total);
1476
5.47k
        digit = detail::hex_digit(*cs);
1477
5.47k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1478
43
        {
1479
43
            BOOST_STATIC_CONSTEXPR source_location loc
1480
43
                = BOOST_CURRENT_LOCATION;
1481
43
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1482
43
        }
1483
5.43k
        ++cs;
1484
5.43k
        u1_ += digit << 4;
1485
5.44k
do_str7:
1486
5.44k
        if(BOOST_JSON_UNLIKELY(! cs))
1487
67
            return maybe_suspend(cs.begin(), state::str7, total);
1488
5.38k
        digit = detail::hex_digit(*cs);
1489
5.38k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1490
18
        {
1491
18
            BOOST_STATIC_CONSTEXPR source_location loc
1492
18
                = BOOST_CURRENT_LOCATION;
1493
18
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1494
18
        }
1495
5.36k
        ++cs;
1496
5.36k
        u1_ += digit;
1497
5.36k
        if(BOOST_JSON_LIKELY(
1498
5.36k
            u1_ < 0xd800 || u1_ > 0xdfff))
1499
3.47k
        {
1500
3.47k
            BOOST_ASSERT(temp.empty());
1501
            // utf-8 codepoint
1502
3.47k
            temp.append_utf8(u1_);
1503
3.47k
            break;
1504
3.47k
        }
1505
1.89k
        if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1506
22
        {
1507
22
            BOOST_STATIC_CONSTEXPR source_location loc
1508
22
                = BOOST_CURRENT_LOCATION;
1509
22
            return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1510
22
        }
1511
1.88k
do_sur1:
1512
1.88k
        if(BOOST_JSON_UNLIKELY(! cs))
1513
40
            return maybe_suspend(cs.begin(), state::sur1, total);
1514
1.84k
        if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1515
18
        {
1516
18
            BOOST_STATIC_CONSTEXPR source_location loc
1517
18
                = BOOST_CURRENT_LOCATION;
1518
18
            return fail(cs.begin(), error::syntax, &loc);
1519
18
        }
1520
1.82k
        ++cs;
1521
1.82k
do_sur2:
1522
1.82k
        if(BOOST_JSON_UNLIKELY(! cs))
1523
6
            return maybe_suspend(cs.begin(), state::sur2, total);
1524
1.82k
        if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1525
2
        {
1526
2
            BOOST_STATIC_CONSTEXPR source_location loc
1527
2
                = BOOST_CURRENT_LOCATION;
1528
2
            return fail(cs.begin(), error::syntax, &loc);
1529
2
        }
1530
1.81k
        ++cs;
1531
1.82k
do_sur3:
1532
1.82k
        if(BOOST_JSON_UNLIKELY(! cs))
1533
7
            return maybe_suspend(cs.begin(), state::sur3, total);
1534
1.81k
        digit = detail::hex_digit(*cs);
1535
1.81k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1536
27
        {
1537
27
            BOOST_STATIC_CONSTEXPR source_location loc
1538
27
                = BOOST_CURRENT_LOCATION;
1539
27
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1540
27
        }
1541
1.78k
        ++cs;
1542
1.78k
        u2_ = digit << 12;
1543
1.79k
do_sur4:
1544
1.79k
        if(BOOST_JSON_UNLIKELY(! cs))
1545
31
            return maybe_suspend(cs.begin(), state::sur4, total);
1546
1.76k
        digit = detail::hex_digit(*cs);
1547
1.76k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1548
24
        {
1549
24
            BOOST_STATIC_CONSTEXPR source_location loc
1550
24
                = BOOST_CURRENT_LOCATION;
1551
24
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1552
24
        }
1553
1.74k
        ++cs;
1554
1.74k
        u2_ += digit << 8;
1555
1.75k
do_sur5:
1556
1.75k
        if(BOOST_JSON_UNLIKELY(! cs))
1557
22
            return maybe_suspend(cs.begin(), state::sur5, total);
1558
1.72k
        digit = detail::hex_digit(*cs);
1559
1.72k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1560
23
        {
1561
23
            BOOST_STATIC_CONSTEXPR source_location loc
1562
23
                = BOOST_CURRENT_LOCATION;
1563
23
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1564
23
        }
1565
1.70k
        ++cs;
1566
1.70k
        u2_ += digit << 4;
1567
1.72k
do_sur6:
1568
1.72k
        if(BOOST_JSON_UNLIKELY(! cs))
1569
51
            return maybe_suspend(cs.begin(), state::sur6, total);
1570
1.67k
        digit = detail::hex_digit(*cs);
1571
1.67k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1572
17
        {
1573
17
            BOOST_STATIC_CONSTEXPR source_location loc
1574
17
                = BOOST_CURRENT_LOCATION;
1575
17
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1576
17
        }
1577
1.65k
        ++cs;
1578
1.65k
        u2_ += digit;
1579
1.65k
        if(BOOST_JSON_UNLIKELY(
1580
1.65k
            u2_ < 0xdc00 || u2_ > 0xdfff))
1581
50
        {
1582
50
            BOOST_STATIC_CONSTEXPR source_location loc
1583
50
                = BOOST_CURRENT_LOCATION;
1584
50
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1585
50
        }
1586
1.60k
        unsigned cp =
1587
1.60k
            ((u1_ - 0xd800) << 10) +
1588
1.60k
            ((u2_ - 0xdc00)) +
1589
1.60k
                0x10000;
1590
1.60k
        BOOST_ASSERT(temp.empty());
1591
        // utf-16 surrogate pair
1592
1.60k
        temp.append_utf8(cp);
1593
5.36M
    }
1594
5.36M
do_str2:
1595
    // KRYSTIAN TODO: we can append the characters
1596
    // all at once instead of one at a time
1597
5.36M
    for(;;)
1598
47.4M
    {
1599
47.4M
        if(BOOST_JSON_UNLIKELY(! cs || temp.capacity() == 0 ))
1600
8.82k
        {
1601
            // flush
1602
8.82k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1603
8.53k
            {
1604
8.53k
                BOOST_ASSERT(total <= max_size);
1605
8.53k
                if(BOOST_JSON_UNLIKELY(
1606
8.53k
                    temp.size() > max_size - total))
1607
0
                {
1608
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1609
0
                        = BOOST_CURRENT_LOCATION;
1610
0
                    return fail(cs.begin(), ev_too_large, &loc);
1611
0
                }
1612
8.53k
                total += temp.size();
1613
8.53k
                {
1614
8.53k
                    bool r = is_key
1615
8.53k
                        ? h_.on_key_part(temp.get(), total, ec_)
1616
8.53k
                        : h_.on_string_part(temp.get(), total, ec_);
1617
1618
8.53k
                    if(BOOST_JSON_UNLIKELY(!r))
1619
0
                    {
1620
0
                        return fail(cs.begin());
1621
0
                    }
1622
8.53k
                }
1623
8.53k
                temp.clear();
1624
8.53k
            }
1625
8.82k
            cs.clip(temp.max_size());
1626
8.82k
            if(BOOST_JSON_UNLIKELY(! cs))
1627
915
                return maybe_suspend(cs.begin(), state::str2, total);
1628
8.82k
        }
1629
47.4M
        c = *cs;
1630
47.4M
        if(BOOST_JSON_LIKELY(c == '\x22')) // '"'
1631
44.1k
        {
1632
44.1k
            BOOST_ASSERT(total <= max_size);
1633
44.1k
            if(BOOST_JSON_UNLIKELY(
1634
44.1k
                temp.size() > max_size - total))
1635
0
            {
1636
0
                BOOST_STATIC_CONSTEXPR source_location loc
1637
0
                    = BOOST_CURRENT_LOCATION;
1638
0
                return fail(cs.begin(), ev_too_large, &loc);
1639
0
            }
1640
44.1k
            total += temp.size();
1641
44.1k
            {
1642
44.1k
                bool r = is_key
1643
44.1k
                    ? h_.on_key(temp.get(), total, ec_)
1644
44.1k
                    : h_.on_string(temp.get(), total, ec_);
1645
1646
44.1k
                if(BOOST_JSON_UNLIKELY(!r))
1647
0
                {
1648
0
                    return fail(cs.begin());
1649
0
                }
1650
44.1k
            }
1651
44.1k
            ++cs;
1652
44.1k
            return cs.begin();
1653
44.1k
        }
1654
47.3M
        else if((c & 0x80) && !allow_bad_utf8)
1655
390k
        {
1656
390k
            seq_.save(cs.begin(), cs.remain());
1657
390k
            if(BOOST_JSON_UNLIKELY(! seq_.complete()))
1658
990
            {
1659
990
                if(BOOST_JSON_LIKELY(! temp.empty()))
1660
982
                {
1661
982
                    BOOST_ASSERT(total <= max_size);
1662
982
                    if(BOOST_JSON_UNLIKELY(
1663
982
                        temp.size() > max_size - total))
1664
0
                    {
1665
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1666
0
                            = BOOST_CURRENT_LOCATION;
1667
0
                        return fail(cs.begin(), ev_too_large, &loc);
1668
0
                    }
1669
982
                    total += temp.size();
1670
982
                    {
1671
982
                        bool r = is_key
1672
982
                            ? h_.on_key_part(temp.get(), total, ec_)
1673
982
                            : h_.on_string_part(temp.get(), total, ec_);
1674
1675
982
                        if(BOOST_JSON_UNLIKELY(!r))
1676
0
                        {
1677
0
                            return fail(cs.begin());
1678
0
                        }
1679
982
                    }
1680
982
                    temp.clear();
1681
982
                }
1682
990
                cs = cs.end();
1683
                // ensure there is room for the saved byte sequence
1684
990
                cs.clip(temp.max_size() - seq_.length());
1685
990
                goto do_str8;
1686
990
            }
1687
389k
            if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1688
305
            {
1689
305
                BOOST_STATIC_CONSTEXPR source_location loc
1690
305
                    = BOOST_CURRENT_LOCATION;
1691
305
                return fail(cs.begin(), error::syntax, &loc);
1692
305
            }
1693
389k
            temp.append(seq_.data(), seq_.length());
1694
389k
            cs += seq_.length();
1695
389k
            continue;
1696
389k
        }
1697
46.9M
        else if(BOOST_JSON_LIKELY(c == '\\'))
1698
5.31M
        {
1699
5.31M
            ++cs;
1700
5.31M
            goto do_str3;
1701
5.31M
        }
1702
41.6M
        else if(BOOST_JSON_UNLIKELY(
1703
41.6M
            detail::is_control(c)))
1704
91
        {
1705
91
            BOOST_STATIC_CONSTEXPR source_location loc
1706
91
                = BOOST_CURRENT_LOCATION;
1707
91
            return fail(cs.begin(), error::syntax, &loc);
1708
91
        }
1709
41.6M
        temp.push_back(c);
1710
41.6M
        ++cs;
1711
41.6M
    }
1712
1.06k
do_str8:
1713
1.06k
    uint8_t needed = seq_.needed();
1714
1.06k
    if(BOOST_JSON_UNLIKELY(
1715
1.06k
        ! seq_.append(cs.begin(), cs.remain())))
1716
159
        return maybe_suspend(cs.end(), state::str8, total);
1717
910
    if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1718
11
    {
1719
11
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1720
11
        return fail(cs.begin(), error::syntax, &loc);
1721
11
    }
1722
899
    temp.append(seq_.data(), seq_.length());
1723
899
    cs += needed;
1724
899
    goto do_str2;
1725
910
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_escaped<true>(char const*, unsigned long, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1184
46.5k
{
1185
    //---------------------------------------------------------------
1186
    //
1187
    // To handle escapes, a local temporary buffer accumulates
1188
    // the unescaped result. The algorithm attempts to fill the
1189
    // buffer to capacity before invoking the handler.
1190
    // In some cases the temporary buffer needs to be flushed
1191
    // before it is full:
1192
    // * When the closing double quote is seen
1193
    // * When there in no more input (and more is expected later)
1194
    // A goal of the algorithm is to call the handler as few times
1195
    // as possible. Thus, when the first escape is encountered,
1196
    // the algorithm attempts to fill the temporary buffer first.
1197
    //
1198
46.5k
    auto const ev_too_large = is_key?
1199
41.2k
        error::key_too_large : error::string_too_large;
1200
46.5k
    auto const max_size = is_key?
1201
41.2k
        Handler::max_key_size : Handler::max_string_size;
1202
46.5k
    detail::clipped_const_stream cs(p, end_);
1203
46.5k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1204
46.5k
    int digit;
1205
46.5k
    char c;
1206
46.5k
    cs.clip(temp.max_size());
1207
46.5k
    if(! stack_empty && ! st_.empty())
1208
0
    {
1209
0
        state st;
1210
0
        st_.pop(st);
1211
0
        st_.pop(total);
1212
0
        switch(st)
1213
0
        {
1214
0
        default: BOOST_JSON_UNREACHABLE();
1215
0
        case state::str2: goto do_str2;
1216
0
        case state::str3: goto do_str3;
1217
0
        case state::str4: goto do_str4;
1218
0
        case state::str5: goto do_str5;
1219
0
        case state::str6: goto do_str6;
1220
0
        case state::str7: goto do_str7;
1221
0
        case state::str8: goto do_str8;
1222
0
        case state::sur1: goto do_sur1;
1223
0
        case state::sur2: goto do_sur2;
1224
0
        case state::sur3: goto do_sur3;
1225
0
        case state::sur4: goto do_sur4;
1226
0
        case state::sur5: goto do_sur5;
1227
0
        case state::sur6: goto do_sur6;
1228
0
        }
1229
0
    }
1230
    // Unescaped JSON is never larger than its escaped version.
1231
    // To efficiently process only what will fit in the temporary buffer,
1232
    // the size of the input stream is temporarily "clipped" to the size
1233
    // of the temporary buffer.
1234
    // handle escaped character
1235
46.5k
    BOOST_ASSERT(*cs == '\\');
1236
46.5k
    ++cs;
1237
5.36M
do_str3:
1238
5.36M
    if(BOOST_JSON_UNLIKELY(! cs))
1239
1.51k
    {
1240
1.51k
        if(BOOST_JSON_LIKELY(! temp.empty()))
1241
1.42k
        {
1242
1.42k
            BOOST_ASSERT(total <= max_size);
1243
1.42k
            if(BOOST_JSON_UNLIKELY(
1244
1.42k
                temp.size() > max_size - total))
1245
0
            {
1246
0
                BOOST_STATIC_CONSTEXPR source_location loc
1247
0
                    = BOOST_CURRENT_LOCATION;
1248
0
                return fail(cs.begin(), ev_too_large, &loc);
1249
0
            }
1250
1.42k
            total += temp.size();
1251
1.42k
            {
1252
1.42k
                bool r = is_key
1253
1.42k
                    ? h_.on_key_part(temp.get(), total, ec_)
1254
1.42k
                    : h_.on_string_part(temp.get(), total, ec_);
1255
1256
1.42k
                if(BOOST_JSON_UNLIKELY(!r))
1257
0
                {
1258
0
                    return fail(cs.begin());
1259
0
                }
1260
1.42k
            }
1261
1.42k
            temp.clear();
1262
1.42k
        }
1263
1.51k
        cs.clip(temp.max_size());
1264
1.51k
        if(BOOST_JSON_UNLIKELY(! cs))
1265
223
            return maybe_suspend(cs.begin(), state::str3, total);
1266
1.51k
    }
1267
5.36M
    switch(*cs)
1268
5.36M
    {
1269
60
    default:
1270
60
        {
1271
60
            BOOST_STATIC_CONSTEXPR source_location loc
1272
60
                = BOOST_CURRENT_LOCATION;
1273
60
            return fail(cs.begin(), error::syntax, &loc);
1274
0
        }
1275
19.7k
    case '\x22': // '"'
1276
19.7k
        temp.push_back('\x22');
1277
19.7k
        ++cs;
1278
19.7k
        break;
1279
3.27M
    case '\\':
1280
3.27M
        temp.push_back('\\');
1281
3.27M
        ++cs;
1282
3.27M
        break;
1283
3.23k
    case '/':
1284
3.23k
        temp.push_back('/');
1285
3.23k
        ++cs;
1286
3.23k
        break;
1287
8.45k
    case 'b':
1288
8.45k
        temp.push_back('\x08');
1289
8.45k
        ++cs;
1290
8.45k
        break;
1291
48.0k
    case 'f':
1292
48.0k
        temp.push_back('\x0c');
1293
48.0k
        ++cs;
1294
48.0k
        break;
1295
17.1k
    case 'n':
1296
17.1k
        temp.push_back('\x0a');
1297
17.1k
        ++cs;
1298
17.1k
        break;
1299
2.11k
    case 'r':
1300
2.11k
        temp.push_back('\x0d');
1301
2.11k
        ++cs;
1302
2.11k
        break;
1303
1.28k
    case 't':
1304
1.28k
        temp.push_back('\x09');
1305
1.28k
        ++cs;
1306
1.28k
        break;
1307
1.99M
    case 'u':
1308
        // utf16 escape
1309
        //
1310
        // fast path only when the buffer
1311
        // is large enough for 2 surrogates
1312
1.99M
        if(BOOST_JSON_LIKELY(cs.remain() > 10))
1313
1.98M
        {
1314
            // KRYSTIAN TODO: this could be done
1315
            // with fewer instructions
1316
1.98M
            digit = detail::load_little_endian<4>(
1317
1.98M
                cs.begin() + 1);
1318
1.98M
            int d4 = detail::hex_digit(static_cast<
1319
1.98M
                unsigned char>(digit >> 24));
1320
1.98M
            int d3 = detail::hex_digit(static_cast<
1321
1.98M
                unsigned char>(digit >> 16));
1322
1.98M
            int d2 = detail::hex_digit(static_cast<
1323
1.98M
                unsigned char>(digit >> 8));
1324
1.98M
            int d1 = detail::hex_digit(static_cast<
1325
1.98M
                unsigned char>(digit));
1326
1.98M
            if(BOOST_JSON_UNLIKELY(
1327
1.98M
                (d1 | d2 | d3 | d4) == -1))
1328
127
            {
1329
127
                if(d1 != -1)
1330
78
                    ++cs;
1331
127
                if(d2 != -1)
1332
55
                    ++cs;
1333
127
                if(d3 != -1)
1334
44
                    ++cs;
1335
127
                BOOST_STATIC_CONSTEXPR source_location loc
1336
127
                    = BOOST_CURRENT_LOCATION;
1337
127
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1338
127
            }
1339
            // 32 bit unicode scalar value
1340
1.98M
            unsigned const u1 =
1341
1.98M
                (d1 << 12) + (d2 << 8) +
1342
1.98M
                (d3 << 4) + d4;
1343
            // valid unicode scalar values are
1344
            // [0, D7FF] and [E000, 10FFFF]
1345
            // values within this range are valid utf-8
1346
            // code points and invalid leading surrogates.
1347
1.98M
            if(BOOST_JSON_LIKELY(
1348
1.98M
                u1 < 0xd800 || u1 > 0xdfff))
1349
1.79M
            {
1350
1.79M
                cs += 5;
1351
1.79M
                temp.append_utf8(u1);
1352
1.79M
                break;
1353
1.79M
            }
1354
191k
            if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1355
19
            {
1356
19
                BOOST_STATIC_CONSTEXPR source_location loc
1357
19
                    = BOOST_CURRENT_LOCATION;
1358
19
                return fail(cs.begin(), error::illegal_leading_surrogate,
1359
19
                    &loc);
1360
19
            }
1361
191k
            cs += 5;
1362
            // KRYSTIAN TODO: this can be a two byte load
1363
            // and a single comparison. We lose error information,
1364
            // but it's faster.
1365
191k
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1366
24
            {
1367
24
                BOOST_STATIC_CONSTEXPR source_location loc
1368
24
                    = BOOST_CURRENT_LOCATION;
1369
24
                return fail(cs.begin(), error::syntax, &loc);
1370
24
            }
1371
191k
            ++cs;
1372
191k
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1373
23
            {
1374
23
                BOOST_STATIC_CONSTEXPR source_location loc
1375
23
                    = BOOST_CURRENT_LOCATION;
1376
23
                return fail(cs.begin(), error::syntax, &loc);
1377
23
            }
1378
191k
            ++cs;
1379
191k
            digit = detail::load_little_endian<4>(cs.begin());
1380
191k
            d4 = detail::hex_digit(static_cast<
1381
191k
                unsigned char>(digit >> 24));
1382
191k
            d3 = detail::hex_digit(static_cast<
1383
191k
                unsigned char>(digit >> 16));
1384
191k
            d2 = detail::hex_digit(static_cast<
1385
191k
                unsigned char>(digit >> 8));
1386
191k
            d1 = detail::hex_digit(static_cast<
1387
191k
                unsigned char>(digit));
1388
191k
            if(BOOST_JSON_UNLIKELY(
1389
191k
                (d1 | d2 | d3 | d4) == -1))
1390
109
            {
1391
109
                if(d1 != -1)
1392
45
                    ++cs;
1393
109
                if(d2 != -1)
1394
41
                    ++cs;
1395
109
                if(d3 != -1)
1396
41
                    ++cs;
1397
109
                BOOST_STATIC_CONSTEXPR source_location loc
1398
109
                    = BOOST_CURRENT_LOCATION;
1399
109
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1400
109
            }
1401
191k
            unsigned const u2 =
1402
191k
                (d1 << 12) + (d2 << 8) +
1403
191k
                (d3 << 4) + d4;
1404
            // valid trailing surrogates are [DC00, DFFF]
1405
191k
            if(BOOST_JSON_UNLIKELY(
1406
191k
                u2 < 0xdc00 || u2 > 0xdfff))
1407
43
            {
1408
43
                BOOST_STATIC_CONSTEXPR source_location loc
1409
43
                    = BOOST_CURRENT_LOCATION;
1410
43
                return fail(cs.begin(), error::illegal_trailing_surrogate,
1411
43
                    &loc);
1412
43
            }
1413
191k
            cs += 4;
1414
191k
            unsigned cp =
1415
191k
                ((u1 - 0xd800) << 10) +
1416
191k
                ((u2 - 0xdc00)) +
1417
191k
                    0x10000;
1418
            // utf-16 surrogate pair
1419
191k
            temp.append_utf8(cp);
1420
191k
            break;
1421
191k
        }
1422
        // flush
1423
5.68k
        if(BOOST_JSON_LIKELY(! temp.empty()))
1424
5.10k
        {
1425
5.10k
            BOOST_ASSERT(total <= max_size);
1426
5.10k
            if(BOOST_JSON_UNLIKELY(
1427
5.10k
                temp.size() > max_size - total))
1428
0
            {
1429
0
                BOOST_STATIC_CONSTEXPR source_location loc
1430
0
                    = BOOST_CURRENT_LOCATION;
1431
0
                return fail(cs.begin(), ev_too_large, &loc);
1432
0
            }
1433
5.10k
            total += temp.size();
1434
5.10k
            {
1435
5.10k
                bool r = is_key
1436
5.10k
                    ? h_.on_key_part(temp.get(), total, ec_)
1437
5.10k
                    : h_.on_string_part(temp.get(), total, ec_);
1438
1439
5.10k
                if(BOOST_JSON_UNLIKELY(!r))
1440
0
                {
1441
0
                    return fail(cs.begin());
1442
0
                }
1443
5.10k
            }
1444
5.10k
            temp.clear();
1445
5.10k
            cs.clip(temp.max_size());
1446
5.10k
        }
1447
5.68k
        ++cs;
1448
        // utf-16 escape
1449
5.68k
do_str4:
1450
5.68k
        if(BOOST_JSON_UNLIKELY(! cs))
1451
37
            return maybe_suspend(cs.begin(), state::str4, total);
1452
5.64k
        digit = detail::hex_digit(*cs);
1453
5.64k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1454
41
        {
1455
41
            BOOST_STATIC_CONSTEXPR source_location loc
1456
41
                = BOOST_CURRENT_LOCATION;
1457
41
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1458
41
        }
1459
5.60k
        ++cs;
1460
5.60k
        u1_ = digit << 12;
1461
5.60k
do_str5:
1462
5.60k
        if(BOOST_JSON_UNLIKELY(! cs))
1463
40
            return maybe_suspend(cs.begin(), state::str5, total);
1464
5.56k
        digit = detail::hex_digit(*cs);
1465
5.56k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1466
53
        {
1467
53
            BOOST_STATIC_CONSTEXPR source_location loc
1468
53
                = BOOST_CURRENT_LOCATION;
1469
53
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1470
53
        }
1471
5.51k
        ++cs;
1472
5.51k
        u1_ += digit << 8;
1473
5.51k
do_str6:
1474
5.51k
        if(BOOST_JSON_UNLIKELY(! cs))
1475
39
            return maybe_suspend(cs.begin(), state::str6, total);
1476
5.47k
        digit = detail::hex_digit(*cs);
1477
5.47k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1478
43
        {
1479
43
            BOOST_STATIC_CONSTEXPR source_location loc
1480
43
                = BOOST_CURRENT_LOCATION;
1481
43
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1482
43
        }
1483
5.43k
        ++cs;
1484
5.43k
        u1_ += digit << 4;
1485
5.43k
do_str7:
1486
5.43k
        if(BOOST_JSON_UNLIKELY(! cs))
1487
48
            return maybe_suspend(cs.begin(), state::str7, total);
1488
5.38k
        digit = detail::hex_digit(*cs);
1489
5.38k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1490
18
        {
1491
18
            BOOST_STATIC_CONSTEXPR source_location loc
1492
18
                = BOOST_CURRENT_LOCATION;
1493
18
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1494
18
        }
1495
5.36k
        ++cs;
1496
5.36k
        u1_ += digit;
1497
5.36k
        if(BOOST_JSON_LIKELY(
1498
5.36k
            u1_ < 0xd800 || u1_ > 0xdfff))
1499
3.47k
        {
1500
3.47k
            BOOST_ASSERT(temp.empty());
1501
            // utf-8 codepoint
1502
3.47k
            temp.append_utf8(u1_);
1503
3.47k
            break;
1504
3.47k
        }
1505
1.89k
        if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1506
22
        {
1507
22
            BOOST_STATIC_CONSTEXPR source_location loc
1508
22
                = BOOST_CURRENT_LOCATION;
1509
22
            return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1510
22
        }
1511
1.87k
do_sur1:
1512
1.87k
        if(BOOST_JSON_UNLIKELY(! cs))
1513
28
            return maybe_suspend(cs.begin(), state::sur1, total);
1514
1.84k
        if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1515
18
        {
1516
18
            BOOST_STATIC_CONSTEXPR source_location loc
1517
18
                = BOOST_CURRENT_LOCATION;
1518
18
            return fail(cs.begin(), error::syntax, &loc);
1519
18
        }
1520
1.82k
        ++cs;
1521
1.82k
do_sur2:
1522
1.82k
        if(BOOST_JSON_UNLIKELY(! cs))
1523
4
            return maybe_suspend(cs.begin(), state::sur2, total);
1524
1.82k
        if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1525
2
        {
1526
2
            BOOST_STATIC_CONSTEXPR source_location loc
1527
2
                = BOOST_CURRENT_LOCATION;
1528
2
            return fail(cs.begin(), error::syntax, &loc);
1529
2
        }
1530
1.81k
        ++cs;
1531
1.81k
do_sur3:
1532
1.81k
        if(BOOST_JSON_UNLIKELY(! cs))
1533
4
            return maybe_suspend(cs.begin(), state::sur3, total);
1534
1.81k
        digit = detail::hex_digit(*cs);
1535
1.81k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1536
27
        {
1537
27
            BOOST_STATIC_CONSTEXPR source_location loc
1538
27
                = BOOST_CURRENT_LOCATION;
1539
27
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1540
27
        }
1541
1.78k
        ++cs;
1542
1.78k
        u2_ = digit << 12;
1543
1.78k
do_sur4:
1544
1.78k
        if(BOOST_JSON_UNLIKELY(! cs))
1545
20
            return maybe_suspend(cs.begin(), state::sur4, total);
1546
1.76k
        digit = detail::hex_digit(*cs);
1547
1.76k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1548
24
        {
1549
24
            BOOST_STATIC_CONSTEXPR source_location loc
1550
24
                = BOOST_CURRENT_LOCATION;
1551
24
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1552
24
        }
1553
1.74k
        ++cs;
1554
1.74k
        u2_ += digit << 8;
1555
1.74k
do_sur5:
1556
1.74k
        if(BOOST_JSON_UNLIKELY(! cs))
1557
15
            return maybe_suspend(cs.begin(), state::sur5, total);
1558
1.72k
        digit = detail::hex_digit(*cs);
1559
1.72k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1560
23
        {
1561
23
            BOOST_STATIC_CONSTEXPR source_location loc
1562
23
                = BOOST_CURRENT_LOCATION;
1563
23
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1564
23
        }
1565
1.70k
        ++cs;
1566
1.70k
        u2_ += digit << 4;
1567
1.70k
do_sur6:
1568
1.70k
        if(BOOST_JSON_UNLIKELY(! cs))
1569
35
            return maybe_suspend(cs.begin(), state::sur6, total);
1570
1.67k
        digit = detail::hex_digit(*cs);
1571
1.67k
        if(BOOST_JSON_UNLIKELY(digit == -1))
1572
17
        {
1573
17
            BOOST_STATIC_CONSTEXPR source_location loc
1574
17
                = BOOST_CURRENT_LOCATION;
1575
17
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1576
17
        }
1577
1.65k
        ++cs;
1578
1.65k
        u2_ += digit;
1579
1.65k
        if(BOOST_JSON_UNLIKELY(
1580
1.65k
            u2_ < 0xdc00 || u2_ > 0xdfff))
1581
50
        {
1582
50
            BOOST_STATIC_CONSTEXPR source_location loc
1583
50
                = BOOST_CURRENT_LOCATION;
1584
50
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1585
50
        }
1586
1.60k
        unsigned cp =
1587
1.60k
            ((u1_ - 0xd800) << 10) +
1588
1.60k
            ((u2_ - 0xdc00)) +
1589
1.60k
                0x10000;
1590
1.60k
        BOOST_ASSERT(temp.empty());
1591
        // utf-16 surrogate pair
1592
1.60k
        temp.append_utf8(cp);
1593
5.36M
    }
1594
5.36M
do_str2:
1595
    // KRYSTIAN TODO: we can append the characters
1596
    // all at once instead of one at a time
1597
5.36M
    for(;;)
1598
47.4M
    {
1599
47.4M
        if(BOOST_JSON_UNLIKELY(! cs || temp.capacity() == 0 ))
1600
8.53k
        {
1601
            // flush
1602
8.53k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1603
8.53k
            {
1604
8.53k
                BOOST_ASSERT(total <= max_size);
1605
8.53k
                if(BOOST_JSON_UNLIKELY(
1606
8.53k
                    temp.size() > max_size - total))
1607
0
                {
1608
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1609
0
                        = BOOST_CURRENT_LOCATION;
1610
0
                    return fail(cs.begin(), ev_too_large, &loc);
1611
0
                }
1612
8.53k
                total += temp.size();
1613
8.53k
                {
1614
8.53k
                    bool r = is_key
1615
8.53k
                        ? h_.on_key_part(temp.get(), total, ec_)
1616
8.53k
                        : h_.on_string_part(temp.get(), total, ec_);
1617
1618
8.53k
                    if(BOOST_JSON_UNLIKELY(!r))
1619
0
                    {
1620
0
                        return fail(cs.begin());
1621
0
                    }
1622
8.53k
                }
1623
8.53k
                temp.clear();
1624
8.53k
            }
1625
8.53k
            cs.clip(temp.max_size());
1626
8.53k
            if(BOOST_JSON_UNLIKELY(! cs))
1627
623
                return maybe_suspend(cs.begin(), state::str2, total);
1628
8.53k
        }
1629
47.4M
        c = *cs;
1630
47.4M
        if(BOOST_JSON_LIKELY(c == '\x22')) // '"'
1631
44.1k
        {
1632
44.1k
            BOOST_ASSERT(total <= max_size);
1633
44.1k
            if(BOOST_JSON_UNLIKELY(
1634
44.1k
                temp.size() > max_size - total))
1635
0
            {
1636
0
                BOOST_STATIC_CONSTEXPR source_location loc
1637
0
                    = BOOST_CURRENT_LOCATION;
1638
0
                return fail(cs.begin(), ev_too_large, &loc);
1639
0
            }
1640
44.1k
            total += temp.size();
1641
44.1k
            {
1642
44.1k
                bool r = is_key
1643
44.1k
                    ? h_.on_key(temp.get(), total, ec_)
1644
44.1k
                    : h_.on_string(temp.get(), total, ec_);
1645
1646
44.1k
                if(BOOST_JSON_UNLIKELY(!r))
1647
0
                {
1648
0
                    return fail(cs.begin());
1649
0
                }
1650
44.1k
            }
1651
44.1k
            ++cs;
1652
44.1k
            return cs.begin();
1653
44.1k
        }
1654
47.3M
        else if((c & 0x80) && !allow_bad_utf8)
1655
390k
        {
1656
390k
            seq_.save(cs.begin(), cs.remain());
1657
390k
            if(BOOST_JSON_UNLIKELY(! seq_.complete()))
1658
990
            {
1659
990
                if(BOOST_JSON_LIKELY(! temp.empty()))
1660
982
                {
1661
982
                    BOOST_ASSERT(total <= max_size);
1662
982
                    if(BOOST_JSON_UNLIKELY(
1663
982
                        temp.size() > max_size - total))
1664
0
                    {
1665
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1666
0
                            = BOOST_CURRENT_LOCATION;
1667
0
                        return fail(cs.begin(), ev_too_large, &loc);
1668
0
                    }
1669
982
                    total += temp.size();
1670
982
                    {
1671
982
                        bool r = is_key
1672
982
                            ? h_.on_key_part(temp.get(), total, ec_)
1673
982
                            : h_.on_string_part(temp.get(), total, ec_);
1674
1675
982
                        if(BOOST_JSON_UNLIKELY(!r))
1676
0
                        {
1677
0
                            return fail(cs.begin());
1678
0
                        }
1679
982
                    }
1680
982
                    temp.clear();
1681
982
                }
1682
990
                cs = cs.end();
1683
                // ensure there is room for the saved byte sequence
1684
990
                cs.clip(temp.max_size() - seq_.length());
1685
990
                goto do_str8;
1686
990
            }
1687
389k
            if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1688
305
            {
1689
305
                BOOST_STATIC_CONSTEXPR source_location loc
1690
305
                    = BOOST_CURRENT_LOCATION;
1691
305
                return fail(cs.begin(), error::syntax, &loc);
1692
305
            }
1693
389k
            temp.append(seq_.data(), seq_.length());
1694
389k
            cs += seq_.length();
1695
389k
            continue;
1696
389k
        }
1697
46.9M
        else if(BOOST_JSON_LIKELY(c == '\\'))
1698
5.31M
        {
1699
5.31M
            ++cs;
1700
5.31M
            goto do_str3;
1701
5.31M
        }
1702
41.6M
        else if(BOOST_JSON_UNLIKELY(
1703
41.6M
            detail::is_control(c)))
1704
91
        {
1705
91
            BOOST_STATIC_CONSTEXPR source_location loc
1706
91
                = BOOST_CURRENT_LOCATION;
1707
91
            return fail(cs.begin(), error::syntax, &loc);
1708
91
        }
1709
41.6M
        temp.push_back(c);
1710
41.6M
        ++cs;
1711
41.6M
    }
1712
990
do_str8:
1713
990
    uint8_t needed = seq_.needed();
1714
990
    if(BOOST_JSON_UNLIKELY(
1715
990
        ! seq_.append(cs.begin(), cs.remain())))
1716
80
        return maybe_suspend(cs.end(), state::str8, total);
1717
910
    if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1718
11
    {
1719
11
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1720
11
        return fail(cs.begin(), error::syntax, &loc);
1721
11
    }
1722
899
    temp.append(seq_.data(), seq_.length());
1723
899
    cs += needed;
1724
899
    goto do_str2;
1725
910
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_escaped<false>(char const*, unsigned long, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
1184
605
{
1185
    //---------------------------------------------------------------
1186
    //
1187
    // To handle escapes, a local temporary buffer accumulates
1188
    // the unescaped result. The algorithm attempts to fill the
1189
    // buffer to capacity before invoking the handler.
1190
    // In some cases the temporary buffer needs to be flushed
1191
    // before it is full:
1192
    // * When the closing double quote is seen
1193
    // * When there in no more input (and more is expected later)
1194
    // A goal of the algorithm is to call the handler as few times
1195
    // as possible. Thus, when the first escape is encountered,
1196
    // the algorithm attempts to fill the temporary buffer first.
1197
    //
1198
605
    auto const ev_too_large = is_key?
1199
521
        error::key_too_large : error::string_too_large;
1200
605
    auto const max_size = is_key?
1201
521
        Handler::max_key_size : Handler::max_string_size;
1202
605
    detail::clipped_const_stream cs(p, end_);
1203
605
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1204
605
    int digit;
1205
605
    char c;
1206
605
    cs.clip(temp.max_size());
1207
605
    if(! stack_empty && ! st_.empty())
1208
605
    {
1209
605
        state st;
1210
605
        st_.pop(st);
1211
605
        st_.pop(total);
1212
605
        switch(st)
1213
605
        {
1214
0
        default: BOOST_JSON_UNREACHABLE();
1215
292
        case state::str2: goto do_str2;
1216
115
        case state::str3: goto do_str3;
1217
18
        case state::str4: goto do_str4;
1218
16
        case state::str5: goto do_str5;
1219
15
        case state::str6: goto do_str6;
1220
19
        case state::str7: goto do_str7;
1221
79
        case state::str8: goto do_str8;
1222
12
        case state::sur1: goto do_sur1;
1223
2
        case state::sur2: goto do_sur2;
1224
3
        case state::sur3: goto do_sur3;
1225
11
        case state::sur4: goto do_sur4;
1226
7
        case state::sur5: goto do_sur5;
1227
16
        case state::sur6: goto do_sur6;
1228
605
        }
1229
605
    }
1230
    // Unescaped JSON is never larger than its escaped version.
1231
    // To efficiently process only what will fit in the temporary buffer,
1232
    // the size of the input stream is temporarily "clipped" to the size
1233
    // of the temporary buffer.
1234
    // handle escaped character
1235
0
    BOOST_ASSERT(*cs == '\\');
1236
0
    ++cs;
1237
115
do_str3:
1238
115
    if(BOOST_JSON_UNLIKELY(! cs))
1239
115
    {
1240
115
        if(BOOST_JSON_LIKELY(! temp.empty()))
1241
0
        {
1242
0
            BOOST_ASSERT(total <= max_size);
1243
0
            if(BOOST_JSON_UNLIKELY(
1244
0
                temp.size() > max_size - total))
1245
0
            {
1246
0
                BOOST_STATIC_CONSTEXPR source_location loc
1247
0
                    = BOOST_CURRENT_LOCATION;
1248
0
                return fail(cs.begin(), ev_too_large, &loc);
1249
0
            }
1250
0
            total += temp.size();
1251
0
            {
1252
0
                bool r = is_key
1253
0
                    ? h_.on_key_part(temp.get(), total, ec_)
1254
0
                    : h_.on_string_part(temp.get(), total, ec_);
1255
1256
0
                if(BOOST_JSON_UNLIKELY(!r))
1257
0
                {
1258
0
                    return fail(cs.begin());
1259
0
                }
1260
0
            }
1261
0
            temp.clear();
1262
0
        }
1263
115
        cs.clip(temp.max_size());
1264
115
        if(BOOST_JSON_UNLIKELY(! cs))
1265
115
            return maybe_suspend(cs.begin(), state::str3, total);
1266
115
    }
1267
0
    switch(*cs)
1268
0
    {
1269
0
    default:
1270
0
        {
1271
0
            BOOST_STATIC_CONSTEXPR source_location loc
1272
0
                = BOOST_CURRENT_LOCATION;
1273
0
            return fail(cs.begin(), error::syntax, &loc);
1274
0
        }
1275
0
    case '\x22': // '"'
1276
0
        temp.push_back('\x22');
1277
0
        ++cs;
1278
0
        break;
1279
0
    case '\\':
1280
0
        temp.push_back('\\');
1281
0
        ++cs;
1282
0
        break;
1283
0
    case '/':
1284
0
        temp.push_back('/');
1285
0
        ++cs;
1286
0
        break;
1287
0
    case 'b':
1288
0
        temp.push_back('\x08');
1289
0
        ++cs;
1290
0
        break;
1291
0
    case 'f':
1292
0
        temp.push_back('\x0c');
1293
0
        ++cs;
1294
0
        break;
1295
0
    case 'n':
1296
0
        temp.push_back('\x0a');
1297
0
        ++cs;
1298
0
        break;
1299
0
    case 'r':
1300
0
        temp.push_back('\x0d');
1301
0
        ++cs;
1302
0
        break;
1303
0
    case 't':
1304
0
        temp.push_back('\x09');
1305
0
        ++cs;
1306
0
        break;
1307
0
    case 'u':
1308
        // utf16 escape
1309
        //
1310
        // fast path only when the buffer
1311
        // is large enough for 2 surrogates
1312
0
        if(BOOST_JSON_LIKELY(cs.remain() > 10))
1313
0
        {
1314
            // KRYSTIAN TODO: this could be done
1315
            // with fewer instructions
1316
0
            digit = detail::load_little_endian<4>(
1317
0
                cs.begin() + 1);
1318
0
            int d4 = detail::hex_digit(static_cast<
1319
0
                unsigned char>(digit >> 24));
1320
0
            int d3 = detail::hex_digit(static_cast<
1321
0
                unsigned char>(digit >> 16));
1322
0
            int d2 = detail::hex_digit(static_cast<
1323
0
                unsigned char>(digit >> 8));
1324
0
            int d1 = detail::hex_digit(static_cast<
1325
0
                unsigned char>(digit));
1326
0
            if(BOOST_JSON_UNLIKELY(
1327
0
                (d1 | d2 | d3 | d4) == -1))
1328
0
            {
1329
0
                if(d1 != -1)
1330
0
                    ++cs;
1331
0
                if(d2 != -1)
1332
0
                    ++cs;
1333
0
                if(d3 != -1)
1334
0
                    ++cs;
1335
0
                BOOST_STATIC_CONSTEXPR source_location loc
1336
0
                    = BOOST_CURRENT_LOCATION;
1337
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1338
0
            }
1339
            // 32 bit unicode scalar value
1340
0
            unsigned const u1 =
1341
0
                (d1 << 12) + (d2 << 8) +
1342
0
                (d3 << 4) + d4;
1343
            // valid unicode scalar values are
1344
            // [0, D7FF] and [E000, 10FFFF]
1345
            // values within this range are valid utf-8
1346
            // code points and invalid leading surrogates.
1347
0
            if(BOOST_JSON_LIKELY(
1348
0
                u1 < 0xd800 || u1 > 0xdfff))
1349
0
            {
1350
0
                cs += 5;
1351
0
                temp.append_utf8(u1);
1352
0
                break;
1353
0
            }
1354
0
            if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1355
0
            {
1356
0
                BOOST_STATIC_CONSTEXPR source_location loc
1357
0
                    = BOOST_CURRENT_LOCATION;
1358
0
                return fail(cs.begin(), error::illegal_leading_surrogate,
1359
0
                    &loc);
1360
0
            }
1361
0
            cs += 5;
1362
            // KRYSTIAN TODO: this can be a two byte load
1363
            // and a single comparison. We lose error information,
1364
            // but it's faster.
1365
0
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1366
0
            {
1367
0
                BOOST_STATIC_CONSTEXPR source_location loc
1368
0
                    = BOOST_CURRENT_LOCATION;
1369
0
                return fail(cs.begin(), error::syntax, &loc);
1370
0
            }
1371
0
            ++cs;
1372
0
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1373
0
            {
1374
0
                BOOST_STATIC_CONSTEXPR source_location loc
1375
0
                    = BOOST_CURRENT_LOCATION;
1376
0
                return fail(cs.begin(), error::syntax, &loc);
1377
0
            }
1378
0
            ++cs;
1379
0
            digit = detail::load_little_endian<4>(cs.begin());
1380
0
            d4 = detail::hex_digit(static_cast<
1381
0
                unsigned char>(digit >> 24));
1382
0
            d3 = detail::hex_digit(static_cast<
1383
0
                unsigned char>(digit >> 16));
1384
0
            d2 = detail::hex_digit(static_cast<
1385
0
                unsigned char>(digit >> 8));
1386
0
            d1 = detail::hex_digit(static_cast<
1387
0
                unsigned char>(digit));
1388
0
            if(BOOST_JSON_UNLIKELY(
1389
0
                (d1 | d2 | d3 | d4) == -1))
1390
0
            {
1391
0
                if(d1 != -1)
1392
0
                    ++cs;
1393
0
                if(d2 != -1)
1394
0
                    ++cs;
1395
0
                if(d3 != -1)
1396
0
                    ++cs;
1397
0
                BOOST_STATIC_CONSTEXPR source_location loc
1398
0
                    = BOOST_CURRENT_LOCATION;
1399
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1400
0
            }
1401
0
            unsigned const u2 =
1402
0
                (d1 << 12) + (d2 << 8) +
1403
0
                (d3 << 4) + d4;
1404
            // valid trailing surrogates are [DC00, DFFF]
1405
0
            if(BOOST_JSON_UNLIKELY(
1406
0
                u2 < 0xdc00 || u2 > 0xdfff))
1407
0
            {
1408
0
                BOOST_STATIC_CONSTEXPR source_location loc
1409
0
                    = BOOST_CURRENT_LOCATION;
1410
0
                return fail(cs.begin(), error::illegal_trailing_surrogate,
1411
0
                    &loc);
1412
0
            }
1413
0
            cs += 4;
1414
0
            unsigned cp =
1415
0
                ((u1 - 0xd800) << 10) +
1416
0
                ((u2 - 0xdc00)) +
1417
0
                    0x10000;
1418
            // utf-16 surrogate pair
1419
0
            temp.append_utf8(cp);
1420
0
            break;
1421
0
        }
1422
        // flush
1423
0
        if(BOOST_JSON_LIKELY(! temp.empty()))
1424
0
        {
1425
0
            BOOST_ASSERT(total <= max_size);
1426
0
            if(BOOST_JSON_UNLIKELY(
1427
0
                temp.size() > max_size - total))
1428
0
            {
1429
0
                BOOST_STATIC_CONSTEXPR source_location loc
1430
0
                    = BOOST_CURRENT_LOCATION;
1431
0
                return fail(cs.begin(), ev_too_large, &loc);
1432
0
            }
1433
0
            total += temp.size();
1434
0
            {
1435
0
                bool r = is_key
1436
0
                    ? h_.on_key_part(temp.get(), total, ec_)
1437
0
                    : h_.on_string_part(temp.get(), total, ec_);
1438
1439
0
                if(BOOST_JSON_UNLIKELY(!r))
1440
0
                {
1441
0
                    return fail(cs.begin());
1442
0
                }
1443
0
            }
1444
0
            temp.clear();
1445
0
            cs.clip(temp.max_size());
1446
0
        }
1447
0
        ++cs;
1448
        // utf-16 escape
1449
18
do_str4:
1450
18
        if(BOOST_JSON_UNLIKELY(! cs))
1451
18
            return maybe_suspend(cs.begin(), state::str4, total);
1452
0
        digit = detail::hex_digit(*cs);
1453
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1454
0
        {
1455
0
            BOOST_STATIC_CONSTEXPR source_location loc
1456
0
                = BOOST_CURRENT_LOCATION;
1457
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1458
0
        }
1459
0
        ++cs;
1460
0
        u1_ = digit << 12;
1461
16
do_str5:
1462
16
        if(BOOST_JSON_UNLIKELY(! cs))
1463
16
            return maybe_suspend(cs.begin(), state::str5, total);
1464
0
        digit = detail::hex_digit(*cs);
1465
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1466
0
        {
1467
0
            BOOST_STATIC_CONSTEXPR source_location loc
1468
0
                = BOOST_CURRENT_LOCATION;
1469
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1470
0
        }
1471
0
        ++cs;
1472
0
        u1_ += digit << 8;
1473
15
do_str6:
1474
15
        if(BOOST_JSON_UNLIKELY(! cs))
1475
15
            return maybe_suspend(cs.begin(), state::str6, total);
1476
0
        digit = detail::hex_digit(*cs);
1477
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1478
0
        {
1479
0
            BOOST_STATIC_CONSTEXPR source_location loc
1480
0
                = BOOST_CURRENT_LOCATION;
1481
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1482
0
        }
1483
0
        ++cs;
1484
0
        u1_ += digit << 4;
1485
19
do_str7:
1486
19
        if(BOOST_JSON_UNLIKELY(! cs))
1487
19
            return maybe_suspend(cs.begin(), state::str7, total);
1488
0
        digit = detail::hex_digit(*cs);
1489
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1490
0
        {
1491
0
            BOOST_STATIC_CONSTEXPR source_location loc
1492
0
                = BOOST_CURRENT_LOCATION;
1493
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1494
0
        }
1495
0
        ++cs;
1496
0
        u1_ += digit;
1497
0
        if(BOOST_JSON_LIKELY(
1498
0
            u1_ < 0xd800 || u1_ > 0xdfff))
1499
0
        {
1500
0
            BOOST_ASSERT(temp.empty());
1501
            // utf-8 codepoint
1502
0
            temp.append_utf8(u1_);
1503
0
            break;
1504
0
        }
1505
0
        if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1506
0
        {
1507
0
            BOOST_STATIC_CONSTEXPR source_location loc
1508
0
                = BOOST_CURRENT_LOCATION;
1509
0
            return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1510
0
        }
1511
12
do_sur1:
1512
12
        if(BOOST_JSON_UNLIKELY(! cs))
1513
12
            return maybe_suspend(cs.begin(), state::sur1, total);
1514
0
        if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1515
0
        {
1516
0
            BOOST_STATIC_CONSTEXPR source_location loc
1517
0
                = BOOST_CURRENT_LOCATION;
1518
0
            return fail(cs.begin(), error::syntax, &loc);
1519
0
        }
1520
0
        ++cs;
1521
2
do_sur2:
1522
2
        if(BOOST_JSON_UNLIKELY(! cs))
1523
2
            return maybe_suspend(cs.begin(), state::sur2, total);
1524
0
        if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1525
0
        {
1526
0
            BOOST_STATIC_CONSTEXPR source_location loc
1527
0
                = BOOST_CURRENT_LOCATION;
1528
0
            return fail(cs.begin(), error::syntax, &loc);
1529
0
        }
1530
0
        ++cs;
1531
3
do_sur3:
1532
3
        if(BOOST_JSON_UNLIKELY(! cs))
1533
3
            return maybe_suspend(cs.begin(), state::sur3, total);
1534
0
        digit = detail::hex_digit(*cs);
1535
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1536
0
        {
1537
0
            BOOST_STATIC_CONSTEXPR source_location loc
1538
0
                = BOOST_CURRENT_LOCATION;
1539
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1540
0
        }
1541
0
        ++cs;
1542
0
        u2_ = digit << 12;
1543
11
do_sur4:
1544
11
        if(BOOST_JSON_UNLIKELY(! cs))
1545
11
            return maybe_suspend(cs.begin(), state::sur4, total);
1546
0
        digit = detail::hex_digit(*cs);
1547
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1548
0
        {
1549
0
            BOOST_STATIC_CONSTEXPR source_location loc
1550
0
                = BOOST_CURRENT_LOCATION;
1551
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1552
0
        }
1553
0
        ++cs;
1554
0
        u2_ += digit << 8;
1555
7
do_sur5:
1556
7
        if(BOOST_JSON_UNLIKELY(! cs))
1557
7
            return maybe_suspend(cs.begin(), state::sur5, total);
1558
0
        digit = detail::hex_digit(*cs);
1559
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1560
0
        {
1561
0
            BOOST_STATIC_CONSTEXPR source_location loc
1562
0
                = BOOST_CURRENT_LOCATION;
1563
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1564
0
        }
1565
0
        ++cs;
1566
0
        u2_ += digit << 4;
1567
16
do_sur6:
1568
16
        if(BOOST_JSON_UNLIKELY(! cs))
1569
16
            return maybe_suspend(cs.begin(), state::sur6, total);
1570
0
        digit = detail::hex_digit(*cs);
1571
0
        if(BOOST_JSON_UNLIKELY(digit == -1))
1572
0
        {
1573
0
            BOOST_STATIC_CONSTEXPR source_location loc
1574
0
                = BOOST_CURRENT_LOCATION;
1575
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1576
0
        }
1577
0
        ++cs;
1578
0
        u2_ += digit;
1579
0
        if(BOOST_JSON_UNLIKELY(
1580
0
            u2_ < 0xdc00 || u2_ > 0xdfff))
1581
0
        {
1582
0
            BOOST_STATIC_CONSTEXPR source_location loc
1583
0
                = BOOST_CURRENT_LOCATION;
1584
0
            return fail(cs.begin(), error::expected_hex_digit, &loc);
1585
0
        }
1586
0
        unsigned cp =
1587
0
            ((u1_ - 0xd800) << 10) +
1588
0
            ((u2_ - 0xdc00)) +
1589
0
                0x10000;
1590
0
        BOOST_ASSERT(temp.empty());
1591
        // utf-16 surrogate pair
1592
0
        temp.append_utf8(cp);
1593
0
    }
1594
292
do_str2:
1595
    // KRYSTIAN TODO: we can append the characters
1596
    // all at once instead of one at a time
1597
292
    for(;;)
1598
292
    {
1599
292
        if(BOOST_JSON_UNLIKELY(! cs || temp.capacity() == 0 ))
1600
292
        {
1601
            // flush
1602
292
            if(BOOST_JSON_LIKELY(! temp.empty()))
1603
0
            {
1604
0
                BOOST_ASSERT(total <= max_size);
1605
0
                if(BOOST_JSON_UNLIKELY(
1606
0
                    temp.size() > max_size - total))
1607
0
                {
1608
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1609
0
                        = BOOST_CURRENT_LOCATION;
1610
0
                    return fail(cs.begin(), ev_too_large, &loc);
1611
0
                }
1612
0
                total += temp.size();
1613
0
                {
1614
0
                    bool r = is_key
1615
0
                        ? h_.on_key_part(temp.get(), total, ec_)
1616
0
                        : h_.on_string_part(temp.get(), total, ec_);
1617
1618
0
                    if(BOOST_JSON_UNLIKELY(!r))
1619
0
                    {
1620
0
                        return fail(cs.begin());
1621
0
                    }
1622
0
                }
1623
0
                temp.clear();
1624
0
            }
1625
292
            cs.clip(temp.max_size());
1626
292
            if(BOOST_JSON_UNLIKELY(! cs))
1627
292
                return maybe_suspend(cs.begin(), state::str2, total);
1628
292
        }
1629
0
        c = *cs;
1630
0
        if(BOOST_JSON_LIKELY(c == '\x22')) // '"'
1631
0
        {
1632
0
            BOOST_ASSERT(total <= max_size);
1633
0
            if(BOOST_JSON_UNLIKELY(
1634
0
                temp.size() > max_size - total))
1635
0
            {
1636
0
                BOOST_STATIC_CONSTEXPR source_location loc
1637
0
                    = BOOST_CURRENT_LOCATION;
1638
0
                return fail(cs.begin(), ev_too_large, &loc);
1639
0
            }
1640
0
            total += temp.size();
1641
0
            {
1642
0
                bool r = is_key
1643
0
                    ? h_.on_key(temp.get(), total, ec_)
1644
0
                    : h_.on_string(temp.get(), total, ec_);
1645
1646
0
                if(BOOST_JSON_UNLIKELY(!r))
1647
0
                {
1648
0
                    return fail(cs.begin());
1649
0
                }
1650
0
            }
1651
0
            ++cs;
1652
0
            return cs.begin();
1653
0
        }
1654
0
        else if((c & 0x80) && !allow_bad_utf8)
1655
0
        {
1656
0
            seq_.save(cs.begin(), cs.remain());
1657
0
            if(BOOST_JSON_UNLIKELY(! seq_.complete()))
1658
0
            {
1659
0
                if(BOOST_JSON_LIKELY(! temp.empty()))
1660
0
                {
1661
0
                    BOOST_ASSERT(total <= max_size);
1662
0
                    if(BOOST_JSON_UNLIKELY(
1663
0
                        temp.size() > max_size - total))
1664
0
                    {
1665
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1666
0
                            = BOOST_CURRENT_LOCATION;
1667
0
                        return fail(cs.begin(), ev_too_large, &loc);
1668
0
                    }
1669
0
                    total += temp.size();
1670
0
                    {
1671
0
                        bool r = is_key
1672
0
                            ? h_.on_key_part(temp.get(), total, ec_)
1673
0
                            : h_.on_string_part(temp.get(), total, ec_);
1674
1675
0
                        if(BOOST_JSON_UNLIKELY(!r))
1676
0
                        {
1677
0
                            return fail(cs.begin());
1678
0
                        }
1679
0
                    }
1680
0
                    temp.clear();
1681
0
                }
1682
0
                cs = cs.end();
1683
                // ensure there is room for the saved byte sequence
1684
0
                cs.clip(temp.max_size() - seq_.length());
1685
0
                goto do_str8;
1686
0
            }
1687
0
            if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1688
0
            {
1689
0
                BOOST_STATIC_CONSTEXPR source_location loc
1690
0
                    = BOOST_CURRENT_LOCATION;
1691
0
                return fail(cs.begin(), error::syntax, &loc);
1692
0
            }
1693
0
            temp.append(seq_.data(), seq_.length());
1694
0
            cs += seq_.length();
1695
0
            continue;
1696
0
        }
1697
0
        else if(BOOST_JSON_LIKELY(c == '\\'))
1698
0
        {
1699
0
            ++cs;
1700
0
            goto do_str3;
1701
0
        }
1702
0
        else if(BOOST_JSON_UNLIKELY(
1703
0
            detail::is_control(c)))
1704
0
        {
1705
0
            BOOST_STATIC_CONSTEXPR source_location loc
1706
0
                = BOOST_CURRENT_LOCATION;
1707
0
            return fail(cs.begin(), error::syntax, &loc);
1708
0
        }
1709
0
        temp.push_back(c);
1710
0
        ++cs;
1711
0
    }
1712
79
do_str8:
1713
79
    uint8_t needed = seq_.needed();
1714
79
    if(BOOST_JSON_UNLIKELY(
1715
79
        ! seq_.append(cs.begin(), cs.remain())))
1716
79
        return maybe_suspend(cs.end(), state::str8, total);
1717
0
    if(BOOST_JSON_UNLIKELY(! seq_.valid()))
1718
0
    {
1719
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1720
0
        return fail(cs.begin(), error::syntax, &loc);
1721
0
    }
1722
0
    temp.append(seq_.data(), seq_.length());
1723
0
    cs += needed;
1724
0
    goto do_str2;
1725
0
}
1726
1727
//----------------------------------------------------------
1728
1729
template<class Handler>
1730
template<
1731
    bool StackEmpty_,
1732
    bool AllowComments_/*,
1733
    bool AllowTrailing_,
1734
    bool AllowBadUTF8_*/>
1735
const char*
1736
basic_parser<Handler>::
1737
parse_object(const char* p,
1738
    std::integral_constant<bool, StackEmpty_> stack_empty,
1739
    std::integral_constant<bool, AllowComments_> allow_comments,
1740
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1741
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8)
1742
23.7k
{
1743
23.7k
    detail::const_stream_wrapper cs(p, end_);
1744
23.7k
    std::size_t size;
1745
23.7k
    if(! stack_empty && ! st_.empty())
1746
1.28k
    {
1747
        // resume
1748
1.28k
        state st;
1749
1.28k
        st_.pop(st);
1750
1.28k
        st_.pop(size);
1751
1.28k
        switch(st)
1752
1.28k
        {
1753
0
        default: BOOST_JSON_UNREACHABLE();
1754
82
        case state::obj1: goto do_obj1;
1755
6
        case state::obj2: goto do_obj2;
1756
223
        case state::obj3: goto do_obj3;
1757
109
        case state::obj4: goto do_obj4;
1758
7
        case state::obj5: goto do_obj5;
1759
57
        case state::obj6: goto do_obj6;
1760
653
        case state::obj7: goto do_obj7;
1761
66
        case state::obj8: goto do_obj8;
1762
64
        case state::obj9: goto do_obj9;
1763
9
        case state::obj10: goto do_obj10;
1764
5
        case state::obj11: goto do_obj11;
1765
1.28k
        }
1766
1.28k
    }
1767
22.4k
    BOOST_ASSERT(*cs == '{');
1768
22.4k
    size = 0;
1769
22.4k
    if(BOOST_JSON_UNLIKELY(! depth_))
1770
14
    {
1771
14
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1772
14
        return fail(cs.begin(), error::too_deep, &loc);
1773
14
    }
1774
22.4k
    --depth_;
1775
22.4k
    if(BOOST_JSON_UNLIKELY(
1776
22.4k
        ! h_.on_object_begin(ec_)))
1777
0
        return fail(cs.begin());
1778
22.4k
    ++cs;
1779
    // object:
1780
    //     '{' *ws '}'
1781
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1782
23.1k
do_obj1:
1783
23.1k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1784
23.1k
    if(BOOST_JSON_UNLIKELY(! cs))
1785
205
        return maybe_suspend(cs.begin(), state::obj1, size);
1786
22.9k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1787
13.2k
    {
1788
13.2k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1789
777
        {
1790
777
            if(allow_comments && *cs == '/')
1791
582
            {
1792
588
do_obj2:
1793
588
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1794
588
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1795
15
                    return suspend_or_fail(state::obj2, size);
1796
573
                goto do_obj1;
1797
588
            }
1798
195
            BOOST_STATIC_CONSTEXPR source_location loc
1799
195
                = BOOST_CURRENT_LOCATION;
1800
195
            return fail(cs.begin(), error::syntax, &loc);
1801
777
        }
1802
991k
loop:
1803
991k
        if(BOOST_JSON_UNLIKELY(++size >
1804
991k
            Handler::max_object_size))
1805
0
        {
1806
0
            BOOST_STATIC_CONSTEXPR source_location loc
1807
0
                = BOOST_CURRENT_LOCATION;
1808
0
            return fail(cs.begin(), error::object_too_large, &loc);
1809
0
        }
1810
991k
do_obj3:
1811
991k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8);
1812
991k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1813
929
            return suspend_or_fail(state::obj3, size);
1814
991k
do_obj4:
1815
991k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1816
991k
        if(BOOST_JSON_UNLIKELY(! cs))
1817
278
            return maybe_suspend(cs.begin(), state::obj4, size);
1818
990k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1819
643
        {
1820
643
            if(allow_comments && *cs == '/')
1821
445
            {
1822
452
do_obj5:
1823
452
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1824
452
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1825
15
                    return suspend_or_fail(state::obj5, size);
1826
437
                goto do_obj4;
1827
452
            }
1828
198
            BOOST_STATIC_CONSTEXPR source_location loc
1829
198
                = BOOST_CURRENT_LOCATION;
1830
198
            return fail(cs.begin(), error::syntax, &loc);
1831
643
        }
1832
990k
        ++cs;
1833
990k
do_obj6:
1834
990k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1835
990k
        if(BOOST_JSON_UNLIKELY(! cs))
1836
146
            return maybe_suspend(cs.begin(), state::obj6, size);
1837
990k
do_obj7:
1838
990k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1839
990k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1840
2.91k
            return suspend_or_fail(state::obj7, size);
1841
988k
do_obj8:
1842
988k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1843
988k
        if(BOOST_JSON_UNLIKELY(! cs))
1844
187
            return maybe_suspend(cs.begin(), state::obj8, size);
1845
988k
        if(BOOST_JSON_LIKELY(*cs == ','))
1846
979k
        {
1847
979k
            ++cs;
1848
980k
do_obj9:
1849
980k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1850
980k
            if(BOOST_JSON_UNLIKELY(! cs))
1851
159
                return maybe_suspend(cs.begin(), state::obj9, size);
1852
1853
            // loop for next element
1854
980k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1855
978k
                goto loop;
1856
1.39k
            if(! allow_trailing || *cs != '}')
1857
900
            {
1858
900
                if(allow_comments && *cs == '/')
1859
782
                {
1860
791
do_obj10:
1861
791
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1862
791
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1863
21
                        return suspend_or_fail(state::obj10, size);
1864
770
                    goto do_obj9;
1865
791
                }
1866
118
                BOOST_STATIC_CONSTEXPR source_location loc
1867
118
                    = BOOST_CURRENT_LOCATION;
1868
118
                return fail(cs.begin(), error::syntax, &loc);
1869
900
            }
1870
1.39k
        }
1871
8.70k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1872
763
        {
1873
763
            if(allow_comments && *cs == '/')
1874
554
            {
1875
559
do_obj11:
1876
559
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1877
559
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1878
15
                    return suspend_or_fail(state::obj11, size);
1879
544
                goto do_obj8;
1880
559
            }
1881
209
            BOOST_STATIC_CONSTEXPR source_location loc
1882
209
                = BOOST_CURRENT_LOCATION;
1883
209
            return fail(cs.begin(), error::syntax, &loc);
1884
763
        }
1885
        // got closing brace, fall through
1886
988k
    }
1887
18.1k
    if(BOOST_JSON_UNLIKELY(
1888
18.1k
        ! h_.on_object_end(size, ec_)))
1889
0
        return fail(cs.begin());
1890
18.1k
    ++depth_;
1891
18.1k
    ++cs;
1892
18.1k
    return cs.begin();
1893
18.1k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_object<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
1742
15.5k
{
1743
15.5k
    detail::const_stream_wrapper cs(p, end_);
1744
15.5k
    std::size_t size;
1745
15.5k
    if(! stack_empty && ! st_.empty())
1746
0
    {
1747
        // resume
1748
0
        state st;
1749
0
        st_.pop(st);
1750
0
        st_.pop(size);
1751
0
        switch(st)
1752
0
        {
1753
0
        default: BOOST_JSON_UNREACHABLE();
1754
0
        case state::obj1: goto do_obj1;
1755
0
        case state::obj2: goto do_obj2;
1756
0
        case state::obj3: goto do_obj3;
1757
0
        case state::obj4: goto do_obj4;
1758
0
        case state::obj5: goto do_obj5;
1759
0
        case state::obj6: goto do_obj6;
1760
0
        case state::obj7: goto do_obj7;
1761
0
        case state::obj8: goto do_obj8;
1762
0
        case state::obj9: goto do_obj9;
1763
0
        case state::obj10: goto do_obj10;
1764
0
        case state::obj11: goto do_obj11;
1765
0
        }
1766
0
    }
1767
15.5k
    BOOST_ASSERT(*cs == '{');
1768
15.5k
    size = 0;
1769
15.5k
    if(BOOST_JSON_UNLIKELY(! depth_))
1770
10
    {
1771
10
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1772
10
        return fail(cs.begin(), error::too_deep, &loc);
1773
10
    }
1774
15.5k
    --depth_;
1775
15.5k
    if(BOOST_JSON_UNLIKELY(
1776
15.5k
        ! h_.on_object_begin(ec_)))
1777
0
        return fail(cs.begin());
1778
15.5k
    ++cs;
1779
    // object:
1780
    //     '{' *ws '}'
1781
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1782
15.5k
do_obj1:
1783
15.5k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1784
15.5k
    if(BOOST_JSON_UNLIKELY(! cs))
1785
79
        return maybe_suspend(cs.begin(), state::obj1, size);
1786
15.4k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1787
6.56k
    {
1788
6.56k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1789
130
        {
1790
130
            if(allow_comments && *cs == '/')
1791
0
            {
1792
0
do_obj2:
1793
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1794
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1795
0
                    return suspend_or_fail(state::obj2, size);
1796
0
                goto do_obj1;
1797
0
            }
1798
130
            BOOST_STATIC_CONSTEXPR source_location loc
1799
130
                = BOOST_CURRENT_LOCATION;
1800
130
            return fail(cs.begin(), error::syntax, &loc);
1801
130
        }
1802
978k
loop:
1803
978k
        if(BOOST_JSON_UNLIKELY(++size >
1804
978k
            Handler::max_object_size))
1805
0
        {
1806
0
            BOOST_STATIC_CONSTEXPR source_location loc
1807
0
                = BOOST_CURRENT_LOCATION;
1808
0
            return fail(cs.begin(), error::object_too_large, &loc);
1809
0
        }
1810
978k
do_obj3:
1811
978k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8);
1812
978k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1813
522
            return suspend_or_fail(state::obj3, size);
1814
978k
do_obj4:
1815
978k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1816
978k
        if(BOOST_JSON_UNLIKELY(! cs))
1817
111
            return maybe_suspend(cs.begin(), state::obj4, size);
1818
978k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1819
141
        {
1820
141
            if(allow_comments && *cs == '/')
1821
0
            {
1822
0
do_obj5:
1823
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1824
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1825
0
                    return suspend_or_fail(state::obj5, size);
1826
0
                goto do_obj4;
1827
0
            }
1828
141
            BOOST_STATIC_CONSTEXPR source_location loc
1829
141
                = BOOST_CURRENT_LOCATION;
1830
141
            return fail(cs.begin(), error::syntax, &loc);
1831
141
        }
1832
978k
        ++cs;
1833
978k
do_obj6:
1834
978k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1835
978k
        if(BOOST_JSON_UNLIKELY(! cs))
1836
60
            return maybe_suspend(cs.begin(), state::obj6, size);
1837
978k
do_obj7:
1838
978k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1839
978k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1840
1.69k
            return suspend_or_fail(state::obj7, size);
1841
976k
do_obj8:
1842
976k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1843
976k
        if(BOOST_JSON_UNLIKELY(! cs))
1844
73
            return maybe_suspend(cs.begin(), state::obj8, size);
1845
976k
        if(BOOST_JSON_LIKELY(*cs == ','))
1846
972k
        {
1847
972k
            ++cs;
1848
972k
do_obj9:
1849
972k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1850
972k
            if(BOOST_JSON_UNLIKELY(! cs))
1851
58
                return maybe_suspend(cs.begin(), state::obj9, size);
1852
1853
            // loop for next element
1854
972k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1855
972k
                goto loop;
1856
307
            if(! allow_trailing || *cs != '}')
1857
81
            {
1858
81
                if(allow_comments && *cs == '/')
1859
0
                {
1860
0
do_obj10:
1861
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1862
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1863
0
                        return suspend_or_fail(state::obj10, size);
1864
0
                    goto do_obj9;
1865
0
                }
1866
81
                BOOST_STATIC_CONSTEXPR source_location loc
1867
81
                    = BOOST_CURRENT_LOCATION;
1868
81
                return fail(cs.begin(), error::syntax, &loc);
1869
81
            }
1870
307
        }
1871
3.47k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1872
143
        {
1873
143
            if(allow_comments && *cs == '/')
1874
0
            {
1875
0
do_obj11:
1876
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1877
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1878
0
                    return suspend_or_fail(state::obj11, size);
1879
0
                goto do_obj8;
1880
0
            }
1881
143
            BOOST_STATIC_CONSTEXPR source_location loc
1882
143
                = BOOST_CURRENT_LOCATION;
1883
143
            return fail(cs.begin(), error::syntax, &loc);
1884
143
        }
1885
        // got closing brace, fall through
1886
976k
    }
1887
12.4k
    if(BOOST_JSON_UNLIKELY(
1888
12.4k
        ! h_.on_object_end(size, ec_)))
1889
0
        return fail(cs.begin());
1890
12.4k
    ++depth_;
1891
12.4k
    ++cs;
1892
12.4k
    return cs.begin();
1893
12.4k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_object<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1742
6.91k
{
1743
6.91k
    detail::const_stream_wrapper cs(p, end_);
1744
6.91k
    std::size_t size;
1745
6.91k
    if(! stack_empty && ! st_.empty())
1746
0
    {
1747
        // resume
1748
0
        state st;
1749
0
        st_.pop(st);
1750
0
        st_.pop(size);
1751
0
        switch(st)
1752
0
        {
1753
0
        default: BOOST_JSON_UNREACHABLE();
1754
0
        case state::obj1: goto do_obj1;
1755
0
        case state::obj2: goto do_obj2;
1756
0
        case state::obj3: goto do_obj3;
1757
0
        case state::obj4: goto do_obj4;
1758
0
        case state::obj5: goto do_obj5;
1759
0
        case state::obj6: goto do_obj6;
1760
0
        case state::obj7: goto do_obj7;
1761
0
        case state::obj8: goto do_obj8;
1762
0
        case state::obj9: goto do_obj9;
1763
0
        case state::obj10: goto do_obj10;
1764
0
        case state::obj11: goto do_obj11;
1765
0
        }
1766
0
    }
1767
6.91k
    BOOST_ASSERT(*cs == '{');
1768
6.91k
    size = 0;
1769
6.91k
    if(BOOST_JSON_UNLIKELY(! depth_))
1770
4
    {
1771
4
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1772
4
        return fail(cs.begin(), error::too_deep, &loc);
1773
4
    }
1774
6.91k
    --depth_;
1775
6.91k
    if(BOOST_JSON_UNLIKELY(
1776
6.91k
        ! h_.on_object_begin(ec_)))
1777
0
        return fail(cs.begin());
1778
6.91k
    ++cs;
1779
    // object:
1780
    //     '{' *ws '}'
1781
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1782
7.48k
do_obj1:
1783
7.48k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1784
7.48k
    if(BOOST_JSON_UNLIKELY(! cs))
1785
44
        return maybe_suspend(cs.begin(), state::obj1, size);
1786
7.43k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1787
6.65k
    {
1788
6.65k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1789
647
        {
1790
647
            if(allow_comments && *cs == '/')
1791
582
            {
1792
582
do_obj2:
1793
582
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1794
582
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1795
9
                    return suspend_or_fail(state::obj2, size);
1796
573
                goto do_obj1;
1797
582
            }
1798
65
            BOOST_STATIC_CONSTEXPR source_location loc
1799
65
                = BOOST_CURRENT_LOCATION;
1800
65
            return fail(cs.begin(), error::syntax, &loc);
1801
647
        }
1802
12.4k
loop:
1803
12.4k
        if(BOOST_JSON_UNLIKELY(++size >
1804
12.4k
            Handler::max_object_size))
1805
0
        {
1806
0
            BOOST_STATIC_CONSTEXPR source_location loc
1807
0
                = BOOST_CURRENT_LOCATION;
1808
0
            return fail(cs.begin(), error::object_too_large, &loc);
1809
0
        }
1810
12.4k
do_obj3:
1811
12.4k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8);
1812
12.4k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1813
184
            return suspend_or_fail(state::obj3, size);
1814
12.6k
do_obj4:
1815
12.6k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1816
12.6k
        if(BOOST_JSON_UNLIKELY(! cs))
1817
58
            return maybe_suspend(cs.begin(), state::obj4, size);
1818
12.6k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1819
502
        {
1820
502
            if(allow_comments && *cs == '/')
1821
445
            {
1822
445
do_obj5:
1823
445
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1824
445
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1825
8
                    return suspend_or_fail(state::obj5, size);
1826
437
                goto do_obj4;
1827
445
            }
1828
57
            BOOST_STATIC_CONSTEXPR source_location loc
1829
57
                = BOOST_CURRENT_LOCATION;
1830
57
            return fail(cs.begin(), error::syntax, &loc);
1831
502
        }
1832
12.1k
        ++cs;
1833
12.1k
do_obj6:
1834
12.1k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1835
12.1k
        if(BOOST_JSON_UNLIKELY(! cs))
1836
29
            return maybe_suspend(cs.begin(), state::obj6, size);
1837
12.1k
do_obj7:
1838
12.1k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1839
12.1k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1840
584
            return suspend_or_fail(state::obj7, size);
1841
12.0k
do_obj8:
1842
12.0k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1843
12.0k
        if(BOOST_JSON_UNLIKELY(! cs))
1844
40
            return maybe_suspend(cs.begin(), state::obj8, size);
1845
12.0k
        if(BOOST_JSON_LIKELY(*cs == ','))
1846
6.78k
        {
1847
6.78k
            ++cs;
1848
7.55k
do_obj9:
1849
7.55k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1850
7.55k
            if(BOOST_JSON_UNLIKELY(! cs))
1851
37
                return maybe_suspend(cs.begin(), state::obj9, size);
1852
1853
            // loop for next element
1854
7.51k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1855
6.43k
                goto loop;
1856
1.08k
            if(! allow_trailing || *cs != '}')
1857
819
            {
1858
819
                if(allow_comments && *cs == '/')
1859
782
                {
1860
782
do_obj10:
1861
782
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1862
782
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1863
12
                        return suspend_or_fail(state::obj10, size);
1864
770
                    goto do_obj9;
1865
782
                }
1866
37
                BOOST_STATIC_CONSTEXPR source_location loc
1867
37
                    = BOOST_CURRENT_LOCATION;
1868
37
                return fail(cs.begin(), error::syntax, &loc);
1869
819
            }
1870
1.08k
        }
1871
5.23k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1872
620
        {
1873
620
            if(allow_comments && *cs == '/')
1874
554
            {
1875
554
do_obj11:
1876
554
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1877
554
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1878
10
                    return suspend_or_fail(state::obj11, size);
1879
544
                goto do_obj8;
1880
554
            }
1881
66
            BOOST_STATIC_CONSTEXPR source_location loc
1882
66
                = BOOST_CURRENT_LOCATION;
1883
66
            return fail(cs.begin(), error::syntax, &loc);
1884
620
        }
1885
        // got closing brace, fall through
1886
12.0k
    }
1887
5.66k
    if(BOOST_JSON_UNLIKELY(
1888
5.66k
        ! h_.on_object_end(size, ec_)))
1889
0
        return fail(cs.begin());
1890
5.66k
    ++depth_;
1891
5.66k
    ++cs;
1892
5.66k
    return cs.begin();
1893
5.66k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_object<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
1742
577
{
1743
577
    detail::const_stream_wrapper cs(p, end_);
1744
577
    std::size_t size;
1745
577
    if(! stack_empty && ! st_.empty())
1746
577
    {
1747
        // resume
1748
577
        state st;
1749
577
        st_.pop(st);
1750
577
        st_.pop(size);
1751
577
        switch(st)
1752
577
        {
1753
0
        default: BOOST_JSON_UNREACHABLE();
1754
38
        case state::obj1: goto do_obj1;
1755
0
        case state::obj2: goto do_obj2;
1756
118
        case state::obj3: goto do_obj3;
1757
51
        case state::obj4: goto do_obj4;
1758
0
        case state::obj5: goto do_obj5;
1759
28
        case state::obj6: goto do_obj6;
1760
289
        case state::obj7: goto do_obj7;
1761
26
        case state::obj8: goto do_obj8;
1762
27
        case state::obj9: goto do_obj9;
1763
0
        case state::obj10: goto do_obj10;
1764
0
        case state::obj11: goto do_obj11;
1765
577
        }
1766
577
    }
1767
0
    BOOST_ASSERT(*cs == '{');
1768
0
    size = 0;
1769
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1770
0
    {
1771
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1772
0
        return fail(cs.begin(), error::too_deep, &loc);
1773
0
    }
1774
0
    --depth_;
1775
0
    if(BOOST_JSON_UNLIKELY(
1776
0
        ! h_.on_object_begin(ec_)))
1777
0
        return fail(cs.begin());
1778
0
    ++cs;
1779
    // object:
1780
    //     '{' *ws '}'
1781
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1782
38
do_obj1:
1783
38
    cs = detail::count_whitespace(cs.begin(), cs.end());
1784
38
    if(BOOST_JSON_UNLIKELY(! cs))
1785
38
        return maybe_suspend(cs.begin(), state::obj1, size);
1786
0
    if(BOOST_JSON_LIKELY(*cs != '}'))
1787
0
    {
1788
0
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1789
0
        {
1790
0
            if(allow_comments && *cs == '/')
1791
0
            {
1792
0
do_obj2:
1793
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1794
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1795
0
                    return suspend_or_fail(state::obj2, size);
1796
0
                goto do_obj1;
1797
0
            }
1798
0
            BOOST_STATIC_CONSTEXPR source_location loc
1799
0
                = BOOST_CURRENT_LOCATION;
1800
0
            return fail(cs.begin(), error::syntax, &loc);
1801
0
        }
1802
0
loop:
1803
0
        if(BOOST_JSON_UNLIKELY(++size >
1804
0
            Handler::max_object_size))
1805
0
        {
1806
0
            BOOST_STATIC_CONSTEXPR source_location loc
1807
0
                = BOOST_CURRENT_LOCATION;
1808
0
            return fail(cs.begin(), error::object_too_large, &loc);
1809
0
        }
1810
118
do_obj3:
1811
118
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8);
1812
118
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1813
118
            return suspend_or_fail(state::obj3, size);
1814
51
do_obj4:
1815
51
        cs = detail::count_whitespace(cs.begin(), cs.end());
1816
51
        if(BOOST_JSON_UNLIKELY(! cs))
1817
51
            return maybe_suspend(cs.begin(), state::obj4, size);
1818
0
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1819
0
        {
1820
0
            if(allow_comments && *cs == '/')
1821
0
            {
1822
0
do_obj5:
1823
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1824
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1825
0
                    return suspend_or_fail(state::obj5, size);
1826
0
                goto do_obj4;
1827
0
            }
1828
0
            BOOST_STATIC_CONSTEXPR source_location loc
1829
0
                = BOOST_CURRENT_LOCATION;
1830
0
            return fail(cs.begin(), error::syntax, &loc);
1831
0
        }
1832
0
        ++cs;
1833
28
do_obj6:
1834
28
        cs = detail::count_whitespace(cs.begin(), cs.end());
1835
28
        if(BOOST_JSON_UNLIKELY(! cs))
1836
28
            return maybe_suspend(cs.begin(), state::obj6, size);
1837
289
do_obj7:
1838
289
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1839
289
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1840
285
            return suspend_or_fail(state::obj7, size);
1841
30
do_obj8:
1842
30
        cs = detail::count_whitespace(cs.begin(), cs.end());
1843
30
        if(BOOST_JSON_UNLIKELY(! cs))
1844
30
            return maybe_suspend(cs.begin(), state::obj8, size);
1845
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1846
0
        {
1847
0
            ++cs;
1848
27
do_obj9:
1849
27
            cs = detail::count_whitespace(cs.begin(), cs.end());
1850
27
            if(BOOST_JSON_UNLIKELY(! cs))
1851
27
                return maybe_suspend(cs.begin(), state::obj9, size);
1852
1853
            // loop for next element
1854
0
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1855
0
                goto loop;
1856
0
            if(! allow_trailing || *cs != '}')
1857
0
            {
1858
0
                if(allow_comments && *cs == '/')
1859
0
                {
1860
0
do_obj10:
1861
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1862
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1863
0
                        return suspend_or_fail(state::obj10, size);
1864
0
                    goto do_obj9;
1865
0
                }
1866
0
                BOOST_STATIC_CONSTEXPR source_location loc
1867
0
                    = BOOST_CURRENT_LOCATION;
1868
0
                return fail(cs.begin(), error::syntax, &loc);
1869
0
            }
1870
0
        }
1871
0
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1872
0
        {
1873
0
            if(allow_comments && *cs == '/')
1874
0
            {
1875
0
do_obj11:
1876
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1877
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1878
0
                    return suspend_or_fail(state::obj11, size);
1879
0
                goto do_obj8;
1880
0
            }
1881
0
            BOOST_STATIC_CONSTEXPR source_location loc
1882
0
                = BOOST_CURRENT_LOCATION;
1883
0
            return fail(cs.begin(), error::syntax, &loc);
1884
0
        }
1885
        // got closing brace, fall through
1886
0
    }
1887
0
    if(BOOST_JSON_UNLIKELY(
1888
0
        ! h_.on_object_end(size, ec_)))
1889
0
        return fail(cs.begin());
1890
0
    ++depth_;
1891
0
    ++cs;
1892
0
    return cs.begin();
1893
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_object<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1742
704
{
1743
704
    detail::const_stream_wrapper cs(p, end_);
1744
704
    std::size_t size;
1745
704
    if(! stack_empty && ! st_.empty())
1746
704
    {
1747
        // resume
1748
704
        state st;
1749
704
        st_.pop(st);
1750
704
        st_.pop(size);
1751
704
        switch(st)
1752
704
        {
1753
0
        default: BOOST_JSON_UNREACHABLE();
1754
44
        case state::obj1: goto do_obj1;
1755
6
        case state::obj2: goto do_obj2;
1756
105
        case state::obj3: goto do_obj3;
1757
58
        case state::obj4: goto do_obj4;
1758
7
        case state::obj5: goto do_obj5;
1759
29
        case state::obj6: goto do_obj6;
1760
364
        case state::obj7: goto do_obj7;
1761
40
        case state::obj8: goto do_obj8;
1762
37
        case state::obj9: goto do_obj9;
1763
9
        case state::obj10: goto do_obj10;
1764
5
        case state::obj11: goto do_obj11;
1765
704
        }
1766
704
    }
1767
0
    BOOST_ASSERT(*cs == '{');
1768
0
    size = 0;
1769
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1770
0
    {
1771
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1772
0
        return fail(cs.begin(), error::too_deep, &loc);
1773
0
    }
1774
0
    --depth_;
1775
0
    if(BOOST_JSON_UNLIKELY(
1776
0
        ! h_.on_object_begin(ec_)))
1777
0
        return fail(cs.begin());
1778
0
    ++cs;
1779
    // object:
1780
    //     '{' *ws '}'
1781
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1782
44
do_obj1:
1783
44
    cs = detail::count_whitespace(cs.begin(), cs.end());
1784
44
    if(BOOST_JSON_UNLIKELY(! cs))
1785
44
        return maybe_suspend(cs.begin(), state::obj1, size);
1786
0
    if(BOOST_JSON_LIKELY(*cs != '}'))
1787
0
    {
1788
0
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1789
0
        {
1790
0
            if(allow_comments && *cs == '/')
1791
0
            {
1792
6
do_obj2:
1793
6
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1794
6
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1795
6
                    return suspend_or_fail(state::obj2, size);
1796
0
                goto do_obj1;
1797
6
            }
1798
0
            BOOST_STATIC_CONSTEXPR source_location loc
1799
0
                = BOOST_CURRENT_LOCATION;
1800
0
            return fail(cs.begin(), error::syntax, &loc);
1801
0
        }
1802
0
loop:
1803
0
        if(BOOST_JSON_UNLIKELY(++size >
1804
0
            Handler::max_object_size))
1805
0
        {
1806
0
            BOOST_STATIC_CONSTEXPR source_location loc
1807
0
                = BOOST_CURRENT_LOCATION;
1808
0
            return fail(cs.begin(), error::object_too_large, &loc);
1809
0
        }
1810
105
do_obj3:
1811
105
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8);
1812
105
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1813
105
            return suspend_or_fail(state::obj3, size);
1814
58
do_obj4:
1815
58
        cs = detail::count_whitespace(cs.begin(), cs.end());
1816
58
        if(BOOST_JSON_UNLIKELY(! cs))
1817
58
            return maybe_suspend(cs.begin(), state::obj4, size);
1818
0
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1819
0
        {
1820
0
            if(allow_comments && *cs == '/')
1821
0
            {
1822
7
do_obj5:
1823
7
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1824
7
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1825
7
                    return suspend_or_fail(state::obj5, size);
1826
0
                goto do_obj4;
1827
7
            }
1828
0
            BOOST_STATIC_CONSTEXPR source_location loc
1829
0
                = BOOST_CURRENT_LOCATION;
1830
0
            return fail(cs.begin(), error::syntax, &loc);
1831
0
        }
1832
0
        ++cs;
1833
29
do_obj6:
1834
29
        cs = detail::count_whitespace(cs.begin(), cs.end());
1835
29
        if(BOOST_JSON_UNLIKELY(! cs))
1836
29
            return maybe_suspend(cs.begin(), state::obj6, size);
1837
364
do_obj7:
1838
364
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1839
364
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1840
360
            return suspend_or_fail(state::obj7, size);
1841
44
do_obj8:
1842
44
        cs = detail::count_whitespace(cs.begin(), cs.end());
1843
44
        if(BOOST_JSON_UNLIKELY(! cs))
1844
44
            return maybe_suspend(cs.begin(), state::obj8, size);
1845
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1846
0
        {
1847
0
            ++cs;
1848
37
do_obj9:
1849
37
            cs = detail::count_whitespace(cs.begin(), cs.end());
1850
37
            if(BOOST_JSON_UNLIKELY(! cs))
1851
37
                return maybe_suspend(cs.begin(), state::obj9, size);
1852
1853
            // loop for next element
1854
0
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1855
0
                goto loop;
1856
0
            if(! allow_trailing || *cs != '}')
1857
0
            {
1858
0
                if(allow_comments && *cs == '/')
1859
0
                {
1860
9
do_obj10:
1861
9
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1862
9
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1863
9
                        return suspend_or_fail(state::obj10, size);
1864
0
                    goto do_obj9;
1865
9
                }
1866
0
                BOOST_STATIC_CONSTEXPR source_location loc
1867
0
                    = BOOST_CURRENT_LOCATION;
1868
0
                return fail(cs.begin(), error::syntax, &loc);
1869
0
            }
1870
0
        }
1871
0
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1872
0
        {
1873
0
            if(allow_comments && *cs == '/')
1874
0
            {
1875
5
do_obj11:
1876
5
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1877
5
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1878
5
                    return suspend_or_fail(state::obj11, size);
1879
0
                goto do_obj8;
1880
5
            }
1881
0
            BOOST_STATIC_CONSTEXPR source_location loc
1882
0
                = BOOST_CURRENT_LOCATION;
1883
0
            return fail(cs.begin(), error::syntax, &loc);
1884
0
        }
1885
        // got closing brace, fall through
1886
0
    }
1887
0
    if(BOOST_JSON_UNLIKELY(
1888
0
        ! h_.on_object_end(size, ec_)))
1889
0
        return fail(cs.begin());
1890
0
    ++depth_;
1891
0
    ++cs;
1892
0
    return cs.begin();
1893
0
}
1894
1895
//----------------------------------------------------------
1896
1897
template<class Handler>
1898
template<
1899
    bool StackEmpty_,
1900
    bool AllowComments_/*,
1901
    bool AllowTrailing_,
1902
    bool AllowBadUTF8_*/>
1903
const char*
1904
basic_parser<Handler>::
1905
parse_array(const char* p,
1906
    std::integral_constant<bool, StackEmpty_> stack_empty,
1907
    std::integral_constant<bool, AllowComments_> allow_comments,
1908
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1909
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8)
1910
22.0k
{
1911
22.0k
    detail::const_stream_wrapper cs(p, end_);
1912
22.0k
    std::size_t size;
1913
22.0k
    if(! stack_empty && ! st_.empty())
1914
1.77k
    {
1915
        // resume
1916
1.77k
        state st;
1917
1.77k
        st_.pop(st);
1918
1.77k
        st_.pop(size);
1919
1.77k
        switch(st)
1920
1.77k
        {
1921
0
        default: BOOST_JSON_UNREACHABLE();
1922
86
        case state::arr1: goto do_arr1;
1923
16
        case state::arr2: goto do_arr2;
1924
1.27k
        case state::arr3: goto do_arr3;
1925
255
        case state::arr4: goto do_arr4;
1926
146
        case state::arr5: goto do_arr5;
1927
1
        case state::arr6: goto do_arr6;
1928
1.77k
        }
1929
1.77k
    }
1930
20.2k
    BOOST_ASSERT(*cs == '[');
1931
20.2k
    size = 0;
1932
20.2k
    if(BOOST_JSON_UNLIKELY(! depth_))
1933
17
    {
1934
17
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1935
17
        return fail(cs.begin(), error::too_deep, &loc);
1936
17
    }
1937
20.2k
    --depth_;
1938
20.2k
    if(BOOST_JSON_UNLIKELY(
1939
20.2k
        ! h_.on_array_begin(ec_)))
1940
0
        return fail(cs.begin());
1941
20.2k
    ++cs;
1942
    // array:
1943
    //     '[' *ws ']'
1944
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1945
20.7k
do_arr1:
1946
20.7k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1947
20.7k
    if(BOOST_JSON_UNLIKELY(! cs))
1948
211
        return maybe_suspend(cs.begin(), state::arr1, size);
1949
20.5k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1950
17.3k
    {
1951
9.81M
loop:
1952
9.81M
        if(allow_comments && *cs == '/')
1953
463
        {
1954
479
do_arr2:
1955
479
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1956
479
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1957
33
                return suspend_or_fail(state::arr2, size);
1958
446
            goto do_arr1;
1959
479
        }
1960
9.81M
        if(BOOST_JSON_UNLIKELY(++size >
1961
9.81M
            Handler::max_array_size))
1962
0
        {
1963
0
            BOOST_STATIC_CONSTEXPR source_location loc
1964
0
                = BOOST_CURRENT_LOCATION;
1965
0
            return fail(cs.begin(), error::array_too_large, &loc);
1966
0
        }
1967
9.81M
do_arr3:
1968
        // array is not empty, value required
1969
9.81M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1970
9.81M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1971
4.06k
            return suspend_or_fail(state::arr3, size);
1972
9.81M
do_arr4:
1973
9.81M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1974
9.81M
        if(BOOST_JSON_UNLIKELY(! cs))
1975
1.52k
            return maybe_suspend(cs.begin(), state::arr4, size);
1976
9.81M
        if(BOOST_JSON_LIKELY(*cs == ','))
1977
9.80M
        {
1978
9.80M
            ++cs;
1979
9.80M
do_arr5:
1980
9.80M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1981
9.80M
            if(BOOST_JSON_UNLIKELY(! cs))
1982
372
                return maybe_suspend(cs.begin(), state::arr5, size);
1983
            // loop for next element
1984
9.80M
            if(! allow_trailing || *cs != ']')
1985
9.79M
                goto loop;
1986
9.80M
        }
1987
11.8k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1988
1.00k
        {
1989
1.00k
            if(allow_comments && *cs == '/')
1990
198
            {
1991
199
do_arr6:
1992
199
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1993
199
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1994
2
                    return suspend_or_fail(state::arr6, size);
1995
197
                goto do_arr4;
1996
199
            }
1997
804
            BOOST_STATIC_CONSTEXPR source_location loc
1998
804
                = BOOST_CURRENT_LOCATION;
1999
804
            return fail(cs.begin(), error::syntax, &loc);
2000
1.00k
        }
2001
        // got closing bracket; fall through
2002
9.81M
    }
2003
14.8k
    if(BOOST_JSON_UNLIKELY(
2004
14.8k
        ! h_.on_array_end(size, ec_)))
2005
0
        return fail(cs.begin());
2006
14.8k
    ++depth_;
2007
14.8k
    ++cs;
2008
14.8k
    return cs.begin();
2009
14.8k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_array<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
1910
12.0k
{
1911
12.0k
    detail::const_stream_wrapper cs(p, end_);
1912
12.0k
    std::size_t size;
1913
12.0k
    if(! stack_empty && ! st_.empty())
1914
0
    {
1915
        // resume
1916
0
        state st;
1917
0
        st_.pop(st);
1918
0
        st_.pop(size);
1919
0
        switch(st)
1920
0
        {
1921
0
        default: BOOST_JSON_UNREACHABLE();
1922
0
        case state::arr1: goto do_arr1;
1923
0
        case state::arr2: goto do_arr2;
1924
0
        case state::arr3: goto do_arr3;
1925
0
        case state::arr4: goto do_arr4;
1926
0
        case state::arr5: goto do_arr5;
1927
0
        case state::arr6: goto do_arr6;
1928
0
        }
1929
0
    }
1930
12.0k
    BOOST_ASSERT(*cs == '[');
1931
12.0k
    size = 0;
1932
12.0k
    if(BOOST_JSON_UNLIKELY(! depth_))
1933
10
    {
1934
10
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1935
10
        return fail(cs.begin(), error::too_deep, &loc);
1936
10
    }
1937
12.0k
    --depth_;
1938
12.0k
    if(BOOST_JSON_UNLIKELY(
1939
12.0k
        ! h_.on_array_begin(ec_)))
1940
0
        return fail(cs.begin());
1941
12.0k
    ++cs;
1942
    // array:
1943
    //     '[' *ws ']'
1944
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1945
12.0k
do_arr1:
1946
12.0k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1947
12.0k
    if(BOOST_JSON_UNLIKELY(! cs))
1948
78
        return maybe_suspend(cs.begin(), state::arr1, size);
1949
12.0k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1950
9.47k
    {
1951
5.09M
loop:
1952
5.09M
        if(allow_comments && *cs == '/')
1953
0
        {
1954
0
do_arr2:
1955
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1956
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1957
0
                return suspend_or_fail(state::arr2, size);
1958
0
            goto do_arr1;
1959
0
        }
1960
5.09M
        if(BOOST_JSON_UNLIKELY(++size >
1961
5.09M
            Handler::max_array_size))
1962
0
        {
1963
0
            BOOST_STATIC_CONSTEXPR source_location loc
1964
0
                = BOOST_CURRENT_LOCATION;
1965
0
            return fail(cs.begin(), error::array_too_large, &loc);
1966
0
        }
1967
5.09M
do_arr3:
1968
        // array is not empty, value required
1969
5.09M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1970
5.09M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1971
2.30k
            return suspend_or_fail(state::arr3, size);
1972
5.08M
do_arr4:
1973
5.08M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1974
5.08M
        if(BOOST_JSON_UNLIKELY(! cs))
1975
772
            return maybe_suspend(cs.begin(), state::arr4, size);
1976
5.08M
        if(BOOST_JSON_LIKELY(*cs == ','))
1977
5.08M
        {
1978
5.08M
            ++cs;
1979
5.08M
do_arr5:
1980
5.08M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1981
5.08M
            if(BOOST_JSON_UNLIKELY(! cs))
1982
152
                return maybe_suspend(cs.begin(), state::arr5, size);
1983
            // loop for next element
1984
5.08M
            if(! allow_trailing || *cs != ']')
1985
5.08M
                goto loop;
1986
5.08M
        }
1987
6.02k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1988
576
        {
1989
576
            if(allow_comments && *cs == '/')
1990
0
            {
1991
0
do_arr6:
1992
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1993
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1994
0
                    return suspend_or_fail(state::arr6, size);
1995
0
                goto do_arr4;
1996
0
            }
1997
576
            BOOST_STATIC_CONSTEXPR source_location loc
1998
576
                = BOOST_CURRENT_LOCATION;
1999
576
            return fail(cs.begin(), error::syntax, &loc);
2000
576
        }
2001
        // got closing bracket; fall through
2002
5.08M
    }
2003
8.19k
    if(BOOST_JSON_UNLIKELY(
2004
8.19k
        ! h_.on_array_end(size, ec_)))
2005
0
        return fail(cs.begin());
2006
8.19k
    ++depth_;
2007
8.19k
    ++cs;
2008
8.19k
    return cs.begin();
2009
8.19k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_array<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1910
8.17k
{
1911
8.17k
    detail::const_stream_wrapper cs(p, end_);
1912
8.17k
    std::size_t size;
1913
8.17k
    if(! stack_empty && ! st_.empty())
1914
0
    {
1915
        // resume
1916
0
        state st;
1917
0
        st_.pop(st);
1918
0
        st_.pop(size);
1919
0
        switch(st)
1920
0
        {
1921
0
        default: BOOST_JSON_UNREACHABLE();
1922
0
        case state::arr1: goto do_arr1;
1923
0
        case state::arr2: goto do_arr2;
1924
0
        case state::arr3: goto do_arr3;
1925
0
        case state::arr4: goto do_arr4;
1926
0
        case state::arr5: goto do_arr5;
1927
0
        case state::arr6: goto do_arr6;
1928
0
        }
1929
0
    }
1930
8.17k
    BOOST_ASSERT(*cs == '[');
1931
8.17k
    size = 0;
1932
8.17k
    if(BOOST_JSON_UNLIKELY(! depth_))
1933
7
    {
1934
7
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1935
7
        return fail(cs.begin(), error::too_deep, &loc);
1936
7
    }
1937
8.16k
    --depth_;
1938
8.16k
    if(BOOST_JSON_UNLIKELY(
1939
8.16k
        ! h_.on_array_begin(ec_)))
1940
0
        return fail(cs.begin());
1941
8.16k
    ++cs;
1942
    // array:
1943
    //     '[' *ws ']'
1944
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1945
8.61k
do_arr1:
1946
8.61k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1947
8.61k
    if(BOOST_JSON_UNLIKELY(! cs))
1948
47
        return maybe_suspend(cs.begin(), state::arr1, size);
1949
8.56k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1950
7.82k
    {
1951
4.72M
loop:
1952
4.72M
        if(allow_comments && *cs == '/')
1953
463
        {
1954
463
do_arr2:
1955
463
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1956
463
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1957
17
                return suspend_or_fail(state::arr2, size);
1958
446
            goto do_arr1;
1959
463
        }
1960
4.72M
        if(BOOST_JSON_UNLIKELY(++size >
1961
4.72M
            Handler::max_array_size))
1962
0
        {
1963
0
            BOOST_STATIC_CONSTEXPR source_location loc
1964
0
                = BOOST_CURRENT_LOCATION;
1965
0
            return fail(cs.begin(), error::array_too_large, &loc);
1966
0
        }
1967
4.72M
do_arr3:
1968
        // array is not empty, value required
1969
4.72M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1970
4.72M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1971
1.04k
            return suspend_or_fail(state::arr3, size);
1972
4.72M
do_arr4:
1973
4.72M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1974
4.72M
        if(BOOST_JSON_UNLIKELY(! cs))
1975
127
            return maybe_suspend(cs.begin(), state::arr4, size);
1976
4.72M
        if(BOOST_JSON_LIKELY(*cs == ','))
1977
4.71M
        {
1978
4.71M
            ++cs;
1979
4.71M
do_arr5:
1980
4.71M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1981
4.71M
            if(BOOST_JSON_UNLIKELY(! cs))
1982
74
                return maybe_suspend(cs.begin(), state::arr5, size);
1983
            // loop for next element
1984
4.71M
            if(! allow_trailing || *cs != ']')
1985
4.71M
                goto loop;
1986
4.71M
        }
1987
5.78k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1988
426
        {
1989
426
            if(allow_comments && *cs == '/')
1990
198
            {
1991
198
do_arr6:
1992
198
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1993
198
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1994
1
                    return suspend_or_fail(state::arr6, size);
1995
197
                goto do_arr4;
1996
198
            }
1997
228
            BOOST_STATIC_CONSTEXPR source_location loc
1998
228
                = BOOST_CURRENT_LOCATION;
1999
228
            return fail(cs.begin(), error::syntax, &loc);
2000
426
        }
2001
        // got closing bracket; fall through
2002
4.72M
    }
2003
6.62k
    if(BOOST_JSON_UNLIKELY(
2004
6.62k
        ! h_.on_array_end(size, ec_)))
2005
0
        return fail(cs.begin());
2006
6.62k
    ++depth_;
2007
6.62k
    ++cs;
2008
6.62k
    return cs.begin();
2009
6.62k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_array<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
1910
818
{
1911
818
    detail::const_stream_wrapper cs(p, end_);
1912
818
    std::size_t size;
1913
818
    if(! stack_empty && ! st_.empty())
1914
818
    {
1915
        // resume
1916
818
        state st;
1917
818
        st_.pop(st);
1918
818
        st_.pop(size);
1919
818
        switch(st)
1920
818
        {
1921
0
        default: BOOST_JSON_UNREACHABLE();
1922
39
        case state::arr1: goto do_arr1;
1923
0
        case state::arr2: goto do_arr2;
1924
579
        case state::arr3: goto do_arr3;
1925
128
        case state::arr4: goto do_arr4;
1926
72
        case state::arr5: goto do_arr5;
1927
0
        case state::arr6: goto do_arr6;
1928
818
        }
1929
818
    }
1930
0
    BOOST_ASSERT(*cs == '[');
1931
0
    size = 0;
1932
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1933
0
    {
1934
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1935
0
        return fail(cs.begin(), error::too_deep, &loc);
1936
0
    }
1937
0
    --depth_;
1938
0
    if(BOOST_JSON_UNLIKELY(
1939
0
        ! h_.on_array_begin(ec_)))
1940
0
        return fail(cs.begin());
1941
0
    ++cs;
1942
    // array:
1943
    //     '[' *ws ']'
1944
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1945
39
do_arr1:
1946
39
    cs = detail::count_whitespace(cs.begin(), cs.end());
1947
39
    if(BOOST_JSON_UNLIKELY(! cs))
1948
39
        return maybe_suspend(cs.begin(), state::arr1, size);
1949
0
    if(BOOST_JSON_LIKELY(*cs != ']'))
1950
0
    {
1951
0
loop:
1952
0
        if(allow_comments && *cs == '/')
1953
0
        {
1954
0
do_arr2:
1955
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1956
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1957
0
                return suspend_or_fail(state::arr2, size);
1958
0
            goto do_arr1;
1959
0
        }
1960
0
        if(BOOST_JSON_UNLIKELY(++size >
1961
0
            Handler::max_array_size))
1962
0
        {
1963
0
            BOOST_STATIC_CONSTEXPR source_location loc
1964
0
                = BOOST_CURRENT_LOCATION;
1965
0
            return fail(cs.begin(), error::array_too_large, &loc);
1966
0
        }
1967
579
do_arr3:
1968
        // array is not empty, value required
1969
579
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1970
579
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1971
333
            return suspend_or_fail(state::arr3, size);
1972
306
do_arr4:
1973
306
        cs = detail::count_whitespace(cs.begin(), cs.end());
1974
306
        if(BOOST_JSON_UNLIKELY(! cs))
1975
306
            return maybe_suspend(cs.begin(), state::arr4, size);
1976
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1977
0
        {
1978
0
            ++cs;
1979
72
do_arr5:
1980
72
            cs = detail::count_whitespace(cs.begin(), cs.end());
1981
72
            if(BOOST_JSON_UNLIKELY(! cs))
1982
72
                return maybe_suspend(cs.begin(), state::arr5, size);
1983
            // loop for next element
1984
0
            if(! allow_trailing || *cs != ']')
1985
0
                goto loop;
1986
0
        }
1987
0
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1988
0
        {
1989
0
            if(allow_comments && *cs == '/')
1990
0
            {
1991
0
do_arr6:
1992
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1993
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1994
0
                    return suspend_or_fail(state::arr6, size);
1995
0
                goto do_arr4;
1996
0
            }
1997
0
            BOOST_STATIC_CONSTEXPR source_location loc
1998
0
                = BOOST_CURRENT_LOCATION;
1999
0
            return fail(cs.begin(), error::syntax, &loc);
2000
0
        }
2001
        // got closing bracket; fall through
2002
0
    }
2003
0
    if(BOOST_JSON_UNLIKELY(
2004
0
        ! h_.on_array_end(size, ec_)))
2005
0
        return fail(cs.begin());
2006
0
    ++depth_;
2007
0
    ++cs;
2008
0
    return cs.begin();
2009
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_array<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1910
959
{
1911
959
    detail::const_stream_wrapper cs(p, end_);
1912
959
    std::size_t size;
1913
959
    if(! stack_empty && ! st_.empty())
1914
959
    {
1915
        // resume
1916
959
        state st;
1917
959
        st_.pop(st);
1918
959
        st_.pop(size);
1919
959
        switch(st)
1920
959
        {
1921
0
        default: BOOST_JSON_UNREACHABLE();
1922
47
        case state::arr1: goto do_arr1;
1923
16
        case state::arr2: goto do_arr2;
1924
694
        case state::arr3: goto do_arr3;
1925
127
        case state::arr4: goto do_arr4;
1926
74
        case state::arr5: goto do_arr5;
1927
1
        case state::arr6: goto do_arr6;
1928
959
        }
1929
959
    }
1930
0
    BOOST_ASSERT(*cs == '[');
1931
0
    size = 0;
1932
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1933
0
    {
1934
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1935
0
        return fail(cs.begin(), error::too_deep, &loc);
1936
0
    }
1937
0
    --depth_;
1938
0
    if(BOOST_JSON_UNLIKELY(
1939
0
        ! h_.on_array_begin(ec_)))
1940
0
        return fail(cs.begin());
1941
0
    ++cs;
1942
    // array:
1943
    //     '[' *ws ']'
1944
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1945
47
do_arr1:
1946
47
    cs = detail::count_whitespace(cs.begin(), cs.end());
1947
47
    if(BOOST_JSON_UNLIKELY(! cs))
1948
47
        return maybe_suspend(cs.begin(), state::arr1, size);
1949
0
    if(BOOST_JSON_LIKELY(*cs != ']'))
1950
0
    {
1951
0
loop:
1952
0
        if(allow_comments && *cs == '/')
1953
0
        {
1954
16
do_arr2:
1955
16
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1956
16
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1957
16
                return suspend_or_fail(state::arr2, size);
1958
0
            goto do_arr1;
1959
16
        }
1960
0
        if(BOOST_JSON_UNLIKELY(++size >
1961
0
            Handler::max_array_size))
1962
0
        {
1963
0
            BOOST_STATIC_CONSTEXPR source_location loc
1964
0
                = BOOST_CURRENT_LOCATION;
1965
0
            return fail(cs.begin(), error::array_too_large, &loc);
1966
0
        }
1967
694
do_arr3:
1968
        // array is not empty, value required
1969
694
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8);
1970
694
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1971
383
            return suspend_or_fail(state::arr3, size);
1972
324
do_arr4:
1973
324
        cs = detail::count_whitespace(cs.begin(), cs.end());
1974
324
        if(BOOST_JSON_UNLIKELY(! cs))
1975
324
            return maybe_suspend(cs.begin(), state::arr4, size);
1976
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1977
0
        {
1978
0
            ++cs;
1979
74
do_arr5:
1980
74
            cs = detail::count_whitespace(cs.begin(), cs.end());
1981
74
            if(BOOST_JSON_UNLIKELY(! cs))
1982
74
                return maybe_suspend(cs.begin(), state::arr5, size);
1983
            // loop for next element
1984
0
            if(! allow_trailing || *cs != ']')
1985
0
                goto loop;
1986
0
        }
1987
0
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1988
0
        {
1989
0
            if(allow_comments && *cs == '/')
1990
0
            {
1991
1
do_arr6:
1992
1
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1993
1
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1994
1
                    return suspend_or_fail(state::arr6, size);
1995
0
                goto do_arr4;
1996
1
            }
1997
0
            BOOST_STATIC_CONSTEXPR source_location loc
1998
0
                = BOOST_CURRENT_LOCATION;
1999
0
            return fail(cs.begin(), error::syntax, &loc);
2000
0
        }
2001
        // got closing bracket; fall through
2002
0
    }
2003
0
    if(BOOST_JSON_UNLIKELY(
2004
0
        ! h_.on_array_end(size, ec_)))
2005
0
        return fail(cs.begin());
2006
0
    ++depth_;
2007
0
    ++cs;
2008
0
    return cs.begin();
2009
0
}
2010
2011
//----------------------------------------------------------
2012
2013
template<class Handler>
2014
template<bool StackEmpty_, char First_, number_precision Numbers_>
2015
const char*
2016
basic_parser<Handler>::
2017
parse_number(const char* p,
2018
    std::integral_constant<bool, StackEmpty_> stack_empty,
2019
    std::integral_constant<char, First_> first,
2020
    std::integral_constant<number_precision, Numbers_> mode)
2021
10.6M
{
2022
10.6M
    constexpr bool precise_parsing = mode == number_precision::precise;
2023
10.6M
    constexpr bool no_parsing = mode == number_precision::none;
2024
2025
    // only one of these will be true if we are not resuming
2026
    // if negative then !zero_first && !nonzero_first
2027
    // if zero_first then !nonzero_first && !negative
2028
    // if nonzero_first then !zero_first && !negative
2029
10.6M
    bool const negative = first == '-';
2030
10.6M
    bool const zero_first = first == '0';
2031
10.6M
    bool const nonzero_first = first == '+';
2032
10.6M
    detail::const_stream_wrapper cs(p, end_);
2033
10.6M
    number num;
2034
10.6M
    const char* begin = cs.begin();
2035
10.6M
    if(stack_empty || st_.empty())
2036
10.6M
    {
2037
10.6M
        num.bias = 0;
2038
10.6M
        num.exp = 0;
2039
10.6M
        num.frac = false;
2040
10.6M
        num_buf_.clear();
2041
2042
        //----------------------------------
2043
        //
2044
        // '-'
2045
        // leading minus sign
2046
        //
2047
10.6M
        BOOST_ASSERT(cs);
2048
10.6M
        if(negative)
2049
37.1k
            ++cs;
2050
2051
10.6M
        num.neg = negative;
2052
10.6M
        num.frac = false;
2053
10.6M
        num.exp = 0;
2054
10.6M
        num.bias = 0;
2055
2056
        // fast path
2057
10.6M
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2058
10.6M
        {
2059
10.6M
            int n1;
2060
2061
10.6M
            if( nonzero_first ||
2062
10.6M
                (negative && *cs != '0') )
2063
10.3M
            {
2064
10.3M
                n1 = detail::count_digits( cs.begin() );
2065
10.3M
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2066
2067
10.3M
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2068
0
                {
2069
0
                    return parse_literal(
2070
0
                        p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2071
0
                }
2072
2073
10.3M
                if( ! nonzero_first && n1 == 0 )
2074
22
                {
2075
                    // digit required
2076
22
                    BOOST_STATIC_CONSTEXPR source_location loc
2077
22
                        = BOOST_CURRENT_LOCATION;
2078
22
                    return fail(cs.begin(), error::syntax, &loc);
2079
22
                }
2080
2081
10.3M
                BOOST_IF_CONSTEXPR( !no_parsing )
2082
10.3M
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2083
0
                else
2084
0
                    num.mant = 0;
2085
2086
10.3M
                cs += n1;
2087
2088
                // integer or floating-point with
2089
                // >= 16 leading digits
2090
10.3M
                if( n1 == 16 )
2091
52.4k
                {
2092
52.4k
                    goto do_num2;
2093
52.4k
                }
2094
10.3M
            }
2095
229k
            else
2096
229k
            {
2097
                // 0. floating-point or 0e integer
2098
229k
                num.mant = 0;
2099
229k
                n1 = 0;
2100
229k
                ++cs;
2101
229k
            }
2102
2103
10.5M
            {
2104
10.5M
                const char c = *cs;
2105
10.5M
                if(c != '.')
2106
10.5M
                {
2107
10.5M
                    if((c | 32) == 'e')
2108
5.49M
                    {
2109
5.49M
                        ++cs;
2110
5.49M
                        goto do_exp1;
2111
5.49M
                    }
2112
5.04M
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2113
8.57k
                        num.mant = ~num.mant + 1;
2114
5.04M
                    goto finish_signed;
2115
10.5M
                }
2116
10.5M
            }
2117
2118
            // floating-point number
2119
2120
32.7k
            ++cs;
2121
2122
32.7k
            int n2 = detail::count_digits( cs.begin() );
2123
32.7k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2124
2125
32.7k
            if( n2 == 0 )
2126
19
            {
2127
                // digit required
2128
19
                BOOST_STATIC_CONSTEXPR source_location loc
2129
19
                    = BOOST_CURRENT_LOCATION;
2130
19
                return fail(cs.begin(), error::syntax, &loc);
2131
19
            }
2132
2133
            // floating-point mantissa overflow
2134
32.7k
            if( n1 + n2 >= 19 )
2135
2.36k
            {
2136
2.36k
                goto do_num7;
2137
2.36k
            }
2138
2139
30.4k
            BOOST_IF_CONSTEXPR( !no_parsing )
2140
30.4k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2141
2142
30.4k
            BOOST_ASSERT(num.bias == 0);
2143
2144
30.4k
            num.bias -= n2;
2145
2146
30.4k
            cs += n2;
2147
2148
30.4k
            char ch = *cs;
2149
2150
30.4k
            if( (ch | 32) == 'e' )
2151
7.72k
            {
2152
7.72k
                ++cs;
2153
7.72k
                goto do_exp1;
2154
7.72k
            }
2155
22.6k
            else if( ch >= '0' && ch <= '9' )
2156
3.67k
            {
2157
3.67k
                goto do_num8;
2158
3.67k
            }
2159
2160
19.0k
            goto finish_dub;
2161
30.4k
        }
2162
10.6M
    }
2163
3.18k
    else
2164
3.18k
    {
2165
3.18k
        num = num_;
2166
3.18k
        state st;
2167
3.18k
        st_.pop(st);
2168
3.18k
        switch(st)
2169
3.18k
        {
2170
0
        default: BOOST_JSON_UNREACHABLE();
2171
28
        case state::num1: goto do_num1;
2172
809
        case state::num2: goto do_num2;
2173
81
        case state::num3: goto do_num3;
2174
8
        case state::num4: goto do_num4;
2175
101
        case state::num5: goto do_num5;
2176
40
        case state::num6: goto do_num6;
2177
18
        case state::num7: goto do_num7;
2178
1.04k
        case state::num8: goto do_num8;
2179
77
        case state::exp1: goto do_exp1;
2180
37
        case state::exp2: goto do_exp2;
2181
944
        case state::exp3: goto do_exp3;
2182
3.18k
        }
2183
3.18k
    }
2184
2185
    //----------------------------------
2186
    //
2187
    // DIGIT
2188
    // first digit
2189
    //
2190
22.7k
do_num1:
2191
22.7k
    if(zero_first || nonzero_first ||
2192
22.7k
        BOOST_JSON_LIKELY(cs))
2193
22.7k
    {
2194
22.7k
        char const c = *cs;
2195
22.7k
        if(zero_first)
2196
4.23k
        {
2197
4.23k
            ++cs;
2198
4.23k
            num.mant = 0;
2199
4.23k
            goto do_num6;
2200
4.23k
        }
2201
18.4k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2202
18.4k
            c >= '1' && c <= '9'))
2203
17.8k
        {
2204
17.8k
            ++cs;
2205
17.8k
            num.mant = c - '0';
2206
17.8k
        }
2207
603
        else if(BOOST_JSON_UNLIKELY(
2208
603
            c == '0'))
2209
547
        {
2210
547
            ++cs;
2211
547
            num.mant = 0;
2212
547
            goto do_num6;
2213
547
        }
2214
56
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2215
0
        {
2216
0
            st_.push(state::lit1);
2217
0
            cur_lit_ = detail::neg_infinity_literal;
2218
0
            lit_offset_ = 1;
2219
0
            return parse_literal(
2220
0
                cs.begin(), mp11::mp_int<detail::resume_literal>() );
2221
0
        }
2222
56
        else
2223
56
        {
2224
56
            BOOST_STATIC_CONSTEXPR source_location loc
2225
56
                = BOOST_CURRENT_LOCATION;
2226
56
            return fail(cs.begin(), error::syntax, &loc);
2227
56
        }
2228
22.7k
    }
2229
67
    else
2230
67
    {
2231
67
        if(BOOST_JSON_UNLIKELY(
2232
67
            ! h_.on_number_part(
2233
67
                {begin, cs.used(begin)}, ec_)))
2234
0
            return fail(cs.begin());
2235
2236
67
        BOOST_IF_CONSTEXPR( precise_parsing )
2237
0
            num_buf_.append( begin, cs.used(begin) );
2238
67
        return maybe_suspend(
2239
67
            cs.begin(), state::num1, num);
2240
67
    }
2241
2242
    //----------------------------------
2243
    //
2244
    // 1*DIGIT
2245
    // significant digits left of decimal
2246
    //
2247
71.1k
do_num2:
2248
71.1k
    if(negative || (!stack_empty && num.neg))
2249
10.9k
    {
2250
10.9k
        for(;;)
2251
34.3k
        {
2252
34.3k
            if(BOOST_JSON_UNLIKELY(! cs))
2253
654
            {
2254
654
                if(BOOST_JSON_UNLIKELY(more_))
2255
254
                {
2256
254
                    if(BOOST_JSON_UNLIKELY(
2257
254
                        ! h_.on_number_part(
2258
254
                            {begin, cs.used(begin)}, ec_)))
2259
0
                        return fail(cs.begin());
2260
2261
254
                    BOOST_IF_CONSTEXPR( precise_parsing )
2262
0
                        num_buf_.append( begin, cs.used(begin) );
2263
254
                    return suspend(cs.begin(), state::num2, num);
2264
254
                }
2265
400
                goto finish_int;
2266
654
            }
2267
33.7k
            char const c = *cs;
2268
33.7k
            if(BOOST_JSON_LIKELY(
2269
33.7k
                c >= '0' && c <= '9'))
2270
26.6k
            {
2271
26.6k
                ++cs;
2272
                //              9223372036854775808 INT64_MIN
2273
26.6k
                if( num.mant  > 922337203685477580 || (
2274
23.8k
                    num.mant == 922337203685477580 && c > '8'))
2275
3.28k
                    break;
2276
23.3k
                BOOST_IF_CONSTEXPR( !no_parsing )
2277
23.3k
                    num.mant = 10 * num.mant + ( c - '0' );
2278
23.3k
                continue;
2279
26.6k
            }
2280
7.05k
            goto do_num6; // [.eE]
2281
33.7k
        }
2282
10.9k
    }
2283
60.1k
    else
2284
60.1k
    {
2285
60.1k
        for(;;)
2286
207k
        {
2287
207k
            if(BOOST_JSON_UNLIKELY(! cs))
2288
1.42k
            {
2289
1.42k
                if(BOOST_JSON_UNLIKELY(more_))
2290
555
                {
2291
555
                    if(BOOST_JSON_UNLIKELY(
2292
555
                        ! h_.on_number_part(
2293
555
                            {begin, cs.used(begin)}, ec_)))
2294
0
                        return fail(cs.begin());
2295
2296
555
                    BOOST_IF_CONSTEXPR( precise_parsing )
2297
0
                        num_buf_.append( begin, cs.used(begin) );
2298
555
                    return suspend(cs.begin(), state::num2, num);
2299
555
                }
2300
869
                goto finish_int;
2301
1.42k
            }
2302
206k
            char const c = *cs;
2303
206k
            if(BOOST_JSON_LIKELY(
2304
206k
                c >= '0' && c <= '9'))
2305
157k
            {
2306
157k
                ++cs;
2307
                //              18446744073709551615 UINT64_MAX
2308
157k
                if( num.mant  > 1844674407370955161 || (
2309
147k
                    num.mant == 1844674407370955161 && c > '5'))
2310
10.2k
                    break;
2311
147k
                BOOST_IF_CONSTEXPR( !no_parsing )
2312
147k
                    num.mant = 10 * num.mant + ( c - '0' );
2313
147k
            }
2314
48.4k
            else
2315
48.4k
            {
2316
48.4k
                goto do_num6; // [.eE]
2317
48.4k
            }
2318
206k
        }
2319
60.1k
    }
2320
13.5k
    ++num.bias;
2321
2322
    //----------------------------------
2323
    //
2324
    // 1*DIGIT
2325
    // non-significant digits left of decimal
2326
    //
2327
13.6k
do_num3:
2328
13.6k
    for(;;)
2329
23.1M
    {
2330
23.1M
        if(BOOST_JSON_UNLIKELY(! cs))
2331
248
        {
2332
248
            if(BOOST_JSON_UNLIKELY(more_))
2333
81
            {
2334
81
                if(BOOST_JSON_UNLIKELY(
2335
81
                    ! h_.on_number_part(
2336
81
                        {begin, cs.used(begin)}, ec_)))
2337
0
                    return fail(cs.begin());
2338
2339
81
                BOOST_IF_CONSTEXPR( precise_parsing )
2340
0
                    num_buf_.append( begin, cs.used(begin) );
2341
81
                return suspend(cs.begin(), state::num3, num);
2342
81
            }
2343
167
            goto finish_dub;
2344
248
        }
2345
23.1M
        char const c = *cs;
2346
23.1M
        if(BOOST_JSON_UNLIKELY(
2347
23.1M
            c >= '0' && c <= '9'))
2348
23.0M
        {
2349
23.0M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2350
0
            {
2351
0
                BOOST_STATIC_CONSTEXPR source_location loc
2352
0
                    = BOOST_CURRENT_LOCATION;
2353
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2354
0
            }
2355
23.0M
            ++cs;
2356
23.0M
            ++num.bias;
2357
23.0M
        }
2358
13.3k
        else if(BOOST_JSON_LIKELY(
2359
13.3k
            c == '.'))
2360
2.03k
        {
2361
2.03k
            ++cs;
2362
2.03k
            break;
2363
2.03k
        }
2364
11.3k
        else if((c | 32) == 'e')
2365
3.20k
        {
2366
3.20k
            ++cs;
2367
3.20k
            goto do_exp1;
2368
3.20k
        }
2369
8.15k
        else
2370
8.15k
        {
2371
8.15k
            goto finish_dub;
2372
8.15k
        }
2373
23.1M
    }
2374
2375
    //----------------------------------
2376
    //
2377
    // DIGIT
2378
    // first non-significant digit
2379
    // to the right of decimal
2380
    //
2381
2.04k
do_num4:
2382
2.04k
    {
2383
2.04k
        if(BOOST_JSON_UNLIKELY(! cs))
2384
25
        {
2385
25
            if(BOOST_JSON_UNLIKELY(
2386
25
                ! h_.on_number_part(
2387
25
                    {begin, cs.used(begin)}, ec_)))
2388
0
                return fail(cs.begin());
2389
2390
25
            BOOST_IF_CONSTEXPR( precise_parsing )
2391
0
                num_buf_.append( begin, cs.used(begin) );
2392
25
            return maybe_suspend(
2393
25
                cs.begin(), state::num4, num);
2394
25
        }
2395
2.01k
        char const c = *cs;
2396
2.01k
        if(BOOST_JSON_LIKELY(
2397
            //static_cast<unsigned char>(c - '0') < 10))
2398
2.01k
            c >= '0' && c <= '9'))
2399
1.98k
        {
2400
1.98k
            ++cs;
2401
1.98k
        }
2402
31
        else
2403
31
        {
2404
            // digit required
2405
31
            BOOST_STATIC_CONSTEXPR source_location loc
2406
31
                = BOOST_CURRENT_LOCATION;
2407
31
            return fail(cs.begin(), error::syntax, &loc);
2408
31
        }
2409
2.01k
    }
2410
2411
    //----------------------------------
2412
    //
2413
    // 1*DIGIT
2414
    // non-significant digits
2415
    // to the right of decimal
2416
    //
2417
11.8k
do_num5:
2418
11.8k
    for(;;)
2419
47.4k
    {
2420
47.4k
        if(BOOST_JSON_UNLIKELY(! cs))
2421
300
        {
2422
300
            if(BOOST_JSON_UNLIKELY(more_))
2423
101
            {
2424
101
                if(BOOST_JSON_UNLIKELY(
2425
101
                    ! h_.on_number_part(
2426
101
                        {begin, cs.used(begin)}, ec_)))
2427
0
                    return fail(cs.begin());
2428
2429
101
                BOOST_IF_CONSTEXPR( precise_parsing )
2430
0
                    num_buf_.append( begin, cs.used(begin) );
2431
101
                return suspend(cs.begin(), state::num5, num);
2432
101
            }
2433
199
            goto finish_dub;
2434
300
        }
2435
47.1k
        char const c = *cs;
2436
47.1k
        if(BOOST_JSON_LIKELY(
2437
47.1k
            c >= '0' && c <= '9'))
2438
35.6k
        {
2439
35.6k
            ++cs;
2440
35.6k
        }
2441
11.5k
        else if((c | 32) == 'e')
2442
1.46k
        {
2443
1.46k
            ++cs;
2444
1.46k
            goto do_exp1;
2445
1.46k
        }
2446
10.1k
        else
2447
10.1k
        {
2448
10.1k
            goto finish_dub;
2449
10.1k
        }
2450
47.1k
    }
2451
2452
    //----------------------------------
2453
    //
2454
    // [.eE]
2455
    //
2456
60.3k
do_num6:
2457
60.3k
    {
2458
60.3k
        if(BOOST_JSON_UNLIKELY(! cs))
2459
97
        {
2460
97
            if(BOOST_JSON_UNLIKELY(more_))
2461
40
            {
2462
40
                if(BOOST_JSON_UNLIKELY(
2463
40
                    ! h_.on_number_part(
2464
40
                        {begin, cs.used(begin)}, ec_)))
2465
0
                    return fail(cs.begin());
2466
2467
40
                BOOST_IF_CONSTEXPR( precise_parsing )
2468
0
                    num_buf_.append( begin, cs.used(begin) );
2469
40
                return suspend(cs.begin(), state::num6, num);
2470
40
            }
2471
57
            goto finish_int;
2472
97
        }
2473
60.2k
        char const c = *cs;
2474
60.2k
        if(BOOST_JSON_LIKELY(
2475
60.2k
            c == '.'))
2476
10.0k
        {
2477
10.0k
            ++cs;
2478
10.0k
        }
2479
50.1k
        else if((c | 32) == 'e')
2480
7.28k
        {
2481
7.28k
            ++cs;
2482
7.28k
            goto do_exp1;
2483
7.28k
        }
2484
42.9k
        else
2485
42.9k
        {
2486
42.9k
            goto finish_int;
2487
42.9k
        }
2488
60.2k
    }
2489
2490
    //----------------------------------
2491
    //
2492
    // DIGIT
2493
    // first significant digit
2494
    // to the right of decimal
2495
    //
2496
12.4k
do_num7:
2497
12.4k
    {
2498
12.4k
        if(BOOST_JSON_UNLIKELY(! cs))
2499
54
        {
2500
54
            if(BOOST_JSON_UNLIKELY(more_))
2501
18
            {
2502
18
                if(BOOST_JSON_UNLIKELY(
2503
18
                    ! h_.on_number_part(
2504
18
                        {begin, cs.used(begin)}, ec_)))
2505
0
                    return fail(cs.begin());
2506
2507
18
                BOOST_IF_CONSTEXPR( precise_parsing )
2508
0
                    num_buf_.append( begin, cs.used(begin) );
2509
18
                return suspend(cs.begin(), state::num7, num);
2510
18
            }
2511
            // digit required
2512
36
            BOOST_STATIC_CONSTEXPR source_location loc
2513
36
                = BOOST_CURRENT_LOCATION;
2514
36
            return fail(cs.begin(), error::syntax, &loc);
2515
54
        }
2516
12.3k
        char const c = *cs;
2517
12.3k
        if(BOOST_JSON_UNLIKELY(
2518
12.3k
            c < '0' || c > '9'))
2519
82
        {
2520
            // digit required
2521
82
            BOOST_STATIC_CONSTEXPR source_location loc
2522
82
                = BOOST_CURRENT_LOCATION;
2523
82
            return fail(cs.begin(), error::syntax, &loc);
2524
82
        }
2525
12.3k
    }
2526
2527
    //----------------------------------
2528
    //
2529
    // 1*DIGIT
2530
    // significant digits
2531
    // to the right of decimal
2532
    //
2533
17.0k
do_num8:
2534
17.0k
    for(;;)
2535
23.6M
    {
2536
23.6M
        if(BOOST_JSON_UNLIKELY(! cs))
2537
2.45k
        {
2538
2.45k
            if(BOOST_JSON_UNLIKELY(more_))
2539
1.04k
            {
2540
1.04k
                if(BOOST_JSON_UNLIKELY(
2541
1.04k
                    ! h_.on_number_part(
2542
1.04k
                        {begin, cs.used(begin)}, ec_)))
2543
0
                    return fail(cs.begin());
2544
2545
1.04k
                BOOST_IF_CONSTEXPR( precise_parsing )
2546
0
                    num_buf_.append( begin, cs.used(begin) );
2547
1.04k
                return suspend(cs.begin(), state::num8, num);
2548
1.04k
            }
2549
1.41k
            goto finish_dub;
2550
2.45k
        }
2551
23.6M
        char const c = *cs;
2552
23.6M
        if(BOOST_JSON_LIKELY(
2553
23.6M
            c >= '0' && c <= '9'))
2554
23.6M
        {
2555
23.6M
            ++cs;
2556
23.6M
            if(!no_parsing && BOOST_JSON_LIKELY(
2557
23.6M
                num.mant <= 9007199254740991)) // 2^53-1
2558
23.6M
            {
2559
23.6M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2560
0
                {
2561
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2562
0
                        = BOOST_CURRENT_LOCATION;
2563
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2564
0
                }
2565
23.6M
                --num.bias;
2566
23.6M
                num.mant = 10 * num.mant + ( c - '0' );
2567
23.6M
            }
2568
9.80k
            else
2569
9.80k
            {
2570
9.80k
                goto do_num5;
2571
9.80k
            }
2572
23.6M
        }
2573
4.76k
        else if((c | 32) == 'e')
2574
1.75k
        {
2575
1.75k
            ++cs;
2576
1.75k
            goto do_exp1;
2577
1.75k
        }
2578
3.00k
        else
2579
3.00k
        {
2580
3.00k
            goto finish_dub;
2581
3.00k
        }
2582
23.6M
    }
2583
2584
    //----------------------------------
2585
    //
2586
    // *[+-]
2587
    //
2588
5.51M
do_exp1:
2589
5.51M
    if(BOOST_JSON_UNLIKELY(! cs))
2590
247
    {
2591
247
        if(BOOST_JSON_UNLIKELY(
2592
247
            ! h_.on_number_part(
2593
247
                {begin, cs.used(begin)}, ec_)))
2594
0
            return fail(cs.begin());
2595
2596
247
        BOOST_IF_CONSTEXPR( precise_parsing )
2597
0
            num_buf_.append( begin, cs.used(begin) );
2598
247
        return maybe_suspend(
2599
247
            cs.begin(), state::exp1, num);
2600
247
    }
2601
5.51M
    if(*cs == '+')
2602
2.38k
    {
2603
2.38k
        ++cs;
2604
2.38k
    }
2605
5.50M
    else if(*cs == '-')
2606
77.7k
    {
2607
77.7k
        ++cs;
2608
77.7k
        num.frac = true;
2609
77.7k
    }
2610
2611
    //----------------------------------
2612
    //
2613
    // DIGIT
2614
    // first digit of the exponent
2615
    //
2616
5.51M
do_exp2:
2617
5.51M
    {
2618
5.51M
        if(BOOST_JSON_UNLIKELY(! cs))
2619
114
        {
2620
114
            if(BOOST_JSON_UNLIKELY(more_))
2621
37
            {
2622
37
                if(BOOST_JSON_UNLIKELY(
2623
37
                    ! h_.on_number_part(
2624
37
                        {begin, cs.used(begin)}, ec_)))
2625
0
                    return fail(cs.begin());
2626
2627
37
                BOOST_IF_CONSTEXPR( precise_parsing )
2628
0
                    num_buf_.append( begin, cs.used(begin) );
2629
37
                return suspend(cs.begin(), state::exp2, num);
2630
37
            }
2631
            // digit required
2632
77
            BOOST_STATIC_CONSTEXPR source_location loc
2633
77
                = BOOST_CURRENT_LOCATION;
2634
77
            return fail(cs.begin(), error::syntax, &loc);
2635
114
        }
2636
5.51M
        char const c = *cs;
2637
5.51M
        if(BOOST_JSON_UNLIKELY(
2638
5.51M
            c < '0' || c > '9'))
2639
165
        {
2640
            // digit required
2641
165
            BOOST_STATIC_CONSTEXPR source_location loc
2642
165
                = BOOST_CURRENT_LOCATION;
2643
165
            return fail(cs.begin(), error::syntax, &loc);
2644
165
        }
2645
5.51M
        ++cs;
2646
5.51M
        num.exp = c - '0';
2647
5.51M
    }
2648
2649
    //----------------------------------
2650
    //
2651
    // 1*DIGIT
2652
    // subsequent digits in the exponent
2653
    //
2654
5.51M
do_exp3:
2655
5.51M
    for(;;)
2656
11.1M
    {
2657
11.1M
        if(BOOST_JSON_UNLIKELY(! cs))
2658
3.08k
        {
2659
3.08k
            if(BOOST_JSON_UNLIKELY(more_))
2660
944
            {
2661
944
                if(BOOST_JSON_UNLIKELY(
2662
944
                    ! h_.on_number_part(
2663
944
                        {begin, cs.used(begin)}, ec_)))
2664
0
                    return fail(cs.begin());
2665
2666
944
                BOOST_IF_CONSTEXPR( precise_parsing )
2667
0
                    num_buf_.append( begin, cs.used(begin) );
2668
944
                return suspend(cs.begin(), state::exp3, num);
2669
944
            }
2670
3.08k
        }
2671
11.1M
        else
2672
11.1M
        {
2673
11.1M
            char const c = *cs;
2674
11.1M
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2675
5.63M
            {
2676
5.63M
                if(BOOST_JSON_UNLIKELY(
2677
                //              2147483647 INT_MAX
2678
5.63M
                    num.exp  >  214748364 ||
2679
5.63M
                    (num.exp == 214748364 && c > '7')
2680
5.63M
                ))
2681
30.0k
                    num.exp = INT_MAX;
2682
5.60M
                else BOOST_IF_CONSTEXPR( !no_parsing )
2683
5.60M
                    num.exp = 10 * num.exp + ( c - '0' );
2684
2685
5.63M
                ++cs;
2686
5.63M
                continue;
2687
5.63M
            }
2688
11.1M
        }
2689
5.51M
        BOOST_ASSERT(num.exp >= 0);
2690
5.51M
        if ( num.frac )
2691
77.7k
        {
2692
77.7k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2693
3.93k
            {
2694
                // if exponent overflowed, bias is a very large negative
2695
                // number, and mantissa isn't zero, then we cannot parse the
2696
                // number correctly
2697
3.93k
                if(BOOST_JSON_UNLIKELY(
2698
3.93k
                    (num.exp == INT_MAX) &&
2699
3.93k
                    (num.bias < 0) &&
2700
3.93k
                    (num.exp + num.bias < 308) &&
2701
3.93k
                    num.mant ))
2702
0
                {
2703
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2704
0
                        = BOOST_CURRENT_LOCATION;
2705
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2706
0
                }
2707
2708
3.93k
                num.bias = 0;
2709
3.93k
                num.exp = INT_MAX;
2710
3.93k
            }
2711
77.7k
        }
2712
5.43M
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2713
1.85k
        {
2714
            // if exponent overflowed, bias is a very large positive number,
2715
            // and mantissa isn't zero, then we cannot parse the
2716
            // number correctly
2717
1.85k
            if(BOOST_JSON_UNLIKELY(
2718
1.85k
                (num.exp == INT_MAX) &&
2719
1.85k
                (num.bias > 0) &&
2720
1.85k
                (num.exp - num.bias < 308) &&
2721
1.85k
                num.mant ))
2722
0
            {
2723
0
                BOOST_STATIC_CONSTEXPR source_location loc
2724
0
                    = BOOST_CURRENT_LOCATION;
2725
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2726
0
            }
2727
2728
1.85k
            num.bias = 0;
2729
1.85k
            num.exp = INT_MAX;
2730
1.85k
        }
2731
5.51M
        goto finish_dub;
2732
5.51M
    }
2733
2734
44.2k
finish_int:
2735
44.2k
    if(negative || (!stack_empty && num.neg))
2736
4.36k
    {
2737
4.36k
        if(BOOST_JSON_UNLIKELY(
2738
4.36k
            ! h_.on_int64(static_cast<
2739
4.36k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
4.36k
        return cs.begin();
2742
4.36k
    }
2743
39.8k
    if(num.mant <= INT64_MAX)
2744
16.6k
    {
2745
5.05M
finish_signed:
2746
5.05M
        if(BOOST_JSON_UNLIKELY(
2747
5.05M
            ! h_.on_int64(static_cast<
2748
5.05M
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2749
0
            return fail(cs.begin());
2750
5.05M
        return cs.begin();
2751
5.05M
    }
2752
23.2k
    if(BOOST_JSON_UNLIKELY(
2753
23.2k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2754
0
        return fail(cs.begin());
2755
23.2k
    return cs.begin();
2756
5.55M
finish_dub:
2757
5.55M
    double d;
2758
5.55M
    std::size_t const size = cs.used(begin);
2759
5.55M
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2760
5.55M
    BOOST_IF_CONSTEXPR( precise_parsing )
2761
0
    {
2762
0
        char const* data = begin;
2763
0
        std::size_t full_size = size;
2764
         // if we previously suspended or if the current input ends with the
2765
         // number, we need to copy the current part of the number to the
2766
         // temporary buffer
2767
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2768
0
        {
2769
0
            data = num_buf_.append( begin, size );
2770
0
            full_size = num_buf_.size();
2771
0
        }
2772
0
        auto const err = detail::charconv::from_chars(
2773
0
            data, data + full_size, d );
2774
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2775
0
        BOOST_ASSERT( err.ptr == data + full_size );
2776
0
        (void)err;
2777
0
    }
2778
5.55M
    else BOOST_IF_CONSTEXPR( no_parsing )
2779
0
        d = 0;
2780
5.55M
    else
2781
5.55M
        d = detail::dec_to_float(
2782
5.55M
            num.mant,
2783
5.55M
            num.bias + (num.frac ?
2784
5.47M
                -num.exp : num.exp),
2785
5.55M
            num.neg);
2786
5.55M
    if(BOOST_JSON_UNLIKELY(
2787
5.55M
        ! h_.on_double(d, {begin, size}, ec_)))
2788
0
        return fail(cs.begin());
2789
5.55M
    return cs.begin();
2790
5.55M
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)48, (boost::json::number_precision)0>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)0>)
Line
Count
Source
2021
228k
{
2022
228k
    constexpr bool precise_parsing = mode == number_precision::precise;
2023
228k
    constexpr bool no_parsing = mode == number_precision::none;
2024
2025
    // only one of these will be true if we are not resuming
2026
    // if negative then !zero_first && !nonzero_first
2027
    // if zero_first then !nonzero_first && !negative
2028
    // if nonzero_first then !zero_first && !negative
2029
228k
    bool const negative = first == '-';
2030
228k
    bool const zero_first = first == '0';
2031
228k
    bool const nonzero_first = first == '+';
2032
228k
    detail::const_stream_wrapper cs(p, end_);
2033
228k
    number num;
2034
228k
    const char* begin = cs.begin();
2035
228k
    if(stack_empty || st_.empty())
2036
228k
    {
2037
228k
        num.bias = 0;
2038
228k
        num.exp = 0;
2039
228k
        num.frac = false;
2040
228k
        num_buf_.clear();
2041
2042
        //----------------------------------
2043
        //
2044
        // '-'
2045
        // leading minus sign
2046
        //
2047
228k
        BOOST_ASSERT(cs);
2048
228k
        if(negative)
2049
0
            ++cs;
2050
2051
228k
        num.neg = negative;
2052
228k
        num.frac = false;
2053
228k
        num.exp = 0;
2054
228k
        num.bias = 0;
2055
2056
        // fast path
2057
228k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2058
224k
        {
2059
224k
            int n1;
2060
2061
224k
            if( nonzero_first ||
2062
224k
                (negative && *cs != '0') )
2063
0
            {
2064
0
                n1 = detail::count_digits( cs.begin() );
2065
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2066
2067
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2068
0
                {
2069
0
                    return parse_literal(
2070
0
                        p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2071
0
                }
2072
2073
0
                if( ! nonzero_first && n1 == 0 )
2074
0
                {
2075
                    // digit required
2076
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2077
0
                        = BOOST_CURRENT_LOCATION;
2078
0
                    return fail(cs.begin(), error::syntax, &loc);
2079
0
                }
2080
2081
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2082
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2083
0
                else
2084
0
                    num.mant = 0;
2085
2086
0
                cs += n1;
2087
2088
                // integer or floating-point with
2089
                // >= 16 leading digits
2090
0
                if( n1 == 16 )
2091
0
                {
2092
0
                    goto do_num2;
2093
0
                }
2094
0
            }
2095
224k
            else
2096
224k
            {
2097
                // 0. floating-point or 0e integer
2098
224k
                num.mant = 0;
2099
224k
                n1 = 0;
2100
224k
                ++cs;
2101
224k
            }
2102
2103
224k
            {
2104
224k
                const char c = *cs;
2105
224k
                if(c != '.')
2106
216k
                {
2107
216k
                    if((c | 32) == 'e')
2108
8.37k
                    {
2109
8.37k
                        ++cs;
2110
8.37k
                        goto do_exp1;
2111
8.37k
                    }
2112
208k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2113
0
                        num.mant = ~num.mant + 1;
2114
208k
                    goto finish_signed;
2115
216k
                }
2116
224k
            }
2117
2118
            // floating-point number
2119
2120
7.41k
            ++cs;
2121
2122
7.41k
            int n2 = detail::count_digits( cs.begin() );
2123
7.41k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2124
2125
7.41k
            if( n2 == 0 )
2126
5
            {
2127
                // digit required
2128
5
                BOOST_STATIC_CONSTEXPR source_location loc
2129
5
                    = BOOST_CURRENT_LOCATION;
2130
5
                return fail(cs.begin(), error::syntax, &loc);
2131
5
            }
2132
2133
            // floating-point mantissa overflow
2134
7.40k
            if( n1 + n2 >= 19 )
2135
0
            {
2136
0
                goto do_num7;
2137
0
            }
2138
2139
7.40k
            BOOST_IF_CONSTEXPR( !no_parsing )
2140
7.40k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2141
2142
7.40k
            BOOST_ASSERT(num.bias == 0);
2143
2144
7.40k
            num.bias -= n2;
2145
2146
7.40k
            cs += n2;
2147
2148
7.40k
            char ch = *cs;
2149
2150
7.40k
            if( (ch | 32) == 'e' )
2151
2.30k
            {
2152
2.30k
                ++cs;
2153
2.30k
                goto do_exp1;
2154
2.30k
            }
2155
5.10k
            else if( ch >= '0' && ch <= '9' )
2156
2.03k
            {
2157
2.03k
                goto do_num8;
2158
2.03k
            }
2159
2160
3.06k
            goto finish_dub;
2161
7.40k
        }
2162
228k
    }
2163
0
    else
2164
0
    {
2165
0
        num = num_;
2166
0
        state st;
2167
0
        st_.pop(st);
2168
0
        switch(st)
2169
0
        {
2170
0
        default: BOOST_JSON_UNREACHABLE();
2171
0
        case state::num1: goto do_num1;
2172
0
        case state::num2: goto do_num2;
2173
0
        case state::num3: goto do_num3;
2174
0
        case state::num4: goto do_num4;
2175
0
        case state::num5: goto do_num5;
2176
0
        case state::num6: goto do_num6;
2177
0
        case state::num7: goto do_num7;
2178
0
        case state::num8: goto do_num8;
2179
0
        case state::exp1: goto do_exp1;
2180
0
        case state::exp2: goto do_exp2;
2181
0
        case state::exp3: goto do_exp3;
2182
0
        }
2183
0
    }
2184
2185
    //----------------------------------
2186
    //
2187
    // DIGIT
2188
    // first digit
2189
    //
2190
4.23k
do_num1:
2191
4.23k
    if(zero_first || nonzero_first ||
2192
4.23k
        BOOST_JSON_LIKELY(cs))
2193
4.23k
    {
2194
4.23k
        char const c = *cs;
2195
4.23k
        if(zero_first)
2196
4.23k
        {
2197
4.23k
            ++cs;
2198
4.23k
            num.mant = 0;
2199
4.23k
            goto do_num6;
2200
4.23k
        }
2201
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2202
0
            c >= '1' && c <= '9'))
2203
0
        {
2204
0
            ++cs;
2205
0
            num.mant = c - '0';
2206
0
        }
2207
0
        else if(BOOST_JSON_UNLIKELY(
2208
0
            c == '0'))
2209
0
        {
2210
0
            ++cs;
2211
0
            num.mant = 0;
2212
0
            goto do_num6;
2213
0
        }
2214
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2215
0
        {
2216
0
            st_.push(state::lit1);
2217
0
            cur_lit_ = detail::neg_infinity_literal;
2218
0
            lit_offset_ = 1;
2219
0
            return parse_literal(
2220
0
                cs.begin(), mp11::mp_int<detail::resume_literal>() );
2221
0
        }
2222
0
        else
2223
0
        {
2224
0
            BOOST_STATIC_CONSTEXPR source_location loc
2225
0
                = BOOST_CURRENT_LOCATION;
2226
0
            return fail(cs.begin(), error::syntax, &loc);
2227
0
        }
2228
4.23k
    }
2229
0
    else
2230
0
    {
2231
0
        if(BOOST_JSON_UNLIKELY(
2232
0
            ! h_.on_number_part(
2233
0
                {begin, cs.used(begin)}, ec_)))
2234
0
            return fail(cs.begin());
2235
2236
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2237
0
            num_buf_.append( begin, cs.used(begin) );
2238
0
        return maybe_suspend(
2239
0
            cs.begin(), state::num1, num);
2240
0
    }
2241
2242
    //----------------------------------
2243
    //
2244
    // 1*DIGIT
2245
    // significant digits left of decimal
2246
    //
2247
0
do_num2:
2248
0
    if(negative || (!stack_empty && num.neg))
2249
0
    {
2250
0
        for(;;)
2251
0
        {
2252
0
            if(BOOST_JSON_UNLIKELY(! cs))
2253
0
            {
2254
0
                if(BOOST_JSON_UNLIKELY(more_))
2255
0
                {
2256
0
                    if(BOOST_JSON_UNLIKELY(
2257
0
                        ! h_.on_number_part(
2258
0
                            {begin, cs.used(begin)}, ec_)))
2259
0
                        return fail(cs.begin());
2260
2261
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2262
0
                        num_buf_.append( begin, cs.used(begin) );
2263
0
                    return suspend(cs.begin(), state::num2, num);
2264
0
                }
2265
0
                goto finish_int;
2266
0
            }
2267
0
            char const c = *cs;
2268
0
            if(BOOST_JSON_LIKELY(
2269
0
                c >= '0' && c <= '9'))
2270
0
            {
2271
0
                ++cs;
2272
                //              9223372036854775808 INT64_MIN
2273
0
                if( num.mant  > 922337203685477580 || (
2274
0
                    num.mant == 922337203685477580 && c > '8'))
2275
0
                    break;
2276
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2277
0
                    num.mant = 10 * num.mant + ( c - '0' );
2278
0
                continue;
2279
0
            }
2280
0
            goto do_num6; // [.eE]
2281
0
        }
2282
0
    }
2283
0
    else
2284
0
    {
2285
0
        for(;;)
2286
0
        {
2287
0
            if(BOOST_JSON_UNLIKELY(! cs))
2288
0
            {
2289
0
                if(BOOST_JSON_UNLIKELY(more_))
2290
0
                {
2291
0
                    if(BOOST_JSON_UNLIKELY(
2292
0
                        ! h_.on_number_part(
2293
0
                            {begin, cs.used(begin)}, ec_)))
2294
0
                        return fail(cs.begin());
2295
2296
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2297
0
                        num_buf_.append( begin, cs.used(begin) );
2298
0
                    return suspend(cs.begin(), state::num2, num);
2299
0
                }
2300
0
                goto finish_int;
2301
0
            }
2302
0
            char const c = *cs;
2303
0
            if(BOOST_JSON_LIKELY(
2304
0
                c >= '0' && c <= '9'))
2305
0
            {
2306
0
                ++cs;
2307
                //              18446744073709551615 UINT64_MAX
2308
0
                if( num.mant  > 1844674407370955161 || (
2309
0
                    num.mant == 1844674407370955161 && c > '5'))
2310
0
                    break;
2311
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2312
0
                    num.mant = 10 * num.mant + ( c - '0' );
2313
0
            }
2314
0
            else
2315
0
            {
2316
0
                goto do_num6; // [.eE]
2317
0
            }
2318
0
        }
2319
0
    }
2320
0
    ++num.bias;
2321
2322
    //----------------------------------
2323
    //
2324
    // 1*DIGIT
2325
    // non-significant digits left of decimal
2326
    //
2327
0
do_num3:
2328
0
    for(;;)
2329
0
    {
2330
0
        if(BOOST_JSON_UNLIKELY(! cs))
2331
0
        {
2332
0
            if(BOOST_JSON_UNLIKELY(more_))
2333
0
            {
2334
0
                if(BOOST_JSON_UNLIKELY(
2335
0
                    ! h_.on_number_part(
2336
0
                        {begin, cs.used(begin)}, ec_)))
2337
0
                    return fail(cs.begin());
2338
2339
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2340
0
                    num_buf_.append( begin, cs.used(begin) );
2341
0
                return suspend(cs.begin(), state::num3, num);
2342
0
            }
2343
0
            goto finish_dub;
2344
0
        }
2345
0
        char const c = *cs;
2346
0
        if(BOOST_JSON_UNLIKELY(
2347
0
            c >= '0' && c <= '9'))
2348
0
        {
2349
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2350
0
            {
2351
0
                BOOST_STATIC_CONSTEXPR source_location loc
2352
0
                    = BOOST_CURRENT_LOCATION;
2353
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2354
0
            }
2355
0
            ++cs;
2356
0
            ++num.bias;
2357
0
        }
2358
0
        else if(BOOST_JSON_LIKELY(
2359
0
            c == '.'))
2360
0
        {
2361
0
            ++cs;
2362
0
            break;
2363
0
        }
2364
0
        else if((c | 32) == 'e')
2365
0
        {
2366
0
            ++cs;
2367
0
            goto do_exp1;
2368
0
        }
2369
0
        else
2370
0
        {
2371
0
            goto finish_dub;
2372
0
        }
2373
0
    }
2374
2375
    //----------------------------------
2376
    //
2377
    // DIGIT
2378
    // first non-significant digit
2379
    // to the right of decimal
2380
    //
2381
0
do_num4:
2382
0
    {
2383
0
        if(BOOST_JSON_UNLIKELY(! cs))
2384
0
        {
2385
0
            if(BOOST_JSON_UNLIKELY(
2386
0
                ! h_.on_number_part(
2387
0
                    {begin, cs.used(begin)}, ec_)))
2388
0
                return fail(cs.begin());
2389
2390
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2391
0
                num_buf_.append( begin, cs.used(begin) );
2392
0
            return maybe_suspend(
2393
0
                cs.begin(), state::num4, num);
2394
0
        }
2395
0
        char const c = *cs;
2396
0
        if(BOOST_JSON_LIKELY(
2397
            //static_cast<unsigned char>(c - '0') < 10))
2398
0
            c >= '0' && c <= '9'))
2399
0
        {
2400
0
            ++cs;
2401
0
        }
2402
0
        else
2403
0
        {
2404
            // digit required
2405
0
            BOOST_STATIC_CONSTEXPR source_location loc
2406
0
                = BOOST_CURRENT_LOCATION;
2407
0
            return fail(cs.begin(), error::syntax, &loc);
2408
0
        }
2409
0
    }
2410
2411
    //----------------------------------
2412
    //
2413
    // 1*DIGIT
2414
    // non-significant digits
2415
    // to the right of decimal
2416
    //
2417
1.07k
do_num5:
2418
1.07k
    for(;;)
2419
2.21k
    {
2420
2.21k
        if(BOOST_JSON_UNLIKELY(! cs))
2421
30
        {
2422
30
            if(BOOST_JSON_UNLIKELY(more_))
2423
15
            {
2424
15
                if(BOOST_JSON_UNLIKELY(
2425
15
                    ! h_.on_number_part(
2426
15
                        {begin, cs.used(begin)}, ec_)))
2427
0
                    return fail(cs.begin());
2428
2429
15
                BOOST_IF_CONSTEXPR( precise_parsing )
2430
0
                    num_buf_.append( begin, cs.used(begin) );
2431
15
                return suspend(cs.begin(), state::num5, num);
2432
15
            }
2433
15
            goto finish_dub;
2434
30
        }
2435
2.18k
        char const c = *cs;
2436
2.18k
        if(BOOST_JSON_LIKELY(
2437
2.18k
            c >= '0' && c <= '9'))
2438
1.14k
        {
2439
1.14k
            ++cs;
2440
1.14k
        }
2441
1.04k
        else if((c | 32) == 'e')
2442
415
        {
2443
415
            ++cs;
2444
415
            goto do_exp1;
2445
415
        }
2446
631
        else
2447
631
        {
2448
631
            goto finish_dub;
2449
631
        }
2450
2.18k
    }
2451
2452
    //----------------------------------
2453
    //
2454
    // [.eE]
2455
    //
2456
4.23k
do_num6:
2457
4.23k
    {
2458
4.23k
        if(BOOST_JSON_UNLIKELY(! cs))
2459
47
        {
2460
47
            if(BOOST_JSON_UNLIKELY(more_))
2461
35
            {
2462
35
                if(BOOST_JSON_UNLIKELY(
2463
35
                    ! h_.on_number_part(
2464
35
                        {begin, cs.used(begin)}, ec_)))
2465
0
                    return fail(cs.begin());
2466
2467
35
                BOOST_IF_CONSTEXPR( precise_parsing )
2468
0
                    num_buf_.append( begin, cs.used(begin) );
2469
35
                return suspend(cs.begin(), state::num6, num);
2470
35
            }
2471
12
            goto finish_int;
2472
47
        }
2473
4.18k
        char const c = *cs;
2474
4.18k
        if(BOOST_JSON_LIKELY(
2475
4.18k
            c == '.'))
2476
825
        {
2477
825
            ++cs;
2478
825
        }
2479
3.36k
        else if((c | 32) == 'e')
2480
1.15k
        {
2481
1.15k
            ++cs;
2482
1.15k
            goto do_exp1;
2483
1.15k
        }
2484
2.20k
        else
2485
2.20k
        {
2486
2.20k
            goto finish_int;
2487
2.20k
        }
2488
4.18k
    }
2489
2490
    //----------------------------------
2491
    //
2492
    // DIGIT
2493
    // first significant digit
2494
    // to the right of decimal
2495
    //
2496
825
do_num7:
2497
825
    {
2498
825
        if(BOOST_JSON_UNLIKELY(! cs))
2499
10
        {
2500
10
            if(BOOST_JSON_UNLIKELY(more_))
2501
5
            {
2502
5
                if(BOOST_JSON_UNLIKELY(
2503
5
                    ! h_.on_number_part(
2504
5
                        {begin, cs.used(begin)}, ec_)))
2505
0
                    return fail(cs.begin());
2506
2507
5
                BOOST_IF_CONSTEXPR( precise_parsing )
2508
0
                    num_buf_.append( begin, cs.used(begin) );
2509
5
                return suspend(cs.begin(), state::num7, num);
2510
5
            }
2511
            // digit required
2512
5
            BOOST_STATIC_CONSTEXPR source_location loc
2513
5
                = BOOST_CURRENT_LOCATION;
2514
5
            return fail(cs.begin(), error::syntax, &loc);
2515
10
        }
2516
815
        char const c = *cs;
2517
815
        if(BOOST_JSON_UNLIKELY(
2518
815
            c < '0' || c > '9'))
2519
31
        {
2520
            // digit required
2521
31
            BOOST_STATIC_CONSTEXPR source_location loc
2522
31
                = BOOST_CURRENT_LOCATION;
2523
31
            return fail(cs.begin(), error::syntax, &loc);
2524
31
        }
2525
815
    }
2526
2527
    //----------------------------------
2528
    //
2529
    // 1*DIGIT
2530
    // significant digits
2531
    // to the right of decimal
2532
    //
2533
2.82k
do_num8:
2534
2.82k
    for(;;)
2535
11.3M
    {
2536
11.3M
        if(BOOST_JSON_UNLIKELY(! cs))
2537
265
        {
2538
265
            if(BOOST_JSON_UNLIKELY(more_))
2539
128
            {
2540
128
                if(BOOST_JSON_UNLIKELY(
2541
128
                    ! h_.on_number_part(
2542
128
                        {begin, cs.used(begin)}, ec_)))
2543
0
                    return fail(cs.begin());
2544
2545
128
                BOOST_IF_CONSTEXPR( precise_parsing )
2546
0
                    num_buf_.append( begin, cs.used(begin) );
2547
128
                return suspend(cs.begin(), state::num8, num);
2548
128
            }
2549
137
            goto finish_dub;
2550
265
        }
2551
11.3M
        char const c = *cs;
2552
11.3M
        if(BOOST_JSON_LIKELY(
2553
11.3M
            c >= '0' && c <= '9'))
2554
11.3M
        {
2555
11.3M
            ++cs;
2556
11.3M
            if(!no_parsing && BOOST_JSON_LIKELY(
2557
11.3M
                num.mant <= 9007199254740991)) // 2^53-1
2558
11.3M
            {
2559
11.3M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2560
0
                {
2561
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2562
0
                        = BOOST_CURRENT_LOCATION;
2563
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2564
0
                }
2565
11.3M
                --num.bias;
2566
11.3M
                num.mant = 10 * num.mant + ( c - '0' );
2567
11.3M
            }
2568
1.07k
            else
2569
1.07k
            {
2570
1.07k
                goto do_num5;
2571
1.07k
            }
2572
11.3M
        }
2573
1.47k
        else if((c | 32) == 'e')
2574
637
        {
2575
637
            ++cs;
2576
637
            goto do_exp1;
2577
637
        }
2578
842
        else
2579
842
        {
2580
842
            goto finish_dub;
2581
842
        }
2582
11.3M
    }
2583
2584
    //----------------------------------
2585
    //
2586
    // *[+-]
2587
    //
2588
12.8k
do_exp1:
2589
12.8k
    if(BOOST_JSON_UNLIKELY(! cs))
2590
41
    {
2591
41
        if(BOOST_JSON_UNLIKELY(
2592
41
            ! h_.on_number_part(
2593
41
                {begin, cs.used(begin)}, ec_)))
2594
0
            return fail(cs.begin());
2595
2596
41
        BOOST_IF_CONSTEXPR( precise_parsing )
2597
0
            num_buf_.append( begin, cs.used(begin) );
2598
41
        return maybe_suspend(
2599
41
            cs.begin(), state::exp1, num);
2600
41
    }
2601
12.8k
    if(*cs == '+')
2602
984
    {
2603
984
        ++cs;
2604
984
    }
2605
11.8k
    else if(*cs == '-')
2606
7.03k
    {
2607
7.03k
        ++cs;
2608
7.03k
        num.frac = true;
2609
7.03k
    }
2610
2611
    //----------------------------------
2612
    //
2613
    // DIGIT
2614
    // first digit of the exponent
2615
    //
2616
12.8k
do_exp2:
2617
12.8k
    {
2618
12.8k
        if(BOOST_JSON_UNLIKELY(! cs))
2619
25
        {
2620
25
            if(BOOST_JSON_UNLIKELY(more_))
2621
11
            {
2622
11
                if(BOOST_JSON_UNLIKELY(
2623
11
                    ! h_.on_number_part(
2624
11
                        {begin, cs.used(begin)}, ec_)))
2625
0
                    return fail(cs.begin());
2626
2627
11
                BOOST_IF_CONSTEXPR( precise_parsing )
2628
0
                    num_buf_.append( begin, cs.used(begin) );
2629
11
                return suspend(cs.begin(), state::exp2, num);
2630
11
            }
2631
            // digit required
2632
14
            BOOST_STATIC_CONSTEXPR source_location loc
2633
14
                = BOOST_CURRENT_LOCATION;
2634
14
            return fail(cs.begin(), error::syntax, &loc);
2635
25
        }
2636
12.8k
        char const c = *cs;
2637
12.8k
        if(BOOST_JSON_UNLIKELY(
2638
12.8k
            c < '0' || c > '9'))
2639
57
        {
2640
            // digit required
2641
57
            BOOST_STATIC_CONSTEXPR source_location loc
2642
57
                = BOOST_CURRENT_LOCATION;
2643
57
            return fail(cs.begin(), error::syntax, &loc);
2644
57
        }
2645
12.7k
        ++cs;
2646
12.7k
        num.exp = c - '0';
2647
12.7k
    }
2648
2649
    //----------------------------------
2650
    //
2651
    // 1*DIGIT
2652
    // subsequent digits in the exponent
2653
    //
2654
12.7k
do_exp3:
2655
12.7k
    for(;;)
2656
67.2k
    {
2657
67.2k
        if(BOOST_JSON_UNLIKELY(! cs))
2658
535
        {
2659
535
            if(BOOST_JSON_UNLIKELY(more_))
2660
172
            {
2661
172
                if(BOOST_JSON_UNLIKELY(
2662
172
                    ! h_.on_number_part(
2663
172
                        {begin, cs.used(begin)}, ec_)))
2664
0
                    return fail(cs.begin());
2665
2666
172
                BOOST_IF_CONSTEXPR( precise_parsing )
2667
0
                    num_buf_.append( begin, cs.used(begin) );
2668
172
                return suspend(cs.begin(), state::exp3, num);
2669
172
            }
2670
535
        }
2671
66.7k
        else
2672
66.7k
        {
2673
66.7k
            char const c = *cs;
2674
66.7k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2675
54.4k
            {
2676
54.4k
                if(BOOST_JSON_UNLIKELY(
2677
                //              2147483647 INT_MAX
2678
54.4k
                    num.exp  >  214748364 ||
2679
54.4k
                    (num.exp == 214748364 && c > '7')
2680
54.4k
                ))
2681
3.27k
                    num.exp = INT_MAX;
2682
51.2k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2683
51.2k
                    num.exp = 10 * num.exp + ( c - '0' );
2684
2685
54.4k
                ++cs;
2686
54.4k
                continue;
2687
54.4k
            }
2688
66.7k
        }
2689
12.5k
        BOOST_ASSERT(num.exp >= 0);
2690
12.5k
        if ( num.frac )
2691
6.94k
        {
2692
6.94k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2693
2.00k
            {
2694
                // if exponent overflowed, bias is a very large negative
2695
                // number, and mantissa isn't zero, then we cannot parse the
2696
                // number correctly
2697
2.00k
                if(BOOST_JSON_UNLIKELY(
2698
2.00k
                    (num.exp == INT_MAX) &&
2699
2.00k
                    (num.bias < 0) &&
2700
2.00k
                    (num.exp + num.bias < 308) &&
2701
2.00k
                    num.mant ))
2702
0
                {
2703
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2704
0
                        = BOOST_CURRENT_LOCATION;
2705
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2706
0
                }
2707
2708
2.00k
                num.bias = 0;
2709
2.00k
                num.exp = INT_MAX;
2710
2.00k
            }
2711
6.94k
        }
2712
5.64k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2713
0
        {
2714
            // if exponent overflowed, bias is a very large positive number,
2715
            // and mantissa isn't zero, then we cannot parse the
2716
            // number correctly
2717
0
            if(BOOST_JSON_UNLIKELY(
2718
0
                (num.exp == INT_MAX) &&
2719
0
                (num.bias > 0) &&
2720
0
                (num.exp - num.bias < 308) &&
2721
0
                num.mant ))
2722
0
            {
2723
0
                BOOST_STATIC_CONSTEXPR source_location loc
2724
0
                    = BOOST_CURRENT_LOCATION;
2725
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2726
0
            }
2727
2728
0
            num.bias = 0;
2729
0
            num.exp = INT_MAX;
2730
0
        }
2731
12.5k
        goto finish_dub;
2732
12.5k
    }
2733
2734
2.21k
finish_int:
2735
2.21k
    if(negative || (!stack_empty && num.neg))
2736
0
    {
2737
0
        if(BOOST_JSON_UNLIKELY(
2738
0
            ! h_.on_int64(static_cast<
2739
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
0
        return cs.begin();
2742
0
    }
2743
2.21k
    if(num.mant <= INT64_MAX)
2744
2.21k
    {
2745
210k
finish_signed:
2746
210k
        if(BOOST_JSON_UNLIKELY(
2747
210k
            ! h_.on_int64(static_cast<
2748
210k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2749
0
            return fail(cs.begin());
2750
210k
        return cs.begin();
2751
210k
    }
2752
0
    if(BOOST_JSON_UNLIKELY(
2753
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2754
0
        return fail(cs.begin());
2755
0
    return cs.begin();
2756
17.2k
finish_dub:
2757
17.2k
    double d;
2758
17.2k
    std::size_t const size = cs.used(begin);
2759
17.2k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2760
17.2k
    BOOST_IF_CONSTEXPR( precise_parsing )
2761
0
    {
2762
0
        char const* data = begin;
2763
0
        std::size_t full_size = size;
2764
         // if we previously suspended or if the current input ends with the
2765
         // number, we need to copy the current part of the number to the
2766
         // temporary buffer
2767
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2768
0
        {
2769
0
            data = num_buf_.append( begin, size );
2770
0
            full_size = num_buf_.size();
2771
0
        }
2772
0
        auto const err = detail::charconv::from_chars(
2773
0
            data, data + full_size, d );
2774
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2775
0
        BOOST_ASSERT( err.ptr == data + full_size );
2776
0
        (void)err;
2777
0
    }
2778
17.2k
    else BOOST_IF_CONSTEXPR( no_parsing )
2779
0
        d = 0;
2780
17.2k
    else
2781
17.2k
        d = detail::dec_to_float(
2782
17.2k
            num.mant,
2783
17.2k
            num.bias + (num.frac ?
2784
10.3k
                -num.exp : num.exp),
2785
17.2k
            num.neg);
2786
17.2k
    if(BOOST_JSON_UNLIKELY(
2787
17.2k
        ! h_.on_double(d, {begin, size}, ec_)))
2788
0
        return fail(cs.begin());
2789
17.2k
    return cs.begin();
2790
17.2k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)48, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)48, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)45, (boost::json::number_precision)0>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)0>)
Line
Count
Source
2021
37.1k
{
2022
37.1k
    constexpr bool precise_parsing = mode == number_precision::precise;
2023
37.1k
    constexpr bool no_parsing = mode == number_precision::none;
2024
2025
    // only one of these will be true if we are not resuming
2026
    // if negative then !zero_first && !nonzero_first
2027
    // if zero_first then !nonzero_first && !negative
2028
    // if nonzero_first then !zero_first && !negative
2029
37.1k
    bool const negative = first == '-';
2030
37.1k
    bool const zero_first = first == '0';
2031
37.1k
    bool const nonzero_first = first == '+';
2032
37.1k
    detail::const_stream_wrapper cs(p, end_);
2033
37.1k
    number num;
2034
37.1k
    const char* begin = cs.begin();
2035
37.1k
    if(stack_empty || st_.empty())
2036
37.1k
    {
2037
37.1k
        num.bias = 0;
2038
37.1k
        num.exp = 0;
2039
37.1k
        num.frac = false;
2040
37.1k
        num_buf_.clear();
2041
2042
        //----------------------------------
2043
        //
2044
        // '-'
2045
        // leading minus sign
2046
        //
2047
37.1k
        BOOST_ASSERT(cs);
2048
37.1k
        if(negative)
2049
37.1k
            ++cs;
2050
2051
37.1k
        num.neg = negative;
2052
37.1k
        num.frac = false;
2053
37.1k
        num.exp = 0;
2054
37.1k
        num.bias = 0;
2055
2056
        // fast path
2057
37.1k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2058
33.9k
        {
2059
33.9k
            int n1;
2060
2061
33.9k
            if( nonzero_first ||
2062
33.9k
                (negative && *cs != '0') )
2063
28.6k
            {
2064
28.6k
                n1 = detail::count_digits( cs.begin() );
2065
28.6k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2066
2067
28.6k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2068
0
                {
2069
0
                    return parse_literal(
2070
0
                        p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2071
0
                }
2072
2073
28.6k
                if( ! nonzero_first && n1 == 0 )
2074
22
                {
2075
                    // digit required
2076
22
                    BOOST_STATIC_CONSTEXPR source_location loc
2077
22
                        = BOOST_CURRENT_LOCATION;
2078
22
                    return fail(cs.begin(), error::syntax, &loc);
2079
22
                }
2080
2081
28.6k
                BOOST_IF_CONSTEXPR( !no_parsing )
2082
28.6k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2083
0
                else
2084
0
                    num.mant = 0;
2085
2086
28.6k
                cs += n1;
2087
2088
                // integer or floating-point with
2089
                // >= 16 leading digits
2090
28.6k
                if( n1 == 16 )
2091
8.17k
                {
2092
8.17k
                    goto do_num2;
2093
8.17k
                }
2094
28.6k
            }
2095
5.27k
            else
2096
5.27k
            {
2097
                // 0. floating-point or 0e integer
2098
5.27k
                num.mant = 0;
2099
5.27k
                n1 = 0;
2100
5.27k
                ++cs;
2101
5.27k
            }
2102
2103
25.7k
            {
2104
25.7k
                const char c = *cs;
2105
25.7k
                if(c != '.')
2106
19.9k
                {
2107
19.9k
                    if((c | 32) == 'e')
2108
11.4k
                    {
2109
11.4k
                        ++cs;
2110
11.4k
                        goto do_exp1;
2111
11.4k
                    }
2112
8.57k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2113
8.57k
                        num.mant = ~num.mant + 1;
2114
8.57k
                    goto finish_signed;
2115
19.9k
                }
2116
25.7k
            }
2117
2118
            // floating-point number
2119
2120
5.73k
            ++cs;
2121
2122
5.73k
            int n2 = detail::count_digits( cs.begin() );
2123
5.73k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2124
2125
5.73k
            if( n2 == 0 )
2126
6
            {
2127
                // digit required
2128
6
                BOOST_STATIC_CONSTEXPR source_location loc
2129
6
                    = BOOST_CURRENT_LOCATION;
2130
6
                return fail(cs.begin(), error::syntax, &loc);
2131
6
            }
2132
2133
            // floating-point mantissa overflow
2134
5.72k
            if( n1 + n2 >= 19 )
2135
562
            {
2136
562
                goto do_num7;
2137
562
            }
2138
2139
5.16k
            BOOST_IF_CONSTEXPR( !no_parsing )
2140
5.16k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2141
2142
5.16k
            BOOST_ASSERT(num.bias == 0);
2143
2144
5.16k
            num.bias -= n2;
2145
2146
5.16k
            cs += n2;
2147
2148
5.16k
            char ch = *cs;
2149
2150
5.16k
            if( (ch | 32) == 'e' )
2151
1.29k
            {
2152
1.29k
                ++cs;
2153
1.29k
                goto do_exp1;
2154
1.29k
            }
2155
3.86k
            else if( ch >= '0' && ch <= '9' )
2156
979
            {
2157
979
                goto do_num8;
2158
979
            }
2159
2160
2.88k
            goto finish_dub;
2161
5.16k
        }
2162
37.1k
    }
2163
0
    else
2164
0
    {
2165
0
        num = num_;
2166
0
        state st;
2167
0
        st_.pop(st);
2168
0
        switch(st)
2169
0
        {
2170
0
        default: BOOST_JSON_UNREACHABLE();
2171
0
        case state::num1: goto do_num1;
2172
0
        case state::num2: goto do_num2;
2173
0
        case state::num3: goto do_num3;
2174
0
        case state::num4: goto do_num4;
2175
0
        case state::num5: goto do_num5;
2176
0
        case state::num6: goto do_num6;
2177
0
        case state::num7: goto do_num7;
2178
0
        case state::num8: goto do_num8;
2179
0
        case state::exp1: goto do_exp1;
2180
0
        case state::exp2: goto do_exp2;
2181
0
        case state::exp3: goto do_exp3;
2182
0
        }
2183
0
    }
2184
2185
    //----------------------------------
2186
    //
2187
    // DIGIT
2188
    // first digit
2189
    //
2190
3.21k
do_num1:
2191
3.21k
    if(zero_first || nonzero_first ||
2192
3.21k
        BOOST_JSON_LIKELY(cs))
2193
3.17k
    {
2194
3.17k
        char const c = *cs;
2195
3.17k
        if(zero_first)
2196
0
        {
2197
0
            ++cs;
2198
0
            num.mant = 0;
2199
0
            goto do_num6;
2200
0
        }
2201
3.17k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2202
3.17k
            c >= '1' && c <= '9'))
2203
2.57k
        {
2204
2.57k
            ++cs;
2205
2.57k
            num.mant = c - '0';
2206
2.57k
        }
2207
603
        else if(BOOST_JSON_UNLIKELY(
2208
603
            c == '0'))
2209
547
        {
2210
547
            ++cs;
2211
547
            num.mant = 0;
2212
547
            goto do_num6;
2213
547
        }
2214
56
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2215
0
        {
2216
0
            st_.push(state::lit1);
2217
0
            cur_lit_ = detail::neg_infinity_literal;
2218
0
            lit_offset_ = 1;
2219
0
            return parse_literal(
2220
0
                cs.begin(), mp11::mp_int<detail::resume_literal>() );
2221
0
        }
2222
56
        else
2223
56
        {
2224
56
            BOOST_STATIC_CONSTEXPR source_location loc
2225
56
                = BOOST_CURRENT_LOCATION;
2226
56
            return fail(cs.begin(), error::syntax, &loc);
2227
56
        }
2228
3.17k
    }
2229
39
    else
2230
39
    {
2231
39
        if(BOOST_JSON_UNLIKELY(
2232
39
            ! h_.on_number_part(
2233
39
                {begin, cs.used(begin)}, ec_)))
2234
0
            return fail(cs.begin());
2235
2236
39
        BOOST_IF_CONSTEXPR( precise_parsing )
2237
0
            num_buf_.append( begin, cs.used(begin) );
2238
39
        return maybe_suspend(
2239
39
            cs.begin(), state::num1, num);
2240
39
    }
2241
2242
    //----------------------------------
2243
    //
2244
    // 1*DIGIT
2245
    // significant digits left of decimal
2246
    //
2247
10.7k
do_num2:
2248
10.7k
    if(negative || (!stack_empty && num.neg))
2249
10.7k
    {
2250
10.7k
        for(;;)
2251
34.1k
        {
2252
34.1k
            if(BOOST_JSON_UNLIKELY(! cs))
2253
400
            {
2254
400
                if(BOOST_JSON_UNLIKELY(more_))
2255
254
                {
2256
254
                    if(BOOST_JSON_UNLIKELY(
2257
254
                        ! h_.on_number_part(
2258
254
                            {begin, cs.used(begin)}, ec_)))
2259
0
                        return fail(cs.begin());
2260
2261
254
                    BOOST_IF_CONSTEXPR( precise_parsing )
2262
0
                        num_buf_.append( begin, cs.used(begin) );
2263
254
                    return suspend(cs.begin(), state::num2, num);
2264
254
                }
2265
146
                goto finish_int;
2266
400
            }
2267
33.7k
            char const c = *cs;
2268
33.7k
            if(BOOST_JSON_LIKELY(
2269
33.7k
                c >= '0' && c <= '9'))
2270
26.6k
            {
2271
26.6k
                ++cs;
2272
                //              9223372036854775808 INT64_MIN
2273
26.6k
                if( num.mant  > 922337203685477580 || (
2274
23.8k
                    num.mant == 922337203685477580 && c > '8'))
2275
3.28k
                    break;
2276
23.3k
                BOOST_IF_CONSTEXPR( !no_parsing )
2277
23.3k
                    num.mant = 10 * num.mant + ( c - '0' );
2278
23.3k
                continue;
2279
26.6k
            }
2280
7.05k
            goto do_num6; // [.eE]
2281
33.7k
        }
2282
10.7k
    }
2283
0
    else
2284
0
    {
2285
0
        for(;;)
2286
0
        {
2287
0
            if(BOOST_JSON_UNLIKELY(! cs))
2288
0
            {
2289
0
                if(BOOST_JSON_UNLIKELY(more_))
2290
0
                {
2291
0
                    if(BOOST_JSON_UNLIKELY(
2292
0
                        ! h_.on_number_part(
2293
0
                            {begin, cs.used(begin)}, ec_)))
2294
0
                        return fail(cs.begin());
2295
2296
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2297
0
                        num_buf_.append( begin, cs.used(begin) );
2298
0
                    return suspend(cs.begin(), state::num2, num);
2299
0
                }
2300
0
                goto finish_int;
2301
0
            }
2302
0
            char const c = *cs;
2303
0
            if(BOOST_JSON_LIKELY(
2304
0
                c >= '0' && c <= '9'))
2305
0
            {
2306
0
                ++cs;
2307
                //              18446744073709551615 UINT64_MAX
2308
0
                if( num.mant  > 1844674407370955161 || (
2309
0
                    num.mant == 1844674407370955161 && c > '5'))
2310
0
                    break;
2311
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2312
0
                    num.mant = 10 * num.mant + ( c - '0' );
2313
0
            }
2314
0
            else
2315
0
            {
2316
0
                goto do_num6; // [.eE]
2317
0
            }
2318
0
        }
2319
0
    }
2320
3.28k
    ++num.bias;
2321
2322
    //----------------------------------
2323
    //
2324
    // 1*DIGIT
2325
    // non-significant digits left of decimal
2326
    //
2327
3.28k
do_num3:
2328
3.28k
    for(;;)
2329
7.87M
    {
2330
7.87M
        if(BOOST_JSON_UNLIKELY(! cs))
2331
88
        {
2332
88
            if(BOOST_JSON_UNLIKELY(more_))
2333
43
            {
2334
43
                if(BOOST_JSON_UNLIKELY(
2335
43
                    ! h_.on_number_part(
2336
43
                        {begin, cs.used(begin)}, ec_)))
2337
0
                    return fail(cs.begin());
2338
2339
43
                BOOST_IF_CONSTEXPR( precise_parsing )
2340
0
                    num_buf_.append( begin, cs.used(begin) );
2341
43
                return suspend(cs.begin(), state::num3, num);
2342
43
            }
2343
45
            goto finish_dub;
2344
88
        }
2345
7.87M
        char const c = *cs;
2346
7.87M
        if(BOOST_JSON_UNLIKELY(
2347
7.87M
            c >= '0' && c <= '9'))
2348
7.86M
        {
2349
7.86M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2350
0
            {
2351
0
                BOOST_STATIC_CONSTEXPR source_location loc
2352
0
                    = BOOST_CURRENT_LOCATION;
2353
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2354
0
            }
2355
7.86M
            ++cs;
2356
7.86M
            ++num.bias;
2357
7.86M
        }
2358
3.20k
        else if(BOOST_JSON_LIKELY(
2359
3.20k
            c == '.'))
2360
638
        {
2361
638
            ++cs;
2362
638
            break;
2363
638
        }
2364
2.56k
        else if((c | 32) == 'e')
2365
1.26k
        {
2366
1.26k
            ++cs;
2367
1.26k
            goto do_exp1;
2368
1.26k
        }
2369
1.30k
        else
2370
1.30k
        {
2371
1.30k
            goto finish_dub;
2372
1.30k
        }
2373
7.87M
    }
2374
2375
    //----------------------------------
2376
    //
2377
    // DIGIT
2378
    // first non-significant digit
2379
    // to the right of decimal
2380
    //
2381
638
do_num4:
2382
638
    {
2383
638
        if(BOOST_JSON_UNLIKELY(! cs))
2384
7
        {
2385
7
            if(BOOST_JSON_UNLIKELY(
2386
7
                ! h_.on_number_part(
2387
7
                    {begin, cs.used(begin)}, ec_)))
2388
0
                return fail(cs.begin());
2389
2390
7
            BOOST_IF_CONSTEXPR( precise_parsing )
2391
0
                num_buf_.append( begin, cs.used(begin) );
2392
7
            return maybe_suspend(
2393
7
                cs.begin(), state::num4, num);
2394
7
        }
2395
631
        char const c = *cs;
2396
631
        if(BOOST_JSON_LIKELY(
2397
            //static_cast<unsigned char>(c - '0') < 10))
2398
631
            c >= '0' && c <= '9'))
2399
611
        {
2400
611
            ++cs;
2401
611
        }
2402
20
        else
2403
20
        {
2404
            // digit required
2405
20
            BOOST_STATIC_CONSTEXPR source_location loc
2406
20
                = BOOST_CURRENT_LOCATION;
2407
20
            return fail(cs.begin(), error::syntax, &loc);
2408
20
        }
2409
631
    }
2410
2411
    //----------------------------------
2412
    //
2413
    // 1*DIGIT
2414
    // non-significant digits
2415
    // to the right of decimal
2416
    //
2417
2.47k
do_num5:
2418
2.47k
    for(;;)
2419
8.64k
    {
2420
8.64k
        if(BOOST_JSON_UNLIKELY(! cs))
2421
65
        {
2422
65
            if(BOOST_JSON_UNLIKELY(more_))
2423
31
            {
2424
31
                if(BOOST_JSON_UNLIKELY(
2425
31
                    ! h_.on_number_part(
2426
31
                        {begin, cs.used(begin)}, ec_)))
2427
0
                    return fail(cs.begin());
2428
2429
31
                BOOST_IF_CONSTEXPR( precise_parsing )
2430
0
                    num_buf_.append( begin, cs.used(begin) );
2431
31
                return suspend(cs.begin(), state::num5, num);
2432
31
            }
2433
34
            goto finish_dub;
2434
65
        }
2435
8.58k
        char const c = *cs;
2436
8.58k
        if(BOOST_JSON_LIKELY(
2437
8.58k
            c >= '0' && c <= '9'))
2438
6.17k
        {
2439
6.17k
            ++cs;
2440
6.17k
        }
2441
2.41k
        else if((c | 32) == 'e')
2442
444
        {
2443
444
            ++cs;
2444
444
            goto do_exp1;
2445
444
        }
2446
1.96k
        else
2447
1.96k
        {
2448
1.96k
            goto finish_dub;
2449
1.96k
        }
2450
8.58k
    }
2451
2452
    //----------------------------------
2453
    //
2454
    // [.eE]
2455
    //
2456
7.60k
do_num6:
2457
7.60k
    {
2458
7.60k
        if(BOOST_JSON_UNLIKELY(! cs))
2459
10
        {
2460
10
            if(BOOST_JSON_UNLIKELY(more_))
2461
5
            {
2462
5
                if(BOOST_JSON_UNLIKELY(
2463
5
                    ! h_.on_number_part(
2464
5
                        {begin, cs.used(begin)}, ec_)))
2465
0
                    return fail(cs.begin());
2466
2467
5
                BOOST_IF_CONSTEXPR( precise_parsing )
2468
0
                    num_buf_.append( begin, cs.used(begin) );
2469
5
                return suspend(cs.begin(), state::num6, num);
2470
5
            }
2471
5
            goto finish_int;
2472
10
        }
2473
7.59k
        char const c = *cs;
2474
7.59k
        if(BOOST_JSON_LIKELY(
2475
7.59k
            c == '.'))
2476
2.23k
        {
2477
2.23k
            ++cs;
2478
2.23k
        }
2479
5.35k
        else if((c | 32) == 'e')
2480
1.40k
        {
2481
1.40k
            ++cs;
2482
1.40k
            goto do_exp1;
2483
1.40k
        }
2484
3.95k
        else
2485
3.95k
        {
2486
3.95k
            goto finish_int;
2487
3.95k
        }
2488
7.59k
    }
2489
2490
    //----------------------------------
2491
    //
2492
    // DIGIT
2493
    // first significant digit
2494
    // to the right of decimal
2495
    //
2496
2.80k
do_num7:
2497
2.80k
    {
2498
2.80k
        if(BOOST_JSON_UNLIKELY(! cs))
2499
13
        {
2500
13
            if(BOOST_JSON_UNLIKELY(more_))
2501
6
            {
2502
6
                if(BOOST_JSON_UNLIKELY(
2503
6
                    ! h_.on_number_part(
2504
6
                        {begin, cs.used(begin)}, ec_)))
2505
0
                    return fail(cs.begin());
2506
2507
6
                BOOST_IF_CONSTEXPR( precise_parsing )
2508
0
                    num_buf_.append( begin, cs.used(begin) );
2509
6
                return suspend(cs.begin(), state::num7, num);
2510
6
            }
2511
            // digit required
2512
7
            BOOST_STATIC_CONSTEXPR source_location loc
2513
7
                = BOOST_CURRENT_LOCATION;
2514
7
            return fail(cs.begin(), error::syntax, &loc);
2515
13
        }
2516
2.78k
        char const c = *cs;
2517
2.78k
        if(BOOST_JSON_UNLIKELY(
2518
2.78k
            c < '0' || c > '9'))
2519
13
        {
2520
            // digit required
2521
13
            BOOST_STATIC_CONSTEXPR source_location loc
2522
13
                = BOOST_CURRENT_LOCATION;
2523
13
            return fail(cs.begin(), error::syntax, &loc);
2524
13
        }
2525
2.78k
    }
2526
2527
    //----------------------------------
2528
    //
2529
    // 1*DIGIT
2530
    // significant digits
2531
    // to the right of decimal
2532
    //
2533
3.75k
do_num8:
2534
3.75k
    for(;;)
2535
12.2M
    {
2536
12.2M
        if(BOOST_JSON_UNLIKELY(! cs))
2537
237
        {
2538
237
            if(BOOST_JSON_UNLIKELY(more_))
2539
115
            {
2540
115
                if(BOOST_JSON_UNLIKELY(
2541
115
                    ! h_.on_number_part(
2542
115
                        {begin, cs.used(begin)}, ec_)))
2543
0
                    return fail(cs.begin());
2544
2545
115
                BOOST_IF_CONSTEXPR( precise_parsing )
2546
0
                    num_buf_.append( begin, cs.used(begin) );
2547
115
                return suspend(cs.begin(), state::num8, num);
2548
115
            }
2549
122
            goto finish_dub;
2550
237
        }
2551
12.2M
        char const c = *cs;
2552
12.2M
        if(BOOST_JSON_LIKELY(
2553
12.2M
            c >= '0' && c <= '9'))
2554
12.2M
        {
2555
12.2M
            ++cs;
2556
12.2M
            if(!no_parsing && BOOST_JSON_LIKELY(
2557
12.2M
                num.mant <= 9007199254740991)) // 2^53-1
2558
12.2M
            {
2559
12.2M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2560
0
                {
2561
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2562
0
                        = BOOST_CURRENT_LOCATION;
2563
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2564
0
                }
2565
12.2M
                --num.bias;
2566
12.2M
                num.mant = 10 * num.mant + ( c - '0' );
2567
12.2M
            }
2568
1.86k
            else
2569
1.86k
            {
2570
1.86k
                goto do_num5;
2571
1.86k
            }
2572
12.2M
        }
2573
1.65k
        else if((c | 32) == 'e')
2574
615
        {
2575
615
            ++cs;
2576
615
            goto do_exp1;
2577
615
        }
2578
1.03k
        else
2579
1.03k
        {
2580
1.03k
            goto finish_dub;
2581
1.03k
        }
2582
12.2M
    }
2583
2584
    //----------------------------------
2585
    //
2586
    // *[+-]
2587
    //
2588
16.4k
do_exp1:
2589
16.4k
    if(BOOST_JSON_UNLIKELY(! cs))
2590
64
    {
2591
64
        if(BOOST_JSON_UNLIKELY(
2592
64
            ! h_.on_number_part(
2593
64
                {begin, cs.used(begin)}, ec_)))
2594
0
            return fail(cs.begin());
2595
2596
64
        BOOST_IF_CONSTEXPR( precise_parsing )
2597
0
            num_buf_.append( begin, cs.used(begin) );
2598
64
        return maybe_suspend(
2599
64
            cs.begin(), state::exp1, num);
2600
64
    }
2601
16.3k
    if(*cs == '+')
2602
489
    {
2603
489
        ++cs;
2604
489
    }
2605
15.8k
    else if(*cs == '-')
2606
3.68k
    {
2607
3.68k
        ++cs;
2608
3.68k
        num.frac = true;
2609
3.68k
    }
2610
2611
    //----------------------------------
2612
    //
2613
    // DIGIT
2614
    // first digit of the exponent
2615
    //
2616
16.3k
do_exp2:
2617
16.3k
    {
2618
16.3k
        if(BOOST_JSON_UNLIKELY(! cs))
2619
25
        {
2620
25
            if(BOOST_JSON_UNLIKELY(more_))
2621
12
            {
2622
12
                if(BOOST_JSON_UNLIKELY(
2623
12
                    ! h_.on_number_part(
2624
12
                        {begin, cs.used(begin)}, ec_)))
2625
0
                    return fail(cs.begin());
2626
2627
12
                BOOST_IF_CONSTEXPR( precise_parsing )
2628
0
                    num_buf_.append( begin, cs.used(begin) );
2629
12
                return suspend(cs.begin(), state::exp2, num);
2630
12
            }
2631
            // digit required
2632
13
            BOOST_STATIC_CONSTEXPR source_location loc
2633
13
                = BOOST_CURRENT_LOCATION;
2634
13
            return fail(cs.begin(), error::syntax, &loc);
2635
25
        }
2636
16.3k
        char const c = *cs;
2637
16.3k
        if(BOOST_JSON_UNLIKELY(
2638
16.3k
            c < '0' || c > '9'))
2639
53
        {
2640
            // digit required
2641
53
            BOOST_STATIC_CONSTEXPR source_location loc
2642
53
                = BOOST_CURRENT_LOCATION;
2643
53
            return fail(cs.begin(), error::syntax, &loc);
2644
53
        }
2645
16.2k
        ++cs;
2646
16.2k
        num.exp = c - '0';
2647
16.2k
    }
2648
2649
    //----------------------------------
2650
    //
2651
    // 1*DIGIT
2652
    // subsequent digits in the exponent
2653
    //
2654
16.2k
do_exp3:
2655
16.2k
    for(;;)
2656
50.0k
    {
2657
50.0k
        if(BOOST_JSON_UNLIKELY(! cs))
2658
535
        {
2659
535
            if(BOOST_JSON_UNLIKELY(more_))
2660
105
            {
2661
105
                if(BOOST_JSON_UNLIKELY(
2662
105
                    ! h_.on_number_part(
2663
105
                        {begin, cs.used(begin)}, ec_)))
2664
0
                    return fail(cs.begin());
2665
2666
105
                BOOST_IF_CONSTEXPR( precise_parsing )
2667
0
                    num_buf_.append( begin, cs.used(begin) );
2668
105
                return suspend(cs.begin(), state::exp3, num);
2669
105
            }
2670
535
        }
2671
49.5k
        else
2672
49.5k
        {
2673
49.5k
            char const c = *cs;
2674
49.5k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2675
33.7k
            {
2676
33.7k
                if(BOOST_JSON_UNLIKELY(
2677
                //              2147483647 INT_MAX
2678
33.7k
                    num.exp  >  214748364 ||
2679
33.7k
                    (num.exp == 214748364 && c > '7')
2680
33.7k
                ))
2681
3.01k
                    num.exp = INT_MAX;
2682
30.7k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2683
30.7k
                    num.exp = 10 * num.exp + ( c - '0' );
2684
2685
33.7k
                ++cs;
2686
33.7k
                continue;
2687
33.7k
            }
2688
49.5k
        }
2689
16.1k
        BOOST_ASSERT(num.exp >= 0);
2690
16.1k
        if ( num.frac )
2691
3.67k
        {
2692
3.67k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2693
965
            {
2694
                // if exponent overflowed, bias is a very large negative
2695
                // number, and mantissa isn't zero, then we cannot parse the
2696
                // number correctly
2697
965
                if(BOOST_JSON_UNLIKELY(
2698
965
                    (num.exp == INT_MAX) &&
2699
965
                    (num.bias < 0) &&
2700
965
                    (num.exp + num.bias < 308) &&
2701
965
                    num.mant ))
2702
0
                {
2703
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2704
0
                        = BOOST_CURRENT_LOCATION;
2705
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2706
0
                }
2707
2708
965
                num.bias = 0;
2709
965
                num.exp = INT_MAX;
2710
965
            }
2711
3.67k
        }
2712
12.5k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2713
864
        {
2714
            // if exponent overflowed, bias is a very large positive number,
2715
            // and mantissa isn't zero, then we cannot parse the
2716
            // number correctly
2717
864
            if(BOOST_JSON_UNLIKELY(
2718
864
                (num.exp == INT_MAX) &&
2719
864
                (num.bias > 0) &&
2720
864
                (num.exp - num.bias < 308) &&
2721
864
                num.mant ))
2722
0
            {
2723
0
                BOOST_STATIC_CONSTEXPR source_location loc
2724
0
                    = BOOST_CURRENT_LOCATION;
2725
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2726
0
            }
2727
2728
864
            num.bias = 0;
2729
864
            num.exp = INT_MAX;
2730
864
        }
2731
16.1k
        goto finish_dub;
2732
16.1k
    }
2733
2734
4.10k
finish_int:
2735
4.10k
    if(negative || (!stack_empty && num.neg))
2736
4.10k
    {
2737
4.10k
        if(BOOST_JSON_UNLIKELY(
2738
4.10k
            ! h_.on_int64(static_cast<
2739
4.10k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
4.10k
        return cs.begin();
2742
4.10k
    }
2743
0
    if(num.mant <= INT64_MAX)
2744
0
    {
2745
8.57k
finish_signed:
2746
8.57k
        if(BOOST_JSON_UNLIKELY(
2747
8.57k
            ! h_.on_int64(static_cast<
2748
8.57k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2749
0
            return fail(cs.begin());
2750
8.57k
        return cs.begin();
2751
8.57k
    }
2752
0
    if(BOOST_JSON_UNLIKELY(
2753
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2754
0
        return fail(cs.begin());
2755
0
    return cs.begin();
2756
23.5k
finish_dub:
2757
23.5k
    double d;
2758
23.5k
    std::size_t const size = cs.used(begin);
2759
23.5k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2760
23.5k
    BOOST_IF_CONSTEXPR( precise_parsing )
2761
0
    {
2762
0
        char const* data = begin;
2763
0
        std::size_t full_size = size;
2764
         // if we previously suspended or if the current input ends with the
2765
         // number, we need to copy the current part of the number to the
2766
         // temporary buffer
2767
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2768
0
        {
2769
0
            data = num_buf_.append( begin, size );
2770
0
            full_size = num_buf_.size();
2771
0
        }
2772
0
        auto const err = detail::charconv::from_chars(
2773
0
            data, data + full_size, d );
2774
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2775
0
        BOOST_ASSERT( err.ptr == data + full_size );
2776
0
        (void)err;
2777
0
    }
2778
23.5k
    else BOOST_IF_CONSTEXPR( no_parsing )
2779
0
        d = 0;
2780
23.5k
    else
2781
23.5k
        d = detail::dec_to_float(
2782
23.5k
            num.mant,
2783
23.5k
            num.bias + (num.frac ?
2784
19.9k
                -num.exp : num.exp),
2785
23.5k
            num.neg);
2786
23.5k
    if(BOOST_JSON_UNLIKELY(
2787
23.5k
        ! h_.on_double(d, {begin, size}, ec_)))
2788
0
        return fail(cs.begin());
2789
23.5k
    return cs.begin();
2790
23.5k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)45, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)45, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)43, (boost::json::number_precision)0>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)43>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)0>)
Line
Count
Source
2021
10.3M
{
2022
10.3M
    constexpr bool precise_parsing = mode == number_precision::precise;
2023
10.3M
    constexpr bool no_parsing = mode == number_precision::none;
2024
2025
    // only one of these will be true if we are not resuming
2026
    // if negative then !zero_first && !nonzero_first
2027
    // if zero_first then !nonzero_first && !negative
2028
    // if nonzero_first then !zero_first && !negative
2029
10.3M
    bool const negative = first == '-';
2030
10.3M
    bool const zero_first = first == '0';
2031
10.3M
    bool const nonzero_first = first == '+';
2032
10.3M
    detail::const_stream_wrapper cs(p, end_);
2033
10.3M
    number num;
2034
10.3M
    const char* begin = cs.begin();
2035
10.3M
    if(stack_empty || st_.empty())
2036
10.3M
    {
2037
10.3M
        num.bias = 0;
2038
10.3M
        num.exp = 0;
2039
10.3M
        num.frac = false;
2040
10.3M
        num_buf_.clear();
2041
2042
        //----------------------------------
2043
        //
2044
        // '-'
2045
        // leading minus sign
2046
        //
2047
10.3M
        BOOST_ASSERT(cs);
2048
10.3M
        if(negative)
2049
0
            ++cs;
2050
2051
10.3M
        num.neg = negative;
2052
10.3M
        num.frac = false;
2053
10.3M
        num.exp = 0;
2054
10.3M
        num.bias = 0;
2055
2056
        // fast path
2057
10.3M
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2058
10.3M
        {
2059
10.3M
            int n1;
2060
2061
10.3M
            if( nonzero_first ||
2062
10.3M
                (negative && *cs != '0') )
2063
10.3M
            {
2064
10.3M
                n1 = detail::count_digits( cs.begin() );
2065
10.3M
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2066
2067
10.3M
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2068
0
                {
2069
0
                    return parse_literal(
2070
0
                        p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2071
0
                }
2072
2073
10.3M
                if( ! nonzero_first && n1 == 0 )
2074
0
                {
2075
                    // digit required
2076
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2077
0
                        = BOOST_CURRENT_LOCATION;
2078
0
                    return fail(cs.begin(), error::syntax, &loc);
2079
0
                }
2080
2081
10.3M
                BOOST_IF_CONSTEXPR( !no_parsing )
2082
10.3M
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2083
0
                else
2084
0
                    num.mant = 0;
2085
2086
10.3M
                cs += n1;
2087
2088
                // integer or floating-point with
2089
                // >= 16 leading digits
2090
10.3M
                if( n1 == 16 )
2091
44.3k
                {
2092
44.3k
                    goto do_num2;
2093
44.3k
                }
2094
10.3M
            }
2095
0
            else
2096
0
            {
2097
                // 0. floating-point or 0e integer
2098
0
                num.mant = 0;
2099
0
                n1 = 0;
2100
0
                ++cs;
2101
0
            }
2102
2103
10.3M
            {
2104
10.3M
                const char c = *cs;
2105
10.3M
                if(c != '.')
2106
10.2M
                {
2107
10.2M
                    if((c | 32) == 'e')
2108
5.47M
                    {
2109
5.47M
                        ++cs;
2110
5.47M
                        goto do_exp1;
2111
5.47M
                    }
2112
4.82M
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2113
0
                        num.mant = ~num.mant + 1;
2114
4.82M
                    goto finish_signed;
2115
10.2M
                }
2116
10.3M
            }
2117
2118
            // floating-point number
2119
2120
19.6k
            ++cs;
2121
2122
19.6k
            int n2 = detail::count_digits( cs.begin() );
2123
19.6k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2124
2125
19.6k
            if( n2 == 0 )
2126
8
            {
2127
                // digit required
2128
8
                BOOST_STATIC_CONSTEXPR source_location loc
2129
8
                    = BOOST_CURRENT_LOCATION;
2130
8
                return fail(cs.begin(), error::syntax, &loc);
2131
8
            }
2132
2133
            // floating-point mantissa overflow
2134
19.6k
            if( n1 + n2 >= 19 )
2135
1.80k
            {
2136
1.80k
                goto do_num7;
2137
1.80k
            }
2138
2139
17.8k
            BOOST_IF_CONSTEXPR( !no_parsing )
2140
17.8k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2141
2142
17.8k
            BOOST_ASSERT(num.bias == 0);
2143
2144
17.8k
            num.bias -= n2;
2145
2146
17.8k
            cs += n2;
2147
2148
17.8k
            char ch = *cs;
2149
2150
17.8k
            if( (ch | 32) == 'e' )
2151
4.12k
            {
2152
4.12k
                ++cs;
2153
4.12k
                goto do_exp1;
2154
4.12k
            }
2155
13.7k
            else if( ch >= '0' && ch <= '9' )
2156
663
            {
2157
663
                goto do_num8;
2158
663
            }
2159
2160
13.0k
            goto finish_dub;
2161
17.8k
        }
2162
10.3M
    }
2163
0
    else
2164
0
    {
2165
0
        num = num_;
2166
0
        state st;
2167
0
        st_.pop(st);
2168
0
        switch(st)
2169
0
        {
2170
0
        default: BOOST_JSON_UNREACHABLE();
2171
0
        case state::num1: goto do_num1;
2172
0
        case state::num2: goto do_num2;
2173
0
        case state::num3: goto do_num3;
2174
0
        case state::num4: goto do_num4;
2175
0
        case state::num5: goto do_num5;
2176
0
        case state::num6: goto do_num6;
2177
0
        case state::num7: goto do_num7;
2178
0
        case state::num8: goto do_num8;
2179
0
        case state::exp1: goto do_exp1;
2180
0
        case state::exp2: goto do_exp2;
2181
0
        case state::exp3: goto do_exp3;
2182
0
        }
2183
0
    }
2184
2185
    //----------------------------------
2186
    //
2187
    // DIGIT
2188
    // first digit
2189
    //
2190
15.3k
do_num1:
2191
15.3k
    if(zero_first || nonzero_first ||
2192
15.3k
        BOOST_JSON_LIKELY(cs))
2193
15.3k
    {
2194
15.3k
        char const c = *cs;
2195
15.3k
        if(zero_first)
2196
0
        {
2197
0
            ++cs;
2198
0
            num.mant = 0;
2199
0
            goto do_num6;
2200
0
        }
2201
15.3k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2202
15.3k
            c >= '1' && c <= '9'))
2203
15.3k
        {
2204
15.3k
            ++cs;
2205
15.3k
            num.mant = c - '0';
2206
15.3k
        }
2207
0
        else if(BOOST_JSON_UNLIKELY(
2208
0
            c == '0'))
2209
0
        {
2210
0
            ++cs;
2211
0
            num.mant = 0;
2212
0
            goto do_num6;
2213
0
        }
2214
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2215
0
        {
2216
0
            st_.push(state::lit1);
2217
0
            cur_lit_ = detail::neg_infinity_literal;
2218
0
            lit_offset_ = 1;
2219
0
            return parse_literal(
2220
0
                cs.begin(), mp11::mp_int<detail::resume_literal>() );
2221
0
        }
2222
0
        else
2223
0
        {
2224
0
            BOOST_STATIC_CONSTEXPR source_location loc
2225
0
                = BOOST_CURRENT_LOCATION;
2226
0
            return fail(cs.begin(), error::syntax, &loc);
2227
0
        }
2228
15.3k
    }
2229
0
    else
2230
0
    {
2231
0
        if(BOOST_JSON_UNLIKELY(
2232
0
            ! h_.on_number_part(
2233
0
                {begin, cs.used(begin)}, ec_)))
2234
0
            return fail(cs.begin());
2235
2236
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2237
0
            num_buf_.append( begin, cs.used(begin) );
2238
0
        return maybe_suspend(
2239
0
            cs.begin(), state::num1, num);
2240
0
    }
2241
2242
    //----------------------------------
2243
    //
2244
    // 1*DIGIT
2245
    // significant digits left of decimal
2246
    //
2247
59.6k
do_num2:
2248
59.6k
    if(negative || (!stack_empty && num.neg))
2249
0
    {
2250
0
        for(;;)
2251
0
        {
2252
0
            if(BOOST_JSON_UNLIKELY(! cs))
2253
0
            {
2254
0
                if(BOOST_JSON_UNLIKELY(more_))
2255
0
                {
2256
0
                    if(BOOST_JSON_UNLIKELY(
2257
0
                        ! h_.on_number_part(
2258
0
                            {begin, cs.used(begin)}, ec_)))
2259
0
                        return fail(cs.begin());
2260
2261
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2262
0
                        num_buf_.append( begin, cs.used(begin) );
2263
0
                    return suspend(cs.begin(), state::num2, num);
2264
0
                }
2265
0
                goto finish_int;
2266
0
            }
2267
0
            char const c = *cs;
2268
0
            if(BOOST_JSON_LIKELY(
2269
0
                c >= '0' && c <= '9'))
2270
0
            {
2271
0
                ++cs;
2272
                //              9223372036854775808 INT64_MIN
2273
0
                if( num.mant  > 922337203685477580 || (
2274
0
                    num.mant == 922337203685477580 && c > '8'))
2275
0
                    break;
2276
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2277
0
                    num.mant = 10 * num.mant + ( c - '0' );
2278
0
                continue;
2279
0
            }
2280
0
            goto do_num6; // [.eE]
2281
0
        }
2282
0
    }
2283
59.6k
    else
2284
59.6k
    {
2285
59.6k
        for(;;)
2286
206k
        {
2287
206k
            if(BOOST_JSON_UNLIKELY(! cs))
2288
869
            {
2289
869
                if(BOOST_JSON_UNLIKELY(more_))
2290
555
                {
2291
555
                    if(BOOST_JSON_UNLIKELY(
2292
555
                        ! h_.on_number_part(
2293
555
                            {begin, cs.used(begin)}, ec_)))
2294
0
                        return fail(cs.begin());
2295
2296
555
                    BOOST_IF_CONSTEXPR( precise_parsing )
2297
0
                        num_buf_.append( begin, cs.used(begin) );
2298
555
                    return suspend(cs.begin(), state::num2, num);
2299
555
                }
2300
314
                goto finish_int;
2301
869
            }
2302
206k
            char const c = *cs;
2303
206k
            if(BOOST_JSON_LIKELY(
2304
206k
                c >= '0' && c <= '9'))
2305
157k
            {
2306
157k
                ++cs;
2307
                //              18446744073709551615 UINT64_MAX
2308
157k
                if( num.mant  > 1844674407370955161 || (
2309
147k
                    num.mant == 1844674407370955161 && c > '5'))
2310
10.2k
                    break;
2311
147k
                BOOST_IF_CONSTEXPR( !no_parsing )
2312
147k
                    num.mant = 10 * num.mant + ( c - '0' );
2313
147k
            }
2314
48.4k
            else
2315
48.4k
            {
2316
48.4k
                goto do_num6; // [.eE]
2317
48.4k
            }
2318
206k
        }
2319
59.6k
    }
2320
10.2k
    ++num.bias;
2321
2322
    //----------------------------------
2323
    //
2324
    // 1*DIGIT
2325
    // non-significant digits left of decimal
2326
    //
2327
10.2k
do_num3:
2328
10.2k
    for(;;)
2329
15.2M
    {
2330
15.2M
        if(BOOST_JSON_UNLIKELY(! cs))
2331
79
        {
2332
79
            if(BOOST_JSON_UNLIKELY(more_))
2333
38
            {
2334
38
                if(BOOST_JSON_UNLIKELY(
2335
38
                    ! h_.on_number_part(
2336
38
                        {begin, cs.used(begin)}, ec_)))
2337
0
                    return fail(cs.begin());
2338
2339
38
                BOOST_IF_CONSTEXPR( precise_parsing )
2340
0
                    num_buf_.append( begin, cs.used(begin) );
2341
38
                return suspend(cs.begin(), state::num3, num);
2342
38
            }
2343
41
            goto finish_dub;
2344
79
        }
2345
15.2M
        char const c = *cs;
2346
15.2M
        if(BOOST_JSON_UNLIKELY(
2347
15.2M
            c >= '0' && c <= '9'))
2348
15.2M
        {
2349
15.2M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2350
0
            {
2351
0
                BOOST_STATIC_CONSTEXPR source_location loc
2352
0
                    = BOOST_CURRENT_LOCATION;
2353
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2354
0
            }
2355
15.2M
            ++cs;
2356
15.2M
            ++num.bias;
2357
15.2M
        }
2358
10.1k
        else if(BOOST_JSON_LIKELY(
2359
10.1k
            c == '.'))
2360
1.39k
        {
2361
1.39k
            ++cs;
2362
1.39k
            break;
2363
1.39k
        }
2364
8.79k
        else if((c | 32) == 'e')
2365
1.94k
        {
2366
1.94k
            ++cs;
2367
1.94k
            goto do_exp1;
2368
1.94k
        }
2369
6.85k
        else
2370
6.85k
        {
2371
6.85k
            goto finish_dub;
2372
6.85k
        }
2373
15.2M
    }
2374
2375
    //----------------------------------
2376
    //
2377
    // DIGIT
2378
    // first non-significant digit
2379
    // to the right of decimal
2380
    //
2381
1.39k
do_num4:
2382
1.39k
    {
2383
1.39k
        if(BOOST_JSON_UNLIKELY(! cs))
2384
10
        {
2385
10
            if(BOOST_JSON_UNLIKELY(
2386
10
                ! h_.on_number_part(
2387
10
                    {begin, cs.used(begin)}, ec_)))
2388
0
                return fail(cs.begin());
2389
2390
10
            BOOST_IF_CONSTEXPR( precise_parsing )
2391
0
                num_buf_.append( begin, cs.used(begin) );
2392
10
            return maybe_suspend(
2393
10
                cs.begin(), state::num4, num);
2394
10
        }
2395
1.38k
        char const c = *cs;
2396
1.38k
        if(BOOST_JSON_LIKELY(
2397
            //static_cast<unsigned char>(c - '0') < 10))
2398
1.38k
            c >= '0' && c <= '9'))
2399
1.37k
        {
2400
1.37k
            ++cs;
2401
1.37k
        }
2402
11
        else
2403
11
        {
2404
            // digit required
2405
11
            BOOST_STATIC_CONSTEXPR source_location loc
2406
11
                = BOOST_CURRENT_LOCATION;
2407
11
            return fail(cs.begin(), error::syntax, &loc);
2408
11
        }
2409
1.38k
    }
2410
2411
    //----------------------------------
2412
    //
2413
    // 1*DIGIT
2414
    // non-significant digits
2415
    // to the right of decimal
2416
    //
2417
8.23k
do_num5:
2418
8.23k
    for(;;)
2419
36.5k
    {
2420
36.5k
        if(BOOST_JSON_UNLIKELY(! cs))
2421
104
        {
2422
104
            if(BOOST_JSON_UNLIKELY(more_))
2423
55
            {
2424
55
                if(BOOST_JSON_UNLIKELY(
2425
55
                    ! h_.on_number_part(
2426
55
                        {begin, cs.used(begin)}, ec_)))
2427
0
                    return fail(cs.begin());
2428
2429
55
                BOOST_IF_CONSTEXPR( precise_parsing )
2430
0
                    num_buf_.append( begin, cs.used(begin) );
2431
55
                return suspend(cs.begin(), state::num5, num);
2432
55
            }
2433
49
            goto finish_dub;
2434
104
        }
2435
36.4k
        char const c = *cs;
2436
36.4k
        if(BOOST_JSON_LIKELY(
2437
36.4k
            c >= '0' && c <= '9'))
2438
28.2k
        {
2439
28.2k
            ++cs;
2440
28.2k
        }
2441
8.13k
        else if((c | 32) == 'e')
2442
602
        {
2443
602
            ++cs;
2444
602
            goto do_exp1;
2445
602
        }
2446
7.53k
        else
2447
7.53k
        {
2448
7.53k
            goto finish_dub;
2449
7.53k
        }
2450
36.4k
    }
2451
2452
    //----------------------------------
2453
    //
2454
    // [.eE]
2455
    //
2456
48.4k
do_num6:
2457
48.4k
    {
2458
48.4k
        if(BOOST_JSON_UNLIKELY(! cs))
2459
0
        {
2460
0
            if(BOOST_JSON_UNLIKELY(more_))
2461
0
            {
2462
0
                if(BOOST_JSON_UNLIKELY(
2463
0
                    ! h_.on_number_part(
2464
0
                        {begin, cs.used(begin)}, ec_)))
2465
0
                    return fail(cs.begin());
2466
2467
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2468
0
                    num_buf_.append( begin, cs.used(begin) );
2469
0
                return suspend(cs.begin(), state::num6, num);
2470
0
            }
2471
0
            goto finish_int;
2472
0
        }
2473
48.4k
        char const c = *cs;
2474
48.4k
        if(BOOST_JSON_LIKELY(
2475
48.4k
            c == '.'))
2476
6.99k
        {
2477
6.99k
            ++cs;
2478
6.99k
        }
2479
41.4k
        else if((c | 32) == 'e')
2480
4.72k
        {
2481
4.72k
            ++cs;
2482
4.72k
            goto do_exp1;
2483
4.72k
        }
2484
36.7k
        else
2485
36.7k
        {
2486
36.7k
            goto finish_int;
2487
36.7k
        }
2488
48.4k
    }
2489
2490
    //----------------------------------
2491
    //
2492
    // DIGIT
2493
    // first significant digit
2494
    // to the right of decimal
2495
    //
2496
8.80k
do_num7:
2497
8.80k
    {
2498
8.80k
        if(BOOST_JSON_UNLIKELY(! cs))
2499
13
        {
2500
13
            if(BOOST_JSON_UNLIKELY(more_))
2501
7
            {
2502
7
                if(BOOST_JSON_UNLIKELY(
2503
7
                    ! h_.on_number_part(
2504
7
                        {begin, cs.used(begin)}, ec_)))
2505
0
                    return fail(cs.begin());
2506
2507
7
                BOOST_IF_CONSTEXPR( precise_parsing )
2508
0
                    num_buf_.append( begin, cs.used(begin) );
2509
7
                return suspend(cs.begin(), state::num7, num);
2510
7
            }
2511
            // digit required
2512
6
            BOOST_STATIC_CONSTEXPR source_location loc
2513
6
                = BOOST_CURRENT_LOCATION;
2514
6
            return fail(cs.begin(), error::syntax, &loc);
2515
13
        }
2516
8.78k
        char const c = *cs;
2517
8.78k
        if(BOOST_JSON_UNLIKELY(
2518
8.78k
            c < '0' || c > '9'))
2519
38
        {
2520
            // digit required
2521
38
            BOOST_STATIC_CONSTEXPR source_location loc
2522
38
                = BOOST_CURRENT_LOCATION;
2523
38
            return fail(cs.begin(), error::syntax, &loc);
2524
38
        }
2525
8.78k
    }
2526
2527
    //----------------------------------
2528
    //
2529
    // 1*DIGIT
2530
    // significant digits
2531
    // to the right of decimal
2532
    //
2533
9.41k
do_num8:
2534
9.41k
    for(;;)
2535
29.8k
    {
2536
29.8k
        if(BOOST_JSON_UNLIKELY(! cs))
2537
911
        {
2538
911
            if(BOOST_JSON_UNLIKELY(more_))
2539
799
            {
2540
799
                if(BOOST_JSON_UNLIKELY(
2541
799
                    ! h_.on_number_part(
2542
799
                        {begin, cs.used(begin)}, ec_)))
2543
0
                    return fail(cs.begin());
2544
2545
799
                BOOST_IF_CONSTEXPR( precise_parsing )
2546
0
                    num_buf_.append( begin, cs.used(begin) );
2547
799
                return suspend(cs.begin(), state::num8, num);
2548
799
            }
2549
112
            goto finish_dub;
2550
911
        }
2551
28.9k
        char const c = *cs;
2552
28.9k
        if(BOOST_JSON_LIKELY(
2553
28.9k
            c >= '0' && c <= '9'))
2554
27.2k
        {
2555
27.2k
            ++cs;
2556
27.2k
            if(!no_parsing && BOOST_JSON_LIKELY(
2557
27.2k
                num.mant <= 9007199254740991)) // 2^53-1
2558
20.4k
            {
2559
20.4k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2560
0
                {
2561
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2562
0
                        = BOOST_CURRENT_LOCATION;
2563
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2564
0
                }
2565
20.4k
                --num.bias;
2566
20.4k
                num.mant = 10 * num.mant + ( c - '0' );
2567
20.4k
            }
2568
6.86k
            else
2569
6.86k
            {
2570
6.86k
                goto do_num5;
2571
6.86k
            }
2572
27.2k
        }
2573
1.63k
        else if((c | 32) == 'e')
2574
507
        {
2575
507
            ++cs;
2576
507
            goto do_exp1;
2577
507
        }
2578
1.13k
        else
2579
1.13k
        {
2580
1.13k
            goto finish_dub;
2581
1.13k
        }
2582
28.9k
    }
2583
2584
    //----------------------------------
2585
    //
2586
    // *[+-]
2587
    //
2588
5.48M
do_exp1:
2589
5.48M
    if(BOOST_JSON_UNLIKELY(! cs))
2590
65
    {
2591
65
        if(BOOST_JSON_UNLIKELY(
2592
65
            ! h_.on_number_part(
2593
65
                {begin, cs.used(begin)}, ec_)))
2594
0
            return fail(cs.begin());
2595
2596
65
        BOOST_IF_CONSTEXPR( precise_parsing )
2597
0
            num_buf_.append( begin, cs.used(begin) );
2598
65
        return maybe_suspend(
2599
65
            cs.begin(), state::exp1, num);
2600
65
    }
2601
5.48M
    if(*cs == '+')
2602
913
    {
2603
913
        ++cs;
2604
913
    }
2605
5.48M
    else if(*cs == '-')
2606
67.0k
    {
2607
67.0k
        ++cs;
2608
67.0k
        num.frac = true;
2609
67.0k
    }
2610
2611
    //----------------------------------
2612
    //
2613
    // DIGIT
2614
    // first digit of the exponent
2615
    //
2616
5.48M
do_exp2:
2617
5.48M
    {
2618
5.48M
        if(BOOST_JSON_UNLIKELY(! cs))
2619
27
        {
2620
27
            if(BOOST_JSON_UNLIKELY(more_))
2621
14
            {
2622
14
                if(BOOST_JSON_UNLIKELY(
2623
14
                    ! h_.on_number_part(
2624
14
                        {begin, cs.used(begin)}, ec_)))
2625
0
                    return fail(cs.begin());
2626
2627
14
                BOOST_IF_CONSTEXPR( precise_parsing )
2628
0
                    num_buf_.append( begin, cs.used(begin) );
2629
14
                return suspend(cs.begin(), state::exp2, num);
2630
14
            }
2631
            // digit required
2632
13
            BOOST_STATIC_CONSTEXPR source_location loc
2633
13
                = BOOST_CURRENT_LOCATION;
2634
13
            return fail(cs.begin(), error::syntax, &loc);
2635
27
        }
2636
5.48M
        char const c = *cs;
2637
5.48M
        if(BOOST_JSON_UNLIKELY(
2638
5.48M
            c < '0' || c > '9'))
2639
55
        {
2640
            // digit required
2641
55
            BOOST_STATIC_CONSTEXPR source_location loc
2642
55
                = BOOST_CURRENT_LOCATION;
2643
55
            return fail(cs.begin(), error::syntax, &loc);
2644
55
        }
2645
5.48M
        ++cs;
2646
5.48M
        num.exp = c - '0';
2647
5.48M
    }
2648
2649
    //----------------------------------
2650
    //
2651
    // 1*DIGIT
2652
    // subsequent digits in the exponent
2653
    //
2654
5.48M
do_exp3:
2655
5.48M
    for(;;)
2656
11.0M
    {
2657
11.0M
        if(BOOST_JSON_UNLIKELY(! cs))
2658
1.07k
        {
2659
1.07k
            if(BOOST_JSON_UNLIKELY(more_))
2660
667
            {
2661
667
                if(BOOST_JSON_UNLIKELY(
2662
667
                    ! h_.on_number_part(
2663
667
                        {begin, cs.used(begin)}, ec_)))
2664
0
                    return fail(cs.begin());
2665
2666
667
                BOOST_IF_CONSTEXPR( precise_parsing )
2667
0
                    num_buf_.append( begin, cs.used(begin) );
2668
667
                return suspend(cs.begin(), state::exp3, num);
2669
667
            }
2670
1.07k
        }
2671
11.0M
        else
2672
11.0M
        {
2673
11.0M
            char const c = *cs;
2674
11.0M
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2675
5.54M
            {
2676
5.54M
                if(BOOST_JSON_UNLIKELY(
2677
                //              2147483647 INT_MAX
2678
5.54M
                    num.exp  >  214748364 ||
2679
5.54M
                    (num.exp == 214748364 && c > '7')
2680
5.54M
                ))
2681
23.7k
                    num.exp = INT_MAX;
2682
5.52M
                else BOOST_IF_CONSTEXPR( !no_parsing )
2683
5.52M
                    num.exp = 10 * num.exp + ( c - '0' );
2684
2685
5.54M
                ++cs;
2686
5.54M
                continue;
2687
5.54M
            }
2688
11.0M
        }
2689
5.48M
        BOOST_ASSERT(num.exp >= 0);
2690
5.48M
        if ( num.frac )
2691
66.8k
        {
2692
66.8k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2693
895
            {
2694
                // if exponent overflowed, bias is a very large negative
2695
                // number, and mantissa isn't zero, then we cannot parse the
2696
                // number correctly
2697
895
                if(BOOST_JSON_UNLIKELY(
2698
895
                    (num.exp == INT_MAX) &&
2699
895
                    (num.bias < 0) &&
2700
895
                    (num.exp + num.bias < 308) &&
2701
895
                    num.mant ))
2702
0
                {
2703
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2704
0
                        = BOOST_CURRENT_LOCATION;
2705
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2706
0
                }
2707
2708
895
                num.bias = 0;
2709
895
                num.exp = INT_MAX;
2710
895
            }
2711
66.8k
        }
2712
5.41M
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2713
912
        {
2714
            // if exponent overflowed, bias is a very large positive number,
2715
            // and mantissa isn't zero, then we cannot parse the
2716
            // number correctly
2717
912
            if(BOOST_JSON_UNLIKELY(
2718
912
                (num.exp == INT_MAX) &&
2719
912
                (num.bias > 0) &&
2720
912
                (num.exp - num.bias < 308) &&
2721
912
                num.mant ))
2722
0
            {
2723
0
                BOOST_STATIC_CONSTEXPR source_location loc
2724
0
                    = BOOST_CURRENT_LOCATION;
2725
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2726
0
            }
2727
2728
912
            num.bias = 0;
2729
912
            num.exp = INT_MAX;
2730
912
        }
2731
5.48M
        goto finish_dub;
2732
5.48M
    }
2733
2734
37.0k
finish_int:
2735
37.0k
    if(negative || (!stack_empty && num.neg))
2736
0
    {
2737
0
        if(BOOST_JSON_UNLIKELY(
2738
0
            ! h_.on_int64(static_cast<
2739
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
0
        return cs.begin();
2742
0
    }
2743
37.0k
    if(num.mant <= INT64_MAX)
2744
13.9k
    {
2745
4.83M
finish_signed:
2746
4.83M
        if(BOOST_JSON_UNLIKELY(
2747
4.83M
            ! h_.on_int64(static_cast<
2748
4.83M
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2749
0
            return fail(cs.begin());
2750
4.83M
        return cs.begin();
2751
4.83M
    }
2752
23.0k
    if(BOOST_JSON_UNLIKELY(
2753
23.0k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2754
0
        return fail(cs.begin());
2755
23.0k
    return cs.begin();
2756
5.51M
finish_dub:
2757
5.51M
    double d;
2758
5.51M
    std::size_t const size = cs.used(begin);
2759
5.51M
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2760
5.51M
    BOOST_IF_CONSTEXPR( precise_parsing )
2761
0
    {
2762
0
        char const* data = begin;
2763
0
        std::size_t full_size = size;
2764
         // if we previously suspended or if the current input ends with the
2765
         // number, we need to copy the current part of the number to the
2766
         // temporary buffer
2767
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2768
0
        {
2769
0
            data = num_buf_.append( begin, size );
2770
0
            full_size = num_buf_.size();
2771
0
        }
2772
0
        auto const err = detail::charconv::from_chars(
2773
0
            data, data + full_size, d );
2774
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2775
0
        BOOST_ASSERT( err.ptr == data + full_size );
2776
0
        (void)err;
2777
0
    }
2778
5.51M
    else BOOST_IF_CONSTEXPR( no_parsing )
2779
0
        d = 0;
2780
5.51M
    else
2781
5.51M
        d = detail::dec_to_float(
2782
5.51M
            num.mant,
2783
5.51M
            num.bias + (num.frac ?
2784
5.44M
                -num.exp : num.exp),
2785
5.51M
            num.neg);
2786
5.51M
    if(BOOST_JSON_UNLIKELY(
2787
5.51M
        ! h_.on_double(d, {begin, size}, ec_)))
2788
0
        return fail(cs.begin());
2789
5.51M
    return cs.begin();
2790
5.51M
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)43, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)43>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<true, (char)43, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)43>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<false, (char)0, (boost::json::number_precision)0>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<char, (char)0>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)0>)
Line
Count
Source
2021
3.18k
{
2022
3.18k
    constexpr bool precise_parsing = mode == number_precision::precise;
2023
3.18k
    constexpr bool no_parsing = mode == number_precision::none;
2024
2025
    // only one of these will be true if we are not resuming
2026
    // if negative then !zero_first && !nonzero_first
2027
    // if zero_first then !nonzero_first && !negative
2028
    // if nonzero_first then !zero_first && !negative
2029
3.18k
    bool const negative = first == '-';
2030
3.18k
    bool const zero_first = first == '0';
2031
3.18k
    bool const nonzero_first = first == '+';
2032
3.18k
    detail::const_stream_wrapper cs(p, end_);
2033
3.18k
    number num;
2034
3.18k
    const char* begin = cs.begin();
2035
3.18k
    if(stack_empty || st_.empty())
2036
0
    {
2037
0
        num.bias = 0;
2038
0
        num.exp = 0;
2039
0
        num.frac = false;
2040
0
        num_buf_.clear();
2041
2042
        //----------------------------------
2043
        //
2044
        // '-'
2045
        // leading minus sign
2046
        //
2047
0
        BOOST_ASSERT(cs);
2048
0
        if(negative)
2049
0
            ++cs;
2050
2051
0
        num.neg = negative;
2052
0
        num.frac = false;
2053
0
        num.exp = 0;
2054
0
        num.bias = 0;
2055
2056
        // fast path
2057
0
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2058
0
        {
2059
0
            int n1;
2060
2061
0
            if( nonzero_first ||
2062
0
                (negative && *cs != '0') )
2063
0
            {
2064
0
                n1 = detail::count_digits( cs.begin() );
2065
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2066
2067
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2068
0
                {
2069
0
                    return parse_literal(
2070
0
                        p - 1, mp11::mp_int<detail::neg_infinity_literal>());
2071
0
                }
2072
2073
0
                if( ! nonzero_first && n1 == 0 )
2074
0
                {
2075
                    // digit required
2076
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2077
0
                        = BOOST_CURRENT_LOCATION;
2078
0
                    return fail(cs.begin(), error::syntax, &loc);
2079
0
                }
2080
2081
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2082
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2083
0
                else
2084
0
                    num.mant = 0;
2085
2086
0
                cs += n1;
2087
2088
                // integer or floating-point with
2089
                // >= 16 leading digits
2090
0
                if( n1 == 16 )
2091
0
                {
2092
0
                    goto do_num2;
2093
0
                }
2094
0
            }
2095
0
            else
2096
0
            {
2097
                // 0. floating-point or 0e integer
2098
0
                num.mant = 0;
2099
0
                n1 = 0;
2100
0
                ++cs;
2101
0
            }
2102
2103
0
            {
2104
0
                const char c = *cs;
2105
0
                if(c != '.')
2106
0
                {
2107
0
                    if((c | 32) == 'e')
2108
0
                    {
2109
0
                        ++cs;
2110
0
                        goto do_exp1;
2111
0
                    }
2112
0
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2113
0
                        num.mant = ~num.mant + 1;
2114
0
                    goto finish_signed;
2115
0
                }
2116
0
            }
2117
2118
            // floating-point number
2119
2120
0
            ++cs;
2121
2122
0
            int n2 = detail::count_digits( cs.begin() );
2123
0
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2124
2125
0
            if( n2 == 0 )
2126
0
            {
2127
                // digit required
2128
0
                BOOST_STATIC_CONSTEXPR source_location loc
2129
0
                    = BOOST_CURRENT_LOCATION;
2130
0
                return fail(cs.begin(), error::syntax, &loc);
2131
0
            }
2132
2133
            // floating-point mantissa overflow
2134
0
            if( n1 + n2 >= 19 )
2135
0
            {
2136
0
                goto do_num7;
2137
0
            }
2138
2139
0
            BOOST_IF_CONSTEXPR( !no_parsing )
2140
0
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2141
2142
0
            BOOST_ASSERT(num.bias == 0);
2143
2144
0
            num.bias -= n2;
2145
2146
0
            cs += n2;
2147
2148
0
            char ch = *cs;
2149
2150
0
            if( (ch | 32) == 'e' )
2151
0
            {
2152
0
                ++cs;
2153
0
                goto do_exp1;
2154
0
            }
2155
0
            else if( ch >= '0' && ch <= '9' )
2156
0
            {
2157
0
                goto do_num8;
2158
0
            }
2159
2160
0
            goto finish_dub;
2161
0
        }
2162
0
    }
2163
3.18k
    else
2164
3.18k
    {
2165
3.18k
        num = num_;
2166
3.18k
        state st;
2167
3.18k
        st_.pop(st);
2168
3.18k
        switch(st)
2169
3.18k
        {
2170
0
        default: BOOST_JSON_UNREACHABLE();
2171
28
        case state::num1: goto do_num1;
2172
809
        case state::num2: goto do_num2;
2173
81
        case state::num3: goto do_num3;
2174
8
        case state::num4: goto do_num4;
2175
101
        case state::num5: goto do_num5;
2176
40
        case state::num6: goto do_num6;
2177
18
        case state::num7: goto do_num7;
2178
1.04k
        case state::num8: goto do_num8;
2179
77
        case state::exp1: goto do_exp1;
2180
37
        case state::exp2: goto do_exp2;
2181
944
        case state::exp3: goto do_exp3;
2182
3.18k
        }
2183
3.18k
    }
2184
2185
    //----------------------------------
2186
    //
2187
    // DIGIT
2188
    // first digit
2189
    //
2190
28
do_num1:
2191
28
    if(zero_first || nonzero_first ||
2192
28
        BOOST_JSON_LIKELY(cs))
2193
0
    {
2194
0
        char const c = *cs;
2195
0
        if(zero_first)
2196
0
        {
2197
0
            ++cs;
2198
0
            num.mant = 0;
2199
0
            goto do_num6;
2200
0
        }
2201
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2202
0
            c >= '1' && c <= '9'))
2203
0
        {
2204
0
            ++cs;
2205
0
            num.mant = c - '0';
2206
0
        }
2207
0
        else if(BOOST_JSON_UNLIKELY(
2208
0
            c == '0'))
2209
0
        {
2210
0
            ++cs;
2211
0
            num.mant = 0;
2212
0
            goto do_num6;
2213
0
        }
2214
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2215
0
        {
2216
0
            st_.push(state::lit1);
2217
0
            cur_lit_ = detail::neg_infinity_literal;
2218
0
            lit_offset_ = 1;
2219
0
            return parse_literal(
2220
0
                cs.begin(), mp11::mp_int<detail::resume_literal>() );
2221
0
        }
2222
0
        else
2223
0
        {
2224
0
            BOOST_STATIC_CONSTEXPR source_location loc
2225
0
                = BOOST_CURRENT_LOCATION;
2226
0
            return fail(cs.begin(), error::syntax, &loc);
2227
0
        }
2228
0
    }
2229
28
    else
2230
28
    {
2231
28
        if(BOOST_JSON_UNLIKELY(
2232
28
            ! h_.on_number_part(
2233
28
                {begin, cs.used(begin)}, ec_)))
2234
0
            return fail(cs.begin());
2235
2236
28
        BOOST_IF_CONSTEXPR( precise_parsing )
2237
0
            num_buf_.append( begin, cs.used(begin) );
2238
28
        return maybe_suspend(
2239
28
            cs.begin(), state::num1, num);
2240
28
    }
2241
2242
    //----------------------------------
2243
    //
2244
    // 1*DIGIT
2245
    // significant digits left of decimal
2246
    //
2247
809
do_num2:
2248
809
    if(negative || (!stack_empty && num.neg))
2249
254
    {
2250
254
        for(;;)
2251
254
        {
2252
254
            if(BOOST_JSON_UNLIKELY(! cs))
2253
254
            {
2254
254
                if(BOOST_JSON_UNLIKELY(more_))
2255
0
                {
2256
0
                    if(BOOST_JSON_UNLIKELY(
2257
0
                        ! h_.on_number_part(
2258
0
                            {begin, cs.used(begin)}, ec_)))
2259
0
                        return fail(cs.begin());
2260
2261
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2262
0
                        num_buf_.append( begin, cs.used(begin) );
2263
0
                    return suspend(cs.begin(), state::num2, num);
2264
0
                }
2265
254
                goto finish_int;
2266
254
            }
2267
0
            char const c = *cs;
2268
0
            if(BOOST_JSON_LIKELY(
2269
0
                c >= '0' && c <= '9'))
2270
0
            {
2271
0
                ++cs;
2272
                //              9223372036854775808 INT64_MIN
2273
0
                if( num.mant  > 922337203685477580 || (
2274
0
                    num.mant == 922337203685477580 && c > '8'))
2275
0
                    break;
2276
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2277
0
                    num.mant = 10 * num.mant + ( c - '0' );
2278
0
                continue;
2279
0
            }
2280
0
            goto do_num6; // [.eE]
2281
0
        }
2282
254
    }
2283
555
    else
2284
555
    {
2285
555
        for(;;)
2286
555
        {
2287
555
            if(BOOST_JSON_UNLIKELY(! cs))
2288
555
            {
2289
555
                if(BOOST_JSON_UNLIKELY(more_))
2290
0
                {
2291
0
                    if(BOOST_JSON_UNLIKELY(
2292
0
                        ! h_.on_number_part(
2293
0
                            {begin, cs.used(begin)}, ec_)))
2294
0
                        return fail(cs.begin());
2295
2296
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2297
0
                        num_buf_.append( begin, cs.used(begin) );
2298
0
                    return suspend(cs.begin(), state::num2, num);
2299
0
                }
2300
555
                goto finish_int;
2301
555
            }
2302
0
            char const c = *cs;
2303
0
            if(BOOST_JSON_LIKELY(
2304
0
                c >= '0' && c <= '9'))
2305
0
            {
2306
0
                ++cs;
2307
                //              18446744073709551615 UINT64_MAX
2308
0
                if( num.mant  > 1844674407370955161 || (
2309
0
                    num.mant == 1844674407370955161 && c > '5'))
2310
0
                    break;
2311
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2312
0
                    num.mant = 10 * num.mant + ( c - '0' );
2313
0
            }
2314
0
            else
2315
0
            {
2316
0
                goto do_num6; // [.eE]
2317
0
            }
2318
0
        }
2319
555
    }
2320
0
    ++num.bias;
2321
2322
    //----------------------------------
2323
    //
2324
    // 1*DIGIT
2325
    // non-significant digits left of decimal
2326
    //
2327
81
do_num3:
2328
81
    for(;;)
2329
81
    {
2330
81
        if(BOOST_JSON_UNLIKELY(! cs))
2331
81
        {
2332
81
            if(BOOST_JSON_UNLIKELY(more_))
2333
0
            {
2334
0
                if(BOOST_JSON_UNLIKELY(
2335
0
                    ! h_.on_number_part(
2336
0
                        {begin, cs.used(begin)}, ec_)))
2337
0
                    return fail(cs.begin());
2338
2339
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2340
0
                    num_buf_.append( begin, cs.used(begin) );
2341
0
                return suspend(cs.begin(), state::num3, num);
2342
0
            }
2343
81
            goto finish_dub;
2344
81
        }
2345
0
        char const c = *cs;
2346
0
        if(BOOST_JSON_UNLIKELY(
2347
0
            c >= '0' && c <= '9'))
2348
0
        {
2349
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2350
0
            {
2351
0
                BOOST_STATIC_CONSTEXPR source_location loc
2352
0
                    = BOOST_CURRENT_LOCATION;
2353
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2354
0
            }
2355
0
            ++cs;
2356
0
            ++num.bias;
2357
0
        }
2358
0
        else if(BOOST_JSON_LIKELY(
2359
0
            c == '.'))
2360
0
        {
2361
0
            ++cs;
2362
0
            break;
2363
0
        }
2364
0
        else if((c | 32) == 'e')
2365
0
        {
2366
0
            ++cs;
2367
0
            goto do_exp1;
2368
0
        }
2369
0
        else
2370
0
        {
2371
0
            goto finish_dub;
2372
0
        }
2373
0
    }
2374
2375
    //----------------------------------
2376
    //
2377
    // DIGIT
2378
    // first non-significant digit
2379
    // to the right of decimal
2380
    //
2381
8
do_num4:
2382
8
    {
2383
8
        if(BOOST_JSON_UNLIKELY(! cs))
2384
8
        {
2385
8
            if(BOOST_JSON_UNLIKELY(
2386
8
                ! h_.on_number_part(
2387
8
                    {begin, cs.used(begin)}, ec_)))
2388
0
                return fail(cs.begin());
2389
2390
8
            BOOST_IF_CONSTEXPR( precise_parsing )
2391
0
                num_buf_.append( begin, cs.used(begin) );
2392
8
            return maybe_suspend(
2393
8
                cs.begin(), state::num4, num);
2394
8
        }
2395
0
        char const c = *cs;
2396
0
        if(BOOST_JSON_LIKELY(
2397
            //static_cast<unsigned char>(c - '0') < 10))
2398
0
            c >= '0' && c <= '9'))
2399
0
        {
2400
0
            ++cs;
2401
0
        }
2402
0
        else
2403
0
        {
2404
            // digit required
2405
0
            BOOST_STATIC_CONSTEXPR source_location loc
2406
0
                = BOOST_CURRENT_LOCATION;
2407
0
            return fail(cs.begin(), error::syntax, &loc);
2408
0
        }
2409
0
    }
2410
2411
    //----------------------------------
2412
    //
2413
    // 1*DIGIT
2414
    // non-significant digits
2415
    // to the right of decimal
2416
    //
2417
101
do_num5:
2418
101
    for(;;)
2419
101
    {
2420
101
        if(BOOST_JSON_UNLIKELY(! cs))
2421
101
        {
2422
101
            if(BOOST_JSON_UNLIKELY(more_))
2423
0
            {
2424
0
                if(BOOST_JSON_UNLIKELY(
2425
0
                    ! h_.on_number_part(
2426
0
                        {begin, cs.used(begin)}, ec_)))
2427
0
                    return fail(cs.begin());
2428
2429
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2430
0
                    num_buf_.append( begin, cs.used(begin) );
2431
0
                return suspend(cs.begin(), state::num5, num);
2432
0
            }
2433
101
            goto finish_dub;
2434
101
        }
2435
0
        char const c = *cs;
2436
0
        if(BOOST_JSON_LIKELY(
2437
0
            c >= '0' && c <= '9'))
2438
0
        {
2439
0
            ++cs;
2440
0
        }
2441
0
        else if((c | 32) == 'e')
2442
0
        {
2443
0
            ++cs;
2444
0
            goto do_exp1;
2445
0
        }
2446
0
        else
2447
0
        {
2448
0
            goto finish_dub;
2449
0
        }
2450
0
    }
2451
2452
    //----------------------------------
2453
    //
2454
    // [.eE]
2455
    //
2456
40
do_num6:
2457
40
    {
2458
40
        if(BOOST_JSON_UNLIKELY(! cs))
2459
40
        {
2460
40
            if(BOOST_JSON_UNLIKELY(more_))
2461
0
            {
2462
0
                if(BOOST_JSON_UNLIKELY(
2463
0
                    ! h_.on_number_part(
2464
0
                        {begin, cs.used(begin)}, ec_)))
2465
0
                    return fail(cs.begin());
2466
2467
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2468
0
                    num_buf_.append( begin, cs.used(begin) );
2469
0
                return suspend(cs.begin(), state::num6, num);
2470
0
            }
2471
40
            goto finish_int;
2472
40
        }
2473
0
        char const c = *cs;
2474
0
        if(BOOST_JSON_LIKELY(
2475
0
            c == '.'))
2476
0
        {
2477
0
            ++cs;
2478
0
        }
2479
0
        else if((c | 32) == 'e')
2480
0
        {
2481
0
            ++cs;
2482
0
            goto do_exp1;
2483
0
        }
2484
0
        else
2485
0
        {
2486
0
            goto finish_int;
2487
0
        }
2488
0
    }
2489
2490
    //----------------------------------
2491
    //
2492
    // DIGIT
2493
    // first significant digit
2494
    // to the right of decimal
2495
    //
2496
18
do_num7:
2497
18
    {
2498
18
        if(BOOST_JSON_UNLIKELY(! cs))
2499
18
        {
2500
18
            if(BOOST_JSON_UNLIKELY(more_))
2501
0
            {
2502
0
                if(BOOST_JSON_UNLIKELY(
2503
0
                    ! h_.on_number_part(
2504
0
                        {begin, cs.used(begin)}, ec_)))
2505
0
                    return fail(cs.begin());
2506
2507
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2508
0
                    num_buf_.append( begin, cs.used(begin) );
2509
0
                return suspend(cs.begin(), state::num7, num);
2510
0
            }
2511
            // digit required
2512
18
            BOOST_STATIC_CONSTEXPR source_location loc
2513
18
                = BOOST_CURRENT_LOCATION;
2514
18
            return fail(cs.begin(), error::syntax, &loc);
2515
18
        }
2516
0
        char const c = *cs;
2517
0
        if(BOOST_JSON_UNLIKELY(
2518
0
            c < '0' || c > '9'))
2519
0
        {
2520
            // digit required
2521
0
            BOOST_STATIC_CONSTEXPR source_location loc
2522
0
                = BOOST_CURRENT_LOCATION;
2523
0
            return fail(cs.begin(), error::syntax, &loc);
2524
0
        }
2525
0
    }
2526
2527
    //----------------------------------
2528
    //
2529
    // 1*DIGIT
2530
    // significant digits
2531
    // to the right of decimal
2532
    //
2533
1.04k
do_num8:
2534
1.04k
    for(;;)
2535
1.04k
    {
2536
1.04k
        if(BOOST_JSON_UNLIKELY(! cs))
2537
1.04k
        {
2538
1.04k
            if(BOOST_JSON_UNLIKELY(more_))
2539
0
            {
2540
0
                if(BOOST_JSON_UNLIKELY(
2541
0
                    ! h_.on_number_part(
2542
0
                        {begin, cs.used(begin)}, ec_)))
2543
0
                    return fail(cs.begin());
2544
2545
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2546
0
                    num_buf_.append( begin, cs.used(begin) );
2547
0
                return suspend(cs.begin(), state::num8, num);
2548
0
            }
2549
1.04k
            goto finish_dub;
2550
1.04k
        }
2551
0
        char const c = *cs;
2552
0
        if(BOOST_JSON_LIKELY(
2553
0
            c >= '0' && c <= '9'))
2554
0
        {
2555
0
            ++cs;
2556
0
            if(!no_parsing && BOOST_JSON_LIKELY(
2557
0
                num.mant <= 9007199254740991)) // 2^53-1
2558
0
            {
2559
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2560
0
                {
2561
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2562
0
                        = BOOST_CURRENT_LOCATION;
2563
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2564
0
                }
2565
0
                --num.bias;
2566
0
                num.mant = 10 * num.mant + ( c - '0' );
2567
0
            }
2568
0
            else
2569
0
            {
2570
0
                goto do_num5;
2571
0
            }
2572
0
        }
2573
0
        else if((c | 32) == 'e')
2574
0
        {
2575
0
            ++cs;
2576
0
            goto do_exp1;
2577
0
        }
2578
0
        else
2579
0
        {
2580
0
            goto finish_dub;
2581
0
        }
2582
0
    }
2583
2584
    //----------------------------------
2585
    //
2586
    // *[+-]
2587
    //
2588
77
do_exp1:
2589
77
    if(BOOST_JSON_UNLIKELY(! cs))
2590
77
    {
2591
77
        if(BOOST_JSON_UNLIKELY(
2592
77
            ! h_.on_number_part(
2593
77
                {begin, cs.used(begin)}, ec_)))
2594
0
            return fail(cs.begin());
2595
2596
77
        BOOST_IF_CONSTEXPR( precise_parsing )
2597
0
            num_buf_.append( begin, cs.used(begin) );
2598
77
        return maybe_suspend(
2599
77
            cs.begin(), state::exp1, num);
2600
77
    }
2601
0
    if(*cs == '+')
2602
0
    {
2603
0
        ++cs;
2604
0
    }
2605
0
    else if(*cs == '-')
2606
0
    {
2607
0
        ++cs;
2608
0
        num.frac = true;
2609
0
    }
2610
2611
    //----------------------------------
2612
    //
2613
    // DIGIT
2614
    // first digit of the exponent
2615
    //
2616
37
do_exp2:
2617
37
    {
2618
37
        if(BOOST_JSON_UNLIKELY(! cs))
2619
37
        {
2620
37
            if(BOOST_JSON_UNLIKELY(more_))
2621
0
            {
2622
0
                if(BOOST_JSON_UNLIKELY(
2623
0
                    ! h_.on_number_part(
2624
0
                        {begin, cs.used(begin)}, ec_)))
2625
0
                    return fail(cs.begin());
2626
2627
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2628
0
                    num_buf_.append( begin, cs.used(begin) );
2629
0
                return suspend(cs.begin(), state::exp2, num);
2630
0
            }
2631
            // digit required
2632
37
            BOOST_STATIC_CONSTEXPR source_location loc
2633
37
                = BOOST_CURRENT_LOCATION;
2634
37
            return fail(cs.begin(), error::syntax, &loc);
2635
37
        }
2636
0
        char const c = *cs;
2637
0
        if(BOOST_JSON_UNLIKELY(
2638
0
            c < '0' || c > '9'))
2639
0
        {
2640
            // digit required
2641
0
            BOOST_STATIC_CONSTEXPR source_location loc
2642
0
                = BOOST_CURRENT_LOCATION;
2643
0
            return fail(cs.begin(), error::syntax, &loc);
2644
0
        }
2645
0
        ++cs;
2646
0
        num.exp = c - '0';
2647
0
    }
2648
2649
    //----------------------------------
2650
    //
2651
    // 1*DIGIT
2652
    // subsequent digits in the exponent
2653
    //
2654
944
do_exp3:
2655
944
    for(;;)
2656
944
    {
2657
944
        if(BOOST_JSON_UNLIKELY(! cs))
2658
944
        {
2659
944
            if(BOOST_JSON_UNLIKELY(more_))
2660
0
            {
2661
0
                if(BOOST_JSON_UNLIKELY(
2662
0
                    ! h_.on_number_part(
2663
0
                        {begin, cs.used(begin)}, ec_)))
2664
0
                    return fail(cs.begin());
2665
2666
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2667
0
                    num_buf_.append( begin, cs.used(begin) );
2668
0
                return suspend(cs.begin(), state::exp3, num);
2669
0
            }
2670
944
        }
2671
0
        else
2672
0
        {
2673
0
            char const c = *cs;
2674
0
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2675
0
            {
2676
0
                if(BOOST_JSON_UNLIKELY(
2677
                //              2147483647 INT_MAX
2678
0
                    num.exp  >  214748364 ||
2679
0
                    (num.exp == 214748364 && c > '7')
2680
0
                ))
2681
0
                    num.exp = INT_MAX;
2682
0
                else BOOST_IF_CONSTEXPR( !no_parsing )
2683
0
                    num.exp = 10 * num.exp + ( c - '0' );
2684
2685
0
                ++cs;
2686
0
                continue;
2687
0
            }
2688
0
        }
2689
944
        BOOST_ASSERT(num.exp >= 0);
2690
944
        if ( num.frac )
2691
238
        {
2692
238
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2693
67
            {
2694
                // if exponent overflowed, bias is a very large negative
2695
                // number, and mantissa isn't zero, then we cannot parse the
2696
                // number correctly
2697
67
                if(BOOST_JSON_UNLIKELY(
2698
67
                    (num.exp == INT_MAX) &&
2699
67
                    (num.bias < 0) &&
2700
67
                    (num.exp + num.bias < 308) &&
2701
67
                    num.mant ))
2702
0
                {
2703
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2704
0
                        = BOOST_CURRENT_LOCATION;
2705
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2706
0
                }
2707
2708
67
                num.bias = 0;
2709
67
                num.exp = INT_MAX;
2710
67
            }
2711
238
        }
2712
706
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2713
83
        {
2714
            // if exponent overflowed, bias is a very large positive number,
2715
            // and mantissa isn't zero, then we cannot parse the
2716
            // number correctly
2717
83
            if(BOOST_JSON_UNLIKELY(
2718
83
                (num.exp == INT_MAX) &&
2719
83
                (num.bias > 0) &&
2720
83
                (num.exp - num.bias < 308) &&
2721
83
                num.mant ))
2722
0
            {
2723
0
                BOOST_STATIC_CONSTEXPR source_location loc
2724
0
                    = BOOST_CURRENT_LOCATION;
2725
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2726
0
            }
2727
2728
83
            num.bias = 0;
2729
83
            num.exp = INT_MAX;
2730
83
        }
2731
944
        goto finish_dub;
2732
944
    }
2733
2734
849
finish_int:
2735
849
    if(negative || (!stack_empty && num.neg))
2736
259
    {
2737
259
        if(BOOST_JSON_UNLIKELY(
2738
259
            ! h_.on_int64(static_cast<
2739
259
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
259
        return cs.begin();
2742
259
    }
2743
590
    if(num.mant <= INT64_MAX)
2744
429
    {
2745
429
finish_signed:
2746
429
        if(BOOST_JSON_UNLIKELY(
2747
429
            ! h_.on_int64(static_cast<
2748
429
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2749
0
            return fail(cs.begin());
2750
429
        return cs.begin();
2751
429
    }
2752
161
    if(BOOST_JSON_UNLIKELY(
2753
161
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2754
0
        return fail(cs.begin());
2755
161
    return cs.begin();
2756
2.16k
finish_dub:
2757
2.16k
    double d;
2758
2.16k
    std::size_t const size = cs.used(begin);
2759
2.16k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2760
2.16k
    BOOST_IF_CONSTEXPR( precise_parsing )
2761
0
    {
2762
0
        char const* data = begin;
2763
0
        std::size_t full_size = size;
2764
         // if we previously suspended or if the current input ends with the
2765
         // number, we need to copy the current part of the number to the
2766
         // temporary buffer
2767
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2768
0
        {
2769
0
            data = num_buf_.append( begin, size );
2770
0
            full_size = num_buf_.size();
2771
0
        }
2772
0
        auto const err = detail::charconv::from_chars(
2773
0
            data, data + full_size, d );
2774
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2775
0
        BOOST_ASSERT( err.ptr == data + full_size );
2776
0
        (void)err;
2777
0
    }
2778
2.16k
    else BOOST_IF_CONSTEXPR( no_parsing )
2779
0
        d = 0;
2780
2.16k
    else
2781
2.16k
        d = detail::dec_to_float(
2782
2.16k
            num.mant,
2783
2.16k
            num.bias + (num.frac ?
2784
1.93k
                -num.exp : num.exp),
2785
2.16k
            num.neg);
2786
2.16k
    if(BOOST_JSON_UNLIKELY(
2787
2.16k
        ! h_.on_double(d, {begin, size}, ec_)))
2788
0
        return fail(cs.begin());
2789
2.16k
    return cs.begin();
2790
2.16k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<false, (char)0, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<char, (char)0>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_number<false, (char)0, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<char, (char)0>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
2791
2792
//----------------------------------------------------------
2793
2794
template<class Handler>
2795
template<class... Args>
2796
basic_parser<Handler>::
2797
basic_parser(
2798
    parse_options const& opt,
2799
    Args&&... args)
2800
    : h_(std::forward<Args>(args)...)
2801
    , opt_(opt)
2802
18.1k
{
2803
18.1k
}
boost::json::basic_parser<boost::json::detail::handler>::basic_parser<boost::json::storage_ptr, unsigned char*&, unsigned long&>(boost::json::parse_options const&, boost::json::storage_ptr&&, unsigned char*&, unsigned long&)
Line
Count
Source
2802
12.1k
{
2803
12.1k
}
boost::json::basic_parser<boost::json::detail::handler>::basic_parser<boost::json::storage_ptr, decltype(nullptr), int>(boost::json::parse_options const&, boost::json::storage_ptr&&, decltype(nullptr)&&, int&&)
Line
Count
Source
2802
5.97k
{
2803
5.97k
}
2804
2805
//----------------------------------------------------------
2806
2807
template<class Handler>
2808
void
2809
basic_parser<Handler>::
2810
reset() noexcept
2811
28.0k
{
2812
28.0k
    ec_ = {};
2813
28.0k
    st_.clear();
2814
28.0k
    more_ = true;
2815
28.0k
    done_ = false;
2816
28.0k
    clean_ = true;
2817
28.0k
    num_buf_.clear();
2818
28.0k
}
2819
2820
template<class Handler>
2821
void
2822
basic_parser<Handler>::
2823
fail(system::error_code ec) noexcept
2824
1.64k
{
2825
1.64k
    if(! ec)
2826
0
    {
2827
        // assign an arbitrary
2828
        // error code to prevent UB
2829
0
        BOOST_JSON_FAIL(ec_, error::incomplete);
2830
0
    }
2831
1.64k
    else
2832
1.64k
    {
2833
1.64k
        ec_ = ec;
2834
1.64k
    }
2835
1.64k
    done_ = false;
2836
1.64k
}
2837
2838
//----------------------------------------------------------
2839
2840
template<class Handler>
2841
std::size_t
2842
basic_parser<Handler>::
2843
write_some(
2844
    bool more,
2845
    char const* data,
2846
    std::size_t size,
2847
    system::error_code& ec)
2848
25.3k
{
2849
    // see if we exited via exception
2850
    // on the last call to write_some
2851
25.3k
    if(! clean_)
2852
0
    {
2853
        // prevent UB
2854
0
        if(! ec_)
2855
0
        {
2856
0
            BOOST_JSON_FAIL(ec_, error::exception);
2857
0
        }
2858
0
    }
2859
25.3k
    if(ec_)
2860
0
    {
2861
        // error is sticky
2862
0
        ec = ec_;
2863
0
        return 0;
2864
0
    }
2865
25.3k
    clean_ = false;
2866
25.3k
    more_ = more;
2867
25.3k
    end_ = data + size;
2868
25.3k
    const char* p;
2869
25.3k
    if(BOOST_JSON_LIKELY(st_.empty()))
2870
18.1k
    {
2871
        // first time
2872
18.1k
        depth_ = opt_.max_depth;
2873
18.1k
        if(BOOST_JSON_UNLIKELY(
2874
18.1k
            ! h_.on_document_begin(ec_)))
2875
0
        {
2876
0
            ec = ec_;
2877
0
            return 0;
2878
0
        }
2879
18.1k
        p = parse_document(data, std::true_type());
2880
18.1k
    }
2881
7.25k
    else
2882
7.25k
    {
2883
7.25k
        p = parse_document(data, std::false_type());
2884
7.25k
    }
2885
2886
25.3k
    if(BOOST_JSON_LIKELY(p != sentinel()))
2887
8.61k
    {
2888
8.61k
        BOOST_ASSERT(! ec_);
2889
8.61k
        if(! done_)
2890
6.57k
        {
2891
6.57k
            done_ = true;
2892
6.57k
            h_.on_document_end(ec_);
2893
6.57k
        }
2894
8.61k
    }
2895
16.7k
    else
2896
16.7k
    {
2897
16.7k
        if(! ec_)
2898
11.8k
        {
2899
11.8k
            if(! more_)
2900
4.60k
            {
2901
4.60k
                BOOST_JSON_FAIL(ec_, error::incomplete);
2902
4.60k
            }
2903
7.25k
            else if(! st_.empty())
2904
7.25k
            {
2905
                // consume as much trailing whitespace in
2906
                // the JSON document as possible, but still
2907
                // consider the parse complete
2908
7.25k
                state st;
2909
7.25k
                st_.peek(st);
2910
7.25k
                if( st == state::doc3 &&
2911
7.25k
                    ! done_)
2912
2.04k
                {
2913
2.04k
                    done_ = true;
2914
2.04k
                    h_.on_document_end(ec_);
2915
2.04k
                }
2916
7.25k
            }
2917
11.8k
        }
2918
16.7k
        p = end_;
2919
16.7k
    }
2920
25.3k
    ec = ec_;
2921
25.3k
    clean_ = true;
2922
25.3k
    return p - data;
2923
25.3k
}
2924
2925
template<class Handler>
2926
std::size_t
2927
basic_parser<Handler>::
2928
write_some(
2929
    bool more,
2930
    char const* data,
2931
    std::size_t size,
2932
    std::error_code& ec)
2933
{
2934
    system::error_code jec;
2935
    std::size_t const result = write_some(more, data, size, jec);
2936
    ec = jec;
2937
    return result;
2938
}
2939
2940
#endif
2941
2942
} // namespace json
2943
} // namespace boost
2944
2945
#ifdef _MSC_VER
2946
#pragma warning(pop)
2947
#endif
2948
2949
#endif