Coverage Report

Created: 2024-07-23 06:34

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