Coverage Report

Created: 2026-09-13 07:10

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/src/boost/boost/json/basic_parser_impl.hpp
Line
Count
Source
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4
//
5
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
//
8
// Official repository: https://github.com/boostorg/json
9
//
10
11
#ifndef BOOST_JSON_BASIC_PARSER_IMPL_HPP
12
#define BOOST_JSON_BASIC_PARSER_IMPL_HPP
13
14
#include <boost/json/detail/config.hpp>
15
#include <boost/json/detail/literals.hpp>
16
#include <boost/json/basic_parser.hpp>
17
#include <boost/json/error.hpp>
18
#include <boost/json/detail/buffer.hpp>
19
#include <boost/json/detail/charconv/from_chars.hpp>
20
#include <boost/json/detail/sse2.hpp>
21
#include <boost/mp11/algorithm.hpp>
22
#include <boost/mp11/integral.hpp>
23
#include <cmath>
24
#include <limits>
25
#include <cstring>
26
27
#ifdef _MSC_VER
28
#pragma warning(push)
29
#pragma warning(disable: 4702) // unreachable code
30
#pragma warning(disable: 4127) // conditional expression is constant
31
#endif
32
33
/*  This file must be manually included to get the
34
    function template definitions for basic_parser.
35
*/
36
37
/*  Reference:
38
39
    https://www.json.org/
40
41
    RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
42
    https://tools.ietf.org/html/rfc7159
43
44
    https://ampl.com/netlib/fp/dtoa.c
45
*/
46
47
#ifndef BOOST_JSON_DOCS
48
49
namespace boost {
50
namespace json {
51
namespace detail {
52
53
inline
54
double
55
pow10(int exp) noexcept
56
4.67M
{
57
4.67M
    static double const tab[618] = {
58
4.67M
                        1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
59
60
4.67M
        1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
61
4.67M
        1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
62
4.67M
        1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
63
4.67M
        1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
64
4.67M
        1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
65
4.67M
        1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
66
4.67M
        1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
67
4.67M
        1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
68
4.67M
        1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
69
4.67M
        1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
70
71
4.67M
        1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
72
4.67M
        1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
73
4.67M
        1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
74
4.67M
        1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
75
4.67M
        1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
76
4.67M
        1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
77
4.67M
        1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
78
4.67M
        1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
79
4.67M
        1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
80
4.67M
        1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
81
82
4.67M
        1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
83
4.67M
        1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
84
4.67M
        1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
85
4.67M
        1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
86
4.67M
        1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
87
4.67M
        1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
88
4.67M
        1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
89
4.67M
        1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
90
4.67M
        1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
91
4.67M
        1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
92
93
4.67M
        1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
94
4.67M
        1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
95
4.67M
        1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
96
4.67M
        1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
97
4.67M
        1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
98
4.67M
        1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
99
4.67M
        1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
100
4.67M
        1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
101
4.67M
        1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
102
4.67M
        1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
103
104
4.67M
        1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
105
4.67M
        1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
106
4.67M
        1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
107
4.67M
        1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
108
4.67M
        1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
109
4.67M
        1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
110
4.67M
        1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
111
4.67M
        1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
112
4.67M
        1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
113
4.67M
        1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
114
115
4.67M
        1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
116
4.67M
        1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
117
4.67M
        1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
118
4.67M
        1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
119
4.67M
        1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
120
4.67M
        1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
121
4.67M
        1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
122
4.67M
        1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
123
4.67M
        1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
124
4.67M
        1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
125
126
4.67M
        1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
127
128
4.67M
    if( exp > 308 )
129
44.2k
    {
130
44.2k
        return std::numeric_limits<double>::infinity();
131
44.2k
    }
132
4.63M
    else if( exp < -308 )
133
4.75k
    {
134
        // due to the way pow10 is used by dec_to_float,
135
        // we can afford to return 0.0 here
136
4.75k
        return 0.0;
137
4.75k
    }
138
4.62M
    else
139
4.62M
    {
140
4.62M
        exp += 308;
141
4.62M
        BOOST_ASSERT(exp >= 0 && exp < 618);
142
4.62M
        return tab[exp];
143
4.62M
    }
144
4.67M
}
145
146
inline
147
double
148
dec_to_float(
149
    std::uint64_t m,
150
    std::int32_t e,
151
    bool neg) noexcept
152
4.72M
{
153
    // convert to double explicitly to silence warnings
154
4.72M
    double x = static_cast<double>(m);
155
4.72M
    if(neg)
156
53.2k
        x = -x;
157
158
4.72M
    if(e < -305)
159
9.81k
    {
160
9.81k
        x *= 1e-305 ;
161
9.81k
        e += 305;
162
9.81k
    }
163
164
4.72M
    if(e >= -22 && e < 0)
165
64.6k
        return x / pow10(-e);
166
167
4.65M
    return x * pow10(e);
168
4.72M
}
169
170
inline
171
bool
172
is_control(char c) noexcept
173
0
{
174
0
    return static_cast<unsigned char>(c) < 32;
175
0
}
176
177
inline
178
int
179
hex_digit(unsigned char c) noexcept
180
3.24M
{
181
    // by Peter Dimov
182
3.24M
    if( c >= '0' && c <= '9' )
183
1.78M
        return c - '0';
184
1.46M
    c &= ~0x20;
185
1.46M
    if( c >= 'A' && c <= 'F' )
186
1.46M
        return 10 + c - 'A';
187
3.17k
    return -1;
188
1.46M
}
189
190
} // detail
191
192
//----------------------------------------------------------
193
194
template< class Handler >
195
template< bool StackEmpty_, char First_ >
196
struct basic_parser<Handler>::
197
parse_number_helper
198
{
199
    basic_parser* parser;
200
    char const* p;
201
202
    template< std::size_t N >
203
    char const*
204
    operator()( mp11::mp_size_t<N> ) const
205
12.1M
    {
206
12.1M
        return parser->parse_number(
207
12.1M
            p,
208
12.1M
            std::integral_constant<bool, StackEmpty_>(),
209
12.1M
            std::integral_constant<char, First_>(),
210
12.1M
            std::integral_constant<
211
12.1M
                number_precision, static_cast<number_precision>(N)>() );
212
12.1M
    }
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
205
237k
    {
206
237k
        return parser->parse_number(
207
237k
            p,
208
237k
            std::integral_constant<bool, StackEmpty_>(),
209
237k
            std::integral_constant<char, First_>(),
210
237k
            std::integral_constant<
211
237k
                number_precision, static_cast<number_precision>(N)>() );
212
237k
    }
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
Line
Count
Source
205
223k
    {
206
223k
        return parser->parse_number(
207
223k
            p,
208
223k
            std::integral_constant<bool, StackEmpty_>(),
209
223k
            std::integral_constant<char, First_>(),
210
223k
            std::integral_constant<
211
223k
                number_precision, static_cast<number_precision>(N)>() );
212
223k
    }
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
Line
Count
Source
205
7.94k
    {
206
7.94k
        return parser->parse_number(
207
7.94k
            p,
208
7.94k
            std::integral_constant<bool, StackEmpty_>(),
209
7.94k
            std::integral_constant<char, First_>(),
210
7.94k
            std::integral_constant<
211
7.94k
                number_precision, static_cast<number_precision>(N)>() );
212
7.94k
    }
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
205
60.0k
    {
206
60.0k
        return parser->parse_number(
207
60.0k
            p,
208
60.0k
            std::integral_constant<bool, StackEmpty_>(),
209
60.0k
            std::integral_constant<char, First_>(),
210
60.0k
            std::integral_constant<
211
60.0k
                number_precision, static_cast<number_precision>(N)>() );
212
60.0k
    }
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
Line
Count
Source
205
14.2k
    {
206
14.2k
        return parser->parse_number(
207
14.2k
            p,
208
14.2k
            std::integral_constant<bool, StackEmpty_>(),
209
14.2k
            std::integral_constant<char, First_>(),
210
14.2k
            std::integral_constant<
211
14.2k
                number_precision, static_cast<number_precision>(N)>() );
212
14.2k
    }
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
Line
Count
Source
205
5.88k
    {
206
5.88k
        return parser->parse_number(
207
5.88k
            p,
208
5.88k
            std::integral_constant<bool, StackEmpty_>(),
209
5.88k
            std::integral_constant<char, First_>(),
210
5.88k
            std::integral_constant<
211
5.88k
                number_precision, static_cast<number_precision>(N)>() );
212
5.88k
    }
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
205
11.0M
    {
206
11.0M
        return parser->parse_number(
207
11.0M
            p,
208
11.0M
            std::integral_constant<bool, StackEmpty_>(),
209
11.0M
            std::integral_constant<char, First_>(),
210
11.0M
            std::integral_constant<
211
11.0M
                number_precision, static_cast<number_precision>(N)>() );
212
11.0M
    }
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
Line
Count
Source
205
442k
    {
206
442k
        return parser->parse_number(
207
442k
            p,
208
442k
            std::integral_constant<bool, StackEmpty_>(),
209
442k
            std::integral_constant<char, First_>(),
210
442k
            std::integral_constant<
211
442k
                number_precision, static_cast<number_precision>(N)>() );
212
442k
    }
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
Line
Count
Source
205
94.9k
    {
206
94.9k
        return parser->parse_number(
207
94.9k
            p,
208
94.9k
            std::integral_constant<bool, StackEmpty_>(),
209
94.9k
            std::integral_constant<char, First_>(),
210
94.9k
            std::integral_constant<
211
94.9k
                number_precision, static_cast<number_precision>(N)>() );
212
94.9k
    }
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
205
2.06k
    {
206
2.06k
        return parser->parse_number(
207
2.06k
            p,
208
2.06k
            std::integral_constant<bool, StackEmpty_>(),
209
2.06k
            std::integral_constant<char, First_>(),
210
2.06k
            std::integral_constant<
211
2.06k
                number_precision, static_cast<number_precision>(N)>() );
212
2.06k
    }
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
Line
Count
Source
205
4.25k
    {
206
4.25k
        return parser->parse_number(
207
4.25k
            p,
208
4.25k
            std::integral_constant<bool, StackEmpty_>(),
209
4.25k
            std::integral_constant<char, First_>(),
210
4.25k
            std::integral_constant<
211
4.25k
                number_precision, static_cast<number_precision>(N)>() );
212
4.25k
    }
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
Line
Count
Source
205
363
    {
206
363
        return parser->parse_number(
207
363
            p,
208
363
            std::integral_constant<bool, StackEmpty_>(),
209
363
            std::integral_constant<char, First_>(),
210
363
            std::integral_constant<
211
363
                number_precision, static_cast<number_precision>(N)>() );
212
363
    }
213
};
214
215
//----------------------------------------------------------
216
217
template<class Handler>
218
void
219
basic_parser<Handler>::
220
reserve()
221
13.7k
{
222
13.7k
    if(BOOST_JSON_LIKELY(
223
13.7k
        ! st_.empty()))
224
3.20k
        return;
225
    // Reserve the largest stack we need,
226
    // to avoid reallocation during suspend.
227
10.5k
    st_.reserve(
228
10.5k
        sizeof(state) + // document parsing state
229
10.5k
        (sizeof(state) +
230
10.5k
            sizeof(std::size_t)) * depth() + // array and object state + size
231
10.5k
        sizeof(state) + // value parsing state
232
10.5k
        sizeof(std::size_t) + // string size
233
10.5k
        sizeof(state)); // comment state
234
10.5k
}
235
236
//----------------------------------------------------------
237
//
238
// The sentinel value is returned by parse functions
239
// to indicate that the parser failed, or suspended.
240
// this is used as it is distinct from all valid values
241
// for data in write
242
243
template<class Handler>
244
const char*
245
basic_parser<Handler>::
246
sentinel()
247
14.4M
{
248
    // the "+1" ensures that the returned pointer is unique even if
249
    // the given input buffer borders on this object
250
14.4M
    return reinterpret_cast<
251
14.4M
        const char*>(this) + 1;
252
14.4M
}
253
254
template<class Handler>
255
bool
256
basic_parser<Handler>::
257
incomplete(
258
    const detail::const_stream_wrapper& cs)
259
14.3M
{
260
14.3M
    return cs.begin() == sentinel();
261
14.3M
}
262
263
//----------------------------------------------------------
264
//
265
// These functions are declared with the BOOST_NOINLINE
266
// attribute to avoid polluting the parsers hot-path.
267
// They return the canary value to indicate suspension
268
// or failure.
269
270
template<class Handler>
271
const char*
272
basic_parser<Handler>::
273
suspend_or_fail(state st)
274
{
275
    if(BOOST_JSON_LIKELY(
276
        ! ec_ && more_))
277
    {
278
        // suspend
279
        reserve();
280
        st_.push_unchecked(st);
281
    }
282
    return sentinel();
283
}
284
285
template<class Handler>
286
const char*
287
basic_parser<Handler>::
288
suspend_or_fail(
289
    state st,
290
    std::size_t n)
291
11.0k
{
292
11.0k
    if(BOOST_JSON_LIKELY(
293
11.0k
        ! ec_ && more_))
294
3.15k
    {
295
        // suspend
296
3.15k
        reserve();
297
3.15k
        st_.push_unchecked(n);
298
3.15k
        st_.push_unchecked(st);
299
3.15k
    }
300
11.0k
    return sentinel();
301
11.0k
}
302
303
304
template<class Handler>
305
const char*
306
basic_parser<Handler>::
307
fail(const char* p) noexcept
308
0
{
309
0
    BOOST_ASSERT( p != sentinel() );
310
0
    end_ = p;
311
0
    return sentinel();
312
0
}
313
314
template<class Handler>
315
const char*
316
basic_parser<Handler>::
317
fail(
318
    const char* p,
319
    error ev,
320
    source_location const* loc) noexcept
321
5.89k
{
322
5.89k
    BOOST_ASSERT( p != sentinel() );
323
5.89k
    end_ = p;
324
5.89k
    ec_.assign(ev, loc);
325
5.89k
    return sentinel();
326
5.89k
}
327
328
template<class Handler>
329
const char*
330
basic_parser<Handler>::
331
maybe_suspend(
332
    const char* p,
333
    state st)
334
1.26k
{
335
1.26k
    if( p != sentinel() )
336
1.17k
        end_ = p;
337
1.26k
    if(BOOST_JSON_LIKELY(more_))
338
496
    {
339
        // suspend
340
496
        reserve();
341
496
        st_.push_unchecked(st);
342
496
    }
343
1.26k
    return sentinel();
344
1.26k
}
345
346
template<class Handler>
347
const char*
348
basic_parser<Handler>::
349
maybe_suspend(
350
    const char* p,
351
    state st,
352
    std::size_t n)
353
5.61k
{
354
5.61k
    BOOST_ASSERT( p != sentinel() );
355
5.61k
    end_ = p;
356
5.61k
    if(BOOST_JSON_LIKELY(more_))
357
1.54k
    {
358
        // suspend
359
1.54k
        reserve();
360
1.54k
        st_.push_unchecked(n);
361
1.54k
        st_.push_unchecked(st);
362
1.54k
    }
363
5.61k
    return sentinel();
364
5.61k
}
365
366
template<class Handler>
367
const char*
368
basic_parser<Handler>::
369
maybe_suspend(
370
    const char* p,
371
    state st,
372
    const number& num)
373
586
{
374
586
    BOOST_ASSERT( p != sentinel() );
375
586
    end_ = p;
376
586
    if(BOOST_JSON_LIKELY(more_))
377
243
    {
378
        // suspend
379
243
        num_ = num;
380
243
        reserve();
381
243
        st_.push_unchecked(st);;
382
243
    }
383
586
    return sentinel();
384
586
}
385
386
template<class Handler>
387
const char*
388
basic_parser<Handler>::
389
suspend(
390
    const char* p,
391
    state st)
392
1.86k
{
393
1.86k
    BOOST_ASSERT( p != sentinel() );
394
1.86k
    end_ = p;
395
    // suspend
396
1.86k
    reserve();
397
1.86k
    st_.push_unchecked(st);
398
1.86k
    return sentinel();
399
1.86k
}
400
401
template<class Handler>
402
const char*
403
basic_parser<Handler>::
404
suspend(
405
    const char* p,
406
    state st,
407
    const number& num)
408
6.43k
{
409
6.43k
    BOOST_ASSERT( p != sentinel() );
410
6.43k
    end_ = p;
411
    // suspend
412
6.43k
    num_ = num;
413
6.43k
    reserve();
414
6.43k
    st_.push_unchecked(st);
415
6.43k
    return sentinel();
416
6.43k
}
417
418
template<class Handler>
419
template<
420
    bool StackEmpty_/*,
421
    bool Terminal_*/>
422
const char*
423
basic_parser<Handler>::
424
parse_comment(const char* p,
425
    std::integral_constant<bool, StackEmpty_> stack_empty,
426
    /*std::integral_constant<bool, Terminal_>*/ bool terminal)
427
4.62k
{
428
4.62k
    detail::const_stream_wrapper cs(p, end_);
429
4.62k
    const char* start = cs.begin();
430
4.62k
    std::size_t remain;
431
4.62k
    if(! stack_empty && ! st_.empty())
432
121
    {
433
121
        state st;
434
121
        st_.pop(st);
435
121
        switch(st)
436
121
        {
437
0
            default: BOOST_JSON_UNREACHABLE();
438
76
            case state::com1: goto do_com1;
439
23
            case state::com2: goto do_com2;
440
19
            case state::com3: goto do_com3;
441
3
            case state::com4: goto do_com4;
442
121
        }
443
121
    }
444
4.50k
    BOOST_ASSERT(*cs == '/');
445
4.50k
    ++cs;
446
4.58k
do_com1:
447
4.58k
    if(BOOST_JSON_UNLIKELY(! cs))
448
152
        return maybe_suspend(cs.begin(), state::com1);
449
4.43k
    switch(*cs)
450
4.43k
    {
451
39
    default:
452
39
        {
453
39
            BOOST_STATIC_CONSTEXPR source_location loc
454
39
                = BOOST_CURRENT_LOCATION;
455
39
            return fail(cs.begin(), error::syntax, &loc);
456
0
        }
457
4.17k
    case '/':
458
4.17k
        ++cs;
459
4.19k
do_com2:
460
        // KRYSTIAN TODO: this is a mess, we have to fix this
461
4.19k
        remain = cs.remain();
462
4.19k
        cs = remain ? static_cast<const char*>(
463
4.16k
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
464
4.19k
        if(! cs.begin())
465
13
            cs = sentinel();
466
4.19k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
467
46
        {
468
            // if the doc does not terminate
469
            // with a newline, treat it as the
470
            // end of the comment
471
46
            if(terminal && ! more_)
472
1
            {
473
1
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
474
1
                    {start, cs.remain(start)}, ec_)))
475
0
                    return fail(cs.end());
476
1
                return cs.end();
477
1
            }
478
45
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479
45
                {start, cs.remain(start)}, ec_)))
480
0
                return fail(cs.end());
481
45
            if(terminal)
482
1
                return suspend(cs.end(), state::com2);
483
44
            return maybe_suspend(cs.end(), state::com2);
484
45
        }
485
4.15k
        break;
486
4.15k
    case '*':
487
218
        do
488
622
        {
489
622
            ++cs;
490
641
do_com3:
491
            // KRYSTIAN TODO: this is a mess, we have to fix this
492
641
            remain = cs.remain();
493
641
            cs = remain ? static_cast<const char*>(
494
608
                std::memchr(cs.begin(), '*', remain)) : sentinel();
495
641
            if(! cs.begin())
496
5
                cs = sentinel();
497
            // stopped inside a c comment
498
641
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
499
38
            {
500
38
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
501
38
                    {start, cs.remain(start)}, ec_)))
502
0
                    return fail(cs.end());
503
38
                return maybe_suspend(cs.end(), state::com3);
504
38
            }
505
            // found a asterisk, check if the next char is a slash
506
603
            ++cs;
507
606
do_com4:
508
606
            if(BOOST_JSON_UNLIKELY(! cs))
509
6
            {
510
6
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
6
                    {start, cs.used(start)}, ec_)))
512
0
                    return fail(cs.begin());
513
6
                return maybe_suspend(cs.begin(), state::com4);
514
6
            }
515
606
        }
516
600
        while(*cs != '/');
517
4.43k
    }
518
4.34k
    ++cs;
519
4.34k
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
520
4.34k
        {start, cs.used(start)}, ec_)))
521
0
        return fail(cs.begin());
522
4.34k
    return cs.begin();
523
4.34k
}
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
427
4.50k
{
428
4.50k
    detail::const_stream_wrapper cs(p, end_);
429
4.50k
    const char* start = cs.begin();
430
4.50k
    std::size_t remain;
431
4.50k
    if(! stack_empty && ! st_.empty())
432
0
    {
433
0
        state st;
434
0
        st_.pop(st);
435
0
        switch(st)
436
0
        {
437
0
            default: BOOST_JSON_UNREACHABLE();
438
0
            case state::com1: goto do_com1;
439
0
            case state::com2: goto do_com2;
440
0
            case state::com3: goto do_com3;
441
0
            case state::com4: goto do_com4;
442
0
        }
443
0
    }
444
4.50k
    BOOST_ASSERT(*cs == '/');
445
4.50k
    ++cs;
446
4.50k
do_com1:
447
4.50k
    if(BOOST_JSON_UNLIKELY(! cs))
448
76
        return maybe_suspend(cs.begin(), state::com1);
449
4.43k
    switch(*cs)
450
4.43k
    {
451
39
    default:
452
39
        {
453
39
            BOOST_STATIC_CONSTEXPR source_location loc
454
39
                = BOOST_CURRENT_LOCATION;
455
39
            return fail(cs.begin(), error::syntax, &loc);
456
0
        }
457
4.17k
    case '/':
458
4.17k
        ++cs;
459
4.17k
do_com2:
460
        // KRYSTIAN TODO: this is a mess, we have to fix this
461
4.17k
        remain = cs.remain();
462
4.17k
        cs = remain ? static_cast<const char*>(
463
4.16k
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
464
4.17k
        if(! cs.begin())
465
13
            cs = sentinel();
466
4.17k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
467
23
        {
468
            // if the doc does not terminate
469
            // with a newline, treat it as the
470
            // end of the comment
471
23
            if(terminal && ! more_)
472
0
            {
473
0
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
474
0
                    {start, cs.remain(start)}, ec_)))
475
0
                    return fail(cs.end());
476
0
                return cs.end();
477
0
            }
478
23
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479
23
                {start, cs.remain(start)}, ec_)))
480
0
                return fail(cs.end());
481
23
            if(terminal)
482
1
                return suspend(cs.end(), state::com2);
483
22
            return maybe_suspend(cs.end(), state::com2);
484
23
        }
485
4.15k
        break;
486
4.15k
    case '*':
487
218
        do
488
622
        {
489
622
            ++cs;
490
622
do_com3:
491
            // KRYSTIAN TODO: this is a mess, we have to fix this
492
622
            remain = cs.remain();
493
622
            cs = remain ? static_cast<const char*>(
494
608
                std::memchr(cs.begin(), '*', remain)) : sentinel();
495
622
            if(! cs.begin())
496
5
                cs = sentinel();
497
            // stopped inside a c comment
498
622
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
499
19
            {
500
19
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
501
19
                    {start, cs.remain(start)}, ec_)))
502
0
                    return fail(cs.end());
503
19
                return maybe_suspend(cs.end(), state::com3);
504
19
            }
505
            // found a asterisk, check if the next char is a slash
506
603
            ++cs;
507
603
do_com4:
508
603
            if(BOOST_JSON_UNLIKELY(! cs))
509
3
            {
510
3
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
3
                    {start, cs.used(start)}, ec_)))
512
0
                    return fail(cs.begin());
513
3
                return maybe_suspend(cs.begin(), state::com4);
514
3
            }
515
603
        }
516
600
        while(*cs != '/');
517
4.43k
    }
518
4.34k
    ++cs;
519
4.34k
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
520
4.34k
        {start, cs.used(start)}, ec_)))
521
0
        return fail(cs.begin());
522
4.34k
    return cs.begin();
523
4.34k
}
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
427
121
{
428
121
    detail::const_stream_wrapper cs(p, end_);
429
121
    const char* start = cs.begin();
430
121
    std::size_t remain;
431
121
    if(! stack_empty && ! st_.empty())
432
121
    {
433
121
        state st;
434
121
        st_.pop(st);
435
121
        switch(st)
436
121
        {
437
0
            default: BOOST_JSON_UNREACHABLE();
438
76
            case state::com1: goto do_com1;
439
23
            case state::com2: goto do_com2;
440
19
            case state::com3: goto do_com3;
441
3
            case state::com4: goto do_com4;
442
121
        }
443
121
    }
444
0
    BOOST_ASSERT(*cs == '/');
445
0
    ++cs;
446
76
do_com1:
447
76
    if(BOOST_JSON_UNLIKELY(! cs))
448
76
        return maybe_suspend(cs.begin(), state::com1);
449
0
    switch(*cs)
450
0
    {
451
0
    default:
452
0
        {
453
0
            BOOST_STATIC_CONSTEXPR source_location loc
454
0
                = BOOST_CURRENT_LOCATION;
455
0
            return fail(cs.begin(), error::syntax, &loc);
456
0
        }
457
0
    case '/':
458
0
        ++cs;
459
23
do_com2:
460
        // KRYSTIAN TODO: this is a mess, we have to fix this
461
23
        remain = cs.remain();
462
23
        cs = remain ? static_cast<const char*>(
463
23
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
464
23
        if(! cs.begin())
465
0
            cs = sentinel();
466
23
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
467
23
        {
468
            // if the doc does not terminate
469
            // with a newline, treat it as the
470
            // end of the comment
471
23
            if(terminal && ! more_)
472
1
            {
473
1
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
474
1
                    {start, cs.remain(start)}, ec_)))
475
0
                    return fail(cs.end());
476
1
                return cs.end();
477
1
            }
478
22
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479
22
                {start, cs.remain(start)}, ec_)))
480
0
                return fail(cs.end());
481
22
            if(terminal)
482
0
                return suspend(cs.end(), state::com2);
483
22
            return maybe_suspend(cs.end(), state::com2);
484
22
        }
485
0
        break;
486
0
    case '*':
487
0
        do
488
0
        {
489
0
            ++cs;
490
19
do_com3:
491
            // KRYSTIAN TODO: this is a mess, we have to fix this
492
19
            remain = cs.remain();
493
19
            cs = remain ? static_cast<const char*>(
494
19
                std::memchr(cs.begin(), '*', remain)) : sentinel();
495
19
            if(! cs.begin())
496
0
                cs = sentinel();
497
            // stopped inside a c comment
498
19
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
499
19
            {
500
19
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
501
19
                    {start, cs.remain(start)}, ec_)))
502
0
                    return fail(cs.end());
503
19
                return maybe_suspend(cs.end(), state::com3);
504
19
            }
505
            // found a asterisk, check if the next char is a slash
506
0
            ++cs;
507
3
do_com4:
508
3
            if(BOOST_JSON_UNLIKELY(! cs))
509
3
            {
510
3
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
3
                    {start, cs.used(start)}, ec_)))
512
0
                    return fail(cs.begin());
513
3
                return maybe_suspend(cs.begin(), state::com4);
514
3
            }
515
3
        }
516
0
        while(*cs != '/');
517
0
    }
518
0
    ++cs;
519
0
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
520
0
        {start, cs.used(start)}, ec_)))
521
0
        return fail(cs.begin());
522
0
    return cs.begin();
523
0
}
524
525
template<class Handler>
526
template<bool StackEmpty_>
527
const char*
528
basic_parser<Handler>::
529
parse_document(const char* p,
530
    std::integral_constant<bool, StackEmpty_> stack_empty)
531
33.2k
{
532
33.2k
    detail::const_stream_wrapper cs(p, end_);
533
33.2k
    if(! stack_empty && ! st_.empty())
534
10.5k
    {
535
10.5k
        state st;
536
10.5k
        st_.peek(st);
537
10.5k
        switch(st)
538
10.5k
        {
539
8.60k
        default: goto do_doc2;
540
8.60k
        case state::doc1:
541
48
                 st_.pop(st);
542
48
                 goto do_doc1;
543
1.86k
        case state::doc3:
544
1.86k
                 st_.pop(st);
545
1.86k
                 goto do_doc3;
546
19
        case state::com1: case state::com2:
547
21
        case state::com3: case state::com4:
548
21
                 goto do_doc4;
549
10.5k
        }
550
10.5k
    }
551
22.7k
do_doc1:
552
22.7k
    cs = detail::count_whitespace(cs.begin(), cs.end());
553
22.7k
    if(BOOST_JSON_UNLIKELY(! cs))
554
120
        return maybe_suspend(cs.begin(), state::doc1);
555
31.2k
do_doc2:
556
31.2k
    switch(+opt_.allow_comments |
557
31.2k
        (opt_.allow_trailing_commas << 1) |
558
31.2k
        (opt_.allow_invalid_utf8 << 2))
559
31.2k
    {
560
    // no extensions
561
9.46k
    default:
562
9.46k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563
9.46k
        break;
564
    // comments
565
2.38k
    case 1:
566
2.38k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567
2.38k
        break;
568
    // trailing
569
2.10k
    case 2:
570
2.10k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571
2.10k
        break;
572
    // comments & trailing
573
3.27k
    case 3:
574
3.27k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575
3.27k
        break;
576
    // skip validation
577
1.96k
    case 4:
578
1.96k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579
1.96k
        break;
580
    // comments & skip validation
581
2.83k
    case 5:
582
2.83k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583
2.83k
        break;
584
    // trailing & skip validation
585
4.67k
    case 6:
586
4.67k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587
4.67k
        break;
588
    // comments & trailing & skip validation
589
4.51k
    case 7:
590
4.51k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591
4.51k
        break;
592
31.2k
    }
593
31.0k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594
        // the appropriate state has already been pushed into stack
595
19.5k
        return sentinel();
596
13.8k
do_doc3:
597
13.8k
    cs = detail::count_whitespace(cs.begin(), cs.end());
598
13.8k
    if(BOOST_JSON_UNLIKELY(! cs))
599
11.0k
    {
600
11.0k
        if(more_)
601
1.86k
            return suspend(cs.begin(), state::doc3);
602
11.0k
    }
603
2.81k
    else if(opt_.allow_comments && *cs == '/')
604
454
    {
605
475
do_doc4:
606
475
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
475
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608
49
            return sentinel();
609
426
        goto do_doc3;
610
475
    }
611
11.5k
    return cs.begin();
612
13.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
531
22.6k
{
532
22.6k
    detail::const_stream_wrapper cs(p, end_);
533
22.6k
    if(! stack_empty && ! st_.empty())
534
0
    {
535
0
        state st;
536
0
        st_.peek(st);
537
0
        switch(st)
538
0
        {
539
0
        default: goto do_doc2;
540
0
        case state::doc1:
541
0
                 st_.pop(st);
542
0
                 goto do_doc1;
543
0
        case state::doc3:
544
0
                 st_.pop(st);
545
0
                 goto do_doc3;
546
0
        case state::com1: case state::com2:
547
0
        case state::com3: case state::com4:
548
0
                 goto do_doc4;
549
0
        }
550
0
    }
551
22.6k
do_doc1:
552
22.6k
    cs = detail::count_whitespace(cs.begin(), cs.end());
553
22.6k
    if(BOOST_JSON_UNLIKELY(! cs))
554
72
        return maybe_suspend(cs.begin(), state::doc1);
555
22.6k
do_doc2:
556
22.6k
    switch(+opt_.allow_comments |
557
22.6k
        (opt_.allow_trailing_commas << 1) |
558
22.6k
        (opt_.allow_invalid_utf8 << 2))
559
22.6k
    {
560
    // no extensions
561
8.48k
    default:
562
8.48k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563
8.48k
        break;
564
    // comments
565
1.48k
    case 1:
566
1.48k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567
1.48k
        break;
568
    // trailing
569
1.35k
    case 2:
570
1.35k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571
1.35k
        break;
572
    // comments & trailing
573
2.08k
    case 3:
574
2.08k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575
2.08k
        break;
576
    // skip validation
577
1.24k
    case 4:
578
1.24k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579
1.24k
        break;
580
    // comments & skip validation
581
1.89k
    case 5:
582
1.89k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583
1.89k
        break;
584
    // trailing & skip validation
585
3.09k
    case 6:
586
3.09k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587
3.09k
        break;
588
    // comments & trailing & skip validation
589
2.98k
    case 7:
590
2.98k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591
2.98k
        break;
592
22.6k
    }
593
22.5k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594
        // the appropriate state has already been pushed into stack
595
16.1k
        return sentinel();
596
6.82k
do_doc3:
597
6.82k
    cs = detail::count_whitespace(cs.begin(), cs.end());
598
6.82k
    if(BOOST_JSON_UNLIKELY(! cs))
599
4.01k
    {
600
4.01k
        if(more_)
601
1.86k
            return suspend(cs.begin(), state::doc3);
602
4.01k
    }
603
2.81k
    else if(opt_.allow_comments && *cs == '/')
604
454
    {
605
454
do_doc4:
606
454
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
454
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608
29
            return sentinel();
609
425
        goto do_doc3;
610
454
    }
611
4.50k
    return cs.begin();
612
6.82k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_document<false>(char const*, std::__1::integral_constant<bool, false>)
Line
Count
Source
531
10.5k
{
532
10.5k
    detail::const_stream_wrapper cs(p, end_);
533
10.5k
    if(! stack_empty && ! st_.empty())
534
10.5k
    {
535
10.5k
        state st;
536
10.5k
        st_.peek(st);
537
10.5k
        switch(st)
538
10.5k
        {
539
8.60k
        default: goto do_doc2;
540
8.60k
        case state::doc1:
541
48
                 st_.pop(st);
542
48
                 goto do_doc1;
543
1.86k
        case state::doc3:
544
1.86k
                 st_.pop(st);
545
1.86k
                 goto do_doc3;
546
19
        case state::com1: case state::com2:
547
21
        case state::com3: case state::com4:
548
21
                 goto do_doc4;
549
10.5k
        }
550
10.5k
    }
551
48
do_doc1:
552
48
    cs = detail::count_whitespace(cs.begin(), cs.end());
553
48
    if(BOOST_JSON_UNLIKELY(! cs))
554
48
        return maybe_suspend(cs.begin(), state::doc1);
555
8.60k
do_doc2:
556
8.60k
    switch(+opt_.allow_comments |
557
8.60k
        (opt_.allow_trailing_commas << 1) |
558
8.60k
        (opt_.allow_invalid_utf8 << 2))
559
8.60k
    {
560
    // no extensions
561
984
    default:
562
984
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563
984
        break;
564
    // comments
565
901
    case 1:
566
901
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567
901
        break;
568
    // trailing
569
749
    case 2:
570
749
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571
749
        break;
572
    // comments & trailing
573
1.19k
    case 3:
574
1.19k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575
1.19k
        break;
576
    // skip validation
577
724
    case 4:
578
724
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579
724
        break;
580
    // comments & skip validation
581
940
    case 5:
582
940
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583
940
        break;
584
    // trailing & skip validation
585
1.57k
    case 6:
586
1.57k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587
1.57k
        break;
588
    // comments & trailing & skip validation
589
1.53k
    case 7:
590
1.53k
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591
1.53k
        break;
592
8.60k
    }
593
8.54k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594
        // the appropriate state has already been pushed into stack
595
3.40k
        return sentinel();
596
7.01k
do_doc3:
597
7.01k
    cs = detail::count_whitespace(cs.begin(), cs.end());
598
7.01k
    if(BOOST_JSON_UNLIKELY(! cs))
599
7.01k
    {
600
7.01k
        if(more_)
601
0
            return suspend(cs.begin(), state::doc3);
602
7.01k
    }
603
0
    else if(opt_.allow_comments && *cs == '/')
604
0
    {
605
21
do_doc4:
606
21
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
21
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608
20
            return sentinel();
609
1
        goto do_doc3;
610
21
    }
611
7.01k
    return cs.begin();
612
7.01k
}
613
614
template<class Handler>
615
template<
616
    bool StackEmpty_,
617
    bool AllowComments_/*,
618
    bool AllowTrailing_,
619
    bool AllowBadUTF8_*/>
620
const char*
621
basic_parser<Handler>::
622
parse_value(const char* p,
623
    std::integral_constant<bool, StackEmpty_> stack_empty,
624
    std::integral_constant<bool, AllowComments_> allow_comments,
625
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
626
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
627
    bool allow_bad_utf16)
628
12.4M
{
629
12.4M
    if(stack_empty || st_.empty())
630
12.4M
    {
631
12.4M
loop:
632
12.4M
        switch(*p)
633
12.4M
        {
634
469k
        case '0':
635
469k
            return mp11::mp_with_index<3>(
636
469k
                static_cast<unsigned char>(opt_.numbers),
637
469k
                parse_number_helper<true, '0'>{ this, p });
638
80.2k
        case '-':
639
80.2k
            return mp11::mp_with_index<3>(
640
80.2k
                static_cast<unsigned char>(opt_.numbers),
641
80.2k
                parse_number_helper<true, '-'>{ this, p });
642
5.84M
        case '1': case '2': case '3':
643
6.25M
        case '4': case '5': case '6':
644
11.5M
        case '7': case '8': case '9':
645
11.5M
            return mp11::mp_with_index<3>(
646
11.5M
                static_cast<unsigned char>(opt_.numbers),
647
11.5M
                parse_number_helper<true, '+'>{ this, p });
648
20.8k
        case 'n':
649
20.8k
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
44.4k
        case 't':
651
44.4k
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
49.0k
        case 'f':
653
49.0k
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
6
        case 'I':
655
6
            if( !opt_.allow_infinity_and_nan )
656
6
            {
657
6
                BOOST_STATIC_CONSTEXPR source_location loc
658
6
                    = BOOST_CURRENT_LOCATION;
659
6
                return fail(p, error::syntax, &loc);
660
6
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
6
        case 'N':
663
6
            if( !opt_.allow_infinity_and_nan )
664
6
            {
665
6
                BOOST_STATIC_CONSTEXPR source_location loc
666
6
                    = BOOST_CURRENT_LOCATION;
667
6
                return fail(p, error::syntax, &loc);
668
6
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
85.8k
        case '"':
671
85.8k
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
41.2k
        case '[':
673
41.2k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
35.5k
        case '{':
675
35.5k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
1.12k
        case '/':
677
1.12k
            if(! allow_comments)
678
8
            {
679
8
                BOOST_STATIC_CONSTEXPR source_location loc
680
8
                    = BOOST_CURRENT_LOCATION;
681
8
                return fail(p, error::syntax, &loc);
682
8
            }
683
1.11k
            p = parse_comment(p, stack_empty, std::false_type());
684
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
685
            // can add an overload, change the existing one to take a pointer,
686
            // or just leave it as is
687
1.11k
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
688
49
                return maybe_suspend(p, state::val2);
689
1.06k
            BOOST_FALLTHROUGH;
690
1.06k
        case ' ':
691
1.06k
        case '\t':
692
1.06k
        case '\n':
693
1.06k
        case '\r':
694
1.06k
            p = detail::count_whitespace(p, end_);
695
1.06k
            if(BOOST_JSON_UNLIKELY(p == end_))
696
38
                return maybe_suspend(p, state::val1);
697
1.02k
            goto loop;
698
1.02k
        default:
699
720
            {
700
720
                BOOST_STATIC_CONSTEXPR source_location loc
701
720
                    = BOOST_CURRENT_LOCATION;
702
720
                return fail(p, error::syntax, &loc);
703
1.06k
            }
704
12.4M
        }
705
12.4M
    }
706
11.3k
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
12.4M
}
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
628
6.60M
{
629
6.60M
    if(stack_empty || st_.empty())
630
6.60M
    {
631
6.60M
loop:
632
6.60M
        switch(*p)
633
6.60M
        {
634
373k
        case '0':
635
373k
            return mp11::mp_with_index<3>(
636
373k
                static_cast<unsigned char>(opt_.numbers),
637
373k
                parse_number_helper<true, '0'>{ this, p });
638
61.0k
        case '-':
639
61.0k
            return mp11::mp_with_index<3>(
640
61.0k
                static_cast<unsigned char>(opt_.numbers),
641
61.0k
                parse_number_helper<true, '-'>{ this, p });
642
1.89M
        case '1': case '2': case '3':
643
2.23M
        case '4': case '5': case '6':
644
5.94M
        case '7': case '8': case '9':
645
5.94M
            return mp11::mp_with_index<3>(
646
5.94M
                static_cast<unsigned char>(opt_.numbers),
647
5.94M
                parse_number_helper<true, '+'>{ this, p });
648
12.0k
        case 'n':
649
12.0k
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
35.5k
        case 't':
651
35.5k
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
45.6k
        case 'f':
653
45.6k
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
3
        case 'I':
655
3
            if( !opt_.allow_infinity_and_nan )
656
3
            {
657
3
                BOOST_STATIC_CONSTEXPR source_location loc
658
3
                    = BOOST_CURRENT_LOCATION;
659
3
                return fail(p, error::syntax, &loc);
660
3
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
4
        case 'N':
663
4
            if( !opt_.allow_infinity_and_nan )
664
4
            {
665
4
                BOOST_STATIC_CONSTEXPR source_location loc
666
4
                    = BOOST_CURRENT_LOCATION;
667
4
                return fail(p, error::syntax, &loc);
668
4
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
73.5k
        case '"':
671
73.5k
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
29.3k
        case '[':
673
29.3k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
28.5k
        case '{':
675
28.5k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
8
        case '/':
677
8
            if(! allow_comments)
678
8
            {
679
8
                BOOST_STATIC_CONSTEXPR source_location loc
680
8
                    = BOOST_CURRENT_LOCATION;
681
8
                return fail(p, error::syntax, &loc);
682
8
            }
683
0
            p = parse_comment(p, stack_empty, std::false_type());
684
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
685
            // can add an overload, change the existing one to take a pointer,
686
            // or just leave it as is
687
0
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
688
0
                return maybe_suspend(p, state::val2);
689
0
            BOOST_FALLTHROUGH;
690
0
        case ' ':
691
0
        case '\t':
692
0
        case '\n':
693
0
        case '\r':
694
0
            p = detail::count_whitespace(p, end_);
695
0
            if(BOOST_JSON_UNLIKELY(p == end_))
696
0
                return maybe_suspend(p, state::val1);
697
0
            goto loop;
698
467
        default:
699
467
            {
700
467
                BOOST_STATIC_CONSTEXPR source_location loc
701
467
                    = BOOST_CURRENT_LOCATION;
702
467
                return fail(p, error::syntax, &loc);
703
0
            }
704
6.60M
        }
705
6.60M
    }
706
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
6.60M
}
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
628
5.81M
{
629
5.81M
    if(stack_empty || st_.empty())
630
5.81M
    {
631
5.81M
loop:
632
5.81M
        switch(*p)
633
5.81M
        {
634
95.9k
        case '0':
635
95.9k
            return mp11::mp_with_index<3>(
636
95.9k
                static_cast<unsigned char>(opt_.numbers),
637
95.9k
                parse_number_helper<true, '0'>{ this, p });
638
19.1k
        case '-':
639
19.1k
            return mp11::mp_with_index<3>(
640
19.1k
                static_cast<unsigned char>(opt_.numbers),
641
19.1k
                parse_number_helper<true, '-'>{ this, p });
642
3.95M
        case '1': case '2': case '3':
643
4.02M
        case '4': case '5': case '6':
644
5.65M
        case '7': case '8': case '9':
645
5.65M
            return mp11::mp_with_index<3>(
646
5.65M
                static_cast<unsigned char>(opt_.numbers),
647
5.65M
                parse_number_helper<true, '+'>{ this, p });
648
8.83k
        case 'n':
649
8.83k
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
8.94k
        case 't':
651
8.94k
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
3.43k
        case 'f':
653
3.43k
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
3
        case 'I':
655
3
            if( !opt_.allow_infinity_and_nan )
656
3
            {
657
3
                BOOST_STATIC_CONSTEXPR source_location loc
658
3
                    = BOOST_CURRENT_LOCATION;
659
3
                return fail(p, error::syntax, &loc);
660
3
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
2
        case 'N':
663
2
            if( !opt_.allow_infinity_and_nan )
664
2
            {
665
2
                BOOST_STATIC_CONSTEXPR source_location loc
666
2
                    = BOOST_CURRENT_LOCATION;
667
2
                return fail(p, error::syntax, &loc);
668
2
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
12.2k
        case '"':
671
12.2k
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
11.9k
        case '[':
673
11.9k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
7.01k
        case '{':
675
7.01k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
1.11k
        case '/':
677
1.11k
            if(! allow_comments)
678
0
            {
679
0
                BOOST_STATIC_CONSTEXPR source_location loc
680
0
                    = BOOST_CURRENT_LOCATION;
681
0
                return fail(p, error::syntax, &loc);
682
0
            }
683
1.11k
            p = parse_comment(p, stack_empty, std::false_type());
684
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
685
            // can add an overload, change the existing one to take a pointer,
686
            // or just leave it as is
687
1.11k
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
688
49
                return maybe_suspend(p, state::val2);
689
1.06k
            BOOST_FALLTHROUGH;
690
1.06k
        case ' ':
691
1.06k
        case '\t':
692
1.06k
        case '\n':
693
1.06k
        case '\r':
694
1.06k
            p = detail::count_whitespace(p, end_);
695
1.06k
            if(BOOST_JSON_UNLIKELY(p == end_))
696
38
                return maybe_suspend(p, state::val1);
697
1.02k
            goto loop;
698
1.02k
        default:
699
253
            {
700
253
                BOOST_STATIC_CONSTEXPR source_location loc
701
253
                    = BOOST_CURRENT_LOCATION;
702
253
                return fail(p, error::syntax, &loc);
703
1.06k
            }
704
5.81M
        }
705
5.81M
    }
706
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
5.81M
}
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
628
5.14k
{
629
5.14k
    if(stack_empty || st_.empty())
630
0
    {
631
0
loop:
632
0
        switch(*p)
633
0
        {
634
0
        case '0':
635
0
            return mp11::mp_with_index<3>(
636
0
                static_cast<unsigned char>(opt_.numbers),
637
0
                parse_number_helper<true, '0'>{ this, p });
638
0
        case '-':
639
0
            return mp11::mp_with_index<3>(
640
0
                static_cast<unsigned char>(opt_.numbers),
641
0
                parse_number_helper<true, '-'>{ this, p });
642
0
        case '1': case '2': case '3':
643
0
        case '4': case '5': case '6':
644
0
        case '7': case '8': case '9':
645
0
            return mp11::mp_with_index<3>(
646
0
                static_cast<unsigned char>(opt_.numbers),
647
0
                parse_number_helper<true, '+'>{ this, p });
648
0
        case 'n':
649
0
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
0
        case 't':
651
0
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
0
        case 'f':
653
0
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
0
        case 'I':
655
0
            if( !opt_.allow_infinity_and_nan )
656
0
            {
657
0
                BOOST_STATIC_CONSTEXPR source_location loc
658
0
                    = BOOST_CURRENT_LOCATION;
659
0
                return fail(p, error::syntax, &loc);
660
0
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
0
        case 'N':
663
0
            if( !opt_.allow_infinity_and_nan )
664
0
            {
665
0
                BOOST_STATIC_CONSTEXPR source_location loc
666
0
                    = BOOST_CURRENT_LOCATION;
667
0
                return fail(p, error::syntax, &loc);
668
0
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
0
        case '"':
671
0
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
0
        case '[':
673
0
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
0
        case '{':
675
0
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
0
        case '/':
677
0
            if(! allow_comments)
678
0
            {
679
0
                BOOST_STATIC_CONSTEXPR source_location loc
680
0
                    = BOOST_CURRENT_LOCATION;
681
0
                return fail(p, error::syntax, &loc);
682
0
            }
683
0
            p = parse_comment(p, stack_empty, std::false_type());
684
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
685
            // can add an overload, change the existing one to take a pointer,
686
            // or just leave it as is
687
0
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
688
0
                return maybe_suspend(p, state::val2);
689
0
            BOOST_FALLTHROUGH;
690
0
        case ' ':
691
0
        case '\t':
692
0
        case '\n':
693
0
        case '\r':
694
0
            p = detail::count_whitespace(p, end_);
695
0
            if(BOOST_JSON_UNLIKELY(p == end_))
696
0
                return maybe_suspend(p, state::val1);
697
0
            goto loop;
698
0
        default:
699
0
            {
700
0
                BOOST_STATIC_CONSTEXPR source_location loc
701
0
                    = BOOST_CURRENT_LOCATION;
702
0
                return fail(p, error::syntax, &loc);
703
0
            }
704
0
        }
705
0
    }
706
5.14k
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
5.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
628
6.17k
{
629
6.17k
    if(stack_empty || st_.empty())
630
0
    {
631
0
loop:
632
0
        switch(*p)
633
0
        {
634
0
        case '0':
635
0
            return mp11::mp_with_index<3>(
636
0
                static_cast<unsigned char>(opt_.numbers),
637
0
                parse_number_helper<true, '0'>{ this, p });
638
0
        case '-':
639
0
            return mp11::mp_with_index<3>(
640
0
                static_cast<unsigned char>(opt_.numbers),
641
0
                parse_number_helper<true, '-'>{ this, p });
642
0
        case '1': case '2': case '3':
643
0
        case '4': case '5': case '6':
644
0
        case '7': case '8': case '9':
645
0
            return mp11::mp_with_index<3>(
646
0
                static_cast<unsigned char>(opt_.numbers),
647
0
                parse_number_helper<true, '+'>{ this, p });
648
0
        case 'n':
649
0
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
0
        case 't':
651
0
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
0
        case 'f':
653
0
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
0
        case 'I':
655
0
            if( !opt_.allow_infinity_and_nan )
656
0
            {
657
0
                BOOST_STATIC_CONSTEXPR source_location loc
658
0
                    = BOOST_CURRENT_LOCATION;
659
0
                return fail(p, error::syntax, &loc);
660
0
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
0
        case 'N':
663
0
            if( !opt_.allow_infinity_and_nan )
664
0
            {
665
0
                BOOST_STATIC_CONSTEXPR source_location loc
666
0
                    = BOOST_CURRENT_LOCATION;
667
0
                return fail(p, error::syntax, &loc);
668
0
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
0
        case '"':
671
0
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
0
        case '[':
673
0
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
0
        case '{':
675
0
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
0
        case '/':
677
0
            if(! allow_comments)
678
0
            {
679
0
                BOOST_STATIC_CONSTEXPR source_location loc
680
0
                    = BOOST_CURRENT_LOCATION;
681
0
                return fail(p, error::syntax, &loc);
682
0
            }
683
0
            p = parse_comment(p, stack_empty, std::false_type());
684
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
685
            // can add an overload, change the existing one to take a pointer,
686
            // or just leave it as is
687
0
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
688
0
                return maybe_suspend(p, state::val2);
689
0
            BOOST_FALLTHROUGH;
690
0
        case ' ':
691
0
        case '\t':
692
0
        case '\n':
693
0
        case '\r':
694
0
            p = detail::count_whitespace(p, end_);
695
0
            if(BOOST_JSON_UNLIKELY(p == end_))
696
0
                return maybe_suspend(p, state::val1);
697
0
            goto loop;
698
0
        default:
699
0
            {
700
0
                BOOST_STATIC_CONSTEXPR source_location loc
701
0
                    = BOOST_CURRENT_LOCATION;
702
0
                return fail(p, error::syntax, &loc);
703
0
            }
704
0
        }
705
0
    }
706
6.17k
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
6.17k
}
708
709
template<class Handler>
710
template<
711
    bool AllowComments_/*,
712
    bool AllowTrailing_,
713
    bool AllowBadUTF8_*/>
714
const char*
715
basic_parser<Handler>::
716
resume_value(const char* p,
717
    std::integral_constant<bool, AllowComments_> allow_comments,
718
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
719
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
720
    bool allow_bad_utf16)
721
11.3k
{
722
11.3k
    state st;
723
11.3k
    st_.peek(st);
724
11.3k
    switch(st)
725
11.3k
    {
726
0
    default: BOOST_JSON_UNREACHABLE();
727
61
    case state::lit1:
728
61
        return parse_literal(p,  detail::literals_c<detail::literals::resume>() );
729
730
494
    case state::str1: case state::str2:
731
507
    case state::str8:
732
507
        return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733
734
110
    case state::arr1: case state::arr2:
735
2.65k
    case state::arr3: case state::arr4:
736
2.94k
    case state::arr5: case state::arr6:
737
2.94k
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738
739
93
    case state::obj1: case state::obj2:
740
412
    case state::obj3: case state::obj4:
741
475
    case state::obj5: case state::obj6:
742
959
    case state::obj7: case state::obj8:
743
1.04k
    case state::obj9: case state::obj10:
744
1.04k
    case state::obj11:
745
1.04k
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746
747
1.22k
    case state::num1: case state::num2:
748
1.80k
    case state::num3: case state::num4:
749
2.93k
    case state::num5: case state::num6:
750
4.21k
    case state::num7: case state::num8:
751
4.49k
    case state::exp1: case state::exp2:
752
6.67k
    case state::exp3:
753
6.67k
        return mp11::mp_with_index<3>(
754
6.67k
            static_cast<unsigned char>(opt_.numbers),
755
6.67k
            parse_number_helper<false, 0>{ this, p });
756
757
    // KRYSTIAN NOTE: these are special cases
758
38
    case state::val1:
759
38
    {
760
38
        st_.pop(st);
761
38
        BOOST_ASSERT(st_.empty());
762
38
        p = detail::count_whitespace(p, end_);
763
38
        if(BOOST_JSON_UNLIKELY(p == end_))
764
38
            return maybe_suspend(p, state::val1);
765
0
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
766
38
    }
767
768
44
    case state::val2:
769
44
    {
770
44
        st_.pop(st);
771
44
        p = parse_comment(p, std::false_type(), std::false_type());
772
44
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
773
44
            return maybe_suspend(p, state::val2);
774
0
        if(BOOST_JSON_UNLIKELY( p == end_ ))
775
0
            return maybe_suspend(p, state::val3);
776
0
        BOOST_ASSERT(st_.empty());
777
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
778
0
    }
779
780
0
    case state::val3:
781
0
    {
782
0
        st_.pop(st);
783
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
784
0
    }
785
11.3k
    }
786
11.3k
}
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
721
5.14k
{
722
5.14k
    state st;
723
5.14k
    st_.peek(st);
724
5.14k
    switch(st)
725
5.14k
    {
726
0
    default: BOOST_JSON_UNREACHABLE();
727
25
    case state::lit1:
728
25
        return parse_literal(p,  detail::literals_c<detail::literals::resume>() );
729
730
207
    case state::str1: case state::str2:
731
212
    case state::str8:
732
212
        return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733
734
44
    case state::arr1: case state::arr2:
735
1.08k
    case state::arr3: case state::arr4:
736
1.22k
    case state::arr5: case state::arr6:
737
1.22k
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738
739
39
    case state::obj1: case state::obj2:
740
196
    case state::obj3: case state::obj4:
741
227
    case state::obj5: case state::obj6:
742
438
    case state::obj7: case state::obj8:
743
465
    case state::obj9: case state::obj10:
744
465
    case state::obj11:
745
465
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746
747
588
    case state::num1: case state::num2:
748
892
    case state::num3: case state::num4:
749
1.42k
    case state::num5: case state::num6:
750
2.05k
    case state::num7: case state::num8:
751
2.19k
    case state::exp1: case state::exp2:
752
3.21k
    case state::exp3:
753
3.21k
        return mp11::mp_with_index<3>(
754
3.21k
            static_cast<unsigned char>(opt_.numbers),
755
3.21k
            parse_number_helper<false, 0>{ this, p });
756
757
    // KRYSTIAN NOTE: these are special cases
758
0
    case state::val1:
759
0
    {
760
0
        st_.pop(st);
761
0
        BOOST_ASSERT(st_.empty());
762
0
        p = detail::count_whitespace(p, end_);
763
0
        if(BOOST_JSON_UNLIKELY(p == end_))
764
0
            return maybe_suspend(p, state::val1);
765
0
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
766
0
    }
767
768
0
    case state::val2:
769
0
    {
770
0
        st_.pop(st);
771
0
        p = parse_comment(p, std::false_type(), std::false_type());
772
0
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
773
0
            return maybe_suspend(p, state::val2);
774
0
        if(BOOST_JSON_UNLIKELY( p == end_ ))
775
0
            return maybe_suspend(p, state::val3);
776
0
        BOOST_ASSERT(st_.empty());
777
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
778
0
    }
779
780
0
    case state::val3:
781
0
    {
782
0
        st_.pop(st);
783
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
784
0
    }
785
5.14k
    }
786
5.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
721
6.17k
{
722
6.17k
    state st;
723
6.17k
    st_.peek(st);
724
6.17k
    switch(st)
725
6.17k
    {
726
0
    default: BOOST_JSON_UNREACHABLE();
727
36
    case state::lit1:
728
36
        return parse_literal(p,  detail::literals_c<detail::literals::resume>() );
729
730
287
    case state::str1: case state::str2:
731
295
    case state::str8:
732
295
        return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733
734
66
    case state::arr1: case state::arr2:
735
1.57k
    case state::arr3: case state::arr4:
736
1.71k
    case state::arr5: case state::arr6:
737
1.71k
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738
739
54
    case state::obj1: case state::obj2:
740
216
    case state::obj3: case state::obj4:
741
248
    case state::obj5: case state::obj6:
742
521
    case state::obj7: case state::obj8:
743
575
    case state::obj9: case state::obj10:
744
581
    case state::obj11:
745
581
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746
747
634
    case state::num1: case state::num2:
748
913
    case state::num3: case state::num4:
749
1.51k
    case state::num5: case state::num6:
750
2.16k
    case state::num7: case state::num8:
751
2.30k
    case state::exp1: case state::exp2:
752
3.46k
    case state::exp3:
753
3.46k
        return mp11::mp_with_index<3>(
754
3.46k
            static_cast<unsigned char>(opt_.numbers),
755
3.46k
            parse_number_helper<false, 0>{ this, p });
756
757
    // KRYSTIAN NOTE: these are special cases
758
38
    case state::val1:
759
38
    {
760
38
        st_.pop(st);
761
38
        BOOST_ASSERT(st_.empty());
762
38
        p = detail::count_whitespace(p, end_);
763
38
        if(BOOST_JSON_UNLIKELY(p == end_))
764
38
            return maybe_suspend(p, state::val1);
765
0
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
766
38
    }
767
768
44
    case state::val2:
769
44
    {
770
44
        st_.pop(st);
771
44
        p = parse_comment(p, std::false_type(), std::false_type());
772
44
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
773
44
            return maybe_suspend(p, state::val2);
774
0
        if(BOOST_JSON_UNLIKELY( p == end_ ))
775
0
            return maybe_suspend(p, state::val3);
776
0
        BOOST_ASSERT(st_.empty());
777
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
778
0
    }
779
780
0
    case state::val3:
781
0
    {
782
0
        st_.pop(st);
783
0
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
784
0
    }
785
6.17k
    }
786
6.17k
}
787
788
template<class Handler>
789
template<class Literal>
790
const char*
791
basic_parser<Handler>::
792
parse_literal(const char* p, Literal)
793
114k
{
794
114k
    using L = detail::literals;
795
796
114k
    std::size_t cur_lit;
797
114k
    std::size_t offset;
798
799
114k
    detail::const_stream_wrapper cs(p, end_);
800
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
114k
    {
802
114k
        constexpr std::size_t index = literal_index(Literal::value);
803
114k
        constexpr char const* literal = detail::literal_strings[index];
804
114k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
114k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
114k
        {
808
114k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
114k
            if( cmp != 0 )
810
114
            {
811
114
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
114
                return fail(cs.begin(), error::syntax, &loc);
813
114
            }
814
815
113k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
113k
            {
817
20.7k
                if(BOOST_JSON_UNLIKELY(
818
20.7k
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
            }
821
93.1k
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
93.1k
            {
823
44.3k
                if(BOOST_JSON_UNLIKELY(
824
44.3k
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
            }
827
48.8k
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
48.8k
            {
829
48.8k
                if(BOOST_JSON_UNLIKELY(
830
48.8k
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
            }
833
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834
0
            {
835
0
                if(BOOST_JSON_UNLIKELY(
836
0
                    ! h_.on_double(
837
0
                        std::numeric_limits<double>::infinity(),
838
0
                        string_view(literal, sz),
839
0
                        ec_)))
840
0
                    return fail(cs.begin());
841
            }
842
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843
0
            {
844
0
                if(BOOST_JSON_UNLIKELY(
845
0
                    ! h_.on_double(
846
0
                        -std::numeric_limits<double>::infinity(),
847
0
                        string_view(literal, sz),
848
0
                        ec_)))
849
0
                    return fail(cs.begin());
850
            }
851
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852
0
            {
853
0
                if(BOOST_JSON_UNLIKELY(
854
0
                    ! h_.on_double(
855
0
                        std::numeric_limits<double>::quiet_NaN(),
856
0
                        string_view(literal, sz),
857
0
                        ec_)))
858
0
                    return fail(cs.begin());
859
            }
860
            else
861
            {
862
                BOOST_JSON_UNREACHABLE();
863
            }
864
865
113k
            cs += sz;
866
113k
            return cs.begin();
867
114k
        }
868
869
334
        offset = 0;
870
334
        cur_lit = index;
871
    }
872
    else
873
61
    {
874
61
        state st;
875
61
        st_.pop(st);
876
61
        BOOST_ASSERT( st == state::lit1 );
877
878
61
        cur_lit = cur_lit_;
879
61
        offset = lit_offset_;
880
61
    }
881
882
0
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
114k
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
114k
    int cmp = 0;
885
114k
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
334
        cmp = std::memcmp(
887
334
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
114k
    if( cmp != 0 )
889
247
    {
890
247
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
247
        return fail(cs.begin(), error::syntax, &loc);
892
247
    }
893
894
114k
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
148
    {
896
148
        BOOST_ASSERT( cur_lit < 256 );
897
148
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
148
        BOOST_ASSERT( offset + size < 256 );
899
148
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
148
        return maybe_suspend(cs.begin() + size, state::lit1);
901
148
    }
902
903
114k
    switch( static_cast<L>(cur_lit) )
904
114k
    {
905
0
    case L::null:
906
0
        if(BOOST_JSON_UNLIKELY(
907
0
            ! h_.on_null(ec_)))
908
0
            return fail(cs.begin());
909
0
        break;
910
0
    case L::true_:
911
0
        if(BOOST_JSON_UNLIKELY(
912
0
            ! h_.on_bool(true, ec_)))
913
0
            return fail(cs.begin());
914
0
        break;
915
0
    case L::false_:
916
0
        if(BOOST_JSON_UNLIKELY(
917
0
            ! h_.on_bool(false, ec_)))
918
0
            return fail(cs.begin());
919
0
        break;
920
0
    case L::infinity:
921
0
        if(BOOST_JSON_UNLIKELY(
922
0
            ! h_.on_double(
923
0
                std::numeric_limits<double>::infinity(),
924
0
                string_view(
925
0
                    detail::literal_strings[ literal_index(L::infinity) ],
926
0
                    detail::literal_sizes[ literal_index(L::infinity) ]),
927
0
                ec_)))
928
0
            return fail(cs.begin());
929
0
        break;
930
0
    case L::neg_infinity:
931
0
        if(BOOST_JSON_UNLIKELY(
932
0
            ! h_.on_double(
933
0
                -std::numeric_limits<double>::infinity(),
934
0
                string_view(
935
0
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
936
0
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
937
0
                ec_)))
938
0
            return fail(cs.begin());
939
0
        break;
940
0
    case L::nan:
941
0
        if(BOOST_JSON_UNLIKELY(
942
0
            ! h_.on_double(
943
0
                std::numeric_limits<double>::quiet_NaN(),
944
0
                string_view(
945
0
                    detail::literal_strings[ literal_index(L::nan) ],
946
0
                    detail::literal_sizes[ literal_index(L::nan) ]),
947
0
                ec_)))
948
0
            return fail(cs.begin());
949
0
        break;
950
0
    default: BOOST_JSON_UNREACHABLE();
951
114k
    }
952
953
0
    cs += size;
954
0
    return cs.begin();
955
114k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)4> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)4>)
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)6> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)6>)
Line
Count
Source
793
61
{
794
61
    using L = detail::literals;
795
796
61
    std::size_t cur_lit;
797
61
    std::size_t offset;
798
799
61
    detail::const_stream_wrapper cs(p, end_);
800
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
    {
802
        constexpr std::size_t index = literal_index(Literal::value);
803
        constexpr char const* literal = detail::literal_strings[index];
804
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
        {
808
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
            if( cmp != 0 )
810
            {
811
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
                return fail(cs.begin(), error::syntax, &loc);
813
            }
814
815
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
            {
817
                if(BOOST_JSON_UNLIKELY(
818
                    ! h_.on_null(ec_)))
819
                    return fail(cs.begin());
820
            }
821
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
            {
823
                if(BOOST_JSON_UNLIKELY(
824
                    ! h_.on_bool(true, ec_)))
825
                    return fail(cs.begin());
826
            }
827
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
            {
829
                if(BOOST_JSON_UNLIKELY(
830
                    ! h_.on_bool(false, ec_)))
831
                    return fail(cs.begin());
832
            }
833
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834
            {
835
                if(BOOST_JSON_UNLIKELY(
836
                    ! h_.on_double(
837
                        std::numeric_limits<double>::infinity(),
838
                        string_view(literal, sz),
839
                        ec_)))
840
                    return fail(cs.begin());
841
            }
842
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843
            {
844
                if(BOOST_JSON_UNLIKELY(
845
                    ! h_.on_double(
846
                        -std::numeric_limits<double>::infinity(),
847
                        string_view(literal, sz),
848
                        ec_)))
849
                    return fail(cs.begin());
850
            }
851
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852
            {
853
                if(BOOST_JSON_UNLIKELY(
854
                    ! h_.on_double(
855
                        std::numeric_limits<double>::quiet_NaN(),
856
                        string_view(literal, sz),
857
                        ec_)))
858
                    return fail(cs.begin());
859
            }
860
            else
861
            {
862
                BOOST_JSON_UNREACHABLE();
863
            }
864
865
            cs += sz;
866
            return cs.begin();
867
        }
868
869
        offset = 0;
870
        cur_lit = index;
871
    }
872
    else
873
61
    {
874
61
        state st;
875
61
        st_.pop(st);
876
61
        BOOST_ASSERT( st == state::lit1 );
877
878
61
        cur_lit = cur_lit_;
879
61
        offset = lit_offset_;
880
61
    }
881
882
61
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
61
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
61
    int cmp = 0;
885
61
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
0
        cmp = std::memcmp(
887
0
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
61
    if( cmp != 0 )
889
0
    {
890
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
0
        return fail(cs.begin(), error::syntax, &loc);
892
0
    }
893
894
61
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
61
    {
896
61
        BOOST_ASSERT( cur_lit < 256 );
897
61
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
61
        BOOST_ASSERT( offset + size < 256 );
899
61
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
61
        return maybe_suspend(cs.begin() + size, state::lit1);
901
61
    }
902
903
0
    switch( static_cast<L>(cur_lit) )
904
0
    {
905
0
    case L::null:
906
0
        if(BOOST_JSON_UNLIKELY(
907
0
            ! h_.on_null(ec_)))
908
0
            return fail(cs.begin());
909
0
        break;
910
0
    case L::true_:
911
0
        if(BOOST_JSON_UNLIKELY(
912
0
            ! h_.on_bool(true, ec_)))
913
0
            return fail(cs.begin());
914
0
        break;
915
0
    case L::false_:
916
0
        if(BOOST_JSON_UNLIKELY(
917
0
            ! h_.on_bool(false, ec_)))
918
0
            return fail(cs.begin());
919
0
        break;
920
0
    case L::infinity:
921
0
        if(BOOST_JSON_UNLIKELY(
922
0
            ! h_.on_double(
923
0
                std::numeric_limits<double>::infinity(),
924
0
                string_view(
925
0
                    detail::literal_strings[ literal_index(L::infinity) ],
926
0
                    detail::literal_sizes[ literal_index(L::infinity) ]),
927
0
                ec_)))
928
0
            return fail(cs.begin());
929
0
        break;
930
0
    case L::neg_infinity:
931
0
        if(BOOST_JSON_UNLIKELY(
932
0
            ! h_.on_double(
933
0
                -std::numeric_limits<double>::infinity(),
934
0
                string_view(
935
0
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
936
0
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
937
0
                ec_)))
938
0
            return fail(cs.begin());
939
0
        break;
940
0
    case L::nan:
941
0
        if(BOOST_JSON_UNLIKELY(
942
0
            ! h_.on_double(
943
0
                std::numeric_limits<double>::quiet_NaN(),
944
0
                string_view(
945
0
                    detail::literal_strings[ literal_index(L::nan) ],
946
0
                    detail::literal_sizes[ literal_index(L::nan) ]),
947
0
                ec_)))
948
0
            return fail(cs.begin());
949
0
        break;
950
0
    default: BOOST_JSON_UNREACHABLE();
951
0
    }
952
953
0
    cs += size;
954
0
    return cs.begin();
955
0
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)0> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)0>)
Line
Count
Source
793
20.8k
{
794
20.8k
    using L = detail::literals;
795
796
20.8k
    std::size_t cur_lit;
797
20.8k
    std::size_t offset;
798
799
20.8k
    detail::const_stream_wrapper cs(p, end_);
800
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
20.8k
    {
802
20.8k
        constexpr std::size_t index = literal_index(Literal::value);
803
20.8k
        constexpr char const* literal = detail::literal_strings[index];
804
20.8k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
20.8k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
20.7k
        {
808
20.7k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
20.7k
            if( cmp != 0 )
810
33
            {
811
33
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
33
                return fail(cs.begin(), error::syntax, &loc);
813
33
            }
814
815
20.7k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
20.7k
            {
817
20.7k
                if(BOOST_JSON_UNLIKELY(
818
20.7k
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
            }
821
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
            {
823
                if(BOOST_JSON_UNLIKELY(
824
                    ! h_.on_bool(true, ec_)))
825
                    return fail(cs.begin());
826
            }
827
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
            {
829
                if(BOOST_JSON_UNLIKELY(
830
                    ! h_.on_bool(false, ec_)))
831
                    return fail(cs.begin());
832
            }
833
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834
            {
835
                if(BOOST_JSON_UNLIKELY(
836
                    ! h_.on_double(
837
                        std::numeric_limits<double>::infinity(),
838
                        string_view(literal, sz),
839
                        ec_)))
840
                    return fail(cs.begin());
841
            }
842
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843
            {
844
                if(BOOST_JSON_UNLIKELY(
845
                    ! h_.on_double(
846
                        -std::numeric_limits<double>::infinity(),
847
                        string_view(literal, sz),
848
                        ec_)))
849
                    return fail(cs.begin());
850
            }
851
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852
            {
853
                if(BOOST_JSON_UNLIKELY(
854
                    ! h_.on_double(
855
                        std::numeric_limits<double>::quiet_NaN(),
856
                        string_view(literal, sz),
857
                        ec_)))
858
                    return fail(cs.begin());
859
            }
860
            else
861
            {
862
                BOOST_JSON_UNREACHABLE();
863
            }
864
865
20.7k
            cs += sz;
866
20.7k
            return cs.begin();
867
20.7k
        }
868
869
103
        offset = 0;
870
103
        cur_lit = index;
871
    }
872
    else
873
    {
874
        state st;
875
        st_.pop(st);
876
        BOOST_ASSERT( st == state::lit1 );
877
878
        cur_lit = cur_lit_;
879
        offset = lit_offset_;
880
    }
881
882
0
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
20.8k
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
20.8k
    int cmp = 0;
885
20.8k
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
103
        cmp = std::memcmp(
887
103
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
20.8k
    if( cmp != 0 )
889
78
    {
890
78
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
78
        return fail(cs.begin(), error::syntax, &loc);
892
78
    }
893
894
20.7k
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
25
    {
896
25
        BOOST_ASSERT( cur_lit < 256 );
897
25
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
25
        BOOST_ASSERT( offset + size < 256 );
899
25
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
25
        return maybe_suspend(cs.begin() + size, state::lit1);
901
25
    }
902
903
20.7k
    switch( static_cast<L>(cur_lit) )
904
20.7k
    {
905
0
    case L::null:
906
0
        if(BOOST_JSON_UNLIKELY(
907
0
            ! h_.on_null(ec_)))
908
0
            return fail(cs.begin());
909
0
        break;
910
0
    case L::true_:
911
0
        if(BOOST_JSON_UNLIKELY(
912
0
            ! h_.on_bool(true, ec_)))
913
0
            return fail(cs.begin());
914
0
        break;
915
0
    case L::false_:
916
0
        if(BOOST_JSON_UNLIKELY(
917
0
            ! h_.on_bool(false, ec_)))
918
0
            return fail(cs.begin());
919
0
        break;
920
0
    case L::infinity:
921
0
        if(BOOST_JSON_UNLIKELY(
922
0
            ! h_.on_double(
923
0
                std::numeric_limits<double>::infinity(),
924
0
                string_view(
925
0
                    detail::literal_strings[ literal_index(L::infinity) ],
926
0
                    detail::literal_sizes[ literal_index(L::infinity) ]),
927
0
                ec_)))
928
0
            return fail(cs.begin());
929
0
        break;
930
0
    case L::neg_infinity:
931
0
        if(BOOST_JSON_UNLIKELY(
932
0
            ! h_.on_double(
933
0
                -std::numeric_limits<double>::infinity(),
934
0
                string_view(
935
0
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
936
0
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
937
0
                ec_)))
938
0
            return fail(cs.begin());
939
0
        break;
940
0
    case L::nan:
941
0
        if(BOOST_JSON_UNLIKELY(
942
0
            ! h_.on_double(
943
0
                std::numeric_limits<double>::quiet_NaN(),
944
0
                string_view(
945
0
                    detail::literal_strings[ literal_index(L::nan) ],
946
0
                    detail::literal_sizes[ literal_index(L::nan) ]),
947
0
                ec_)))
948
0
            return fail(cs.begin());
949
0
        break;
950
0
    default: BOOST_JSON_UNREACHABLE();
951
20.7k
    }
952
953
0
    cs += size;
954
0
    return cs.begin();
955
20.7k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)1> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)1>)
Line
Count
Source
793
44.4k
{
794
44.4k
    using L = detail::literals;
795
796
44.4k
    std::size_t cur_lit;
797
44.4k
    std::size_t offset;
798
799
44.4k
    detail::const_stream_wrapper cs(p, end_);
800
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
44.4k
    {
802
44.4k
        constexpr std::size_t index = literal_index(Literal::value);
803
44.4k
        constexpr char const* literal = detail::literal_strings[index];
804
44.4k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
44.4k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
44.3k
        {
808
44.3k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
44.3k
            if( cmp != 0 )
810
40
            {
811
40
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
40
                return fail(cs.begin(), error::syntax, &loc);
813
40
            }
814
815
44.3k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
44.3k
            {
817
44.3k
                if(BOOST_JSON_UNLIKELY(
818
44.3k
                    ! h_.on_null(ec_)))
819
44.3k
                    return fail(cs.begin());
820
44.3k
            }
821
44.3k
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
44.3k
            {
823
44.3k
                if(BOOST_JSON_UNLIKELY(
824
44.3k
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
            }
827
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
            {
829
                if(BOOST_JSON_UNLIKELY(
830
                    ! h_.on_bool(false, ec_)))
831
                    return fail(cs.begin());
832
            }
833
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834
            {
835
                if(BOOST_JSON_UNLIKELY(
836
                    ! h_.on_double(
837
                        std::numeric_limits<double>::infinity(),
838
                        string_view(literal, sz),
839
                        ec_)))
840
                    return fail(cs.begin());
841
            }
842
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843
            {
844
                if(BOOST_JSON_UNLIKELY(
845
                    ! h_.on_double(
846
                        -std::numeric_limits<double>::infinity(),
847
                        string_view(literal, sz),
848
                        ec_)))
849
                    return fail(cs.begin());
850
            }
851
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852
            {
853
                if(BOOST_JSON_UNLIKELY(
854
                    ! h_.on_double(
855
                        std::numeric_limits<double>::quiet_NaN(),
856
                        string_view(literal, sz),
857
                        ec_)))
858
                    return fail(cs.begin());
859
            }
860
            else
861
            {
862
                BOOST_JSON_UNREACHABLE();
863
            }
864
865
44.3k
            cs += sz;
866
44.3k
            return cs.begin();
867
44.3k
        }
868
869
117
        offset = 0;
870
117
        cur_lit = index;
871
    }
872
    else
873
    {
874
        state st;
875
        st_.pop(st);
876
        BOOST_ASSERT( st == state::lit1 );
877
878
        cur_lit = cur_lit_;
879
        offset = lit_offset_;
880
    }
881
882
0
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
44.4k
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
44.4k
    int cmp = 0;
885
44.4k
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
117
        cmp = std::memcmp(
887
117
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
44.4k
    if( cmp != 0 )
889
83
    {
890
83
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
83
        return fail(cs.begin(), error::syntax, &loc);
892
83
    }
893
894
44.3k
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
34
    {
896
34
        BOOST_ASSERT( cur_lit < 256 );
897
34
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
34
        BOOST_ASSERT( offset + size < 256 );
899
34
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
34
        return maybe_suspend(cs.begin() + size, state::lit1);
901
34
    }
902
903
44.3k
    switch( static_cast<L>(cur_lit) )
904
44.3k
    {
905
0
    case L::null:
906
0
        if(BOOST_JSON_UNLIKELY(
907
0
            ! h_.on_null(ec_)))
908
0
            return fail(cs.begin());
909
0
        break;
910
0
    case L::true_:
911
0
        if(BOOST_JSON_UNLIKELY(
912
0
            ! h_.on_bool(true, ec_)))
913
0
            return fail(cs.begin());
914
0
        break;
915
0
    case L::false_:
916
0
        if(BOOST_JSON_UNLIKELY(
917
0
            ! h_.on_bool(false, ec_)))
918
0
            return fail(cs.begin());
919
0
        break;
920
0
    case L::infinity:
921
0
        if(BOOST_JSON_UNLIKELY(
922
0
            ! h_.on_double(
923
0
                std::numeric_limits<double>::infinity(),
924
0
                string_view(
925
0
                    detail::literal_strings[ literal_index(L::infinity) ],
926
0
                    detail::literal_sizes[ literal_index(L::infinity) ]),
927
0
                ec_)))
928
0
            return fail(cs.begin());
929
0
        break;
930
0
    case L::neg_infinity:
931
0
        if(BOOST_JSON_UNLIKELY(
932
0
            ! h_.on_double(
933
0
                -std::numeric_limits<double>::infinity(),
934
0
                string_view(
935
0
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
936
0
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
937
0
                ec_)))
938
0
            return fail(cs.begin());
939
0
        break;
940
0
    case L::nan:
941
0
        if(BOOST_JSON_UNLIKELY(
942
0
            ! h_.on_double(
943
0
                std::numeric_limits<double>::quiet_NaN(),
944
0
                string_view(
945
0
                    detail::literal_strings[ literal_index(L::nan) ],
946
0
                    detail::literal_sizes[ literal_index(L::nan) ]),
947
0
                ec_)))
948
0
            return fail(cs.begin());
949
0
        break;
950
0
    default: BOOST_JSON_UNREACHABLE();
951
44.3k
    }
952
953
0
    cs += size;
954
0
    return cs.begin();
955
44.3k
}
char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)2> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)2>)
Line
Count
Source
793
49.0k
{
794
49.0k
    using L = detail::literals;
795
796
49.0k
    std::size_t cur_lit;
797
49.0k
    std::size_t offset;
798
799
49.0k
    detail::const_stream_wrapper cs(p, end_);
800
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
49.0k
    {
802
49.0k
        constexpr std::size_t index = literal_index(Literal::value);
803
49.0k
        constexpr char const* literal = detail::literal_strings[index];
804
49.0k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
49.0k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
48.9k
        {
808
48.9k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
48.9k
            if( cmp != 0 )
810
41
            {
811
41
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
41
                return fail(cs.begin(), error::syntax, &loc);
813
41
            }
814
815
48.8k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
48.8k
            {
817
48.8k
                if(BOOST_JSON_UNLIKELY(
818
48.8k
                    ! h_.on_null(ec_)))
819
48.8k
                    return fail(cs.begin());
820
48.8k
            }
821
48.8k
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
48.8k
            {
823
48.8k
                if(BOOST_JSON_UNLIKELY(
824
48.8k
                    ! h_.on_bool(true, ec_)))
825
48.8k
                    return fail(cs.begin());
826
48.8k
            }
827
48.8k
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
48.8k
            {
829
48.8k
                if(BOOST_JSON_UNLIKELY(
830
48.8k
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
            }
833
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834
            {
835
                if(BOOST_JSON_UNLIKELY(
836
                    ! h_.on_double(
837
                        std::numeric_limits<double>::infinity(),
838
                        string_view(literal, sz),
839
                        ec_)))
840
                    return fail(cs.begin());
841
            }
842
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843
            {
844
                if(BOOST_JSON_UNLIKELY(
845
                    ! h_.on_double(
846
                        -std::numeric_limits<double>::infinity(),
847
                        string_view(literal, sz),
848
                        ec_)))
849
                    return fail(cs.begin());
850
            }
851
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852
            {
853
                if(BOOST_JSON_UNLIKELY(
854
                    ! h_.on_double(
855
                        std::numeric_limits<double>::quiet_NaN(),
856
                        string_view(literal, sz),
857
                        ec_)))
858
                    return fail(cs.begin());
859
            }
860
            else
861
            {
862
                BOOST_JSON_UNREACHABLE();
863
            }
864
865
48.8k
            cs += sz;
866
48.8k
            return cs.begin();
867
48.9k
        }
868
869
114
        offset = 0;
870
114
        cur_lit = index;
871
    }
872
    else
873
    {
874
        state st;
875
        st_.pop(st);
876
        BOOST_ASSERT( st == state::lit1 );
877
878
        cur_lit = cur_lit_;
879
        offset = lit_offset_;
880
    }
881
882
0
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
49.0k
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
49.0k
    int cmp = 0;
885
49.0k
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
114
        cmp = std::memcmp(
887
114
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
49.0k
    if( cmp != 0 )
889
86
    {
890
86
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
86
        return fail(cs.begin(), error::syntax, &loc);
892
86
    }
893
894
48.9k
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
28
    {
896
28
        BOOST_ASSERT( cur_lit < 256 );
897
28
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
28
        BOOST_ASSERT( offset + size < 256 );
899
28
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
28
        return maybe_suspend(cs.begin() + size, state::lit1);
901
28
    }
902
903
48.9k
    switch( static_cast<L>(cur_lit) )
904
48.9k
    {
905
0
    case L::null:
906
0
        if(BOOST_JSON_UNLIKELY(
907
0
            ! h_.on_null(ec_)))
908
0
            return fail(cs.begin());
909
0
        break;
910
0
    case L::true_:
911
0
        if(BOOST_JSON_UNLIKELY(
912
0
            ! h_.on_bool(true, ec_)))
913
0
            return fail(cs.begin());
914
0
        break;
915
0
    case L::false_:
916
0
        if(BOOST_JSON_UNLIKELY(
917
0
            ! h_.on_bool(false, ec_)))
918
0
            return fail(cs.begin());
919
0
        break;
920
0
    case L::infinity:
921
0
        if(BOOST_JSON_UNLIKELY(
922
0
            ! h_.on_double(
923
0
                std::numeric_limits<double>::infinity(),
924
0
                string_view(
925
0
                    detail::literal_strings[ literal_index(L::infinity) ],
926
0
                    detail::literal_sizes[ literal_index(L::infinity) ]),
927
0
                ec_)))
928
0
            return fail(cs.begin());
929
0
        break;
930
0
    case L::neg_infinity:
931
0
        if(BOOST_JSON_UNLIKELY(
932
0
            ! h_.on_double(
933
0
                -std::numeric_limits<double>::infinity(),
934
0
                string_view(
935
0
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
936
0
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
937
0
                ec_)))
938
0
            return fail(cs.begin());
939
0
        break;
940
0
    case L::nan:
941
0
        if(BOOST_JSON_UNLIKELY(
942
0
            ! h_.on_double(
943
0
                std::numeric_limits<double>::quiet_NaN(),
944
0
                string_view(
945
0
                    detail::literal_strings[ literal_index(L::nan) ],
946
0
                    detail::literal_sizes[ literal_index(L::nan) ]),
947
0
                ec_)))
948
0
            return fail(cs.begin());
949
0
        break;
950
0
    default: BOOST_JSON_UNREACHABLE();
951
48.9k
    }
952
953
0
    cs += size;
954
0
    return cs.begin();
955
48.9k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)3> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)3>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::handler>::parse_literal<std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)5> >(char const*, std::__1::integral_constant<boost::json::detail::literals, (boost::json::detail::literals)5>)
956
957
//----------------------------------------------------------
958
959
template<class Handler>
960
template<bool StackEmpty_, bool IsKey_>
961
const char*
962
basic_parser<Handler>::
963
parse_string(const char* p,
964
    std::integral_constant<bool, StackEmpty_> stack_empty,
965
    std::integral_constant<bool, IsKey_> is_key,
966
    bool allow_bad_utf8,
967
    bool allow_bad_utf16)
968
1.89M
{
969
1.89M
    detail::const_stream_wrapper cs(p, end_);
970
1.89M
    std::size_t total;
971
1.89M
    char const* start;
972
1.89M
    std::size_t size;
973
1.89M
    if(! stack_empty && ! st_.empty())
974
717
    {
975
717
        state st;
976
717
        st_.pop(st);
977
717
        st_.pop(total);
978
717
        switch(st)
979
717
        {
980
0
        default: BOOST_JSON_UNREACHABLE();
981
180
        case state::str2: goto do_str2;
982
20
        case state::str8: goto do_str8;
983
517
        case state::str1: break;
984
717
        }
985
717
    }
986
1.89M
    else
987
1.89M
    {
988
1.89M
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
1.89M
        ++cs;
990
1.89M
        total = 0;
991
1.89M
    }
992
993
2.00M
do_str1:
994
2.00M
    start = cs.begin();
995
2.00M
    cs = allow_bad_utf8?
996
475k
        detail::count_valid<true>(cs.begin(), cs.end()):
997
2.00M
        detail::count_valid<false>(cs.begin(), cs.end());
998
2.00M
    size = cs.used(start);
999
2.00M
    if(is_key)
1000
1.85M
    {
1001
1.85M
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
1.85M
        if(BOOST_JSON_UNLIKELY(size >
1003
1.85M
            Handler::max_key_size - total))
1004
0
        {
1005
0
            BOOST_STATIC_CONSTEXPR source_location loc
1006
0
                = BOOST_CURRENT_LOCATION;
1007
0
            return fail(cs.begin(), error::key_too_large, &loc);
1008
0
        }
1009
1.85M
    }
1010
143k
    else
1011
143k
    {
1012
143k
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
143k
        if(BOOST_JSON_UNLIKELY(size >
1014
143k
            Handler::max_string_size - total))
1015
0
        {
1016
0
            BOOST_STATIC_CONSTEXPR source_location loc
1017
0
                = BOOST_CURRENT_LOCATION;
1018
0
            return fail(cs.begin(), error::string_too_large, &loc);
1019
0
        }
1020
143k
    }
1021
2.00M
    total += size;
1022
2.00M
    if(BOOST_JSON_UNLIKELY(! cs))
1023
1.59k
    {
1024
        // call handler if the string isn't empty
1025
1.59k
        if(BOOST_JSON_LIKELY(size))
1026
518
        {
1027
518
            {
1028
518
                bool r = is_key?
1029
223
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
518
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
518
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
518
            }
1037
518
        }
1038
1.59k
        return maybe_suspend(cs.begin(), state::str1, total);
1039
1.59k
    }
1040
    // at this point all valid characters have been skipped, so any remaining
1041
    // if there are any more characters, they are either escaped, or incomplete
1042
    // utf8, or invalid utf8
1043
2.00M
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
112k
    {
1045
        // sequence is invalid or incomplete
1046
112k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
552
        {
1048
552
            seq_.save(cs.begin(), cs.remain());
1049
552
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
514
            {
1051
514
                BOOST_STATIC_CONSTEXPR source_location loc
1052
514
                    = BOOST_CURRENT_LOCATION;
1053
514
                return fail(cs.begin(), error::syntax, &loc);
1054
514
            }
1055
38
            if(BOOST_JSON_LIKELY(size))
1056
6
            {
1057
6
                bool const r = is_key?
1058
2
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
6
                    h_.on_string_part( {start, size}, total, ec_ );
1060
6
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
6
            }
1063
38
            return maybe_suspend(cs.end(), state::str8, total);
1064
38
        }
1065
112k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
112k
        {
1067
            // flush unescaped run from input
1068
112k
            if(BOOST_JSON_LIKELY(size))
1069
85.1k
            {
1070
85.1k
                bool const r = is_key?
1071
34.6k
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
85.1k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
85.1k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
85.1k
            }
1076
112k
do_str2:
1077
112k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
112k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
1.65k
                return suspend_or_fail(state::str2, total);
1080
1081
110k
            goto do_str1;
1082
112k
        }
1083
        // illegal control
1084
112k
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
166
        return fail(cs.begin(), error::syntax, &loc);
1086
112k
    }
1087
1088
1.88M
    {
1089
1.88M
        bool r = is_key?
1090
1.80M
            h_.on_key( {start, size}, total, ec_ ):
1091
1.88M
            h_.on_string( {start, size}, total, ec_ );
1092
1093
1.88M
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
1.88M
    }
1098
1099
1.88M
    ++cs;
1100
1.88M
    return cs.begin();
1101
1102
20
do_str8:
1103
20
    uint8_t needed = seq_.needed();
1104
20
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105
20
        return maybe_suspend(cs.end(), state::str8, total);
1106
0
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107
0
    {
1108
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109
0
        return fail(cs.begin(), error::syntax, &loc);
1110
0
    }
1111
0
    {
1112
0
        std::size_t const n = seq_.length();
1113
0
        bool r;
1114
0
        if(is_key)
1115
0
        {
1116
0
            BOOST_ASSERT(total <= Handler::max_key_size);
1117
0
            if(BOOST_JSON_UNLIKELY(n >
1118
0
                Handler::max_key_size - total))
1119
0
            {
1120
0
                BOOST_STATIC_CONSTEXPR source_location loc
1121
0
                    = BOOST_CURRENT_LOCATION;
1122
0
                return fail(cs.begin(), error::key_too_large, &loc);
1123
0
            }
1124
0
            total += n;
1125
0
            r = h_.on_key_part( {seq_.data(), n}, total, ec_ );
1126
0
        }
1127
0
        else
1128
0
        {
1129
0
            BOOST_ASSERT(total <= Handler::max_string_size);
1130
0
            if(BOOST_JSON_UNLIKELY(n >
1131
0
                Handler::max_string_size - total))
1132
0
            {
1133
0
                BOOST_STATIC_CONSTEXPR source_location loc
1134
0
                    = BOOST_CURRENT_LOCATION;
1135
0
                return fail(cs.begin(), error::string_too_large, &loc);
1136
0
            }
1137
0
            total += n;
1138
0
            r = h_.on_string_part( {seq_.data(), n}, total, ec_ );
1139
0
        }
1140
0
        if(BOOST_JSON_UNLIKELY( !r ))
1141
0
            return fail( cs.begin() );
1142
0
    }
1143
0
    cs += needed;
1144
0
    goto do_str1;
1145
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
968
85.8k
{
969
85.8k
    detail::const_stream_wrapper cs(p, end_);
970
85.8k
    std::size_t total;
971
85.8k
    char const* start;
972
85.8k
    std::size_t size;
973
85.8k
    if(! stack_empty && ! st_.empty())
974
0
    {
975
0
        state st;
976
0
        st_.pop(st);
977
0
        st_.pop(total);
978
0
        switch(st)
979
0
        {
980
0
        default: BOOST_JSON_UNREACHABLE();
981
0
        case state::str2: goto do_str2;
982
0
        case state::str8: goto do_str8;
983
0
        case state::str1: break;
984
0
        }
985
0
    }
986
85.8k
    else
987
85.8k
    {
988
85.8k
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
85.8k
        ++cs;
990
85.8k
        total = 0;
991
85.8k
    }
992
993
143k
do_str1:
994
143k
    start = cs.begin();
995
143k
    cs = allow_bad_utf8?
996
97.1k
        detail::count_valid<true>(cs.begin(), cs.end()):
997
143k
        detail::count_valid<false>(cs.begin(), cs.end());
998
143k
    size = cs.used(start);
999
143k
    if(is_key)
1000
0
    {
1001
0
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
0
        if(BOOST_JSON_UNLIKELY(size >
1003
0
            Handler::max_key_size - total))
1004
0
        {
1005
0
            BOOST_STATIC_CONSTEXPR source_location loc
1006
0
                = BOOST_CURRENT_LOCATION;
1007
0
            return fail(cs.begin(), error::key_too_large, &loc);
1008
0
        }
1009
0
    }
1010
143k
    else
1011
143k
    {
1012
143k
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
143k
        if(BOOST_JSON_UNLIKELY(size >
1014
143k
            Handler::max_string_size - total))
1015
0
        {
1016
0
            BOOST_STATIC_CONSTEXPR source_location loc
1017
0
                = BOOST_CURRENT_LOCATION;
1018
0
            return fail(cs.begin(), error::string_too_large, &loc);
1019
0
        }
1020
143k
    }
1021
143k
    total += size;
1022
143k
    if(BOOST_JSON_UNLIKELY(! cs))
1023
770
    {
1024
        // call handler if the string isn't empty
1025
770
        if(BOOST_JSON_LIKELY(size))
1026
295
        {
1027
295
            {
1028
295
                bool r = is_key?
1029
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
295
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
295
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
295
            }
1037
295
        }
1038
770
        return maybe_suspend(cs.begin(), state::str1, total);
1039
770
    }
1040
    // at this point all valid characters have been skipped, so any remaining
1041
    // if there are any more characters, they are either escaped, or incomplete
1042
    // utf8, or invalid utf8
1043
142k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
58.8k
    {
1045
        // sequence is invalid or incomplete
1046
58.8k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
285
        {
1048
285
            seq_.save(cs.begin(), cs.remain());
1049
285
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
262
            {
1051
262
                BOOST_STATIC_CONSTEXPR source_location loc
1052
262
                    = BOOST_CURRENT_LOCATION;
1053
262
                return fail(cs.begin(), error::syntax, &loc);
1054
262
            }
1055
23
            if(BOOST_JSON_LIKELY(size))
1056
4
            {
1057
4
                bool const r = is_key?
1058
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
4
                    h_.on_string_part( {start, size}, total, ec_ );
1060
4
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
4
            }
1063
23
            return maybe_suspend(cs.end(), state::str8, total);
1064
23
        }
1065
58.6k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
58.4k
        {
1067
            // flush unescaped run from input
1068
58.4k
            if(BOOST_JSON_LIKELY(size))
1069
50.4k
            {
1070
50.4k
                bool const r = is_key?
1071
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
50.4k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
50.4k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
50.4k
            }
1076
58.4k
do_str2:
1077
58.4k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
58.4k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
1.33k
                return suspend_or_fail(state::str2, total);
1080
1081
57.1k
            goto do_str1;
1082
58.4k
        }
1083
        // illegal control
1084
58.8k
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
103
        return fail(cs.begin(), error::syntax, &loc);
1086
58.8k
    }
1087
1088
83.3k
    {
1089
83.3k
        bool r = is_key?
1090
0
            h_.on_key( {start, size}, total, ec_ ):
1091
83.3k
            h_.on_string( {start, size}, total, ec_ );
1092
1093
83.3k
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
83.3k
    }
1098
1099
83.3k
    ++cs;
1100
83.3k
    return cs.begin();
1101
1102
0
do_str8:
1103
0
    uint8_t needed = seq_.needed();
1104
0
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105
0
        return maybe_suspend(cs.end(), state::str8, total);
1106
0
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107
0
    {
1108
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109
0
        return fail(cs.begin(), error::syntax, &loc);
1110
0
    }
1111
0
    {
1112
0
        std::size_t const n = seq_.length();
1113
0
        bool r;
1114
0
        if(is_key)
1115
0
        {
1116
0
            BOOST_ASSERT(total <= Handler::max_key_size);
1117
0
            if(BOOST_JSON_UNLIKELY(n >
1118
0
                Handler::max_key_size - total))
1119
0
            {
1120
0
                BOOST_STATIC_CONSTEXPR source_location loc
1121
0
                    = BOOST_CURRENT_LOCATION;
1122
0
                return fail(cs.begin(), error::key_too_large, &loc);
1123
0
            }
1124
0
            total += n;
1125
0
            r = h_.on_key_part( {seq_.data(), n}, total, ec_ );
1126
0
        }
1127
0
        else
1128
0
        {
1129
0
            BOOST_ASSERT(total <= Handler::max_string_size);
1130
0
            if(BOOST_JSON_UNLIKELY(n >
1131
0
                Handler::max_string_size - total))
1132
0
            {
1133
0
                BOOST_STATIC_CONSTEXPR source_location loc
1134
0
                    = BOOST_CURRENT_LOCATION;
1135
0
                return fail(cs.begin(), error::string_too_large, &loc);
1136
0
            }
1137
0
            total += n;
1138
0
            r = h_.on_string_part( {seq_.data(), n}, total, ec_ );
1139
0
        }
1140
0
        if(BOOST_JSON_UNLIKELY( !r ))
1141
0
            return fail( cs.begin() );
1142
0
    }
1143
0
    cs += needed;
1144
0
    goto do_str1;
1145
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
968
1.80M
{
969
1.80M
    detail::const_stream_wrapper cs(p, end_);
970
1.80M
    std::size_t total;
971
1.80M
    char const* start;
972
1.80M
    std::size_t size;
973
1.80M
    if(! stack_empty && ! st_.empty())
974
0
    {
975
0
        state st;
976
0
        st_.pop(st);
977
0
        st_.pop(total);
978
0
        switch(st)
979
0
        {
980
0
        default: BOOST_JSON_UNREACHABLE();
981
0
        case state::str2: goto do_str2;
982
0
        case state::str8: goto do_str8;
983
0
        case state::str1: break;
984
0
        }
985
0
    }
986
1.80M
    else
987
1.80M
    {
988
1.80M
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
1.80M
        ++cs;
990
1.80M
        total = 0;
991
1.80M
    }
992
993
1.85M
do_str1:
994
1.85M
    start = cs.begin();
995
1.85M
    cs = allow_bad_utf8?
996
378k
        detail::count_valid<true>(cs.begin(), cs.end()):
997
1.85M
        detail::count_valid<false>(cs.begin(), cs.end());
998
1.85M
    size = cs.used(start);
999
1.85M
    if(is_key)
1000
1.85M
    {
1001
1.85M
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
1.85M
        if(BOOST_JSON_UNLIKELY(size >
1003
1.85M
            Handler::max_key_size - total))
1004
0
        {
1005
0
            BOOST_STATIC_CONSTEXPR source_location loc
1006
0
                = BOOST_CURRENT_LOCATION;
1007
0
            return fail(cs.begin(), error::key_too_large, &loc);
1008
0
        }
1009
1.85M
    }
1010
0
    else
1011
0
    {
1012
0
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
0
        if(BOOST_JSON_UNLIKELY(size >
1014
0
            Handler::max_string_size - total))
1015
0
        {
1016
0
            BOOST_STATIC_CONSTEXPR source_location loc
1017
0
                = BOOST_CURRENT_LOCATION;
1018
0
            return fail(cs.begin(), error::string_too_large, &loc);
1019
0
        }
1020
0
    }
1021
1.85M
    total += size;
1022
1.85M
    if(BOOST_JSON_UNLIKELY(! cs))
1023
307
    {
1024
        // call handler if the string isn't empty
1025
307
        if(BOOST_JSON_LIKELY(size))
1026
223
        {
1027
223
            {
1028
223
                bool r = is_key?
1029
223
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
223
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
223
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
223
            }
1037
223
        }
1038
307
        return maybe_suspend(cs.begin(), state::str1, total);
1039
307
    }
1040
    // at this point all valid characters have been skipped, so any remaining
1041
    // if there are any more characters, they are either escaped, or incomplete
1042
    // utf8, or invalid utf8
1043
1.85M
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
53.9k
    {
1045
        // sequence is invalid or incomplete
1046
53.9k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
267
        {
1048
267
            seq_.save(cs.begin(), cs.remain());
1049
267
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
252
            {
1051
252
                BOOST_STATIC_CONSTEXPR source_location loc
1052
252
                    = BOOST_CURRENT_LOCATION;
1053
252
                return fail(cs.begin(), error::syntax, &loc);
1054
252
            }
1055
15
            if(BOOST_JSON_LIKELY(size))
1056
2
            {
1057
2
                bool const r = is_key?
1058
2
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
2
                    h_.on_string_part( {start, size}, total, ec_ );
1060
2
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
2
            }
1063
15
            return maybe_suspend(cs.end(), state::str8, total);
1064
15
        }
1065
53.6k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
53.6k
        {
1067
            // flush unescaped run from input
1068
53.6k
            if(BOOST_JSON_LIKELY(size))
1069
34.6k
            {
1070
34.6k
                bool const r = is_key?
1071
34.6k
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
34.6k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
34.6k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
34.6k
            }
1076
53.6k
do_str2:
1077
53.6k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
53.6k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
141
                return suspend_or_fail(state::str2, total);
1080
1081
53.4k
            goto do_str1;
1082
53.6k
        }
1083
        // illegal control
1084
53.9k
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
63
        return fail(cs.begin(), error::syntax, &loc);
1086
53.9k
    }
1087
1088
1.80M
    {
1089
1.80M
        bool r = is_key?
1090
1.80M
            h_.on_key( {start, size}, total, ec_ ):
1091
1.80M
            h_.on_string( {start, size}, total, ec_ );
1092
1093
1.80M
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
1.80M
    }
1098
1099
1.80M
    ++cs;
1100
1.80M
    return cs.begin();
1101
1102
0
do_str8:
1103
0
    uint8_t needed = seq_.needed();
1104
0
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105
0
        return maybe_suspend(cs.end(), state::str8, total);
1106
0
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107
0
    {
1108
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109
0
        return fail(cs.begin(), error::syntax, &loc);
1110
0
    }
1111
0
    {
1112
0
        std::size_t const n = seq_.length();
1113
0
        bool r;
1114
0
        if(is_key)
1115
0
        {
1116
0
            BOOST_ASSERT(total <= Handler::max_key_size);
1117
0
            if(BOOST_JSON_UNLIKELY(n >
1118
0
                Handler::max_key_size - total))
1119
0
            {
1120
0
                BOOST_STATIC_CONSTEXPR source_location loc
1121
0
                    = BOOST_CURRENT_LOCATION;
1122
0
                return fail(cs.begin(), error::key_too_large, &loc);
1123
0
            }
1124
0
            total += n;
1125
0
            r = h_.on_key_part( {seq_.data(), n}, total, ec_ );
1126
0
        }
1127
0
        else
1128
0
        {
1129
0
            BOOST_ASSERT(total <= Handler::max_string_size);
1130
0
            if(BOOST_JSON_UNLIKELY(n >
1131
0
                Handler::max_string_size - total))
1132
0
            {
1133
0
                BOOST_STATIC_CONSTEXPR source_location loc
1134
0
                    = BOOST_CURRENT_LOCATION;
1135
0
                return fail(cs.begin(), error::string_too_large, &loc);
1136
0
            }
1137
0
            total += n;
1138
0
            r = h_.on_string_part( {seq_.data(), n}, total, ec_ );
1139
0
        }
1140
0
        if(BOOST_JSON_UNLIKELY( !r ))
1141
0
            return fail( cs.begin() );
1142
0
    }
1143
0
    cs += needed;
1144
0
    goto do_str1;
1145
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
968
507
{
969
507
    detail::const_stream_wrapper cs(p, end_);
970
507
    std::size_t total;
971
507
    char const* start;
972
507
    std::size_t size;
973
507
    if(! stack_empty && ! st_.empty())
974
507
    {
975
507
        state st;
976
507
        st_.pop(st);
977
507
        st_.pop(total);
978
507
        switch(st)
979
507
        {
980
0
        default: BOOST_JSON_UNREACHABLE();
981
135
        case state::str2: goto do_str2;
982
13
        case state::str8: goto do_str8;
983
359
        case state::str1: break;
984
507
        }
985
507
    }
986
0
    else
987
0
    {
988
0
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
0
        total = 0;
991
0
    }
992
993
359
do_str1:
994
359
    start = cs.begin();
995
359
    cs = allow_bad_utf8?
996
218
        detail::count_valid<true>(cs.begin(), cs.end()):
997
359
        detail::count_valid<false>(cs.begin(), cs.end());
998
359
    size = cs.used(start);
999
359
    if(is_key)
1000
0
    {
1001
0
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
0
        if(BOOST_JSON_UNLIKELY(size >
1003
0
            Handler::max_key_size - total))
1004
0
        {
1005
0
            BOOST_STATIC_CONSTEXPR source_location loc
1006
0
                = BOOST_CURRENT_LOCATION;
1007
0
            return fail(cs.begin(), error::key_too_large, &loc);
1008
0
        }
1009
0
    }
1010
359
    else
1011
359
    {
1012
359
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
359
        if(BOOST_JSON_UNLIKELY(size >
1014
359
            Handler::max_string_size - total))
1015
0
        {
1016
0
            BOOST_STATIC_CONSTEXPR source_location loc
1017
0
                = BOOST_CURRENT_LOCATION;
1018
0
            return fail(cs.begin(), error::string_too_large, &loc);
1019
0
        }
1020
359
    }
1021
359
    total += size;
1022
359
    if(BOOST_JSON_UNLIKELY(! cs))
1023
359
    {
1024
        // call handler if the string isn't empty
1025
359
        if(BOOST_JSON_LIKELY(size))
1026
0
        {
1027
0
            {
1028
0
                bool r = is_key?
1029
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
0
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
0
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
0
            }
1037
0
        }
1038
359
        return maybe_suspend(cs.begin(), state::str1, total);
1039
359
    }
1040
    // at this point all valid characters have been skipped, so any remaining
1041
    // if there are any more characters, they are either escaped, or incomplete
1042
    // utf8, or invalid utf8
1043
0
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
0
    {
1045
        // sequence is invalid or incomplete
1046
0
        if((*cs & 0x80) && !allow_bad_utf8)
1047
0
        {
1048
0
            seq_.save(cs.begin(), cs.remain());
1049
0
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
0
            {
1051
0
                BOOST_STATIC_CONSTEXPR source_location loc
1052
0
                    = BOOST_CURRENT_LOCATION;
1053
0
                return fail(cs.begin(), error::syntax, &loc);
1054
0
            }
1055
0
            if(BOOST_JSON_LIKELY(size))
1056
0
            {
1057
0
                bool const r = is_key?
1058
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
0
                    h_.on_string_part( {start, size}, total, ec_ );
1060
0
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
0
            }
1063
0
            return maybe_suspend(cs.end(), state::str8, total);
1064
0
        }
1065
0
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
0
        {
1067
            // flush unescaped run from input
1068
0
            if(BOOST_JSON_LIKELY(size))
1069
0
            {
1070
0
                bool const r = is_key?
1071
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
0
                    h_.on_string_part( {start, size}, total, ec_ );
1073
0
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
0
            }
1076
135
do_str2:
1077
135
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
135
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
135
                return suspend_or_fail(state::str2, total);
1080
1081
0
            goto do_str1;
1082
135
        }
1083
        // illegal control
1084
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
0
        return fail(cs.begin(), error::syntax, &loc);
1086
0
    }
1087
1088
0
    {
1089
0
        bool r = is_key?
1090
0
            h_.on_key( {start, size}, total, ec_ ):
1091
0
            h_.on_string( {start, size}, total, ec_ );
1092
1093
0
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
0
    }
1098
1099
0
    ++cs;
1100
0
    return cs.begin();
1101
1102
13
do_str8:
1103
13
    uint8_t needed = seq_.needed();
1104
13
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105
13
        return maybe_suspend(cs.end(), state::str8, total);
1106
0
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107
0
    {
1108
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109
0
        return fail(cs.begin(), error::syntax, &loc);
1110
0
    }
1111
0
    {
1112
0
        std::size_t const n = seq_.length();
1113
0
        bool r;
1114
0
        if(is_key)
1115
0
        {
1116
0
            BOOST_ASSERT(total <= Handler::max_key_size);
1117
0
            if(BOOST_JSON_UNLIKELY(n >
1118
0
                Handler::max_key_size - total))
1119
0
            {
1120
0
                BOOST_STATIC_CONSTEXPR source_location loc
1121
0
                    = BOOST_CURRENT_LOCATION;
1122
0
                return fail(cs.begin(), error::key_too_large, &loc);
1123
0
            }
1124
0
            total += n;
1125
0
            r = h_.on_key_part( {seq_.data(), n}, total, ec_ );
1126
0
        }
1127
0
        else
1128
0
        {
1129
0
            BOOST_ASSERT(total <= Handler::max_string_size);
1130
0
            if(BOOST_JSON_UNLIKELY(n >
1131
0
                Handler::max_string_size - total))
1132
0
            {
1133
0
                BOOST_STATIC_CONSTEXPR source_location loc
1134
0
                    = BOOST_CURRENT_LOCATION;
1135
0
                return fail(cs.begin(), error::string_too_large, &loc);
1136
0
            }
1137
0
            total += n;
1138
0
            r = h_.on_string_part( {seq_.data(), n}, total, ec_ );
1139
0
        }
1140
0
        if(BOOST_JSON_UNLIKELY( !r ))
1141
0
            return fail( cs.begin() );
1142
0
    }
1143
0
    cs += needed;
1144
0
    goto do_str1;
1145
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
968
210
{
969
210
    detail::const_stream_wrapper cs(p, end_);
970
210
    std::size_t total;
971
210
    char const* start;
972
210
    std::size_t size;
973
210
    if(! stack_empty && ! st_.empty())
974
210
    {
975
210
        state st;
976
210
        st_.pop(st);
977
210
        st_.pop(total);
978
210
        switch(st)
979
210
        {
980
0
        default: BOOST_JSON_UNREACHABLE();
981
45
        case state::str2: goto do_str2;
982
7
        case state::str8: goto do_str8;
983
158
        case state::str1: break;
984
210
        }
985
210
    }
986
0
    else
987
0
    {
988
0
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
0
        total = 0;
991
0
    }
992
993
158
do_str1:
994
158
    start = cs.begin();
995
158
    cs = allow_bad_utf8?
996
69
        detail::count_valid<true>(cs.begin(), cs.end()):
997
158
        detail::count_valid<false>(cs.begin(), cs.end());
998
158
    size = cs.used(start);
999
158
    if(is_key)
1000
158
    {
1001
158
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
158
        if(BOOST_JSON_UNLIKELY(size >
1003
158
            Handler::max_key_size - total))
1004
0
        {
1005
0
            BOOST_STATIC_CONSTEXPR source_location loc
1006
0
                = BOOST_CURRENT_LOCATION;
1007
0
            return fail(cs.begin(), error::key_too_large, &loc);
1008
0
        }
1009
158
    }
1010
0
    else
1011
0
    {
1012
0
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
0
        if(BOOST_JSON_UNLIKELY(size >
1014
0
            Handler::max_string_size - total))
1015
0
        {
1016
0
            BOOST_STATIC_CONSTEXPR source_location loc
1017
0
                = BOOST_CURRENT_LOCATION;
1018
0
            return fail(cs.begin(), error::string_too_large, &loc);
1019
0
        }
1020
0
    }
1021
158
    total += size;
1022
158
    if(BOOST_JSON_UNLIKELY(! cs))
1023
158
    {
1024
        // call handler if the string isn't empty
1025
158
        if(BOOST_JSON_LIKELY(size))
1026
0
        {
1027
0
            {
1028
0
                bool r = is_key?
1029
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
0
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
0
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
0
            }
1037
0
        }
1038
158
        return maybe_suspend(cs.begin(), state::str1, total);
1039
158
    }
1040
    // at this point all valid characters have been skipped, so any remaining
1041
    // if there are any more characters, they are either escaped, or incomplete
1042
    // utf8, or invalid utf8
1043
0
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
0
    {
1045
        // sequence is invalid or incomplete
1046
0
        if((*cs & 0x80) && !allow_bad_utf8)
1047
0
        {
1048
0
            seq_.save(cs.begin(), cs.remain());
1049
0
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
0
            {
1051
0
                BOOST_STATIC_CONSTEXPR source_location loc
1052
0
                    = BOOST_CURRENT_LOCATION;
1053
0
                return fail(cs.begin(), error::syntax, &loc);
1054
0
            }
1055
0
            if(BOOST_JSON_LIKELY(size))
1056
0
            {
1057
0
                bool const r = is_key?
1058
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
0
                    h_.on_string_part( {start, size}, total, ec_ );
1060
0
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
0
            }
1063
0
            return maybe_suspend(cs.end(), state::str8, total);
1064
0
        }
1065
0
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
0
        {
1067
            // flush unescaped run from input
1068
0
            if(BOOST_JSON_LIKELY(size))
1069
0
            {
1070
0
                bool const r = is_key?
1071
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
0
                    h_.on_string_part( {start, size}, total, ec_ );
1073
0
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
0
            }
1076
45
do_str2:
1077
45
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
45
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
45
                return suspend_or_fail(state::str2, total);
1080
1081
0
            goto do_str1;
1082
45
        }
1083
        // illegal control
1084
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
0
        return fail(cs.begin(), error::syntax, &loc);
1086
0
    }
1087
1088
0
    {
1089
0
        bool r = is_key?
1090
0
            h_.on_key( {start, size}, total, ec_ ):
1091
0
            h_.on_string( {start, size}, total, ec_ );
1092
1093
0
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
0
    }
1098
1099
0
    ++cs;
1100
0
    return cs.begin();
1101
1102
7
do_str8:
1103
7
    uint8_t needed = seq_.needed();
1104
7
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105
7
        return maybe_suspend(cs.end(), state::str8, total);
1106
0
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107
0
    {
1108
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109
0
        return fail(cs.begin(), error::syntax, &loc);
1110
0
    }
1111
0
    {
1112
0
        std::size_t const n = seq_.length();
1113
0
        bool r;
1114
0
        if(is_key)
1115
0
        {
1116
0
            BOOST_ASSERT(total <= Handler::max_key_size);
1117
0
            if(BOOST_JSON_UNLIKELY(n >
1118
0
                Handler::max_key_size - total))
1119
0
            {
1120
0
                BOOST_STATIC_CONSTEXPR source_location loc
1121
0
                    = BOOST_CURRENT_LOCATION;
1122
0
                return fail(cs.begin(), error::key_too_large, &loc);
1123
0
            }
1124
0
            total += n;
1125
0
            r = h_.on_key_part( {seq_.data(), n}, total, ec_ );
1126
0
        }
1127
0
        else
1128
0
        {
1129
0
            BOOST_ASSERT(total <= Handler::max_string_size);
1130
0
            if(BOOST_JSON_UNLIKELY(n >
1131
0
                Handler::max_string_size - total))
1132
0
            {
1133
0
                BOOST_STATIC_CONSTEXPR source_location loc
1134
0
                    = BOOST_CURRENT_LOCATION;
1135
0
                return fail(cs.begin(), error::string_too_large, &loc);
1136
0
            }
1137
0
            total += n;
1138
0
            r = h_.on_string_part( {seq_.data(), n}, total, ec_ );
1139
0
        }
1140
0
        if(BOOST_JSON_UNLIKELY( !r ))
1141
0
            return fail( cs.begin() );
1142
0
    }
1143
0
    cs += needed;
1144
0
    goto do_str1;
1145
0
}
1146
1147
template<class Handler>
1148
template<bool StackEmpty_>
1149
const char*
1150
basic_parser<Handler>::
1151
parse_escaped(
1152
    const char* p,
1153
    std::size_t& total,
1154
    std::integral_constant<bool, StackEmpty_> stack_empty,
1155
    bool is_key,
1156
    bool allow_bad_utf16)
1157
112k
{
1158
112k
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1159
112k
    auto const ev_too_large = is_key?
1160
58.6k
        error::key_too_large : error::string_too_large;
1161
112k
    auto const max_size = is_key?
1162
58.6k
        Handler::max_key_size : Handler::max_string_size;
1163
112k
    int digit;
1164
1165
    //---------------------------------------------------------------
1166
    //
1167
    // To handle escapes, a local temporary buffer accumulates
1168
    // the unescaped result. The algorithm attempts to fill the
1169
    // buffer to capacity before invoking the handler.
1170
    // In some cases the temporary buffer needs to be flushed
1171
    // before it is full:
1172
    // * When the closing double quote is seen
1173
    // * When there in no more input (and more is expected later)
1174
    // A goal of the algorithm is to call the handler as few times
1175
    // as possible. Thus, when the first escape is encountered,
1176
    // the algorithm attempts to fill the temporary buffer first.
1177
    //
1178
112k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1179
1180
    // Unescaped JSON is never larger than its escaped version.
1181
    // To efficiently process only what will fit in the temporary buffer,
1182
    // the size of the input stream is temporarily "clipped" to the size
1183
    // of the temporary buffer.
1184
    // handle escaped character
1185
112k
    detail::clipped_const_stream cs(p, end_);
1186
112k
    cs.clip(temp.max_size());
1187
1188
112k
    if(! stack_empty && ! st_.empty())
1189
180
    {
1190
180
        state st;
1191
180
        st_.pop(st);
1192
180
        switch(st)
1193
180
        {
1194
0
        default: BOOST_JSON_UNREACHABLE();
1195
89
        case state::str3: goto do_str3;
1196
15
        case state::str4: goto do_str4;
1197
15
        case state::str5: goto do_str5;
1198
12
        case state::str6: goto do_str6;
1199
15
        case state::str7: goto do_str7;
1200
9
        case state::sur1: goto do_sur1;
1201
1
        case state::sur2: goto do_sur2;
1202
1
        case state::sur3: goto do_sur3;
1203
7
        case state::sur4: goto do_sur4;
1204
7
        case state::sur5: goto do_sur5;
1205
9
        case state::sur6: goto do_sur6;
1206
180
        }
1207
180
    }
1208
1209
9.89M
    while(true)
1210
9.89M
    {
1211
9.89M
        BOOST_ASSERT( temp.capacity() );
1212
9.89M
        BOOST_ASSERT(*cs == '\\');
1213
9.89M
        ++cs;
1214
9.89M
do_str3:
1215
9.89M
        if(BOOST_JSON_UNLIKELY(! cs))
1216
1.64k
        {
1217
1.64k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1218
1.43k
            {
1219
1.43k
                BOOST_ASSERT(total <= max_size);
1220
1.43k
                if(BOOST_JSON_UNLIKELY(
1221
1.43k
                    temp.size() > max_size - total))
1222
0
                {
1223
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1224
0
                        = BOOST_CURRENT_LOCATION;
1225
0
                    return fail(cs.begin(), ev_too_large, &loc);
1226
0
                }
1227
1.43k
                total += temp.size();
1228
1.43k
                {
1229
1.43k
                    bool r = is_key
1230
1.43k
                        ? h_.on_key_part(temp.get(), total, ec_)
1231
1.43k
                        : h_.on_string_part(temp.get(), total, ec_);
1232
1233
1.43k
                    if(BOOST_JSON_UNLIKELY(!r))
1234
0
                    {
1235
0
                        return fail(cs.begin());
1236
0
                    }
1237
1.43k
                }
1238
1.43k
                temp.clear();
1239
1.43k
            }
1240
1.64k
            cs.clip(temp.max_size());
1241
1.64k
            if(BOOST_JSON_UNLIKELY(! cs))
1242
287
                return maybe_suspend(cs.begin(), state::str3);
1243
1.64k
        }
1244
9.89M
        switch(*cs)
1245
9.89M
        {
1246
105
        default:
1247
105
            {
1248
105
                BOOST_STATIC_CONSTEXPR source_location loc
1249
105
                    = BOOST_CURRENT_LOCATION;
1250
105
                return fail(cs.begin(), error::syntax, &loc);
1251
0
            }
1252
18.1k
        case '\x22': // '"'
1253
18.1k
            temp.push_back('\x22');
1254
18.1k
            ++cs;
1255
18.1k
            break;
1256
9.51M
        case '\\':
1257
9.51M
            temp.push_back('\\');
1258
9.51M
            ++cs;
1259
9.51M
            break;
1260
1.63k
        case '/':
1261
1.63k
            temp.push_back('/');
1262
1.63k
            ++cs;
1263
1.63k
            break;
1264
18.4k
        case 'b':
1265
18.4k
            temp.push_back('\x08');
1266
18.4k
            ++cs;
1267
18.4k
            break;
1268
7.09k
        case 'f':
1269
7.09k
            temp.push_back('\x0c');
1270
7.09k
            ++cs;
1271
7.09k
            break;
1272
22.7k
        case 'n':
1273
22.7k
            temp.push_back('\x0a');
1274
22.7k
            ++cs;
1275
22.7k
            break;
1276
19.2k
        case 'r':
1277
19.2k
            temp.push_back('\x0d');
1278
19.2k
            ++cs;
1279
19.2k
            break;
1280
3.71k
        case 't':
1281
3.71k
            temp.push_back('\x09');
1282
3.71k
            ++cs;
1283
3.71k
            break;
1284
292k
        case 'u':
1285
            // utf16 escape
1286
            //
1287
            // fast path only when the buffer
1288
            // is large enough for 2 surrogates
1289
292k
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1290
288k
            {
1291
                // KRYSTIAN TODO: this could be done
1292
                // with fewer instructions
1293
288k
                digit = detail::load_little_endian<4>(
1294
288k
                    cs.begin() + 1);
1295
288k
                int d4 = detail::hex_digit(static_cast<
1296
288k
                    unsigned char>(digit >> 24));
1297
288k
                int d3 = detail::hex_digit(static_cast<
1298
288k
                    unsigned char>(digit >> 16));
1299
288k
                int d2 = detail::hex_digit(static_cast<
1300
288k
                    unsigned char>(digit >> 8));
1301
288k
                int d1 = detail::hex_digit(static_cast<
1302
288k
                    unsigned char>(digit));
1303
288k
                if(BOOST_JSON_UNLIKELY(
1304
288k
                    (d1 | d2 | d3 | d4) == -1))
1305
218
                {
1306
218
                    if(d1 != -1)
1307
79
                        ++cs;
1308
218
                    if(d2 != -1)
1309
51
                        ++cs;
1310
218
                    if(d3 != -1)
1311
30
                        ++cs;
1312
218
                    BOOST_STATIC_CONSTEXPR source_location loc
1313
218
                        = BOOST_CURRENT_LOCATION;
1314
218
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1315
218
                }
1316
                // 32 bit unicode scalar value
1317
288k
                unsigned u1 =
1318
288k
                    (d1 << 12) + (d2 << 8) +
1319
288k
                    (d3 << 4) + d4;
1320
                // valid unicode scalar values are
1321
                // [0, D7FF] and [E000, 10FFFF]
1322
                // values within this range are valid utf-8
1323
                // code points and invalid leading surrogates.
1324
288k
                if(BOOST_JSON_LIKELY(
1325
288k
                    u1 < 0xd800 || u1 > 0xdfff))
1326
242k
                {
1327
242k
                    cs += 5;
1328
242k
                    temp.append_utf8(u1);
1329
242k
                    break;
1330
242k
                }
1331
46.4k
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1332
24
                {
1333
                    // If it's an illegal leading surrogate and
1334
                    // the parser does not allow it, return an error.
1335
24
                    if(!allow_bad_utf16)
1336
24
                    {
1337
24
                        BOOST_STATIC_CONSTEXPR source_location loc
1338
24
                            = BOOST_CURRENT_LOCATION;
1339
24
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1340
24
                            &loc);
1341
24
                    }
1342
                    // Otherwise, append the Unicode replacement character
1343
0
                    else
1344
0
                    {
1345
0
                        cs += 5;
1346
0
                        temp.append_utf8(urc);
1347
0
                        break;
1348
0
                    }
1349
24
                }
1350
46.4k
                cs += 5;
1351
                // KRYSTIAN TODO: this can be a two byte load
1352
                // and a single comparison. We lose error information,
1353
                // but it's faster.
1354
46.4k
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1355
26
                {
1356
                    // If the next character is not a backslash and
1357
                    // the parser does not allow it, return a syntax error.
1358
26
                    if(!allow_bad_utf16)
1359
26
                    {
1360
26
                        BOOST_STATIC_CONSTEXPR source_location loc
1361
26
                            = BOOST_CURRENT_LOCATION;
1362
26
                        return fail(cs.begin(), error::syntax, &loc);
1363
26
                    }
1364
                    // Otherwise, append the Unicode replacement character since
1365
                    // the first code point is a valid leading surrogate
1366
0
                    else
1367
0
                    {
1368
0
                        temp.append_utf8(urc);
1369
0
                        break;
1370
0
                    }
1371
26
                }
1372
46.3k
                ++cs;
1373
46.3k
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1374
23
                {
1375
23
                    if (!allow_bad_utf16)
1376
23
                    {
1377
23
                        BOOST_STATIC_CONSTEXPR source_location loc
1378
23
                            = BOOST_CURRENT_LOCATION;
1379
23
                        return fail(cs.begin(), error::syntax, &loc);
1380
23
                    }
1381
                    // Otherwise, append the Unicode replacement character since
1382
                    // the first code point is a valid leading surrogate
1383
0
                    else
1384
0
                    {
1385
0
                        temp.append_utf8(urc);
1386
0
                        goto do_str3;
1387
0
                    }
1388
23
                }
1389
46.3k
                ++cs;
1390
46.3k
                digit = detail::load_little_endian<4>(cs.begin());
1391
46.3k
                d4 = detail::hex_digit(static_cast<
1392
46.3k
                    unsigned char>(digit >> 24));
1393
46.3k
                d3 = detail::hex_digit(static_cast<
1394
46.3k
                    unsigned char>(digit >> 16));
1395
46.3k
                d2 = detail::hex_digit(static_cast<
1396
46.3k
                    unsigned char>(digit >> 8));
1397
46.3k
                d1 = detail::hex_digit(static_cast<
1398
46.3k
                    unsigned char>(digit));
1399
46.3k
                if(BOOST_JSON_UNLIKELY(
1400
46.3k
                    (d1 | d2 | d3 | d4) == -1))
1401
215
                {
1402
215
                    if(d1 != -1)
1403
76
                        ++cs;
1404
215
                    if(d2 != -1)
1405
36
                        ++cs;
1406
215
                    if(d3 != -1)
1407
40
                        ++cs;
1408
215
                    BOOST_STATIC_CONSTEXPR source_location loc
1409
215
                        = BOOST_CURRENT_LOCATION;
1410
215
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1411
215
                }
1412
46.1k
                unsigned u2 =
1413
46.1k
                    (d1 << 12) + (d2 << 8) +
1414
46.1k
                    (d3 << 4) + d4;
1415
                // Check if the second code point is a valid trailing surrogate.
1416
                // Valid trailing surrogates are [DC00, DFFF]
1417
46.1k
                if(BOOST_JSON_UNLIKELY(
1418
46.1k
                    u2 < 0xdc00 || u2 > 0xdfff))
1419
58
                {
1420
                    // If not valid and the parser does not allow it, return an error.
1421
58
                    if(!allow_bad_utf16)
1422
58
                    {
1423
58
                        BOOST_STATIC_CONSTEXPR source_location loc
1424
58
                            = BOOST_CURRENT_LOCATION;
1425
58
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1426
58
                            &loc);
1427
58
                    }
1428
                    // Append the replacement character for the
1429
                    // first leading surrogate.
1430
0
                    cs += 4;
1431
0
                    temp.append_utf8(urc);
1432
                    // Check if the second code point is a
1433
                    // valid unicode scalar value (invalid leading
1434
                    // or trailing surrogate)
1435
0
                    if (u2 < 0xd800 || u2 > 0xdbff)
1436
0
                    {
1437
0
                        temp.append_utf8(u2);
1438
0
                        break;
1439
0
                    }
1440
                    // If it is a valid leading surrogate
1441
0
                    else
1442
0
                    {
1443
0
                        u1_ = u2;
1444
0
                        goto do_sur1;
1445
0
                    }
1446
0
                }
1447
46.0k
                cs += 4;
1448
                // Calculate the Unicode code point from the surrogate pair and
1449
                // append the UTF-8 representation.
1450
46.0k
                unsigned cp =
1451
46.0k
                    ((u1 - 0xd800) << 10) +
1452
46.0k
                    ((u2 - 0xdc00)) +
1453
46.0k
                        0x10000;
1454
                // utf-16 surrogate pair
1455
46.0k
                temp.append_utf8(cp);
1456
46.0k
                break;
1457
46.1k
            }
1458
            // flush
1459
3.29k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1460
2.66k
            {
1461
2.66k
                BOOST_ASSERT(total <= max_size);
1462
2.66k
                if(BOOST_JSON_UNLIKELY(
1463
2.66k
                    temp.size() > max_size - total))
1464
0
                {
1465
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1466
0
                        = BOOST_CURRENT_LOCATION;
1467
0
                    return fail(cs.begin(), ev_too_large, &loc);
1468
0
                }
1469
2.66k
                total += temp.size();
1470
2.66k
                {
1471
2.66k
                    bool r = is_key
1472
2.66k
                        ? h_.on_key_part(temp.get(), total, ec_)
1473
2.66k
                        : h_.on_string_part(temp.get(), total, ec_);
1474
1475
2.66k
                    if(BOOST_JSON_UNLIKELY(!r))
1476
0
                    {
1477
0
                        return fail(cs.begin());
1478
0
                    }
1479
2.66k
                }
1480
2.66k
                temp.clear();
1481
2.66k
                cs.clip(temp.max_size());
1482
2.66k
            }
1483
3.29k
            ++cs;
1484
            // utf-16 escape
1485
3.30k
    do_str4:
1486
3.30k
            if(BOOST_JSON_UNLIKELY(! cs))
1487
54
                return maybe_suspend(cs.begin(), state::str4);
1488
3.25k
            digit = detail::hex_digit(*cs);
1489
3.25k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1490
58
            {
1491
58
                BOOST_STATIC_CONSTEXPR source_location loc
1492
58
                    = BOOST_CURRENT_LOCATION;
1493
58
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1494
58
            }
1495
3.19k
            ++cs;
1496
3.19k
            u1_ = digit << 12;
1497
3.20k
    do_str5:
1498
3.20k
            if(BOOST_JSON_UNLIKELY(! cs))
1499
51
                return maybe_suspend(cs.begin(), state::str5);
1500
3.15k
            digit = detail::hex_digit(*cs);
1501
3.15k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1502
44
            {
1503
44
                BOOST_STATIC_CONSTEXPR source_location loc
1504
44
                    = BOOST_CURRENT_LOCATION;
1505
44
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1506
44
            }
1507
3.11k
            ++cs;
1508
3.11k
            u1_ += digit << 8;
1509
3.12k
    do_str6:
1510
3.12k
            if(BOOST_JSON_UNLIKELY(! cs))
1511
39
                return maybe_suspend(cs.begin(), state::str6);
1512
3.08k
            digit = detail::hex_digit(*cs);
1513
3.08k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1514
35
            {
1515
35
                BOOST_STATIC_CONSTEXPR source_location loc
1516
35
                    = BOOST_CURRENT_LOCATION;
1517
35
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1518
35
            }
1519
3.05k
            ++cs;
1520
3.05k
            u1_ += digit << 4;
1521
3.06k
    do_str7:
1522
3.06k
            if(BOOST_JSON_UNLIKELY(! cs))
1523
43
                return maybe_suspend(cs.begin(), state::str7);
1524
3.02k
            digit = detail::hex_digit(*cs);
1525
3.02k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1526
36
            {
1527
36
                BOOST_STATIC_CONSTEXPR source_location loc
1528
36
                    = BOOST_CURRENT_LOCATION;
1529
36
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1530
36
            }
1531
2.98k
            ++cs;
1532
2.98k
            u1_ += digit;
1533
2.98k
            if(BOOST_JSON_LIKELY(
1534
2.98k
                u1_ < 0xd800 || u1_ > 0xdfff))
1535
1.77k
            {
1536
1.77k
                BOOST_ASSERT(temp.empty());
1537
                // utf-8 codepoint
1538
1.77k
                temp.append_utf8(u1_);
1539
1.77k
                break;
1540
1.77k
            }
1541
1.20k
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1542
32
            {
1543
                // If it's an illegal leading surrogate and
1544
                // the parser does not allow it, return an error.
1545
32
                if(!allow_bad_utf16)
1546
32
                {
1547
32
                    BOOST_STATIC_CONSTEXPR source_location loc
1548
32
                        = BOOST_CURRENT_LOCATION;
1549
32
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1550
32
                }
1551
                // Otherwise, append the Unicode replacement character
1552
0
                else
1553
0
                {
1554
0
                    BOOST_ASSERT(temp.empty());
1555
0
                    temp.append_utf8(urc);
1556
0
                    break;
1557
0
                }
1558
32
            }
1559
1.18k
    do_sur1:
1560
1.18k
            if(BOOST_JSON_UNLIKELY(! cs))
1561
31
                return maybe_suspend(cs.begin(), state::sur1);
1562
1.15k
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1563
22
            {
1564
                // If the next character is not a backslash and
1565
                // the parser does not allow it, return a syntax error.
1566
22
                if(!allow_bad_utf16)
1567
22
                {
1568
22
                    BOOST_STATIC_CONSTEXPR source_location loc
1569
22
                        = BOOST_CURRENT_LOCATION;
1570
22
                    return fail(cs.begin(), error::syntax, &loc);
1571
22
                }
1572
                // Otherwise, append the Unicode replacement character since
1573
                // the first code point is a valid leading surrogate
1574
0
                else
1575
0
                {
1576
0
                    temp.append_utf8(urc);
1577
0
                    break;
1578
0
                }
1579
22
            }
1580
1.13k
            ++cs;
1581
1.13k
    do_sur2:
1582
1.13k
            if(BOOST_JSON_UNLIKELY(! cs))
1583
3
                return maybe_suspend(cs.begin(), state::sur2);
1584
1.13k
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1585
24
            {
1586
24
                if (!allow_bad_utf16)
1587
24
                {
1588
24
                    BOOST_STATIC_CONSTEXPR source_location loc
1589
24
                        = BOOST_CURRENT_LOCATION;
1590
24
                    return fail(cs.begin(), error::syntax, &loc);
1591
24
                }
1592
                // Otherwise, append the Unicode replacement character since
1593
                // the first code point is a valid leading surrogate
1594
0
                else
1595
0
                {
1596
0
                    temp.append_utf8(urc);
1597
0
                    goto do_str3;
1598
0
                }
1599
24
            }
1600
1.10k
            ++cs;
1601
1.10k
    do_sur3:
1602
1.10k
            if(BOOST_JSON_UNLIKELY(! cs))
1603
4
                return maybe_suspend(cs.begin(), state::sur3);
1604
1.10k
            digit = detail::hex_digit(*cs);
1605
1.10k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1606
29
            {
1607
29
                BOOST_STATIC_CONSTEXPR source_location loc
1608
29
                    = BOOST_CURRENT_LOCATION;
1609
29
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1610
29
            }
1611
1.07k
            ++cs;
1612
1.07k
            u2_ = digit << 12;
1613
1.08k
    do_sur4:
1614
1.08k
            if(BOOST_JSON_UNLIKELY(! cs))
1615
22
                return maybe_suspend(cs.begin(), state::sur4);
1616
1.06k
            digit = detail::hex_digit(*cs);
1617
1.06k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1618
28
            {
1619
28
                BOOST_STATIC_CONSTEXPR source_location loc
1620
28
                    = BOOST_CURRENT_LOCATION;
1621
28
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1622
28
            }
1623
1.03k
            ++cs;
1624
1.03k
            u2_ += digit << 8;
1625
1.03k
    do_sur5:
1626
1.03k
            if(BOOST_JSON_UNLIKELY(! cs))
1627
23
                return maybe_suspend(cs.begin(), state::sur5);
1628
1.01k
            digit = detail::hex_digit(*cs);
1629
1.01k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1630
33
            {
1631
33
                BOOST_STATIC_CONSTEXPR source_location loc
1632
33
                    = BOOST_CURRENT_LOCATION;
1633
33
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1634
33
            }
1635
983
            ++cs;
1636
983
            u2_ += digit << 4;
1637
992
    do_sur6:
1638
992
            if(BOOST_JSON_UNLIKELY(! cs))
1639
35
                return maybe_suspend(cs.begin(), state::sur6);
1640
957
            digit = detail::hex_digit(*cs);
1641
957
            if(BOOST_JSON_UNLIKELY(digit == -1))
1642
18
            {
1643
18
                BOOST_STATIC_CONSTEXPR source_location loc
1644
18
                    = BOOST_CURRENT_LOCATION;
1645
18
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1646
18
            }
1647
939
            ++cs;
1648
939
            u2_ += digit;
1649
            // Check if the second code point is a valid trailing surrogate.
1650
            // Valid trailing surrogates are [DC00, DFFF]
1651
939
            if(BOOST_JSON_UNLIKELY(
1652
939
                u2_ < 0xdc00 || u2_ > 0xdfff))
1653
38
            {
1654
                // If not valid and the parser does not allow it, return an error.
1655
38
                if(!allow_bad_utf16)
1656
38
                {
1657
38
                    BOOST_STATIC_CONSTEXPR source_location loc
1658
38
                        = BOOST_CURRENT_LOCATION;
1659
38
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1660
38
                }
1661
                // Append the replacement character for the
1662
                // first leading surrogate.
1663
0
                temp.append_utf8(urc);
1664
                // Check if the second code point is a
1665
                // valid unicode scalar value (invalid leading
1666
                // or trailing surrogate)
1667
0
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1668
0
                {
1669
0
                    temp.append_utf8(u2_);
1670
0
                    break;
1671
0
                }
1672
                // If it is a valid leading surrogate
1673
0
                else
1674
0
                {
1675
0
                    u1_ = u2_;
1676
0
                    goto do_sur1;
1677
0
                }
1678
0
            }
1679
            // Calculate the Unicode code point from the surrogate pair and
1680
            // append the UTF-8 representation.
1681
901
            unsigned cp =
1682
901
                ((u1_ - 0xd800) << 10) +
1683
901
                ((u2_ - 0xdc00)) +
1684
901
                    0x10000;
1685
            // utf-16 surrogate pair
1686
901
            temp.append_utf8(cp);
1687
9.89M
        }
1688
1689
        // flush
1690
9.89M
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1691
110k
            break;
1692
9.89M
    }
1693
1694
110k
    if(BOOST_JSON_LIKELY( temp.size() ))
1695
110k
    {
1696
110k
        BOOST_ASSERT(total <= max_size);
1697
110k
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1698
0
        {
1699
0
            BOOST_STATIC_CONSTEXPR source_location loc
1700
0
                = BOOST_CURRENT_LOCATION;
1701
0
            return fail(cs.begin(), ev_too_large, &loc);
1702
0
        }
1703
1704
110k
        total += temp.size();
1705
110k
        bool const r = is_key
1706
110k
            ? h_.on_key_part(temp.get(), total, ec_)
1707
110k
            : h_.on_string_part(temp.get(), total, ec_);
1708
110k
        if(BOOST_JSON_UNLIKELY( !r ))
1709
0
            return fail( cs.begin() );
1710
110k
    }
1711
1712
110k
    return cs.begin();
1713
110k
}
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
1157
112k
{
1158
112k
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1159
112k
    auto const ev_too_large = is_key?
1160
58.4k
        error::key_too_large : error::string_too_large;
1161
112k
    auto const max_size = is_key?
1162
58.4k
        Handler::max_key_size : Handler::max_string_size;
1163
112k
    int digit;
1164
1165
    //---------------------------------------------------------------
1166
    //
1167
    // To handle escapes, a local temporary buffer accumulates
1168
    // the unescaped result. The algorithm attempts to fill the
1169
    // buffer to capacity before invoking the handler.
1170
    // In some cases the temporary buffer needs to be flushed
1171
    // before it is full:
1172
    // * When the closing double quote is seen
1173
    // * When there in no more input (and more is expected later)
1174
    // A goal of the algorithm is to call the handler as few times
1175
    // as possible. Thus, when the first escape is encountered,
1176
    // the algorithm attempts to fill the temporary buffer first.
1177
    //
1178
112k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1179
1180
    // Unescaped JSON is never larger than its escaped version.
1181
    // To efficiently process only what will fit in the temporary buffer,
1182
    // the size of the input stream is temporarily "clipped" to the size
1183
    // of the temporary buffer.
1184
    // handle escaped character
1185
112k
    detail::clipped_const_stream cs(p, end_);
1186
112k
    cs.clip(temp.max_size());
1187
1188
112k
    if(! stack_empty && ! st_.empty())
1189
0
    {
1190
0
        state st;
1191
0
        st_.pop(st);
1192
0
        switch(st)
1193
0
        {
1194
0
        default: BOOST_JSON_UNREACHABLE();
1195
0
        case state::str3: goto do_str3;
1196
0
        case state::str4: goto do_str4;
1197
0
        case state::str5: goto do_str5;
1198
0
        case state::str6: goto do_str6;
1199
0
        case state::str7: goto do_str7;
1200
0
        case state::sur1: goto do_sur1;
1201
0
        case state::sur2: goto do_sur2;
1202
0
        case state::sur3: goto do_sur3;
1203
0
        case state::sur4: goto do_sur4;
1204
0
        case state::sur5: goto do_sur5;
1205
0
        case state::sur6: goto do_sur6;
1206
0
        }
1207
0
    }
1208
1209
9.89M
    while(true)
1210
9.89M
    {
1211
9.89M
        BOOST_ASSERT( temp.capacity() );
1212
9.89M
        BOOST_ASSERT(*cs == '\\');
1213
9.89M
        ++cs;
1214
9.89M
do_str3:
1215
9.89M
        if(BOOST_JSON_UNLIKELY(! cs))
1216
1.55k
        {
1217
1.55k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1218
1.43k
            {
1219
1.43k
                BOOST_ASSERT(total <= max_size);
1220
1.43k
                if(BOOST_JSON_UNLIKELY(
1221
1.43k
                    temp.size() > max_size - total))
1222
0
                {
1223
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1224
0
                        = BOOST_CURRENT_LOCATION;
1225
0
                    return fail(cs.begin(), ev_too_large, &loc);
1226
0
                }
1227
1.43k
                total += temp.size();
1228
1.43k
                {
1229
1.43k
                    bool r = is_key
1230
1.43k
                        ? h_.on_key_part(temp.get(), total, ec_)
1231
1.43k
                        : h_.on_string_part(temp.get(), total, ec_);
1232
1233
1.43k
                    if(BOOST_JSON_UNLIKELY(!r))
1234
0
                    {
1235
0
                        return fail(cs.begin());
1236
0
                    }
1237
1.43k
                }
1238
1.43k
                temp.clear();
1239
1.43k
            }
1240
1.55k
            cs.clip(temp.max_size());
1241
1.55k
            if(BOOST_JSON_UNLIKELY(! cs))
1242
198
                return maybe_suspend(cs.begin(), state::str3);
1243
1.55k
        }
1244
9.89M
        switch(*cs)
1245
9.89M
        {
1246
105
        default:
1247
105
            {
1248
105
                BOOST_STATIC_CONSTEXPR source_location loc
1249
105
                    = BOOST_CURRENT_LOCATION;
1250
105
                return fail(cs.begin(), error::syntax, &loc);
1251
0
            }
1252
18.1k
        case '\x22': // '"'
1253
18.1k
            temp.push_back('\x22');
1254
18.1k
            ++cs;
1255
18.1k
            break;
1256
9.51M
        case '\\':
1257
9.51M
            temp.push_back('\\');
1258
9.51M
            ++cs;
1259
9.51M
            break;
1260
1.63k
        case '/':
1261
1.63k
            temp.push_back('/');
1262
1.63k
            ++cs;
1263
1.63k
            break;
1264
18.4k
        case 'b':
1265
18.4k
            temp.push_back('\x08');
1266
18.4k
            ++cs;
1267
18.4k
            break;
1268
7.09k
        case 'f':
1269
7.09k
            temp.push_back('\x0c');
1270
7.09k
            ++cs;
1271
7.09k
            break;
1272
22.7k
        case 'n':
1273
22.7k
            temp.push_back('\x0a');
1274
22.7k
            ++cs;
1275
22.7k
            break;
1276
19.2k
        case 'r':
1277
19.2k
            temp.push_back('\x0d');
1278
19.2k
            ++cs;
1279
19.2k
            break;
1280
3.71k
        case 't':
1281
3.71k
            temp.push_back('\x09');
1282
3.71k
            ++cs;
1283
3.71k
            break;
1284
292k
        case 'u':
1285
            // utf16 escape
1286
            //
1287
            // fast path only when the buffer
1288
            // is large enough for 2 surrogates
1289
292k
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1290
288k
            {
1291
                // KRYSTIAN TODO: this could be done
1292
                // with fewer instructions
1293
288k
                digit = detail::load_little_endian<4>(
1294
288k
                    cs.begin() + 1);
1295
288k
                int d4 = detail::hex_digit(static_cast<
1296
288k
                    unsigned char>(digit >> 24));
1297
288k
                int d3 = detail::hex_digit(static_cast<
1298
288k
                    unsigned char>(digit >> 16));
1299
288k
                int d2 = detail::hex_digit(static_cast<
1300
288k
                    unsigned char>(digit >> 8));
1301
288k
                int d1 = detail::hex_digit(static_cast<
1302
288k
                    unsigned char>(digit));
1303
288k
                if(BOOST_JSON_UNLIKELY(
1304
288k
                    (d1 | d2 | d3 | d4) == -1))
1305
218
                {
1306
218
                    if(d1 != -1)
1307
79
                        ++cs;
1308
218
                    if(d2 != -1)
1309
51
                        ++cs;
1310
218
                    if(d3 != -1)
1311
30
                        ++cs;
1312
218
                    BOOST_STATIC_CONSTEXPR source_location loc
1313
218
                        = BOOST_CURRENT_LOCATION;
1314
218
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1315
218
                }
1316
                // 32 bit unicode scalar value
1317
288k
                unsigned u1 =
1318
288k
                    (d1 << 12) + (d2 << 8) +
1319
288k
                    (d3 << 4) + d4;
1320
                // valid unicode scalar values are
1321
                // [0, D7FF] and [E000, 10FFFF]
1322
                // values within this range are valid utf-8
1323
                // code points and invalid leading surrogates.
1324
288k
                if(BOOST_JSON_LIKELY(
1325
288k
                    u1 < 0xd800 || u1 > 0xdfff))
1326
242k
                {
1327
242k
                    cs += 5;
1328
242k
                    temp.append_utf8(u1);
1329
242k
                    break;
1330
242k
                }
1331
46.4k
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1332
24
                {
1333
                    // If it's an illegal leading surrogate and
1334
                    // the parser does not allow it, return an error.
1335
24
                    if(!allow_bad_utf16)
1336
24
                    {
1337
24
                        BOOST_STATIC_CONSTEXPR source_location loc
1338
24
                            = BOOST_CURRENT_LOCATION;
1339
24
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1340
24
                            &loc);
1341
24
                    }
1342
                    // Otherwise, append the Unicode replacement character
1343
0
                    else
1344
0
                    {
1345
0
                        cs += 5;
1346
0
                        temp.append_utf8(urc);
1347
0
                        break;
1348
0
                    }
1349
24
                }
1350
46.4k
                cs += 5;
1351
                // KRYSTIAN TODO: this can be a two byte load
1352
                // and a single comparison. We lose error information,
1353
                // but it's faster.
1354
46.4k
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1355
26
                {
1356
                    // If the next character is not a backslash and
1357
                    // the parser does not allow it, return a syntax error.
1358
26
                    if(!allow_bad_utf16)
1359
26
                    {
1360
26
                        BOOST_STATIC_CONSTEXPR source_location loc
1361
26
                            = BOOST_CURRENT_LOCATION;
1362
26
                        return fail(cs.begin(), error::syntax, &loc);
1363
26
                    }
1364
                    // Otherwise, append the Unicode replacement character since
1365
                    // the first code point is a valid leading surrogate
1366
0
                    else
1367
0
                    {
1368
0
                        temp.append_utf8(urc);
1369
0
                        break;
1370
0
                    }
1371
26
                }
1372
46.3k
                ++cs;
1373
46.3k
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1374
23
                {
1375
23
                    if (!allow_bad_utf16)
1376
23
                    {
1377
23
                        BOOST_STATIC_CONSTEXPR source_location loc
1378
23
                            = BOOST_CURRENT_LOCATION;
1379
23
                        return fail(cs.begin(), error::syntax, &loc);
1380
23
                    }
1381
                    // Otherwise, append the Unicode replacement character since
1382
                    // the first code point is a valid leading surrogate
1383
0
                    else
1384
0
                    {
1385
0
                        temp.append_utf8(urc);
1386
0
                        goto do_str3;
1387
0
                    }
1388
23
                }
1389
46.3k
                ++cs;
1390
46.3k
                digit = detail::load_little_endian<4>(cs.begin());
1391
46.3k
                d4 = detail::hex_digit(static_cast<
1392
46.3k
                    unsigned char>(digit >> 24));
1393
46.3k
                d3 = detail::hex_digit(static_cast<
1394
46.3k
                    unsigned char>(digit >> 16));
1395
46.3k
                d2 = detail::hex_digit(static_cast<
1396
46.3k
                    unsigned char>(digit >> 8));
1397
46.3k
                d1 = detail::hex_digit(static_cast<
1398
46.3k
                    unsigned char>(digit));
1399
46.3k
                if(BOOST_JSON_UNLIKELY(
1400
46.3k
                    (d1 | d2 | d3 | d4) == -1))
1401
215
                {
1402
215
                    if(d1 != -1)
1403
76
                        ++cs;
1404
215
                    if(d2 != -1)
1405
36
                        ++cs;
1406
215
                    if(d3 != -1)
1407
40
                        ++cs;
1408
215
                    BOOST_STATIC_CONSTEXPR source_location loc
1409
215
                        = BOOST_CURRENT_LOCATION;
1410
215
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1411
215
                }
1412
46.1k
                unsigned u2 =
1413
46.1k
                    (d1 << 12) + (d2 << 8) +
1414
46.1k
                    (d3 << 4) + d4;
1415
                // Check if the second code point is a valid trailing surrogate.
1416
                // Valid trailing surrogates are [DC00, DFFF]
1417
46.1k
                if(BOOST_JSON_UNLIKELY(
1418
46.1k
                    u2 < 0xdc00 || u2 > 0xdfff))
1419
58
                {
1420
                    // If not valid and the parser does not allow it, return an error.
1421
58
                    if(!allow_bad_utf16)
1422
58
                    {
1423
58
                        BOOST_STATIC_CONSTEXPR source_location loc
1424
58
                            = BOOST_CURRENT_LOCATION;
1425
58
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1426
58
                            &loc);
1427
58
                    }
1428
                    // Append the replacement character for the
1429
                    // first leading surrogate.
1430
0
                    cs += 4;
1431
0
                    temp.append_utf8(urc);
1432
                    // Check if the second code point is a
1433
                    // valid unicode scalar value (invalid leading
1434
                    // or trailing surrogate)
1435
0
                    if (u2 < 0xd800 || u2 > 0xdbff)
1436
0
                    {
1437
0
                        temp.append_utf8(u2);
1438
0
                        break;
1439
0
                    }
1440
                    // If it is a valid leading surrogate
1441
0
                    else
1442
0
                    {
1443
0
                        u1_ = u2;
1444
0
                        goto do_sur1;
1445
0
                    }
1446
0
                }
1447
46.0k
                cs += 4;
1448
                // Calculate the Unicode code point from the surrogate pair and
1449
                // append the UTF-8 representation.
1450
46.0k
                unsigned cp =
1451
46.0k
                    ((u1 - 0xd800) << 10) +
1452
46.0k
                    ((u2 - 0xdc00)) +
1453
46.0k
                        0x10000;
1454
                // utf-16 surrogate pair
1455
46.0k
                temp.append_utf8(cp);
1456
46.0k
                break;
1457
46.1k
            }
1458
            // flush
1459
3.29k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1460
2.66k
            {
1461
2.66k
                BOOST_ASSERT(total <= max_size);
1462
2.66k
                if(BOOST_JSON_UNLIKELY(
1463
2.66k
                    temp.size() > max_size - total))
1464
0
                {
1465
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1466
0
                        = BOOST_CURRENT_LOCATION;
1467
0
                    return fail(cs.begin(), ev_too_large, &loc);
1468
0
                }
1469
2.66k
                total += temp.size();
1470
2.66k
                {
1471
2.66k
                    bool r = is_key
1472
2.66k
                        ? h_.on_key_part(temp.get(), total, ec_)
1473
2.66k
                        : h_.on_string_part(temp.get(), total, ec_);
1474
1475
2.66k
                    if(BOOST_JSON_UNLIKELY(!r))
1476
0
                    {
1477
0
                        return fail(cs.begin());
1478
0
                    }
1479
2.66k
                }
1480
2.66k
                temp.clear();
1481
2.66k
                cs.clip(temp.max_size());
1482
2.66k
            }
1483
3.29k
            ++cs;
1484
            // utf-16 escape
1485
3.29k
    do_str4:
1486
3.29k
            if(BOOST_JSON_UNLIKELY(! cs))
1487
39
                return maybe_suspend(cs.begin(), state::str4);
1488
3.25k
            digit = detail::hex_digit(*cs);
1489
3.25k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1490
58
            {
1491
58
                BOOST_STATIC_CONSTEXPR source_location loc
1492
58
                    = BOOST_CURRENT_LOCATION;
1493
58
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1494
58
            }
1495
3.19k
            ++cs;
1496
3.19k
            u1_ = digit << 12;
1497
3.19k
    do_str5:
1498
3.19k
            if(BOOST_JSON_UNLIKELY(! cs))
1499
36
                return maybe_suspend(cs.begin(), state::str5);
1500
3.15k
            digit = detail::hex_digit(*cs);
1501
3.15k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1502
44
            {
1503
44
                BOOST_STATIC_CONSTEXPR source_location loc
1504
44
                    = BOOST_CURRENT_LOCATION;
1505
44
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1506
44
            }
1507
3.11k
            ++cs;
1508
3.11k
            u1_ += digit << 8;
1509
3.11k
    do_str6:
1510
3.11k
            if(BOOST_JSON_UNLIKELY(! cs))
1511
27
                return maybe_suspend(cs.begin(), state::str6);
1512
3.08k
            digit = detail::hex_digit(*cs);
1513
3.08k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1514
35
            {
1515
35
                BOOST_STATIC_CONSTEXPR source_location loc
1516
35
                    = BOOST_CURRENT_LOCATION;
1517
35
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1518
35
            }
1519
3.05k
            ++cs;
1520
3.05k
            u1_ += digit << 4;
1521
3.05k
    do_str7:
1522
3.05k
            if(BOOST_JSON_UNLIKELY(! cs))
1523
28
                return maybe_suspend(cs.begin(), state::str7);
1524
3.02k
            digit = detail::hex_digit(*cs);
1525
3.02k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1526
36
            {
1527
36
                BOOST_STATIC_CONSTEXPR source_location loc
1528
36
                    = BOOST_CURRENT_LOCATION;
1529
36
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1530
36
            }
1531
2.98k
            ++cs;
1532
2.98k
            u1_ += digit;
1533
2.98k
            if(BOOST_JSON_LIKELY(
1534
2.98k
                u1_ < 0xd800 || u1_ > 0xdfff))
1535
1.77k
            {
1536
1.77k
                BOOST_ASSERT(temp.empty());
1537
                // utf-8 codepoint
1538
1.77k
                temp.append_utf8(u1_);
1539
1.77k
                break;
1540
1.77k
            }
1541
1.20k
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1542
32
            {
1543
                // If it's an illegal leading surrogate and
1544
                // the parser does not allow it, return an error.
1545
32
                if(!allow_bad_utf16)
1546
32
                {
1547
32
                    BOOST_STATIC_CONSTEXPR source_location loc
1548
32
                        = BOOST_CURRENT_LOCATION;
1549
32
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1550
32
                }
1551
                // Otherwise, append the Unicode replacement character
1552
0
                else
1553
0
                {
1554
0
                    BOOST_ASSERT(temp.empty());
1555
0
                    temp.append_utf8(urc);
1556
0
                    break;
1557
0
                }
1558
32
            }
1559
1.17k
    do_sur1:
1560
1.17k
            if(BOOST_JSON_UNLIKELY(! cs))
1561
22
                return maybe_suspend(cs.begin(), state::sur1);
1562
1.15k
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1563
22
            {
1564
                // If the next character is not a backslash and
1565
                // the parser does not allow it, return a syntax error.
1566
22
                if(!allow_bad_utf16)
1567
22
                {
1568
22
                    BOOST_STATIC_CONSTEXPR source_location loc
1569
22
                        = BOOST_CURRENT_LOCATION;
1570
22
                    return fail(cs.begin(), error::syntax, &loc);
1571
22
                }
1572
                // Otherwise, append the Unicode replacement character since
1573
                // the first code point is a valid leading surrogate
1574
0
                else
1575
0
                {
1576
0
                    temp.append_utf8(urc);
1577
0
                    break;
1578
0
                }
1579
22
            }
1580
1.13k
            ++cs;
1581
1.13k
    do_sur2:
1582
1.13k
            if(BOOST_JSON_UNLIKELY(! cs))
1583
2
                return maybe_suspend(cs.begin(), state::sur2);
1584
1.13k
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1585
24
            {
1586
24
                if (!allow_bad_utf16)
1587
24
                {
1588
24
                    BOOST_STATIC_CONSTEXPR source_location loc
1589
24
                        = BOOST_CURRENT_LOCATION;
1590
24
                    return fail(cs.begin(), error::syntax, &loc);
1591
24
                }
1592
                // Otherwise, append the Unicode replacement character since
1593
                // the first code point is a valid leading surrogate
1594
0
                else
1595
0
                {
1596
0
                    temp.append_utf8(urc);
1597
0
                    goto do_str3;
1598
0
                }
1599
24
            }
1600
1.10k
            ++cs;
1601
1.10k
    do_sur3:
1602
1.10k
            if(BOOST_JSON_UNLIKELY(! cs))
1603
3
                return maybe_suspend(cs.begin(), state::sur3);
1604
1.10k
            digit = detail::hex_digit(*cs);
1605
1.10k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1606
29
            {
1607
29
                BOOST_STATIC_CONSTEXPR source_location loc
1608
29
                    = BOOST_CURRENT_LOCATION;
1609
29
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1610
29
            }
1611
1.07k
            ++cs;
1612
1.07k
            u2_ = digit << 12;
1613
1.07k
    do_sur4:
1614
1.07k
            if(BOOST_JSON_UNLIKELY(! cs))
1615
15
                return maybe_suspend(cs.begin(), state::sur4);
1616
1.06k
            digit = detail::hex_digit(*cs);
1617
1.06k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1618
28
            {
1619
28
                BOOST_STATIC_CONSTEXPR source_location loc
1620
28
                    = BOOST_CURRENT_LOCATION;
1621
28
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1622
28
            }
1623
1.03k
            ++cs;
1624
1.03k
            u2_ += digit << 8;
1625
1.03k
    do_sur5:
1626
1.03k
            if(BOOST_JSON_UNLIKELY(! cs))
1627
16
                return maybe_suspend(cs.begin(), state::sur5);
1628
1.01k
            digit = detail::hex_digit(*cs);
1629
1.01k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1630
33
            {
1631
33
                BOOST_STATIC_CONSTEXPR source_location loc
1632
33
                    = BOOST_CURRENT_LOCATION;
1633
33
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1634
33
            }
1635
983
            ++cs;
1636
983
            u2_ += digit << 4;
1637
983
    do_sur6:
1638
983
            if(BOOST_JSON_UNLIKELY(! cs))
1639
26
                return maybe_suspend(cs.begin(), state::sur6);
1640
957
            digit = detail::hex_digit(*cs);
1641
957
            if(BOOST_JSON_UNLIKELY(digit == -1))
1642
18
            {
1643
18
                BOOST_STATIC_CONSTEXPR source_location loc
1644
18
                    = BOOST_CURRENT_LOCATION;
1645
18
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1646
18
            }
1647
939
            ++cs;
1648
939
            u2_ += digit;
1649
            // Check if the second code point is a valid trailing surrogate.
1650
            // Valid trailing surrogates are [DC00, DFFF]
1651
939
            if(BOOST_JSON_UNLIKELY(
1652
939
                u2_ < 0xdc00 || u2_ > 0xdfff))
1653
38
            {
1654
                // If not valid and the parser does not allow it, return an error.
1655
38
                if(!allow_bad_utf16)
1656
38
                {
1657
38
                    BOOST_STATIC_CONSTEXPR source_location loc
1658
38
                        = BOOST_CURRENT_LOCATION;
1659
38
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1660
38
                }
1661
                // Append the replacement character for the
1662
                // first leading surrogate.
1663
0
                temp.append_utf8(urc);
1664
                // Check if the second code point is a
1665
                // valid unicode scalar value (invalid leading
1666
                // or trailing surrogate)
1667
0
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1668
0
                {
1669
0
                    temp.append_utf8(u2_);
1670
0
                    break;
1671
0
                }
1672
                // If it is a valid leading surrogate
1673
0
                else
1674
0
                {
1675
0
                    u1_ = u2_;
1676
0
                    goto do_sur1;
1677
0
                }
1678
0
            }
1679
            // Calculate the Unicode code point from the surrogate pair and
1680
            // append the UTF-8 representation.
1681
901
            unsigned cp =
1682
901
                ((u1_ - 0xd800) << 10) +
1683
901
                ((u2_ - 0xdc00)) +
1684
901
                    0x10000;
1685
            // utf-16 surrogate pair
1686
901
            temp.append_utf8(cp);
1687
9.89M
        }
1688
1689
        // flush
1690
9.89M
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1691
110k
            break;
1692
9.89M
    }
1693
1694
110k
    if(BOOST_JSON_LIKELY( temp.size() ))
1695
110k
    {
1696
110k
        BOOST_ASSERT(total <= max_size);
1697
110k
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1698
0
        {
1699
0
            BOOST_STATIC_CONSTEXPR source_location loc
1700
0
                = BOOST_CURRENT_LOCATION;
1701
0
            return fail(cs.begin(), ev_too_large, &loc);
1702
0
        }
1703
1704
110k
        total += temp.size();
1705
110k
        bool const r = is_key
1706
110k
            ? h_.on_key_part(temp.get(), total, ec_)
1707
110k
            : h_.on_string_part(temp.get(), total, ec_);
1708
110k
        if(BOOST_JSON_UNLIKELY( !r ))
1709
0
            return fail( cs.begin() );
1710
110k
    }
1711
1712
110k
    return cs.begin();
1713
110k
}
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
1157
180
{
1158
180
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1159
180
    auto const ev_too_large = is_key?
1160
135
        error::key_too_large : error::string_too_large;
1161
180
    auto const max_size = is_key?
1162
135
        Handler::max_key_size : Handler::max_string_size;
1163
180
    int digit;
1164
1165
    //---------------------------------------------------------------
1166
    //
1167
    // To handle escapes, a local temporary buffer accumulates
1168
    // the unescaped result. The algorithm attempts to fill the
1169
    // buffer to capacity before invoking the handler.
1170
    // In some cases the temporary buffer needs to be flushed
1171
    // before it is full:
1172
    // * When the closing double quote is seen
1173
    // * When there in no more input (and more is expected later)
1174
    // A goal of the algorithm is to call the handler as few times
1175
    // as possible. Thus, when the first escape is encountered,
1176
    // the algorithm attempts to fill the temporary buffer first.
1177
    //
1178
180
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1179
1180
    // Unescaped JSON is never larger than its escaped version.
1181
    // To efficiently process only what will fit in the temporary buffer,
1182
    // the size of the input stream is temporarily "clipped" to the size
1183
    // of the temporary buffer.
1184
    // handle escaped character
1185
180
    detail::clipped_const_stream cs(p, end_);
1186
180
    cs.clip(temp.max_size());
1187
1188
180
    if(! stack_empty && ! st_.empty())
1189
180
    {
1190
180
        state st;
1191
180
        st_.pop(st);
1192
180
        switch(st)
1193
180
        {
1194
0
        default: BOOST_JSON_UNREACHABLE();
1195
89
        case state::str3: goto do_str3;
1196
15
        case state::str4: goto do_str4;
1197
15
        case state::str5: goto do_str5;
1198
12
        case state::str6: goto do_str6;
1199
15
        case state::str7: goto do_str7;
1200
9
        case state::sur1: goto do_sur1;
1201
1
        case state::sur2: goto do_sur2;
1202
1
        case state::sur3: goto do_sur3;
1203
7
        case state::sur4: goto do_sur4;
1204
7
        case state::sur5: goto do_sur5;
1205
9
        case state::sur6: goto do_sur6;
1206
180
        }
1207
180
    }
1208
1209
0
    while(true)
1210
0
    {
1211
0
        BOOST_ASSERT( temp.capacity() );
1212
0
        BOOST_ASSERT(*cs == '\\');
1213
0
        ++cs;
1214
89
do_str3:
1215
89
        if(BOOST_JSON_UNLIKELY(! cs))
1216
89
        {
1217
89
            if(BOOST_JSON_LIKELY(! temp.empty()))
1218
0
            {
1219
0
                BOOST_ASSERT(total <= max_size);
1220
0
                if(BOOST_JSON_UNLIKELY(
1221
0
                    temp.size() > max_size - total))
1222
0
                {
1223
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1224
0
                        = BOOST_CURRENT_LOCATION;
1225
0
                    return fail(cs.begin(), ev_too_large, &loc);
1226
0
                }
1227
0
                total += temp.size();
1228
0
                {
1229
0
                    bool r = is_key
1230
0
                        ? h_.on_key_part(temp.get(), total, ec_)
1231
0
                        : h_.on_string_part(temp.get(), total, ec_);
1232
1233
0
                    if(BOOST_JSON_UNLIKELY(!r))
1234
0
                    {
1235
0
                        return fail(cs.begin());
1236
0
                    }
1237
0
                }
1238
0
                temp.clear();
1239
0
            }
1240
89
            cs.clip(temp.max_size());
1241
89
            if(BOOST_JSON_UNLIKELY(! cs))
1242
89
                return maybe_suspend(cs.begin(), state::str3);
1243
89
        }
1244
0
        switch(*cs)
1245
0
        {
1246
0
        default:
1247
0
            {
1248
0
                BOOST_STATIC_CONSTEXPR source_location loc
1249
0
                    = BOOST_CURRENT_LOCATION;
1250
0
                return fail(cs.begin(), error::syntax, &loc);
1251
0
            }
1252
0
        case '\x22': // '"'
1253
0
            temp.push_back('\x22');
1254
0
            ++cs;
1255
0
            break;
1256
0
        case '\\':
1257
0
            temp.push_back('\\');
1258
0
            ++cs;
1259
0
            break;
1260
0
        case '/':
1261
0
            temp.push_back('/');
1262
0
            ++cs;
1263
0
            break;
1264
0
        case 'b':
1265
0
            temp.push_back('\x08');
1266
0
            ++cs;
1267
0
            break;
1268
0
        case 'f':
1269
0
            temp.push_back('\x0c');
1270
0
            ++cs;
1271
0
            break;
1272
0
        case 'n':
1273
0
            temp.push_back('\x0a');
1274
0
            ++cs;
1275
0
            break;
1276
0
        case 'r':
1277
0
            temp.push_back('\x0d');
1278
0
            ++cs;
1279
0
            break;
1280
0
        case 't':
1281
0
            temp.push_back('\x09');
1282
0
            ++cs;
1283
0
            break;
1284
0
        case 'u':
1285
            // utf16 escape
1286
            //
1287
            // fast path only when the buffer
1288
            // is large enough for 2 surrogates
1289
0
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1290
0
            {
1291
                // KRYSTIAN TODO: this could be done
1292
                // with fewer instructions
1293
0
                digit = detail::load_little_endian<4>(
1294
0
                    cs.begin() + 1);
1295
0
                int d4 = detail::hex_digit(static_cast<
1296
0
                    unsigned char>(digit >> 24));
1297
0
                int d3 = detail::hex_digit(static_cast<
1298
0
                    unsigned char>(digit >> 16));
1299
0
                int d2 = detail::hex_digit(static_cast<
1300
0
                    unsigned char>(digit >> 8));
1301
0
                int d1 = detail::hex_digit(static_cast<
1302
0
                    unsigned char>(digit));
1303
0
                if(BOOST_JSON_UNLIKELY(
1304
0
                    (d1 | d2 | d3 | d4) == -1))
1305
0
                {
1306
0
                    if(d1 != -1)
1307
0
                        ++cs;
1308
0
                    if(d2 != -1)
1309
0
                        ++cs;
1310
0
                    if(d3 != -1)
1311
0
                        ++cs;
1312
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1313
0
                        = BOOST_CURRENT_LOCATION;
1314
0
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1315
0
                }
1316
                // 32 bit unicode scalar value
1317
0
                unsigned u1 =
1318
0
                    (d1 << 12) + (d2 << 8) +
1319
0
                    (d3 << 4) + d4;
1320
                // valid unicode scalar values are
1321
                // [0, D7FF] and [E000, 10FFFF]
1322
                // values within this range are valid utf-8
1323
                // code points and invalid leading surrogates.
1324
0
                if(BOOST_JSON_LIKELY(
1325
0
                    u1 < 0xd800 || u1 > 0xdfff))
1326
0
                {
1327
0
                    cs += 5;
1328
0
                    temp.append_utf8(u1);
1329
0
                    break;
1330
0
                }
1331
0
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1332
0
                {
1333
                    // If it's an illegal leading surrogate and
1334
                    // the parser does not allow it, return an error.
1335
0
                    if(!allow_bad_utf16)
1336
0
                    {
1337
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1338
0
                            = BOOST_CURRENT_LOCATION;
1339
0
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1340
0
                            &loc);
1341
0
                    }
1342
                    // Otherwise, append the Unicode replacement character
1343
0
                    else
1344
0
                    {
1345
0
                        cs += 5;
1346
0
                        temp.append_utf8(urc);
1347
0
                        break;
1348
0
                    }
1349
0
                }
1350
0
                cs += 5;
1351
                // KRYSTIAN TODO: this can be a two byte load
1352
                // and a single comparison. We lose error information,
1353
                // but it's faster.
1354
0
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1355
0
                {
1356
                    // If the next character is not a backslash and
1357
                    // the parser does not allow it, return a syntax error.
1358
0
                    if(!allow_bad_utf16)
1359
0
                    {
1360
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1361
0
                            = BOOST_CURRENT_LOCATION;
1362
0
                        return fail(cs.begin(), error::syntax, &loc);
1363
0
                    }
1364
                    // Otherwise, append the Unicode replacement character since
1365
                    // the first code point is a valid leading surrogate
1366
0
                    else
1367
0
                    {
1368
0
                        temp.append_utf8(urc);
1369
0
                        break;
1370
0
                    }
1371
0
                }
1372
0
                ++cs;
1373
0
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1374
0
                {
1375
0
                    if (!allow_bad_utf16)
1376
0
                    {
1377
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1378
0
                            = BOOST_CURRENT_LOCATION;
1379
0
                        return fail(cs.begin(), error::syntax, &loc);
1380
0
                    }
1381
                    // Otherwise, append the Unicode replacement character since
1382
                    // the first code point is a valid leading surrogate
1383
0
                    else
1384
0
                    {
1385
0
                        temp.append_utf8(urc);
1386
0
                        goto do_str3;
1387
0
                    }
1388
0
                }
1389
0
                ++cs;
1390
0
                digit = detail::load_little_endian<4>(cs.begin());
1391
0
                d4 = detail::hex_digit(static_cast<
1392
0
                    unsigned char>(digit >> 24));
1393
0
                d3 = detail::hex_digit(static_cast<
1394
0
                    unsigned char>(digit >> 16));
1395
0
                d2 = detail::hex_digit(static_cast<
1396
0
                    unsigned char>(digit >> 8));
1397
0
                d1 = detail::hex_digit(static_cast<
1398
0
                    unsigned char>(digit));
1399
0
                if(BOOST_JSON_UNLIKELY(
1400
0
                    (d1 | d2 | d3 | d4) == -1))
1401
0
                {
1402
0
                    if(d1 != -1)
1403
0
                        ++cs;
1404
0
                    if(d2 != -1)
1405
0
                        ++cs;
1406
0
                    if(d3 != -1)
1407
0
                        ++cs;
1408
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1409
0
                        = BOOST_CURRENT_LOCATION;
1410
0
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1411
0
                }
1412
0
                unsigned u2 =
1413
0
                    (d1 << 12) + (d2 << 8) +
1414
0
                    (d3 << 4) + d4;
1415
                // Check if the second code point is a valid trailing surrogate.
1416
                // Valid trailing surrogates are [DC00, DFFF]
1417
0
                if(BOOST_JSON_UNLIKELY(
1418
0
                    u2 < 0xdc00 || u2 > 0xdfff))
1419
0
                {
1420
                    // If not valid and the parser does not allow it, return an error.
1421
0
                    if(!allow_bad_utf16)
1422
0
                    {
1423
0
                        BOOST_STATIC_CONSTEXPR source_location loc
1424
0
                            = BOOST_CURRENT_LOCATION;
1425
0
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1426
0
                            &loc);
1427
0
                    }
1428
                    // Append the replacement character for the
1429
                    // first leading surrogate.
1430
0
                    cs += 4;
1431
0
                    temp.append_utf8(urc);
1432
                    // Check if the second code point is a
1433
                    // valid unicode scalar value (invalid leading
1434
                    // or trailing surrogate)
1435
0
                    if (u2 < 0xd800 || u2 > 0xdbff)
1436
0
                    {
1437
0
                        temp.append_utf8(u2);
1438
0
                        break;
1439
0
                    }
1440
                    // If it is a valid leading surrogate
1441
0
                    else
1442
0
                    {
1443
0
                        u1_ = u2;
1444
0
                        goto do_sur1;
1445
0
                    }
1446
0
                }
1447
0
                cs += 4;
1448
                // Calculate the Unicode code point from the surrogate pair and
1449
                // append the UTF-8 representation.
1450
0
                unsigned cp =
1451
0
                    ((u1 - 0xd800) << 10) +
1452
0
                    ((u2 - 0xdc00)) +
1453
0
                        0x10000;
1454
                // utf-16 surrogate pair
1455
0
                temp.append_utf8(cp);
1456
0
                break;
1457
0
            }
1458
            // flush
1459
0
            if(BOOST_JSON_LIKELY(! temp.empty()))
1460
0
            {
1461
0
                BOOST_ASSERT(total <= max_size);
1462
0
                if(BOOST_JSON_UNLIKELY(
1463
0
                    temp.size() > max_size - total))
1464
0
                {
1465
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1466
0
                        = BOOST_CURRENT_LOCATION;
1467
0
                    return fail(cs.begin(), ev_too_large, &loc);
1468
0
                }
1469
0
                total += temp.size();
1470
0
                {
1471
0
                    bool r = is_key
1472
0
                        ? h_.on_key_part(temp.get(), total, ec_)
1473
0
                        : h_.on_string_part(temp.get(), total, ec_);
1474
1475
0
                    if(BOOST_JSON_UNLIKELY(!r))
1476
0
                    {
1477
0
                        return fail(cs.begin());
1478
0
                    }
1479
0
                }
1480
0
                temp.clear();
1481
0
                cs.clip(temp.max_size());
1482
0
            }
1483
0
            ++cs;
1484
            // utf-16 escape
1485
15
    do_str4:
1486
15
            if(BOOST_JSON_UNLIKELY(! cs))
1487
15
                return maybe_suspend(cs.begin(), state::str4);
1488
0
            digit = detail::hex_digit(*cs);
1489
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1490
0
            {
1491
0
                BOOST_STATIC_CONSTEXPR source_location loc
1492
0
                    = BOOST_CURRENT_LOCATION;
1493
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1494
0
            }
1495
0
            ++cs;
1496
0
            u1_ = digit << 12;
1497
15
    do_str5:
1498
15
            if(BOOST_JSON_UNLIKELY(! cs))
1499
15
                return maybe_suspend(cs.begin(), state::str5);
1500
0
            digit = detail::hex_digit(*cs);
1501
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1502
0
            {
1503
0
                BOOST_STATIC_CONSTEXPR source_location loc
1504
0
                    = BOOST_CURRENT_LOCATION;
1505
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1506
0
            }
1507
0
            ++cs;
1508
0
            u1_ += digit << 8;
1509
12
    do_str6:
1510
12
            if(BOOST_JSON_UNLIKELY(! cs))
1511
12
                return maybe_suspend(cs.begin(), state::str6);
1512
0
            digit = detail::hex_digit(*cs);
1513
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1514
0
            {
1515
0
                BOOST_STATIC_CONSTEXPR source_location loc
1516
0
                    = BOOST_CURRENT_LOCATION;
1517
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1518
0
            }
1519
0
            ++cs;
1520
0
            u1_ += digit << 4;
1521
15
    do_str7:
1522
15
            if(BOOST_JSON_UNLIKELY(! cs))
1523
15
                return maybe_suspend(cs.begin(), state::str7);
1524
0
            digit = detail::hex_digit(*cs);
1525
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1526
0
            {
1527
0
                BOOST_STATIC_CONSTEXPR source_location loc
1528
0
                    = BOOST_CURRENT_LOCATION;
1529
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1530
0
            }
1531
0
            ++cs;
1532
0
            u1_ += digit;
1533
0
            if(BOOST_JSON_LIKELY(
1534
0
                u1_ < 0xd800 || u1_ > 0xdfff))
1535
0
            {
1536
0
                BOOST_ASSERT(temp.empty());
1537
                // utf-8 codepoint
1538
0
                temp.append_utf8(u1_);
1539
0
                break;
1540
0
            }
1541
0
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1542
0
            {
1543
                // If it's an illegal leading surrogate and
1544
                // the parser does not allow it, return an error.
1545
0
                if(!allow_bad_utf16)
1546
0
                {
1547
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1548
0
                        = BOOST_CURRENT_LOCATION;
1549
0
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1550
0
                }
1551
                // Otherwise, append the Unicode replacement character
1552
0
                else
1553
0
                {
1554
0
                    BOOST_ASSERT(temp.empty());
1555
0
                    temp.append_utf8(urc);
1556
0
                    break;
1557
0
                }
1558
0
            }
1559
9
    do_sur1:
1560
9
            if(BOOST_JSON_UNLIKELY(! cs))
1561
9
                return maybe_suspend(cs.begin(), state::sur1);
1562
0
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1563
0
            {
1564
                // If the next character is not a backslash and
1565
                // the parser does not allow it, return a syntax error.
1566
0
                if(!allow_bad_utf16)
1567
0
                {
1568
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1569
0
                        = BOOST_CURRENT_LOCATION;
1570
0
                    return fail(cs.begin(), error::syntax, &loc);
1571
0
                }
1572
                // Otherwise, append the Unicode replacement character since
1573
                // the first code point is a valid leading surrogate
1574
0
                else
1575
0
                {
1576
0
                    temp.append_utf8(urc);
1577
0
                    break;
1578
0
                }
1579
0
            }
1580
0
            ++cs;
1581
1
    do_sur2:
1582
1
            if(BOOST_JSON_UNLIKELY(! cs))
1583
1
                return maybe_suspend(cs.begin(), state::sur2);
1584
0
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1585
0
            {
1586
0
                if (!allow_bad_utf16)
1587
0
                {
1588
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1589
0
                        = BOOST_CURRENT_LOCATION;
1590
0
                    return fail(cs.begin(), error::syntax, &loc);
1591
0
                }
1592
                // Otherwise, append the Unicode replacement character since
1593
                // the first code point is a valid leading surrogate
1594
0
                else
1595
0
                {
1596
0
                    temp.append_utf8(urc);
1597
0
                    goto do_str3;
1598
0
                }
1599
0
            }
1600
0
            ++cs;
1601
1
    do_sur3:
1602
1
            if(BOOST_JSON_UNLIKELY(! cs))
1603
1
                return maybe_suspend(cs.begin(), state::sur3);
1604
0
            digit = detail::hex_digit(*cs);
1605
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1606
0
            {
1607
0
                BOOST_STATIC_CONSTEXPR source_location loc
1608
0
                    = BOOST_CURRENT_LOCATION;
1609
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1610
0
            }
1611
0
            ++cs;
1612
0
            u2_ = digit << 12;
1613
7
    do_sur4:
1614
7
            if(BOOST_JSON_UNLIKELY(! cs))
1615
7
                return maybe_suspend(cs.begin(), state::sur4);
1616
0
            digit = detail::hex_digit(*cs);
1617
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1618
0
            {
1619
0
                BOOST_STATIC_CONSTEXPR source_location loc
1620
0
                    = BOOST_CURRENT_LOCATION;
1621
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1622
0
            }
1623
0
            ++cs;
1624
0
            u2_ += digit << 8;
1625
7
    do_sur5:
1626
7
            if(BOOST_JSON_UNLIKELY(! cs))
1627
7
                return maybe_suspend(cs.begin(), state::sur5);
1628
0
            digit = detail::hex_digit(*cs);
1629
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1630
0
            {
1631
0
                BOOST_STATIC_CONSTEXPR source_location loc
1632
0
                    = BOOST_CURRENT_LOCATION;
1633
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1634
0
            }
1635
0
            ++cs;
1636
0
            u2_ += digit << 4;
1637
9
    do_sur6:
1638
9
            if(BOOST_JSON_UNLIKELY(! cs))
1639
9
                return maybe_suspend(cs.begin(), state::sur6);
1640
0
            digit = detail::hex_digit(*cs);
1641
0
            if(BOOST_JSON_UNLIKELY(digit == -1))
1642
0
            {
1643
0
                BOOST_STATIC_CONSTEXPR source_location loc
1644
0
                    = BOOST_CURRENT_LOCATION;
1645
0
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1646
0
            }
1647
0
            ++cs;
1648
0
            u2_ += digit;
1649
            // Check if the second code point is a valid trailing surrogate.
1650
            // Valid trailing surrogates are [DC00, DFFF]
1651
0
            if(BOOST_JSON_UNLIKELY(
1652
0
                u2_ < 0xdc00 || u2_ > 0xdfff))
1653
0
            {
1654
                // If not valid and the parser does not allow it, return an error.
1655
0
                if(!allow_bad_utf16)
1656
0
                {
1657
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1658
0
                        = BOOST_CURRENT_LOCATION;
1659
0
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1660
0
                }
1661
                // Append the replacement character for the
1662
                // first leading surrogate.
1663
0
                temp.append_utf8(urc);
1664
                // Check if the second code point is a
1665
                // valid unicode scalar value (invalid leading
1666
                // or trailing surrogate)
1667
0
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1668
0
                {
1669
0
                    temp.append_utf8(u2_);
1670
0
                    break;
1671
0
                }
1672
                // If it is a valid leading surrogate
1673
0
                else
1674
0
                {
1675
0
                    u1_ = u2_;
1676
0
                    goto do_sur1;
1677
0
                }
1678
0
            }
1679
            // Calculate the Unicode code point from the surrogate pair and
1680
            // append the UTF-8 representation.
1681
0
            unsigned cp =
1682
0
                ((u1_ - 0xd800) << 10) +
1683
0
                ((u2_ - 0xdc00)) +
1684
0
                    0x10000;
1685
            // utf-16 surrogate pair
1686
0
            temp.append_utf8(cp);
1687
0
        }
1688
1689
        // flush
1690
0
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1691
0
            break;
1692
0
    }
1693
1694
0
    if(BOOST_JSON_LIKELY( temp.size() ))
1695
0
    {
1696
0
        BOOST_ASSERT(total <= max_size);
1697
0
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1698
0
        {
1699
0
            BOOST_STATIC_CONSTEXPR source_location loc
1700
0
                = BOOST_CURRENT_LOCATION;
1701
0
            return fail(cs.begin(), ev_too_large, &loc);
1702
0
        }
1703
1704
0
        total += temp.size();
1705
0
        bool const r = is_key
1706
0
            ? h_.on_key_part(temp.get(), total, ec_)
1707
0
            : h_.on_string_part(temp.get(), total, ec_);
1708
0
        if(BOOST_JSON_UNLIKELY( !r ))
1709
0
            return fail( cs.begin() );
1710
0
    }
1711
1712
0
    return cs.begin();
1713
0
}
1714
1715
//----------------------------------------------------------
1716
1717
template<class Handler>
1718
template<
1719
    bool StackEmpty_,
1720
    bool AllowComments_/*,
1721
    bool AllowTrailing_,
1722
    bool AllowBadUTF8_*/>
1723
const char*
1724
basic_parser<Handler>::
1725
parse_object(const char* p,
1726
    std::integral_constant<bool, StackEmpty_> stack_empty,
1727
    std::integral_constant<bool, AllowComments_> allow_comments,
1728
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1729
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1730
    bool allow_bad_utf16)
1731
36.6k
{
1732
36.6k
    detail::const_stream_wrapper cs(p, end_);
1733
36.6k
    std::size_t size;
1734
36.6k
    if(! stack_empty && ! st_.empty())
1735
1.04k
    {
1736
        // resume
1737
1.04k
        state st;
1738
1.04k
        st_.pop(st);
1739
1.04k
        st_.pop(size);
1740
1.04k
        switch(st)
1741
1.04k
        {
1742
0
        default: BOOST_JSON_UNREACHABLE();
1743
88
        case state::obj1: goto do_obj1;
1744
5
        case state::obj2: goto do_obj2;
1745
210
        case state::obj3: goto do_obj3;
1746
109
        case state::obj4: goto do_obj4;
1747
5
        case state::obj5: goto do_obj5;
1748
58
        case state::obj6: goto do_obj6;
1749
415
        case state::obj7: goto do_obj7;
1750
69
        case state::obj8: goto do_obj8;
1751
69
        case state::obj9: goto do_obj9;
1752
12
        case state::obj10: goto do_obj10;
1753
6
        case state::obj11: goto do_obj11;
1754
1.04k
        }
1755
1.04k
    }
1756
35.5k
    BOOST_ASSERT(*cs == '{');
1757
35.5k
    size = 0;
1758
35.5k
    if(BOOST_JSON_UNLIKELY(! depth_))
1759
12
    {
1760
12
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1761
12
        return fail(cs.begin(), error::too_deep, &loc);
1762
12
    }
1763
35.5k
    --depth_;
1764
35.5k
    if(BOOST_JSON_UNLIKELY(
1765
35.5k
        ! h_.on_object_begin(ec_)))
1766
0
        return fail(cs.begin());
1767
35.5k
    ++cs;
1768
    // object:
1769
    //     '{' *ws '}'
1770
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1771
36.0k
do_obj1:
1772
36.0k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1773
36.0k
    if(BOOST_JSON_UNLIKELY(! cs))
1774
212
        return maybe_suspend(cs.begin(), state::obj1, size);
1775
35.8k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1776
14.7k
    {
1777
14.7k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1778
602
        {
1779
602
            if(allow_comments && *cs == '/')
1780
415
            {
1781
420
do_obj2:
1782
420
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1783
420
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1784
12
                    return suspend_or_fail(state::obj2, size);
1785
408
                goto do_obj1;
1786
420
            }
1787
602
            BOOST_STATIC_CONSTEXPR source_location loc
1788
187
                = BOOST_CURRENT_LOCATION;
1789
187
            return fail(cs.begin(), error::syntax, &loc);
1790
602
        }
1791
1.80M
loop:
1792
1.80M
        if(BOOST_JSON_UNLIKELY(++size >
1793
1.80M
            Handler::max_object_size))
1794
0
        {
1795
0
            BOOST_STATIC_CONSTEXPR source_location loc
1796
0
                = BOOST_CURRENT_LOCATION;
1797
0
            return fail(cs.begin(), error::object_too_large, &loc);
1798
0
        }
1799
1.80M
do_obj3:
1800
1.80M
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1801
1.80M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1802
981
            return suspend_or_fail(state::obj3, size);
1803
1.80M
do_obj4:
1804
1.80M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1805
1.80M
        if(BOOST_JSON_UNLIKELY(! cs))
1806
270
            return maybe_suspend(cs.begin(), state::obj4, size);
1807
1.80M
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1808
608
        {
1809
608
            if(allow_comments && *cs == '/')
1810
421
            {
1811
426
do_obj5:
1812
426
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1813
426
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1814
14
                    return suspend_or_fail(state::obj5, size);
1815
412
                goto do_obj4;
1816
426
            }
1817
608
            BOOST_STATIC_CONSTEXPR source_location loc
1818
187
                = BOOST_CURRENT_LOCATION;
1819
187
            return fail(cs.begin(), error::syntax, &loc);
1820
608
        }
1821
1.80M
        ++cs;
1822
1.80M
do_obj6:
1823
1.80M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1824
1.80M
        if(BOOST_JSON_UNLIKELY(! cs))
1825
150
            return maybe_suspend(cs.begin(), state::obj6, size);
1826
1.80M
do_obj7:
1827
1.80M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1828
1.80M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1829
2.20k
            return suspend_or_fail(state::obj7, size);
1830
1.80M
do_obj8:
1831
1.80M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1832
1.80M
        if(BOOST_JSON_UNLIKELY(! cs))
1833
177
            return maybe_suspend(cs.begin(), state::obj8, size);
1834
1.80M
        if(BOOST_JSON_LIKELY(*cs == ','))
1835
1.79M
        {
1836
1.79M
            ++cs;
1837
1.79M
do_obj9:
1838
1.79M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1839
1.79M
            if(BOOST_JSON_UNLIKELY(! cs))
1840
166
                return maybe_suspend(cs.begin(), state::obj9, size);
1841
1842
            // loop for next element
1843
1.79M
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1844
1.79M
                goto loop;
1845
1.82k
            if(! allow_trailing || *cs != '}')
1846
994
            {
1847
994
                if(allow_comments && *cs == '/')
1848
797
                {
1849
809
do_obj10:
1850
809
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1851
809
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1852
27
                        return suspend_or_fail(state::obj10, size);
1853
782
                    goto do_obj9;
1854
809
                }
1855
994
                BOOST_STATIC_CONSTEXPR source_location loc
1856
197
                    = BOOST_CURRENT_LOCATION;
1857
197
                return fail(cs.begin(), error::syntax, &loc);
1858
994
            }
1859
1.82k
        }
1860
10.2k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1861
603
        {
1862
603
            if(allow_comments && *cs == '/')
1863
419
            {
1864
425
do_obj11:
1865
425
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1866
425
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1867
16
                    return suspend_or_fail(state::obj11, size);
1868
409
                goto do_obj8;
1869
425
            }
1870
603
            BOOST_STATIC_CONSTEXPR source_location loc
1871
184
                = BOOST_CURRENT_LOCATION;
1872
184
            return fail(cs.begin(), error::syntax, &loc);
1873
603
        }
1874
        // got closing brace, fall through
1875
1.80M
    }
1876
31.5k
    if(BOOST_JSON_UNLIKELY(
1877
31.5k
        ! h_.on_object_end(size, ec_)))
1878
0
        return fail(cs.begin());
1879
31.5k
    ++depth_;
1880
31.5k
    ++cs;
1881
31.5k
    return cs.begin();
1882
31.5k
}
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
1731
28.5k
{
1732
28.5k
    detail::const_stream_wrapper cs(p, end_);
1733
28.5k
    std::size_t size;
1734
28.5k
    if(! stack_empty && ! st_.empty())
1735
0
    {
1736
        // resume
1737
0
        state st;
1738
0
        st_.pop(st);
1739
0
        st_.pop(size);
1740
0
        switch(st)
1741
0
        {
1742
0
        default: BOOST_JSON_UNREACHABLE();
1743
0
        case state::obj1: goto do_obj1;
1744
0
        case state::obj2: goto do_obj2;
1745
0
        case state::obj3: goto do_obj3;
1746
0
        case state::obj4: goto do_obj4;
1747
0
        case state::obj5: goto do_obj5;
1748
0
        case state::obj6: goto do_obj6;
1749
0
        case state::obj7: goto do_obj7;
1750
0
        case state::obj8: goto do_obj8;
1751
0
        case state::obj9: goto do_obj9;
1752
0
        case state::obj10: goto do_obj10;
1753
0
        case state::obj11: goto do_obj11;
1754
0
        }
1755
0
    }
1756
28.5k
    BOOST_ASSERT(*cs == '{');
1757
28.5k
    size = 0;
1758
28.5k
    if(BOOST_JSON_UNLIKELY(! depth_))
1759
8
    {
1760
8
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1761
8
        return fail(cs.begin(), error::too_deep, &loc);
1762
8
    }
1763
28.5k
    --depth_;
1764
28.5k
    if(BOOST_JSON_UNLIKELY(
1765
28.5k
        ! h_.on_object_begin(ec_)))
1766
0
        return fail(cs.begin());
1767
28.5k
    ++cs;
1768
    // object:
1769
    //     '{' *ws '}'
1770
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1771
28.5k
do_obj1:
1772
28.5k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1773
28.5k
    if(BOOST_JSON_UNLIKELY(! cs))
1774
75
        return maybe_suspend(cs.begin(), state::obj1, size);
1775
28.4k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1776
10.9k
    {
1777
10.9k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1778
134
        {
1779
134
            if(allow_comments && *cs == '/')
1780
0
            {
1781
0
do_obj2:
1782
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1783
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1784
0
                    return suspend_or_fail(state::obj2, size);
1785
0
                goto do_obj1;
1786
0
            }
1787
134
            BOOST_STATIC_CONSTEXPR source_location loc
1788
134
                = BOOST_CURRENT_LOCATION;
1789
134
            return fail(cs.begin(), error::syntax, &loc);
1790
134
        }
1791
1.72M
loop:
1792
1.72M
        if(BOOST_JSON_UNLIKELY(++size >
1793
1.72M
            Handler::max_object_size))
1794
0
        {
1795
0
            BOOST_STATIC_CONSTEXPR source_location loc
1796
0
                = BOOST_CURRENT_LOCATION;
1797
0
            return fail(cs.begin(), error::object_too_large, &loc);
1798
0
        }
1799
1.72M
do_obj3:
1800
1.72M
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1801
1.72M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1802
565
            return suspend_or_fail(state::obj3, size);
1803
1.72M
do_obj4:
1804
1.72M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1805
1.72M
        if(BOOST_JSON_UNLIKELY(! cs))
1806
109
            return maybe_suspend(cs.begin(), state::obj4, size);
1807
1.72M
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1808
123
        {
1809
123
            if(allow_comments && *cs == '/')
1810
0
            {
1811
0
do_obj5:
1812
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1813
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1814
0
                    return suspend_or_fail(state::obj5, size);
1815
0
                goto do_obj4;
1816
0
            }
1817
123
            BOOST_STATIC_CONSTEXPR source_location loc
1818
123
                = BOOST_CURRENT_LOCATION;
1819
123
            return fail(cs.begin(), error::syntax, &loc);
1820
123
        }
1821
1.72M
        ++cs;
1822
1.72M
do_obj6:
1823
1.72M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1824
1.72M
        if(BOOST_JSON_UNLIKELY(! cs))
1825
65
            return maybe_suspend(cs.begin(), state::obj6, size);
1826
1.72M
do_obj7:
1827
1.72M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1828
1.72M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1829
1.36k
            return suspend_or_fail(state::obj7, size);
1830
1.72M
do_obj8:
1831
1.72M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1832
1.72M
        if(BOOST_JSON_UNLIKELY(! cs))
1833
64
            return maybe_suspend(cs.begin(), state::obj8, size);
1834
1.72M
        if(BOOST_JSON_LIKELY(*cs == ','))
1835
1.71M
        {
1836
1.71M
            ++cs;
1837
1.71M
do_obj9:
1838
1.71M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1839
1.71M
            if(BOOST_JSON_UNLIKELY(! cs))
1840
55
                return maybe_suspend(cs.begin(), state::obj9, size);
1841
1842
            // loop for next element
1843
1.71M
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1844
1.71M
                goto loop;
1845
703
            if(! allow_trailing || *cs != '}')
1846
133
            {
1847
133
                if(allow_comments && *cs == '/')
1848
0
                {
1849
0
do_obj10:
1850
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1851
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1852
0
                        return suspend_or_fail(state::obj10, size);
1853
0
                    goto do_obj9;
1854
0
                }
1855
133
                BOOST_STATIC_CONSTEXPR source_location loc
1856
133
                    = BOOST_CURRENT_LOCATION;
1857
133
                return fail(cs.begin(), error::syntax, &loc);
1858
133
            }
1859
703
        }
1860
7.80k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1861
134
        {
1862
134
            if(allow_comments && *cs == '/')
1863
0
            {
1864
0
do_obj11:
1865
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1866
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1867
0
                    return suspend_or_fail(state::obj11, size);
1868
0
                goto do_obj8;
1869
0
            }
1870
134
            BOOST_STATIC_CONSTEXPR source_location loc
1871
134
                = BOOST_CURRENT_LOCATION;
1872
134
            return fail(cs.begin(), error::syntax, &loc);
1873
134
        }
1874
        // got closing brace, fall through
1875
1.72M
    }
1876
25.7k
    if(BOOST_JSON_UNLIKELY(
1877
25.7k
        ! h_.on_object_end(size, ec_)))
1878
0
        return fail(cs.begin());
1879
25.7k
    ++depth_;
1880
25.7k
    ++cs;
1881
25.7k
    return cs.begin();
1882
25.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
1731
7.01k
{
1732
7.01k
    detail::const_stream_wrapper cs(p, end_);
1733
7.01k
    std::size_t size;
1734
7.01k
    if(! stack_empty && ! st_.empty())
1735
0
    {
1736
        // resume
1737
0
        state st;
1738
0
        st_.pop(st);
1739
0
        st_.pop(size);
1740
0
        switch(st)
1741
0
        {
1742
0
        default: BOOST_JSON_UNREACHABLE();
1743
0
        case state::obj1: goto do_obj1;
1744
0
        case state::obj2: goto do_obj2;
1745
0
        case state::obj3: goto do_obj3;
1746
0
        case state::obj4: goto do_obj4;
1747
0
        case state::obj5: goto do_obj5;
1748
0
        case state::obj6: goto do_obj6;
1749
0
        case state::obj7: goto do_obj7;
1750
0
        case state::obj8: goto do_obj8;
1751
0
        case state::obj9: goto do_obj9;
1752
0
        case state::obj10: goto do_obj10;
1753
0
        case state::obj11: goto do_obj11;
1754
0
        }
1755
0
    }
1756
7.01k
    BOOST_ASSERT(*cs == '{');
1757
7.01k
    size = 0;
1758
7.01k
    if(BOOST_JSON_UNLIKELY(! depth_))
1759
4
    {
1760
4
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1761
4
        return fail(cs.begin(), error::too_deep, &loc);
1762
4
    }
1763
7.01k
    --depth_;
1764
7.01k
    if(BOOST_JSON_UNLIKELY(
1765
7.01k
        ! h_.on_object_begin(ec_)))
1766
0
        return fail(cs.begin());
1767
7.01k
    ++cs;
1768
    // object:
1769
    //     '{' *ws '}'
1770
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1771
7.42k
do_obj1:
1772
7.42k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1773
7.42k
    if(BOOST_JSON_UNLIKELY(! cs))
1774
49
        return maybe_suspend(cs.begin(), state::obj1, size);
1775
7.37k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1776
3.73k
    {
1777
3.73k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1778
468
        {
1779
468
            if(allow_comments && *cs == '/')
1780
415
            {
1781
415
do_obj2:
1782
415
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1783
415
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1784
7
                    return suspend_or_fail(state::obj2, size);
1785
408
                goto do_obj1;
1786
415
            }
1787
468
            BOOST_STATIC_CONSTEXPR source_location loc
1788
53
                = BOOST_CURRENT_LOCATION;
1789
53
            return fail(cs.begin(), error::syntax, &loc);
1790
468
        }
1791
75.7k
loop:
1792
75.7k
        if(BOOST_JSON_UNLIKELY(++size >
1793
75.7k
            Handler::max_object_size))
1794
0
        {
1795
0
            BOOST_STATIC_CONSTEXPR source_location loc
1796
0
                = BOOST_CURRENT_LOCATION;
1797
0
            return fail(cs.begin(), error::object_too_large, &loc);
1798
0
        }
1799
75.7k
do_obj3:
1800
75.7k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1801
75.7k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1802
206
            return suspend_or_fail(state::obj3, size);
1803
75.9k
do_obj4:
1804
75.9k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1805
75.9k
        if(BOOST_JSON_UNLIKELY(! cs))
1806
52
            return maybe_suspend(cs.begin(), state::obj4, size);
1807
75.8k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1808
485
        {
1809
485
            if(allow_comments && *cs == '/')
1810
421
            {
1811
421
do_obj5:
1812
421
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1813
421
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1814
9
                    return suspend_or_fail(state::obj5, size);
1815
412
                goto do_obj4;
1816
421
            }
1817
485
            BOOST_STATIC_CONSTEXPR source_location loc
1818
64
                = BOOST_CURRENT_LOCATION;
1819
64
            return fail(cs.begin(), error::syntax, &loc);
1820
485
        }
1821
75.3k
        ++cs;
1822
75.3k
do_obj6:
1823
75.3k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1824
75.3k
        if(BOOST_JSON_UNLIKELY(! cs))
1825
27
            return maybe_suspend(cs.begin(), state::obj6, size);
1826
75.3k
do_obj7:
1827
75.3k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1828
75.3k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1829
435
            return suspend_or_fail(state::obj7, size);
1830
75.3k
do_obj8:
1831
75.3k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1832
75.3k
        if(BOOST_JSON_UNLIKELY(! cs))
1833
39
            return maybe_suspend(cs.begin(), state::obj8, size);
1834
75.2k
        if(BOOST_JSON_LIKELY(*cs == ','))
1835
72.8k
        {
1836
72.8k
            ++cs;
1837
73.6k
do_obj9:
1838
73.6k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1839
73.6k
            if(BOOST_JSON_UNLIKELY(! cs))
1840
42
                return maybe_suspend(cs.begin(), state::obj9, size);
1841
1842
            // loop for next element
1843
73.5k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1844
72.4k
                goto loop;
1845
1.12k
            if(! allow_trailing || *cs != '}')
1846
861
            {
1847
861
                if(allow_comments && *cs == '/')
1848
797
                {
1849
797
do_obj10:
1850
797
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1851
797
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1852
15
                        return suspend_or_fail(state::obj10, size);
1853
782
                    goto do_obj9;
1854
797
                }
1855
861
                BOOST_STATIC_CONSTEXPR source_location loc
1856
64
                    = BOOST_CURRENT_LOCATION;
1857
64
                return fail(cs.begin(), error::syntax, &loc);
1858
861
            }
1859
1.12k
        }
1860
2.44k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1861
469
        {
1862
469
            if(allow_comments && *cs == '/')
1863
419
            {
1864
419
do_obj11:
1865
419
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1866
419
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1867
10
                    return suspend_or_fail(state::obj11, size);
1868
409
                goto do_obj8;
1869
419
            }
1870
469
            BOOST_STATIC_CONSTEXPR source_location loc
1871
50
                = BOOST_CURRENT_LOCATION;
1872
50
            return fail(cs.begin(), error::syntax, &loc);
1873
469
        }
1874
        // got closing brace, fall through
1875
75.2k
    }
1876
5.88k
    if(BOOST_JSON_UNLIKELY(
1877
5.88k
        ! h_.on_object_end(size, ec_)))
1878
0
        return fail(cs.begin());
1879
5.88k
    ++depth_;
1880
5.88k
    ++cs;
1881
5.88k
    return cs.begin();
1882
5.88k
}
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
1731
465
{
1732
465
    detail::const_stream_wrapper cs(p, end_);
1733
465
    std::size_t size;
1734
465
    if(! stack_empty && ! st_.empty())
1735
465
    {
1736
        // resume
1737
465
        state st;
1738
465
        st_.pop(st);
1739
465
        st_.pop(size);
1740
465
        switch(st)
1741
465
        {
1742
0
        default: BOOST_JSON_UNREACHABLE();
1743
39
        case state::obj1: goto do_obj1;
1744
0
        case state::obj2: goto do_obj2;
1745
100
        case state::obj3: goto do_obj3;
1746
57
        case state::obj4: goto do_obj4;
1747
0
        case state::obj5: goto do_obj5;
1748
31
        case state::obj6: goto do_obj6;
1749
181
        case state::obj7: goto do_obj7;
1750
30
        case state::obj8: goto do_obj8;
1751
27
        case state::obj9: goto do_obj9;
1752
0
        case state::obj10: goto do_obj10;
1753
0
        case state::obj11: goto do_obj11;
1754
465
        }
1755
465
    }
1756
0
    BOOST_ASSERT(*cs == '{');
1757
0
    size = 0;
1758
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1759
0
    {
1760
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1761
0
        return fail(cs.begin(), error::too_deep, &loc);
1762
0
    }
1763
0
    --depth_;
1764
0
    if(BOOST_JSON_UNLIKELY(
1765
0
        ! h_.on_object_begin(ec_)))
1766
0
        return fail(cs.begin());
1767
0
    ++cs;
1768
    // object:
1769
    //     '{' *ws '}'
1770
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1771
39
do_obj1:
1772
39
    cs = detail::count_whitespace(cs.begin(), cs.end());
1773
39
    if(BOOST_JSON_UNLIKELY(! cs))
1774
39
        return maybe_suspend(cs.begin(), state::obj1, size);
1775
0
    if(BOOST_JSON_LIKELY(*cs != '}'))
1776
0
    {
1777
0
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1778
0
        {
1779
0
            if(allow_comments && *cs == '/')
1780
0
            {
1781
0
do_obj2:
1782
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1783
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1784
0
                    return suspend_or_fail(state::obj2, size);
1785
0
                goto do_obj1;
1786
0
            }
1787
0
            BOOST_STATIC_CONSTEXPR source_location loc
1788
0
                = BOOST_CURRENT_LOCATION;
1789
0
            return fail(cs.begin(), error::syntax, &loc);
1790
0
        }
1791
0
loop:
1792
0
        if(BOOST_JSON_UNLIKELY(++size >
1793
0
            Handler::max_object_size))
1794
0
        {
1795
0
            BOOST_STATIC_CONSTEXPR source_location loc
1796
0
                = BOOST_CURRENT_LOCATION;
1797
0
            return fail(cs.begin(), error::object_too_large, &loc);
1798
0
        }
1799
100
do_obj3:
1800
100
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1801
100
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1802
100
            return suspend_or_fail(state::obj3, size);
1803
57
do_obj4:
1804
57
        cs = detail::count_whitespace(cs.begin(), cs.end());
1805
57
        if(BOOST_JSON_UNLIKELY(! cs))
1806
57
            return maybe_suspend(cs.begin(), state::obj4, size);
1807
0
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1808
0
        {
1809
0
            if(allow_comments && *cs == '/')
1810
0
            {
1811
0
do_obj5:
1812
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1813
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1814
0
                    return suspend_or_fail(state::obj5, size);
1815
0
                goto do_obj4;
1816
0
            }
1817
0
            BOOST_STATIC_CONSTEXPR source_location loc
1818
0
                = BOOST_CURRENT_LOCATION;
1819
0
            return fail(cs.begin(), error::syntax, &loc);
1820
0
        }
1821
0
        ++cs;
1822
31
do_obj6:
1823
31
        cs = detail::count_whitespace(cs.begin(), cs.end());
1824
31
        if(BOOST_JSON_UNLIKELY(! cs))
1825
31
            return maybe_suspend(cs.begin(), state::obj6, size);
1826
181
do_obj7:
1827
181
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1828
181
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1829
178
            return suspend_or_fail(state::obj7, size);
1830
33
do_obj8:
1831
33
        cs = detail::count_whitespace(cs.begin(), cs.end());
1832
33
        if(BOOST_JSON_UNLIKELY(! cs))
1833
33
            return maybe_suspend(cs.begin(), state::obj8, size);
1834
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1835
0
        {
1836
0
            ++cs;
1837
27
do_obj9:
1838
27
            cs = detail::count_whitespace(cs.begin(), cs.end());
1839
27
            if(BOOST_JSON_UNLIKELY(! cs))
1840
27
                return maybe_suspend(cs.begin(), state::obj9, size);
1841
1842
            // loop for next element
1843
0
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1844
0
                goto loop;
1845
0
            if(! allow_trailing || *cs != '}')
1846
0
            {
1847
0
                if(allow_comments && *cs == '/')
1848
0
                {
1849
0
do_obj10:
1850
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1851
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1852
0
                        return suspend_or_fail(state::obj10, size);
1853
0
                    goto do_obj9;
1854
0
                }
1855
0
                BOOST_STATIC_CONSTEXPR source_location loc
1856
0
                    = BOOST_CURRENT_LOCATION;
1857
0
                return fail(cs.begin(), error::syntax, &loc);
1858
0
            }
1859
0
        }
1860
0
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1861
0
        {
1862
0
            if(allow_comments && *cs == '/')
1863
0
            {
1864
0
do_obj11:
1865
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1866
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1867
0
                    return suspend_or_fail(state::obj11, size);
1868
0
                goto do_obj8;
1869
0
            }
1870
0
            BOOST_STATIC_CONSTEXPR source_location loc
1871
0
                = BOOST_CURRENT_LOCATION;
1872
0
            return fail(cs.begin(), error::syntax, &loc);
1873
0
        }
1874
        // got closing brace, fall through
1875
0
    }
1876
0
    if(BOOST_JSON_UNLIKELY(
1877
0
        ! h_.on_object_end(size, ec_)))
1878
0
        return fail(cs.begin());
1879
0
    ++depth_;
1880
0
    ++cs;
1881
0
    return cs.begin();
1882
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
1731
581
{
1732
581
    detail::const_stream_wrapper cs(p, end_);
1733
581
    std::size_t size;
1734
581
    if(! stack_empty && ! st_.empty())
1735
581
    {
1736
        // resume
1737
581
        state st;
1738
581
        st_.pop(st);
1739
581
        st_.pop(size);
1740
581
        switch(st)
1741
581
        {
1742
0
        default: BOOST_JSON_UNREACHABLE();
1743
49
        case state::obj1: goto do_obj1;
1744
5
        case state::obj2: goto do_obj2;
1745
110
        case state::obj3: goto do_obj3;
1746
52
        case state::obj4: goto do_obj4;
1747
5
        case state::obj5: goto do_obj5;
1748
27
        case state::obj6: goto do_obj6;
1749
234
        case state::obj7: goto do_obj7;
1750
39
        case state::obj8: goto do_obj8;
1751
42
        case state::obj9: goto do_obj9;
1752
12
        case state::obj10: goto do_obj10;
1753
6
        case state::obj11: goto do_obj11;
1754
581
        }
1755
581
    }
1756
0
    BOOST_ASSERT(*cs == '{');
1757
0
    size = 0;
1758
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1759
0
    {
1760
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1761
0
        return fail(cs.begin(), error::too_deep, &loc);
1762
0
    }
1763
0
    --depth_;
1764
0
    if(BOOST_JSON_UNLIKELY(
1765
0
        ! h_.on_object_begin(ec_)))
1766
0
        return fail(cs.begin());
1767
0
    ++cs;
1768
    // object:
1769
    //     '{' *ws '}'
1770
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1771
49
do_obj1:
1772
49
    cs = detail::count_whitespace(cs.begin(), cs.end());
1773
49
    if(BOOST_JSON_UNLIKELY(! cs))
1774
49
        return maybe_suspend(cs.begin(), state::obj1, size);
1775
0
    if(BOOST_JSON_LIKELY(*cs != '}'))
1776
0
    {
1777
0
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1778
0
        {
1779
0
            if(allow_comments && *cs == '/')
1780
0
            {
1781
5
do_obj2:
1782
5
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1783
5
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1784
5
                    return suspend_or_fail(state::obj2, size);
1785
0
                goto do_obj1;
1786
5
            }
1787
0
            BOOST_STATIC_CONSTEXPR source_location loc
1788
0
                = BOOST_CURRENT_LOCATION;
1789
0
            return fail(cs.begin(), error::syntax, &loc);
1790
0
        }
1791
0
loop:
1792
0
        if(BOOST_JSON_UNLIKELY(++size >
1793
0
            Handler::max_object_size))
1794
0
        {
1795
0
            BOOST_STATIC_CONSTEXPR source_location loc
1796
0
                = BOOST_CURRENT_LOCATION;
1797
0
            return fail(cs.begin(), error::object_too_large, &loc);
1798
0
        }
1799
110
do_obj3:
1800
110
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1801
110
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1802
110
            return suspend_or_fail(state::obj3, size);
1803
52
do_obj4:
1804
52
        cs = detail::count_whitespace(cs.begin(), cs.end());
1805
52
        if(BOOST_JSON_UNLIKELY(! cs))
1806
52
            return maybe_suspend(cs.begin(), state::obj4, size);
1807
0
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1808
0
        {
1809
0
            if(allow_comments && *cs == '/')
1810
0
            {
1811
5
do_obj5:
1812
5
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1813
5
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1814
5
                    return suspend_or_fail(state::obj5, size);
1815
0
                goto do_obj4;
1816
5
            }
1817
0
            BOOST_STATIC_CONSTEXPR source_location loc
1818
0
                = BOOST_CURRENT_LOCATION;
1819
0
            return fail(cs.begin(), error::syntax, &loc);
1820
0
        }
1821
0
        ++cs;
1822
27
do_obj6:
1823
27
        cs = detail::count_whitespace(cs.begin(), cs.end());
1824
27
        if(BOOST_JSON_UNLIKELY(! cs))
1825
27
            return maybe_suspend(cs.begin(), state::obj6, size);
1826
234
do_obj7:
1827
234
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1828
234
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1829
232
            return suspend_or_fail(state::obj7, size);
1830
41
do_obj8:
1831
41
        cs = detail::count_whitespace(cs.begin(), cs.end());
1832
41
        if(BOOST_JSON_UNLIKELY(! cs))
1833
41
            return maybe_suspend(cs.begin(), state::obj8, size);
1834
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1835
0
        {
1836
0
            ++cs;
1837
42
do_obj9:
1838
42
            cs = detail::count_whitespace(cs.begin(), cs.end());
1839
42
            if(BOOST_JSON_UNLIKELY(! cs))
1840
42
                return maybe_suspend(cs.begin(), state::obj9, size);
1841
1842
            // loop for next element
1843
0
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1844
0
                goto loop;
1845
0
            if(! allow_trailing || *cs != '}')
1846
0
            {
1847
0
                if(allow_comments && *cs == '/')
1848
0
                {
1849
12
do_obj10:
1850
12
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1851
12
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1852
12
                        return suspend_or_fail(state::obj10, size);
1853
0
                    goto do_obj9;
1854
12
                }
1855
0
                BOOST_STATIC_CONSTEXPR source_location loc
1856
0
                    = BOOST_CURRENT_LOCATION;
1857
0
                return fail(cs.begin(), error::syntax, &loc);
1858
0
            }
1859
0
        }
1860
0
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1861
0
        {
1862
0
            if(allow_comments && *cs == '/')
1863
0
            {
1864
6
do_obj11:
1865
6
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1866
6
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1867
6
                    return suspend_or_fail(state::obj11, size);
1868
0
                goto do_obj8;
1869
6
            }
1870
0
            BOOST_STATIC_CONSTEXPR source_location loc
1871
0
                = BOOST_CURRENT_LOCATION;
1872
0
            return fail(cs.begin(), error::syntax, &loc);
1873
0
        }
1874
        // got closing brace, fall through
1875
0
    }
1876
0
    if(BOOST_JSON_UNLIKELY(
1877
0
        ! h_.on_object_end(size, ec_)))
1878
0
        return fail(cs.begin());
1879
0
    ++depth_;
1880
0
    ++cs;
1881
0
    return cs.begin();
1882
0
}
1883
1884
//----------------------------------------------------------
1885
1886
template<class Handler>
1887
template<
1888
    bool StackEmpty_,
1889
    bool AllowComments_/*,
1890
    bool AllowTrailing_,
1891
    bool AllowBadUTF8_*/>
1892
const char*
1893
basic_parser<Handler>::
1894
parse_array(const char* p,
1895
    std::integral_constant<bool, StackEmpty_> stack_empty,
1896
    std::integral_constant<bool, AllowComments_> allow_comments,
1897
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1898
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1899
    bool allow_bad_utf16)
1900
44.2k
{
1901
44.2k
    detail::const_stream_wrapper cs(p, end_);
1902
44.2k
    std::size_t size;
1903
44.2k
    if(! stack_empty && ! st_.empty())
1904
2.94k
    {
1905
        // resume
1906
2.94k
        state st;
1907
2.94k
        st_.pop(st);
1908
2.94k
        st_.pop(size);
1909
2.94k
        switch(st)
1910
2.94k
        {
1911
0
        default: BOOST_JSON_UNREACHABLE();
1912
93
        case state::arr1: goto do_arr1;
1913
17
        case state::arr2: goto do_arr2;
1914
2.29k
        case state::arr3: goto do_arr3;
1915
250
        case state::arr4: goto do_arr4;
1916
272
        case state::arr5: goto do_arr5;
1917
11
        case state::arr6: goto do_arr6;
1918
2.94k
        }
1919
2.94k
    }
1920
41.2k
    BOOST_ASSERT(*cs == '[');
1921
41.2k
    size = 0;
1922
41.2k
    if(BOOST_JSON_UNLIKELY(! depth_))
1923
12
    {
1924
12
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1925
12
        return fail(cs.begin(), error::too_deep, &loc);
1926
12
    }
1927
41.2k
    --depth_;
1928
41.2k
    if(BOOST_JSON_UNLIKELY(
1929
41.2k
        ! h_.on_array_begin(ec_)))
1930
0
        return fail(cs.begin());
1931
41.2k
    ++cs;
1932
    // array:
1933
    //     '[' *ws ']'
1934
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1935
41.8k
do_arr1:
1936
41.8k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1937
41.8k
    if(BOOST_JSON_UNLIKELY(! cs))
1938
223
        return maybe_suspend(cs.begin(), state::arr1, size);
1939
41.6k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1940
34.1k
    {
1941
10.5M
loop:
1942
10.5M
        if(allow_comments && *cs == '/')
1943
544
        {
1944
561
do_arr2:
1945
561
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1946
561
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1947
38
                return suspend_or_fail(state::arr2, size);
1948
523
            goto do_arr1;
1949
561
        }
1950
10.5M
        if(BOOST_JSON_UNLIKELY(++size >
1951
10.5M
            Handler::max_array_size))
1952
0
        {
1953
0
            BOOST_STATIC_CONSTEXPR source_location loc
1954
0
                = BOOST_CURRENT_LOCATION;
1955
0
            return fail(cs.begin(), error::array_too_large, &loc);
1956
0
        }
1957
10.5M
do_arr3:
1958
        // array is not empty, value required
1959
10.5M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1960
10.5M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1961
6.06k
            return suspend_or_fail(state::arr3, size);
1962
10.5M
do_arr4:
1963
10.5M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1964
10.5M
        if(BOOST_JSON_UNLIKELY(! cs))
1965
2.16k
            return maybe_suspend(cs.begin(), state::arr4, size);
1966
10.5M
        if(BOOST_JSON_LIKELY(*cs == ','))
1967
10.5M
        {
1968
10.5M
            ++cs;
1969
10.5M
do_arr5:
1970
10.5M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1971
10.5M
            if(BOOST_JSON_UNLIKELY(! cs))
1972
622
                return maybe_suspend(cs.begin(), state::arr5, size);
1973
            // loop for next element
1974
10.5M
            if(! allow_trailing || *cs != ']')
1975
10.5M
                goto loop;
1976
10.5M
        }
1977
27.1k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1978
1.73k
        {
1979
1.73k
            if(allow_comments && *cs == '/')
1980
344
            {
1981
355
do_arr6:
1982
355
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1983
355
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1984
31
                    return suspend_or_fail(state::arr6, size);
1985
324
                goto do_arr4;
1986
355
            }
1987
1.73k
            BOOST_STATIC_CONSTEXPR source_location loc
1988
1.38k
                = BOOST_CURRENT_LOCATION;
1989
1.38k
            return fail(cs.begin(), error::syntax, &loc);
1990
1.73k
        }
1991
        // got closing bracket; fall through
1992
10.5M
    }
1993
33.6k
    if(BOOST_JSON_UNLIKELY(
1994
33.6k
        ! h_.on_array_end(size, ec_)))
1995
0
        return fail(cs.begin());
1996
33.6k
    ++depth_;
1997
33.6k
    ++cs;
1998
33.6k
    return cs.begin();
1999
33.6k
}
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
1900
29.3k
{
1901
29.3k
    detail::const_stream_wrapper cs(p, end_);
1902
29.3k
    std::size_t size;
1903
29.3k
    if(! stack_empty && ! st_.empty())
1904
0
    {
1905
        // resume
1906
0
        state st;
1907
0
        st_.pop(st);
1908
0
        st_.pop(size);
1909
0
        switch(st)
1910
0
        {
1911
0
        default: BOOST_JSON_UNREACHABLE();
1912
0
        case state::arr1: goto do_arr1;
1913
0
        case state::arr2: goto do_arr2;
1914
0
        case state::arr3: goto do_arr3;
1915
0
        case state::arr4: goto do_arr4;
1916
0
        case state::arr5: goto do_arr5;
1917
0
        case state::arr6: goto do_arr6;
1918
0
        }
1919
0
    }
1920
29.3k
    BOOST_ASSERT(*cs == '[');
1921
29.3k
    size = 0;
1922
29.3k
    if(BOOST_JSON_UNLIKELY(! depth_))
1923
9
    {
1924
9
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1925
9
        return fail(cs.begin(), error::too_deep, &loc);
1926
9
    }
1927
29.3k
    --depth_;
1928
29.3k
    if(BOOST_JSON_UNLIKELY(
1929
29.3k
        ! h_.on_array_begin(ec_)))
1930
0
        return fail(cs.begin());
1931
29.3k
    ++cs;
1932
    // array:
1933
    //     '[' *ws ']'
1934
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1935
29.3k
do_arr1:
1936
29.3k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1937
29.3k
    if(BOOST_JSON_UNLIKELY(! cs))
1938
81
        return maybe_suspend(cs.begin(), state::arr1, size);
1939
29.2k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1940
22.4k
    {
1941
4.86M
loop:
1942
4.86M
        if(allow_comments && *cs == '/')
1943
0
        {
1944
0
do_arr2:
1945
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1946
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1947
0
                return suspend_or_fail(state::arr2, size);
1948
0
            goto do_arr1;
1949
0
        }
1950
4.86M
        if(BOOST_JSON_UNLIKELY(++size >
1951
4.86M
            Handler::max_array_size))
1952
0
        {
1953
0
            BOOST_STATIC_CONSTEXPR source_location loc
1954
0
                = BOOST_CURRENT_LOCATION;
1955
0
            return fail(cs.begin(), error::array_too_large, &loc);
1956
0
        }
1957
4.86M
do_arr3:
1958
        // array is not empty, value required
1959
4.86M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1960
4.86M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1961
2.99k
            return suspend_or_fail(state::arr3, size);
1962
4.85M
do_arr4:
1963
4.85M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1964
4.85M
        if(BOOST_JSON_UNLIKELY(! cs))
1965
691
            return maybe_suspend(cs.begin(), state::arr4, size);
1966
4.85M
        if(BOOST_JSON_LIKELY(*cs == ','))
1967
4.84M
        {
1968
4.84M
            ++cs;
1969
4.84M
do_arr5:
1970
4.84M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1971
4.84M
            if(BOOST_JSON_UNLIKELY(! cs))
1972
218
                return maybe_suspend(cs.begin(), state::arr5, size);
1973
            // loop for next element
1974
4.84M
            if(! allow_trailing || *cs != ']')
1975
4.83M
                goto loop;
1976
4.84M
        }
1977
18.0k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1978
876
        {
1979
876
            if(allow_comments && *cs == '/')
1980
0
            {
1981
0
do_arr6:
1982
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1983
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1984
0
                    return suspend_or_fail(state::arr6, size);
1985
0
                goto do_arr4;
1986
0
            }
1987
876
            BOOST_STATIC_CONSTEXPR source_location loc
1988
876
                = BOOST_CURRENT_LOCATION;
1989
876
            return fail(cs.begin(), error::syntax, &loc);
1990
876
        }
1991
        // got closing bracket; fall through
1992
4.85M
    }
1993
24.4k
    if(BOOST_JSON_UNLIKELY(
1994
24.4k
        ! h_.on_array_end(size, ec_)))
1995
0
        return fail(cs.begin());
1996
24.4k
    ++depth_;
1997
24.4k
    ++cs;
1998
24.4k
    return cs.begin();
1999
24.4k
}
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
1900
11.9k
{
1901
11.9k
    detail::const_stream_wrapper cs(p, end_);
1902
11.9k
    std::size_t size;
1903
11.9k
    if(! stack_empty && ! st_.empty())
1904
0
    {
1905
        // resume
1906
0
        state st;
1907
0
        st_.pop(st);
1908
0
        st_.pop(size);
1909
0
        switch(st)
1910
0
        {
1911
0
        default: BOOST_JSON_UNREACHABLE();
1912
0
        case state::arr1: goto do_arr1;
1913
0
        case state::arr2: goto do_arr2;
1914
0
        case state::arr3: goto do_arr3;
1915
0
        case state::arr4: goto do_arr4;
1916
0
        case state::arr5: goto do_arr5;
1917
0
        case state::arr6: goto do_arr6;
1918
0
        }
1919
0
    }
1920
11.9k
    BOOST_ASSERT(*cs == '[');
1921
11.9k
    size = 0;
1922
11.9k
    if(BOOST_JSON_UNLIKELY(! depth_))
1923
3
    {
1924
3
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1925
3
        return fail(cs.begin(), error::too_deep, &loc);
1926
3
    }
1927
11.9k
    --depth_;
1928
11.9k
    if(BOOST_JSON_UNLIKELY(
1929
11.9k
        ! h_.on_array_begin(ec_)))
1930
0
        return fail(cs.begin());
1931
11.9k
    ++cs;
1932
    // array:
1933
    //     '[' *ws ']'
1934
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1935
12.4k
do_arr1:
1936
12.4k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1937
12.4k
    if(BOOST_JSON_UNLIKELY(! cs))
1938
49
        return maybe_suspend(cs.begin(), state::arr1, size);
1939
12.3k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1940
11.7k
    {
1941
5.73M
loop:
1942
5.73M
        if(allow_comments && *cs == '/')
1943
544
        {
1944
544
do_arr2:
1945
544
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1946
544
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1947
21
                return suspend_or_fail(state::arr2, size);
1948
523
            goto do_arr1;
1949
544
        }
1950
5.73M
        if(BOOST_JSON_UNLIKELY(++size >
1951
5.73M
            Handler::max_array_size))
1952
0
        {
1953
0
            BOOST_STATIC_CONSTEXPR source_location loc
1954
0
                = BOOST_CURRENT_LOCATION;
1955
0
            return fail(cs.begin(), error::array_too_large, &loc);
1956
0
        }
1957
5.73M
do_arr3:
1958
        // array is not empty, value required
1959
5.73M
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1960
5.73M
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1961
1.86k
            return suspend_or_fail(state::arr3, size);
1962
5.73M
do_arr4:
1963
5.73M
        cs = detail::count_whitespace(cs.begin(), cs.end());
1964
5.73M
        if(BOOST_JSON_UNLIKELY(! cs))
1965
136
            return maybe_suspend(cs.begin(), state::arr4, size);
1966
5.73M
        if(BOOST_JSON_LIKELY(*cs == ','))
1967
5.72M
        {
1968
5.72M
            ++cs;
1969
5.72M
do_arr5:
1970
5.72M
            cs = detail::count_whitespace(cs.begin(), cs.end());
1971
5.72M
            if(BOOST_JSON_UNLIKELY(! cs))
1972
132
                return maybe_suspend(cs.begin(), state::arr5, size);
1973
            // loop for next element
1974
5.72M
            if(! allow_trailing || *cs != ']')
1975
5.72M
                goto loop;
1976
5.72M
        }
1977
9.06k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1978
857
        {
1979
857
            if(allow_comments && *cs == '/')
1980
344
            {
1981
344
do_arr6:
1982
344
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1983
344
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1984
20
                    return suspend_or_fail(state::arr6, size);
1985
324
                goto do_arr4;
1986
344
            }
1987
857
            BOOST_STATIC_CONSTEXPR source_location loc
1988
513
                = BOOST_CURRENT_LOCATION;
1989
513
            return fail(cs.begin(), error::syntax, &loc);
1990
857
        }
1991
        // got closing bracket; fall through
1992
5.73M
    }
1993
9.17k
    if(BOOST_JSON_UNLIKELY(
1994
9.17k
        ! h_.on_array_end(size, ec_)))
1995
0
        return fail(cs.begin());
1996
9.17k
    ++depth_;
1997
9.17k
    ++cs;
1998
9.17k
    return cs.begin();
1999
9.17k
}
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
1900
1.22k
{
1901
1.22k
    detail::const_stream_wrapper cs(p, end_);
1902
1.22k
    std::size_t size;
1903
1.22k
    if(! stack_empty && ! st_.empty())
1904
1.22k
    {
1905
        // resume
1906
1.22k
        state st;
1907
1.22k
        st_.pop(st);
1908
1.22k
        st_.pop(size);
1909
1.22k
        switch(st)
1910
1.22k
        {
1911
0
        default: BOOST_JSON_UNREACHABLE();
1912
44
        case state::arr1: goto do_arr1;
1913
0
        case state::arr2: goto do_arr2;
1914
926
        case state::arr3: goto do_arr3;
1915
114
        case state::arr4: goto do_arr4;
1916
140
        case state::arr5: goto do_arr5;
1917
0
        case state::arr6: goto do_arr6;
1918
1.22k
        }
1919
1.22k
    }
1920
0
    BOOST_ASSERT(*cs == '[');
1921
0
    size = 0;
1922
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1923
0
    {
1924
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1925
0
        return fail(cs.begin(), error::too_deep, &loc);
1926
0
    }
1927
0
    --depth_;
1928
0
    if(BOOST_JSON_UNLIKELY(
1929
0
        ! h_.on_array_begin(ec_)))
1930
0
        return fail(cs.begin());
1931
0
    ++cs;
1932
    // array:
1933
    //     '[' *ws ']'
1934
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1935
44
do_arr1:
1936
44
    cs = detail::count_whitespace(cs.begin(), cs.end());
1937
44
    if(BOOST_JSON_UNLIKELY(! cs))
1938
44
        return maybe_suspend(cs.begin(), state::arr1, size);
1939
0
    if(BOOST_JSON_LIKELY(*cs != ']'))
1940
0
    {
1941
0
loop:
1942
0
        if(allow_comments && *cs == '/')
1943
0
        {
1944
0
do_arr2:
1945
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1946
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1947
0
                return suspend_or_fail(state::arr2, size);
1948
0
            goto do_arr1;
1949
0
        }
1950
0
        if(BOOST_JSON_UNLIKELY(++size >
1951
0
            Handler::max_array_size))
1952
0
        {
1953
0
            BOOST_STATIC_CONSTEXPR source_location loc
1954
0
                = BOOST_CURRENT_LOCATION;
1955
0
            return fail(cs.begin(), error::array_too_large, &loc);
1956
0
        }
1957
926
do_arr3:
1958
        // array is not empty, value required
1959
926
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1960
926
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1961
401
            return suspend_or_fail(state::arr3, size);
1962
639
do_arr4:
1963
639
        cs = detail::count_whitespace(cs.begin(), cs.end());
1964
639
        if(BOOST_JSON_UNLIKELY(! cs))
1965
639
            return maybe_suspend(cs.begin(), state::arr4, size);
1966
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1967
0
        {
1968
0
            ++cs;
1969
140
do_arr5:
1970
140
            cs = detail::count_whitespace(cs.begin(), cs.end());
1971
140
            if(BOOST_JSON_UNLIKELY(! cs))
1972
140
                return maybe_suspend(cs.begin(), state::arr5, size);
1973
            // loop for next element
1974
0
            if(! allow_trailing || *cs != ']')
1975
0
                goto loop;
1976
0
        }
1977
0
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1978
0
        {
1979
0
            if(allow_comments && *cs == '/')
1980
0
            {
1981
0
do_arr6:
1982
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1983
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1984
0
                    return suspend_or_fail(state::arr6, size);
1985
0
                goto do_arr4;
1986
0
            }
1987
0
            BOOST_STATIC_CONSTEXPR source_location loc
1988
0
                = BOOST_CURRENT_LOCATION;
1989
0
            return fail(cs.begin(), error::syntax, &loc);
1990
0
        }
1991
        // got closing bracket; fall through
1992
0
    }
1993
0
    if(BOOST_JSON_UNLIKELY(
1994
0
        ! h_.on_array_end(size, ec_)))
1995
0
        return fail(cs.begin());
1996
0
    ++depth_;
1997
0
    ++cs;
1998
0
    return cs.begin();
1999
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
1900
1.71k
{
1901
1.71k
    detail::const_stream_wrapper cs(p, end_);
1902
1.71k
    std::size_t size;
1903
1.71k
    if(! stack_empty && ! st_.empty())
1904
1.71k
    {
1905
        // resume
1906
1.71k
        state st;
1907
1.71k
        st_.pop(st);
1908
1.71k
        st_.pop(size);
1909
1.71k
        switch(st)
1910
1.71k
        {
1911
0
        default: BOOST_JSON_UNREACHABLE();
1912
49
        case state::arr1: goto do_arr1;
1913
17
        case state::arr2: goto do_arr2;
1914
1.37k
        case state::arr3: goto do_arr3;
1915
136
        case state::arr4: goto do_arr4;
1916
132
        case state::arr5: goto do_arr5;
1917
11
        case state::arr6: goto do_arr6;
1918
1.71k
        }
1919
1.71k
    }
1920
0
    BOOST_ASSERT(*cs == '[');
1921
0
    size = 0;
1922
0
    if(BOOST_JSON_UNLIKELY(! depth_))
1923
0
    {
1924
0
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1925
0
        return fail(cs.begin(), error::too_deep, &loc);
1926
0
    }
1927
0
    --depth_;
1928
0
    if(BOOST_JSON_UNLIKELY(
1929
0
        ! h_.on_array_begin(ec_)))
1930
0
        return fail(cs.begin());
1931
0
    ++cs;
1932
    // array:
1933
    //     '[' *ws ']'
1934
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1935
49
do_arr1:
1936
49
    cs = detail::count_whitespace(cs.begin(), cs.end());
1937
49
    if(BOOST_JSON_UNLIKELY(! cs))
1938
49
        return maybe_suspend(cs.begin(), state::arr1, size);
1939
0
    if(BOOST_JSON_LIKELY(*cs != ']'))
1940
0
    {
1941
0
loop:
1942
0
        if(allow_comments && *cs == '/')
1943
0
        {
1944
17
do_arr2:
1945
17
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1946
17
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1947
17
                return suspend_or_fail(state::arr2, size);
1948
0
            goto do_arr1;
1949
17
        }
1950
0
        if(BOOST_JSON_UNLIKELY(++size >
1951
0
            Handler::max_array_size))
1952
0
        {
1953
0
            BOOST_STATIC_CONSTEXPR source_location loc
1954
0
                = BOOST_CURRENT_LOCATION;
1955
0
            return fail(cs.begin(), error::array_too_large, &loc);
1956
0
        }
1957
1.37k
do_arr3:
1958
        // array is not empty, value required
1959
1.37k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1960
1.37k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1961
811
            return suspend_or_fail(state::arr3, size);
1962
697
do_arr4:
1963
697
        cs = detail::count_whitespace(cs.begin(), cs.end());
1964
697
        if(BOOST_JSON_UNLIKELY(! cs))
1965
697
            return maybe_suspend(cs.begin(), state::arr4, size);
1966
0
        if(BOOST_JSON_LIKELY(*cs == ','))
1967
0
        {
1968
0
            ++cs;
1969
132
do_arr5:
1970
132
            cs = detail::count_whitespace(cs.begin(), cs.end());
1971
132
            if(BOOST_JSON_UNLIKELY(! cs))
1972
132
                return maybe_suspend(cs.begin(), state::arr5, size);
1973
            // loop for next element
1974
0
            if(! allow_trailing || *cs != ']')
1975
0
                goto loop;
1976
0
        }
1977
0
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1978
0
        {
1979
0
            if(allow_comments && *cs == '/')
1980
0
            {
1981
11
do_arr6:
1982
11
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1983
11
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1984
11
                    return suspend_or_fail(state::arr6, size);
1985
0
                goto do_arr4;
1986
11
            }
1987
0
            BOOST_STATIC_CONSTEXPR source_location loc
1988
0
                = BOOST_CURRENT_LOCATION;
1989
0
            return fail(cs.begin(), error::syntax, &loc);
1990
0
        }
1991
        // got closing bracket; fall through
1992
0
    }
1993
0
    if(BOOST_JSON_UNLIKELY(
1994
0
        ! h_.on_array_end(size, ec_)))
1995
0
        return fail(cs.begin());
1996
0
    ++depth_;
1997
0
    ++cs;
1998
0
    return cs.begin();
1999
0
}
2000
2001
//----------------------------------------------------------
2002
2003
template<class Handler>
2004
template<bool StackEmpty_, char First_, number_precision Numbers_>
2005
const char*
2006
basic_parser<Handler>::
2007
parse_number(const char* p,
2008
    std::integral_constant<bool, StackEmpty_> stack_empty,
2009
    std::integral_constant<char, First_> first,
2010
    std::integral_constant<number_precision, Numbers_> mode)
2011
12.1M
{
2012
12.1M
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
12.1M
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
12.1M
    bool const negative = first == '-';
2020
12.1M
    bool const zero_first = first == '0';
2021
12.1M
    bool const nonzero_first = first == '+';
2022
12.1M
    detail::const_stream_wrapper cs(p, end_);
2023
12.1M
    number num;
2024
12.1M
    const char* begin = cs.begin();
2025
12.1M
    if(stack_empty || st_.empty())
2026
12.1M
    {
2027
12.1M
        num.bias = 0;
2028
12.1M
        num.exp = 0;
2029
12.1M
        num.frac = false;
2030
12.1M
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
12.1M
        BOOST_ASSERT(cs);
2038
12.1M
        if(negative)
2039
80.2k
            ++cs;
2040
2041
12.1M
        num.neg = negative;
2042
12.1M
        num.frac = false;
2043
12.1M
        num.exp = 0;
2044
12.1M
        num.bias = 0;
2045
2046
        // fast path
2047
12.1M
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
12.1M
        {
2049
12.1M
            int n1;
2050
2051
12.1M
            if( nonzero_first ||
2052
75.5k
                (negative && *cs != '0') )
2053
11.6M
            {
2054
11.6M
                n1 = detail::count_digits( cs.begin() );
2055
11.6M
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
11.6M
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
11.6M
                if( ! nonzero_first && n1 == 0 )
2065
30
                {
2066
                    // digit required
2067
30
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
30
                        = BOOST_CURRENT_LOCATION;
2069
30
                    return fail(cs.begin(), error::syntax, &loc);
2070
30
                }
2071
2072
11.6M
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
11.6M
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
97.6k
                    num.mant = 0;
2076
2077
11.6M
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
11.6M
                if( n1 == 16 )
2082
115k
                {
2083
115k
                    goto do_num2;
2084
115k
                }
2085
11.6M
            }
2086
474k
            else
2087
474k
            {
2088
                // 0. floating-point or 0e integer
2089
474k
                num.mant = 0;
2090
474k
                n1 = 0;
2091
474k
                ++cs;
2092
474k
            }
2093
2094
12.0M
            {
2095
12.0M
                const char c = *cs;
2096
12.0M
                if(c != '.')
2097
11.9M
                {
2098
11.9M
                    if((c | 32) == 'e')
2099
4.87M
                    {
2100
4.87M
                        ++cs;
2101
4.87M
                        goto do_exp1;
2102
4.87M
                    }
2103
7.07M
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
7.07M
                        num.mant = ~num.mant + 1;
2105
7.07M
                    goto finish_signed;
2106
11.9M
                }
2107
12.0M
            }
2108
2109
            // floating-point number
2110
2111
57.5k
            ++cs;
2112
2113
57.5k
            int n2 = detail::count_digits( cs.begin() );
2114
57.5k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
57.5k
            if( n2 == 0 )
2117
32
            {
2118
                // digit required
2119
32
                BOOST_STATIC_CONSTEXPR source_location loc
2120
32
                    = BOOST_CURRENT_LOCATION;
2121
32
                return fail(cs.begin(), error::syntax, &loc);
2122
32
            }
2123
2124
            // floating-point mantissa overflow
2125
57.5k
            if( n1 + n2 >= 19 )
2126
5.62k
            {
2127
5.62k
                goto do_num7;
2128
5.62k
            }
2129
2130
51.9k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
51.9k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
51.9k
            BOOST_ASSERT(num.bias == 0);
2134
2135
51.9k
            num.bias -= n2;
2136
2137
51.9k
            cs += n2;
2138
2139
51.9k
            char ch = *cs;
2140
2141
51.9k
            if( (ch | 32) == 'e' )
2142
10.2k
            {
2143
10.2k
                ++cs;
2144
10.2k
                goto do_exp1;
2145
10.2k
            }
2146
41.6k
            else if( ch >= '0' && ch <= '9' )
2147
14.0k
            {
2148
14.0k
                goto do_num8;
2149
14.0k
            }
2150
2151
27.6k
            goto finish_dub;
2152
51.9k
        }
2153
12.1M
    }
2154
6.67k
    else
2155
6.67k
    {
2156
6.67k
        num = num_;
2157
6.67k
        state st;
2158
6.67k
        st_.pop(st);
2159
6.67k
        switch(st)
2160
6.67k
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
52
        case state::num1: goto do_num1;
2163
1.17k
        case state::num2: goto do_num2;
2164
577
        case state::num3: goto do_num3;
2165
6
        case state::num4: goto do_num4;
2166
1.04k
        case state::num5: goto do_num5;
2167
90
        case state::num6: goto do_num6;
2168
47
        case state::num7: goto do_num7;
2169
1.23k
        case state::num8: goto do_num8;
2170
185
        case state::exp1: goto do_exp1;
2171
95
        case state::exp2: goto do_exp2;
2172
2.18k
        case state::exp3: goto do_exp3;
2173
6.67k
        }
2174
6.67k
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
27.6k
do_num1:
2182
27.6k
    if(zero_first || nonzero_first ||
2183
4.66k
        BOOST_JSON_LIKELY(cs))
2184
27.5k
    {
2185
27.5k
        char const c = *cs;
2186
27.5k
        if(zero_first)
2187
5.95k
        {
2188
5.95k
            ++cs;
2189
5.95k
            num.mant = 0;
2190
5.95k
            goto do_num6;
2191
5.95k
        }
2192
21.5k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
21.5k
            c >= '1' && c <= '9'))
2194
20.6k
        {
2195
20.6k
            ++cs;
2196
20.6k
            num.mant = c - '0';
2197
20.6k
        }
2198
929
        else if(BOOST_JSON_UNLIKELY(
2199
929
            c == '0'))
2200
827
        {
2201
827
            ++cs;
2202
827
            num.mant = 0;
2203
827
            goto do_num6;
2204
827
        }
2205
102
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
102
        else
2214
102
        {
2215
102
            BOOST_STATIC_CONSTEXPR source_location loc
2216
102
                = BOOST_CURRENT_LOCATION;
2217
102
            return fail(cs.begin(), error::syntax, &loc);
2218
102
        }
2219
27.5k
    }
2220
116
    else
2221
116
    {
2222
116
        if(BOOST_JSON_UNLIKELY(
2223
116
            ! h_.on_number_part(
2224
116
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
116
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
116
            num_buf_.append( begin, cs.used(begin) );
2229
116
        return maybe_suspend(
2230
116
            cs.begin(), state::num1, num);
2231
116
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
137k
do_num2:
2239
137k
    if(negative || (!stack_empty && num.neg))
2240
20.1k
    {
2241
20.1k
        for(;;)
2242
64.4k
        {
2243
64.4k
            if(BOOST_JSON_UNLIKELY(! cs))
2244
963
            {
2245
963
                if(BOOST_JSON_UNLIKELY(more_))
2246
410
                {
2247
410
                    if(BOOST_JSON_UNLIKELY(
2248
410
                        ! h_.on_number_part(
2249
410
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
410
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
410
                        num_buf_.append( begin, cs.used(begin) );
2254
410
                    return suspend(cs.begin(), state::num2, num);
2255
410
                }
2256
553
                goto finish_int;
2257
963
            }
2258
63.5k
            char const c = *cs;
2259
63.5k
            if(BOOST_JSON_LIKELY(
2260
63.5k
                c >= '0' && c <= '9'))
2261
52.1k
            {
2262
52.1k
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
52.1k
                if( num.mant  > 922337203685477580 || (
2265
45.8k
                    num.mant == 922337203685477580 && c > '8'))
2266
7.79k
                    break;
2267
44.3k
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
44.3k
                    num.mant = 10 * num.mant + ( c - '0' );
2269
44.3k
                continue;
2270
52.1k
            }
2271
11.3k
            goto do_num6; // [.eE]
2272
63.5k
        }
2273
20.1k
    }
2274
116k
    else
2275
116k
    {
2276
116k
        for(;;)
2277
464k
        {
2278
464k
            if(BOOST_JSON_UNLIKELY(! cs))
2279
1.81k
            {
2280
1.81k
                if(BOOST_JSON_UNLIKELY(more_))
2281
760
                {
2282
760
                    if(BOOST_JSON_UNLIKELY(
2283
760
                        ! h_.on_number_part(
2284
760
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
760
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
760
                        num_buf_.append( begin, cs.used(begin) );
2289
760
                    return suspend(cs.begin(), state::num2, num);
2290
760
                }
2291
1.05k
                goto finish_int;
2292
1.81k
            }
2293
462k
            char const c = *cs;
2294
462k
            if(BOOST_JSON_LIKELY(
2295
462k
                c >= '0' && c <= '9'))
2296
373k
            {
2297
373k
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
373k
                if( num.mant  > 1844674407370955161 || (
2300
349k
                    num.mant == 1844674407370955161 && c > '5'))
2301
25.9k
                    break;
2302
347k
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
347k
                    num.mant = 10 * num.mant + ( c - '0' );
2304
347k
            }
2305
89.1k
            else
2306
89.1k
            {
2307
89.1k
                goto do_num6; // [.eE]
2308
89.1k
            }
2309
462k
        }
2310
116k
    }
2311
33.7k
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
34.3k
do_num3:
2319
34.3k
    for(;;)
2320
47.5M
    {
2321
47.5M
        if(BOOST_JSON_UNLIKELY(! cs))
2322
1.22k
        {
2323
1.22k
            if(BOOST_JSON_UNLIKELY(more_))
2324
577
            {
2325
577
                if(BOOST_JSON_UNLIKELY(
2326
577
                    ! h_.on_number_part(
2327
577
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
577
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
577
                    num_buf_.append( begin, cs.used(begin) );
2332
577
                return suspend(cs.begin(), state::num3, num);
2333
577
            }
2334
645
            goto finish_dub;
2335
1.22k
        }
2336
47.5M
        char const c = *cs;
2337
47.5M
        if(BOOST_JSON_UNLIKELY(
2338
47.5M
            c >= '0' && c <= '9'))
2339
47.5M
        {
2340
47.5M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
47.5M
            ++cs;
2347
47.5M
            ++num.bias;
2348
47.5M
        }
2349
33.1k
        else if(BOOST_JSON_LIKELY(
2350
33.1k
            c == '.'))
2351
5.52k
        {
2352
5.52k
            ++cs;
2353
5.52k
            break;
2354
5.52k
        }
2355
27.5k
        else if((c | 32) == 'e')
2356
8.43k
        {
2357
8.43k
            ++cs;
2358
8.43k
            goto do_exp1;
2359
8.43k
        }
2360
19.1k
        else
2361
19.1k
        {
2362
19.1k
            goto finish_dub;
2363
19.1k
        }
2364
47.5M
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
5.53k
do_num4:
2373
5.53k
    {
2374
5.53k
        if(BOOST_JSON_UNLIKELY(! cs))
2375
19
        {
2376
19
            if(BOOST_JSON_UNLIKELY(
2377
19
                ! h_.on_number_part(
2378
19
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
19
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
19
                num_buf_.append( begin, cs.used(begin) );
2383
19
            return maybe_suspend(
2384
19
                cs.begin(), state::num4, num);
2385
19
        }
2386
5.51k
        char const c = *cs;
2387
5.51k
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
5.51k
            c >= '0' && c <= '9'))
2390
5.46k
        {
2391
5.46k
            ++cs;
2392
5.46k
        }
2393
54
        else
2394
54
        {
2395
            // digit required
2396
54
            BOOST_STATIC_CONSTEXPR source_location loc
2397
54
                = BOOST_CURRENT_LOCATION;
2398
54
            return fail(cs.begin(), error::syntax, &loc);
2399
54
        }
2400
5.51k
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
31.4k
do_num5:
2409
31.4k
    for(;;)
2410
12.2M
    {
2411
12.2M
        if(BOOST_JSON_UNLIKELY(! cs))
2412
2.17k
        {
2413
2.17k
            if(BOOST_JSON_UNLIKELY(more_))
2414
1.04k
            {
2415
1.04k
                if(BOOST_JSON_UNLIKELY(
2416
1.04k
                    ! h_.on_number_part(
2417
1.04k
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
1.04k
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
1.04k
                    num_buf_.append( begin, cs.used(begin) );
2422
1.04k
                return suspend(cs.begin(), state::num5, num);
2423
1.04k
            }
2424
1.13k
            goto finish_dub;
2425
2.17k
        }
2426
12.2M
        char const c = *cs;
2427
12.2M
        if(BOOST_JSON_LIKELY(
2428
12.2M
            c >= '0' && c <= '9'))
2429
12.1M
        {
2430
12.1M
            ++cs;
2431
12.1M
        }
2432
29.2k
        else if((c | 32) == 'e')
2433
7.83k
        {
2434
7.83k
            ++cs;
2435
7.83k
            goto do_exp1;
2436
7.83k
        }
2437
21.4k
        else
2438
21.4k
        {
2439
21.4k
            goto finish_dub;
2440
21.4k
        }
2441
12.2M
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
107k
do_num6:
2448
107k
    {
2449
107k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
199
        {
2451
199
            if(BOOST_JSON_UNLIKELY(more_))
2452
90
            {
2453
90
                if(BOOST_JSON_UNLIKELY(
2454
90
                    ! h_.on_number_part(
2455
90
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
90
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
90
                    num_buf_.append( begin, cs.used(begin) );
2460
90
                return suspend(cs.begin(), state::num6, num);
2461
90
            }
2462
109
            goto finish_int;
2463
199
        }
2464
107k
        char const c = *cs;
2465
107k
        if(BOOST_JSON_LIKELY(
2466
107k
            c == '.'))
2467
14.3k
        {
2468
14.3k
            ++cs;
2469
14.3k
        }
2470
92.9k
        else if((c | 32) == 'e')
2471
9.07k
        {
2472
9.07k
            ++cs;
2473
9.07k
            goto do_exp1;
2474
9.07k
        }
2475
83.8k
        else
2476
83.8k
        {
2477
83.8k
            goto finish_int;
2478
83.8k
        }
2479
107k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
19.9k
do_num7:
2488
19.9k
    {
2489
19.9k
        if(BOOST_JSON_UNLIKELY(! cs))
2490
109
        {
2491
109
            if(BOOST_JSON_UNLIKELY(more_))
2492
47
            {
2493
47
                if(BOOST_JSON_UNLIKELY(
2494
47
                    ! h_.on_number_part(
2495
47
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
47
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
47
                    num_buf_.append( begin, cs.used(begin) );
2500
47
                return suspend(cs.begin(), state::num7, num);
2501
47
            }
2502
            // digit required
2503
109
            BOOST_STATIC_CONSTEXPR source_location loc
2504
62
                = BOOST_CURRENT_LOCATION;
2505
62
            return fail(cs.begin(), error::syntax, &loc);
2506
109
        }
2507
19.8k
        char const c = *cs;
2508
19.8k
        if(BOOST_JSON_UNLIKELY(
2509
19.8k
            c < '0' || c > '9'))
2510
152
        {
2511
            // digit required
2512
152
            BOOST_STATIC_CONSTEXPR source_location loc
2513
152
                = BOOST_CURRENT_LOCATION;
2514
152
            return fail(cs.begin(), error::syntax, &loc);
2515
152
        }
2516
19.8k
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
35.0k
do_num8:
2525
35.0k
    for(;;)
2526
28.2M
    {
2527
28.2M
        if(BOOST_JSON_UNLIKELY(! cs))
2528
2.80k
        {
2529
2.80k
            if(BOOST_JSON_UNLIKELY(more_))
2530
1.23k
            {
2531
1.23k
                if(BOOST_JSON_UNLIKELY(
2532
1.23k
                    ! h_.on_number_part(
2533
1.23k
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
1.23k
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
1.23k
                    num_buf_.append( begin, cs.used(begin) );
2538
1.23k
                return suspend(cs.begin(), state::num8, num);
2539
1.23k
            }
2540
1.57k
            goto finish_dub;
2541
2.80k
        }
2542
28.2M
        char const c = *cs;
2543
28.2M
        if(BOOST_JSON_LIKELY(
2544
28.2M
            c >= '0' && c <= '9'))
2545
28.2M
        {
2546
28.2M
            ++cs;
2547
28.2M
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
28.2M
                num.mant <= 9007199254740991)) // 2^53-1
2549
28.1M
            {
2550
28.1M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
28.1M
                --num.bias;
2557
28.1M
                num.mant = 10 * num.mant + ( c - '0' );
2558
28.1M
            }
2559
24.9k
            else
2560
24.9k
            {
2561
24.9k
                goto do_num5;
2562
24.9k
            }
2563
28.2M
        }
2564
7.23k
        else if((c | 32) == 'e')
2565
2.60k
        {
2566
2.60k
            ++cs;
2567
2.60k
            goto do_exp1;
2568
2.60k
        }
2569
4.63k
        else
2570
4.63k
        {
2571
4.63k
            goto finish_dub;
2572
4.63k
        }
2573
28.2M
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
4.91M
do_exp1:
2580
4.91M
    if(BOOST_JSON_UNLIKELY(! cs))
2581
451
    {
2582
451
        if(BOOST_JSON_UNLIKELY(
2583
451
            ! h_.on_number_part(
2584
451
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
451
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
451
            num_buf_.append( begin, cs.used(begin) );
2589
451
        return maybe_suspend(
2590
451
            cs.begin(), state::exp1, num);
2591
451
    }
2592
4.91M
    if(*cs == '+')
2593
3.06k
    {
2594
3.06k
        ++cs;
2595
3.06k
    }
2596
4.90M
    else if(*cs == '-')
2597
82.5k
    {
2598
82.5k
        ++cs;
2599
82.5k
        num.frac = true;
2600
82.5k
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
4.91M
do_exp2:
2608
4.91M
    {
2609
4.91M
        if(BOOST_JSON_UNLIKELY(! cs))
2610
228
        {
2611
228
            if(BOOST_JSON_UNLIKELY(more_))
2612
95
            {
2613
95
                if(BOOST_JSON_UNLIKELY(
2614
95
                    ! h_.on_number_part(
2615
95
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
95
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
95
                    num_buf_.append( begin, cs.used(begin) );
2620
95
                return suspend(cs.begin(), state::exp2, num);
2621
95
            }
2622
            // digit required
2623
228
            BOOST_STATIC_CONSTEXPR source_location loc
2624
133
                = BOOST_CURRENT_LOCATION;
2625
133
            return fail(cs.begin(), error::syntax, &loc);
2626
228
        }
2627
4.91M
        char const c = *cs;
2628
4.91M
        if(BOOST_JSON_UNLIKELY(
2629
4.91M
            c < '0' || c > '9'))
2630
272
        {
2631
            // digit required
2632
272
            BOOST_STATIC_CONSTEXPR source_location loc
2633
272
                = BOOST_CURRENT_LOCATION;
2634
272
            return fail(cs.begin(), error::syntax, &loc);
2635
272
        }
2636
4.91M
        ++cs;
2637
4.91M
        num.exp = c - '0';
2638
4.91M
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
4.91M
do_exp3:
2646
4.91M
    for(;;)
2647
10.1M
    {
2648
10.1M
        if(BOOST_JSON_UNLIKELY(! cs))
2649
5.45k
        {
2650
5.45k
            if(BOOST_JSON_UNLIKELY(more_))
2651
2.18k
            {
2652
2.18k
                if(BOOST_JSON_UNLIKELY(
2653
2.18k
                    ! h_.on_number_part(
2654
2.18k
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
2.18k
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
2.18k
                    num_buf_.append( begin, cs.used(begin) );
2659
2.18k
                return suspend(cs.begin(), state::exp3, num);
2660
2.18k
            }
2661
5.45k
        }
2662
10.1M
        else
2663
10.1M
        {
2664
10.1M
            char const c = *cs;
2665
10.1M
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
5.23M
            {
2667
5.23M
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
5.23M
                    num.exp  >  214748364 ||
2670
5.23M
                    (num.exp == 214748364 && c > '7')
2671
5.23M
                ))
2672
166k
                    num.exp = INT_MAX;
2673
5.06M
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
5.06M
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
5.23M
                ++cs;
2677
5.23M
                continue;
2678
5.23M
            }
2679
10.1M
        }
2680
4.91M
        BOOST_ASSERT(num.exp >= 0);
2681
4.91M
        if ( num.frac )
2682
82.4k
        {
2683
82.4k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
4.21k
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
4.21k
                if(BOOST_JSON_UNLIKELY(
2689
4.21k
                    (num.exp == INT_MAX) &&
2690
4.21k
                    (num.bias < 0) &&
2691
4.21k
                    (num.exp + num.bias < 308) &&
2692
4.21k
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
4.21k
                num.bias = 0;
2700
4.21k
                num.exp = INT_MAX;
2701
4.21k
            }
2702
82.4k
        }
2703
4.82M
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
2.92k
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
2.92k
            if(BOOST_JSON_UNLIKELY(
2709
2.92k
                (num.exp == INT_MAX) &&
2710
2.92k
                (num.bias > 0) &&
2711
2.92k
                (num.exp - num.bias < 308) &&
2712
2.92k
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
2.92k
            num.bias = 0;
2720
2.92k
            num.exp = INT_MAX;
2721
2.92k
        }
2722
4.91M
        goto finish_dub;
2723
4.91M
    }
2724
2725
85.5k
finish_int:
2726
85.5k
    if(negative || (!stack_empty && num.neg))
2727
7.39k
    {
2728
7.39k
        if(BOOST_JSON_UNLIKELY(
2729
7.39k
            ! h_.on_int64(static_cast<
2730
7.39k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
7.39k
        return cs.begin();
2733
7.39k
    }
2734
78.1k
    if(num.mant <= INT64_MAX)
2735
22.8k
    {
2736
7.09M
finish_signed:
2737
7.09M
        if(BOOST_JSON_UNLIKELY(
2738
7.09M
            ! h_.on_int64(static_cast<
2739
7.09M
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
7.09M
        return cs.begin();
2742
7.09M
    }
2743
55.2k
    if(BOOST_JSON_UNLIKELY(
2744
55.2k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
55.2k
    return cs.begin();
2747
4.98M
finish_dub:
2748
4.98M
    double d;
2749
4.98M
    std::size_t const size = cs.used(begin);
2750
4.98M
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
280k
    {
2753
280k
        char const* data = begin;
2754
280k
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
280k
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
3.55k
        {
2760
3.55k
            data = num_buf_.append( begin, size );
2761
3.55k
            full_size = num_buf_.size();
2762
3.55k
        }
2763
280k
        auto const err = detail::charconv::from_chars(
2764
280k
            data, data + full_size, d );
2765
280k
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
280k
        BOOST_ASSERT( err.ptr == data + full_size );
2767
280k
        (void)err;
2768
    }
2769
4.70M
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
4.70M
        d = 0;
2771
    else
2772
4.67M
        d = detail::dec_to_float(
2773
4.67M
            num.mant,
2774
4.67M
            num.bias + (num.frac ?
2775
4.60M
                -num.exp : num.exp),
2776
4.67M
            num.neg);
2777
4.98M
    if(BOOST_JSON_UNLIKELY(
2778
4.98M
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
4.98M
    return cs.begin();
2781
4.98M
}
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
2011
237k
{
2012
237k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
237k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
237k
    bool const negative = first == '-';
2020
237k
    bool const zero_first = first == '0';
2021
237k
    bool const nonzero_first = first == '+';
2022
237k
    detail::const_stream_wrapper cs(p, end_);
2023
237k
    number num;
2024
237k
    const char* begin = cs.begin();
2025
237k
    if(stack_empty || st_.empty())
2026
237k
    {
2027
237k
        num.bias = 0;
2028
237k
        num.exp = 0;
2029
237k
        num.frac = false;
2030
237k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
237k
        BOOST_ASSERT(cs);
2038
237k
        if(negative)
2039
0
            ++cs;
2040
2041
237k
        num.neg = negative;
2042
237k
        num.frac = false;
2043
237k
        num.exp = 0;
2044
237k
        num.bias = 0;
2045
2046
        // fast path
2047
237k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
233k
        {
2049
233k
            int n1;
2050
2051
233k
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
0
            {
2054
0
                n1 = detail::count_digits( cs.begin() );
2055
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
0
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
0
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
0
                if( n1 == 16 )
2082
0
                {
2083
0
                    goto do_num2;
2084
0
                }
2085
0
            }
2086
233k
            else
2087
233k
            {
2088
                // 0. floating-point or 0e integer
2089
233k
                num.mant = 0;
2090
233k
                n1 = 0;
2091
233k
                ++cs;
2092
233k
            }
2093
2094
233k
            {
2095
233k
                const char c = *cs;
2096
233k
                if(c != '.')
2097
223k
                {
2098
223k
                    if((c | 32) == 'e')
2099
3.29k
                    {
2100
3.29k
                        ++cs;
2101
3.29k
                        goto do_exp1;
2102
3.29k
                    }
2103
220k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
220k
                        num.mant = ~num.mant + 1;
2105
220k
                    goto finish_signed;
2106
223k
                }
2107
233k
            }
2108
2109
            // floating-point number
2110
2111
10.1k
            ++cs;
2112
2113
10.1k
            int n2 = detail::count_digits( cs.begin() );
2114
10.1k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
10.1k
            if( n2 == 0 )
2117
6
            {
2118
                // digit required
2119
6
                BOOST_STATIC_CONSTEXPR source_location loc
2120
6
                    = BOOST_CURRENT_LOCATION;
2121
6
                return fail(cs.begin(), error::syntax, &loc);
2122
6
            }
2123
2124
            // floating-point mantissa overflow
2125
10.1k
            if( n1 + n2 >= 19 )
2126
0
            {
2127
0
                goto do_num7;
2128
0
            }
2129
2130
10.1k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
10.1k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
10.1k
            BOOST_ASSERT(num.bias == 0);
2134
2135
10.1k
            num.bias -= n2;
2136
2137
10.1k
            cs += n2;
2138
2139
10.1k
            char ch = *cs;
2140
2141
10.1k
            if( (ch | 32) == 'e' )
2142
1.39k
            {
2143
1.39k
                ++cs;
2144
1.39k
                goto do_exp1;
2145
1.39k
            }
2146
8.73k
            else if( ch >= '0' && ch <= '9' )
2147
4.83k
            {
2148
4.83k
                goto do_num8;
2149
4.83k
            }
2150
2151
3.90k
            goto finish_dub;
2152
10.1k
        }
2153
237k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
3.81k
do_num1:
2182
3.81k
    if(zero_first || nonzero_first ||
2183
0
        BOOST_JSON_LIKELY(cs))
2184
3.81k
    {
2185
3.81k
        char const c = *cs;
2186
3.81k
        if(zero_first)
2187
3.81k
        {
2188
3.81k
            ++cs;
2189
3.81k
            num.mant = 0;
2190
3.81k
            goto do_num6;
2191
3.81k
        }
2192
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
0
            c >= '1' && c <= '9'))
2194
0
        {
2195
0
            ++cs;
2196
0
            num.mant = c - '0';
2197
0
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
3.81k
    }
2220
0
    else
2221
0
    {
2222
0
        if(BOOST_JSON_UNLIKELY(
2223
0
            ! h_.on_number_part(
2224
0
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
0
            num_buf_.append( begin, cs.used(begin) );
2229
0
        return maybe_suspend(
2230
0
            cs.begin(), state::num1, num);
2231
0
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
0
do_num2:
2239
0
    if(negative || (!stack_empty && num.neg))
2240
0
    {
2241
0
        for(;;)
2242
0
        {
2243
0
            if(BOOST_JSON_UNLIKELY(! cs))
2244
0
            {
2245
0
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
0
                goto finish_int;
2257
0
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
0
    }
2274
0
    else
2275
0
    {
2276
0
        for(;;)
2277
0
        {
2278
0
            if(BOOST_JSON_UNLIKELY(! cs))
2279
0
            {
2280
0
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
0
                goto finish_int;
2292
0
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
0
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
0
do_num3:
2319
0
    for(;;)
2320
0
    {
2321
0
        if(BOOST_JSON_UNLIKELY(! cs))
2322
0
        {
2323
0
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
0
            goto finish_dub;
2335
0
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
0
do_num4:
2373
0
    {
2374
0
        if(BOOST_JSON_UNLIKELY(! cs))
2375
0
        {
2376
0
            if(BOOST_JSON_UNLIKELY(
2377
0
                ! h_.on_number_part(
2378
0
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
0
                num_buf_.append( begin, cs.used(begin) );
2383
0
            return maybe_suspend(
2384
0
                cs.begin(), state::num4, num);
2385
0
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
3.58k
do_num5:
2409
3.58k
    for(;;)
2410
42.3k
    {
2411
42.3k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
30
        {
2413
30
            if(BOOST_JSON_UNLIKELY(more_))
2414
14
            {
2415
14
                if(BOOST_JSON_UNLIKELY(
2416
14
                    ! h_.on_number_part(
2417
14
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
14
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
14
                    num_buf_.append( begin, cs.used(begin) );
2422
14
                return suspend(cs.begin(), state::num5, num);
2423
14
            }
2424
16
            goto finish_dub;
2425
30
        }
2426
42.3k
        char const c = *cs;
2427
42.3k
        if(BOOST_JSON_LIKELY(
2428
42.3k
            c >= '0' && c <= '9'))
2429
38.7k
        {
2430
38.7k
            ++cs;
2431
38.7k
        }
2432
3.55k
        else if((c | 32) == 'e')
2433
683
        {
2434
683
            ++cs;
2435
683
            goto do_exp1;
2436
683
        }
2437
2.86k
        else
2438
2.86k
        {
2439
2.86k
            goto finish_dub;
2440
2.86k
        }
2441
42.3k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
3.81k
do_num6:
2448
3.81k
    {
2449
3.81k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
39
        {
2451
39
            if(BOOST_JSON_UNLIKELY(more_))
2452
26
            {
2453
26
                if(BOOST_JSON_UNLIKELY(
2454
26
                    ! h_.on_number_part(
2455
26
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
26
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
26
                    num_buf_.append( begin, cs.used(begin) );
2460
26
                return suspend(cs.begin(), state::num6, num);
2461
26
            }
2462
13
            goto finish_int;
2463
39
        }
2464
3.77k
        char const c = *cs;
2465
3.77k
        if(BOOST_JSON_LIKELY(
2466
3.77k
            c == '.'))
2467
803
        {
2468
803
            ++cs;
2469
803
        }
2470
2.97k
        else if((c | 32) == 'e')
2471
1.06k
        {
2472
1.06k
            ++cs;
2473
1.06k
            goto do_exp1;
2474
1.06k
        }
2475
1.90k
        else
2476
1.90k
        {
2477
1.90k
            goto finish_int;
2478
1.90k
        }
2479
3.77k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
803
do_num7:
2488
803
    {
2489
803
        if(BOOST_JSON_UNLIKELY(! cs))
2490
14
        {
2491
14
            if(BOOST_JSON_UNLIKELY(more_))
2492
8
            {
2493
8
                if(BOOST_JSON_UNLIKELY(
2494
8
                    ! h_.on_number_part(
2495
8
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
8
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
8
                    num_buf_.append( begin, cs.used(begin) );
2500
8
                return suspend(cs.begin(), state::num7, num);
2501
8
            }
2502
            // digit required
2503
14
            BOOST_STATIC_CONSTEXPR source_location loc
2504
6
                = BOOST_CURRENT_LOCATION;
2505
6
            return fail(cs.begin(), error::syntax, &loc);
2506
14
        }
2507
789
        char const c = *cs;
2508
789
        if(BOOST_JSON_UNLIKELY(
2509
789
            c < '0' || c > '9'))
2510
30
        {
2511
            // digit required
2512
30
            BOOST_STATIC_CONSTEXPR source_location loc
2513
30
                = BOOST_CURRENT_LOCATION;
2514
30
            return fail(cs.begin(), error::syntax, &loc);
2515
30
        }
2516
789
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
5.59k
do_num8:
2525
5.59k
    for(;;)
2526
8.77M
    {
2527
8.77M
        if(BOOST_JSON_UNLIKELY(! cs))
2528
225
        {
2529
225
            if(BOOST_JSON_UNLIKELY(more_))
2530
101
            {
2531
101
                if(BOOST_JSON_UNLIKELY(
2532
101
                    ! h_.on_number_part(
2533
101
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
101
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
101
                    num_buf_.append( begin, cs.used(begin) );
2538
101
                return suspend(cs.begin(), state::num8, num);
2539
101
            }
2540
124
            goto finish_dub;
2541
225
        }
2542
8.77M
        char const c = *cs;
2543
8.77M
        if(BOOST_JSON_LIKELY(
2544
8.77M
            c >= '0' && c <= '9'))
2545
8.77M
        {
2546
8.77M
            ++cs;
2547
8.77M
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
8.77M
                num.mant <= 9007199254740991)) // 2^53-1
2549
8.77M
            {
2550
8.77M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
8.77M
                --num.bias;
2557
8.77M
                num.mant = 10 * num.mant + ( c - '0' );
2558
8.77M
            }
2559
3.58k
            else
2560
3.58k
            {
2561
3.58k
                goto do_num5;
2562
3.58k
            }
2563
8.77M
        }
2564
1.78k
        else if((c | 32) == 'e')
2565
653
        {
2566
653
            ++cs;
2567
653
            goto do_exp1;
2568
653
        }
2569
1.13k
        else
2570
1.13k
        {
2571
1.13k
            goto finish_dub;
2572
1.13k
        }
2573
8.77M
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
7.08k
do_exp1:
2580
7.08k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
39
    {
2582
39
        if(BOOST_JSON_UNLIKELY(
2583
39
            ! h_.on_number_part(
2584
39
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
39
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
39
            num_buf_.append( begin, cs.used(begin) );
2589
39
        return maybe_suspend(
2590
39
            cs.begin(), state::exp1, num);
2591
39
    }
2592
7.04k
    if(*cs == '+')
2593
724
    {
2594
724
        ++cs;
2595
724
    }
2596
6.32k
    else if(*cs == '-')
2597
2.19k
    {
2598
2.19k
        ++cs;
2599
2.19k
        num.frac = true;
2600
2.19k
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
7.04k
do_exp2:
2608
7.04k
    {
2609
7.04k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
23
        {
2611
23
            if(BOOST_JSON_UNLIKELY(more_))
2612
11
            {
2613
11
                if(BOOST_JSON_UNLIKELY(
2614
11
                    ! h_.on_number_part(
2615
11
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
11
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
11
                    num_buf_.append( begin, cs.used(begin) );
2620
11
                return suspend(cs.begin(), state::exp2, num);
2621
11
            }
2622
            // digit required
2623
23
            BOOST_STATIC_CONSTEXPR source_location loc
2624
12
                = BOOST_CURRENT_LOCATION;
2625
12
            return fail(cs.begin(), error::syntax, &loc);
2626
23
        }
2627
7.02k
        char const c = *cs;
2628
7.02k
        if(BOOST_JSON_UNLIKELY(
2629
7.02k
            c < '0' || c > '9'))
2630
46
        {
2631
            // digit required
2632
46
            BOOST_STATIC_CONSTEXPR source_location loc
2633
46
                = BOOST_CURRENT_LOCATION;
2634
46
            return fail(cs.begin(), error::syntax, &loc);
2635
46
        }
2636
6.98k
        ++cs;
2637
6.98k
        num.exp = c - '0';
2638
6.98k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
6.98k
do_exp3:
2646
6.98k
    for(;;)
2647
30.0k
    {
2648
30.0k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
503
        {
2650
503
            if(BOOST_JSON_UNLIKELY(more_))
2651
141
            {
2652
141
                if(BOOST_JSON_UNLIKELY(
2653
141
                    ! h_.on_number_part(
2654
141
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
141
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
141
                    num_buf_.append( begin, cs.used(begin) );
2659
141
                return suspend(cs.begin(), state::exp3, num);
2660
141
            }
2661
503
        }
2662
29.5k
        else
2663
29.5k
        {
2664
29.5k
            char const c = *cs;
2665
29.5k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
23.0k
            {
2667
23.0k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
23.0k
                    num.exp  >  214748364 ||
2670
23.0k
                    (num.exp == 214748364 && c > '7')
2671
23.0k
                ))
2672
2.20k
                    num.exp = INT_MAX;
2673
20.8k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
20.8k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
23.0k
                ++cs;
2677
23.0k
                continue;
2678
23.0k
            }
2679
29.5k
        }
2680
6.83k
        BOOST_ASSERT(num.exp >= 0);
2681
6.83k
        if ( num.frac )
2682
2.14k
        {
2683
2.14k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
883
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
883
                if(BOOST_JSON_UNLIKELY(
2689
883
                    (num.exp == INT_MAX) &&
2690
883
                    (num.bias < 0) &&
2691
883
                    (num.exp + num.bias < 308) &&
2692
883
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
883
                num.bias = 0;
2700
883
                num.exp = INT_MAX;
2701
883
            }
2702
2.14k
        }
2703
4.69k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
0
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
0
            if(BOOST_JSON_UNLIKELY(
2709
0
                (num.exp == INT_MAX) &&
2710
0
                (num.bias > 0) &&
2711
0
                (num.exp - num.bias < 308) &&
2712
0
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
0
            num.bias = 0;
2720
0
            num.exp = INT_MAX;
2721
0
        }
2722
6.83k
        goto finish_dub;
2723
6.83k
    }
2724
2725
1.92k
finish_int:
2726
1.92k
    if(negative || (!stack_empty && num.neg))
2727
0
    {
2728
0
        if(BOOST_JSON_UNLIKELY(
2729
0
            ! h_.on_int64(static_cast<
2730
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
0
        return cs.begin();
2733
0
    }
2734
1.92k
    if(num.mant <= INT64_MAX)
2735
1.92k
    {
2736
222k
finish_signed:
2737
222k
        if(BOOST_JSON_UNLIKELY(
2738
222k
            ! h_.on_int64(static_cast<
2739
222k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
222k
        return cs.begin();
2742
222k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
14.8k
finish_dub:
2748
14.8k
    double d;
2749
14.8k
    std::size_t const size = cs.used(begin);
2750
14.8k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
14.8k
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
14.8k
        d = 0;
2771
14.8k
    else
2772
14.8k
        d = detail::dec_to_float(
2773
14.8k
            num.mant,
2774
14.8k
            num.bias + (num.frac ?
2775
12.7k
                -num.exp : num.exp),
2776
14.8k
            num.neg);
2777
14.8k
    if(BOOST_JSON_UNLIKELY(
2778
14.8k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
14.8k
    return cs.begin();
2781
14.8k
}
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>)
Line
Count
Source
2011
223k
{
2012
223k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
223k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
223k
    bool const negative = first == '-';
2020
223k
    bool const zero_first = first == '0';
2021
223k
    bool const nonzero_first = first == '+';
2022
223k
    detail::const_stream_wrapper cs(p, end_);
2023
223k
    number num;
2024
223k
    const char* begin = cs.begin();
2025
223k
    if(stack_empty || st_.empty())
2026
223k
    {
2027
223k
        num.bias = 0;
2028
223k
        num.exp = 0;
2029
223k
        num.frac = false;
2030
223k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
223k
        BOOST_ASSERT(cs);
2038
223k
        if(negative)
2039
0
            ++cs;
2040
2041
223k
        num.neg = negative;
2042
223k
        num.frac = false;
2043
223k
        num.exp = 0;
2044
223k
        num.bias = 0;
2045
2046
        // fast path
2047
223k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
222k
        {
2049
222k
            int n1;
2050
2051
222k
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
0
            {
2054
0
                n1 = detail::count_digits( cs.begin() );
2055
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
0
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
0
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
0
                if( n1 == 16 )
2082
0
                {
2083
0
                    goto do_num2;
2084
0
                }
2085
0
            }
2086
222k
            else
2087
222k
            {
2088
                // 0. floating-point or 0e integer
2089
222k
                num.mant = 0;
2090
222k
                n1 = 0;
2091
222k
                ++cs;
2092
222k
            }
2093
2094
222k
            {
2095
222k
                const char c = *cs;
2096
222k
                if(c != '.')
2097
217k
                {
2098
217k
                    if((c | 32) == 'e')
2099
1.07k
                    {
2100
1.07k
                        ++cs;
2101
1.07k
                        goto do_exp1;
2102
1.07k
                    }
2103
216k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
216k
                        num.mant = ~num.mant + 1;
2105
216k
                    goto finish_signed;
2106
217k
                }
2107
222k
            }
2108
2109
            // floating-point number
2110
2111
4.79k
            ++cs;
2112
2113
4.79k
            int n2 = detail::count_digits( cs.begin() );
2114
4.79k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
4.79k
            if( n2 == 0 )
2117
1
            {
2118
                // digit required
2119
1
                BOOST_STATIC_CONSTEXPR source_location loc
2120
1
                    = BOOST_CURRENT_LOCATION;
2121
1
                return fail(cs.begin(), error::syntax, &loc);
2122
1
            }
2123
2124
            // floating-point mantissa overflow
2125
4.79k
            if( n1 + n2 >= 19 )
2126
0
            {
2127
0
                goto do_num7;
2128
0
            }
2129
2130
4.79k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
4.79k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
4.79k
            BOOST_ASSERT(num.bias == 0);
2134
2135
4.79k
            num.bias -= n2;
2136
2137
4.79k
            cs += n2;
2138
2139
4.79k
            char ch = *cs;
2140
2141
4.79k
            if( (ch | 32) == 'e' )
2142
985
            {
2143
985
                ++cs;
2144
985
                goto do_exp1;
2145
985
            }
2146
3.81k
            else if( ch >= '0' && ch <= '9' )
2147
1.75k
            {
2148
1.75k
                goto do_num8;
2149
1.75k
            }
2150
2151
2.05k
            goto finish_dub;
2152
4.79k
        }
2153
223k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
1.30k
do_num1:
2182
1.30k
    if(zero_first || nonzero_first ||
2183
0
        BOOST_JSON_LIKELY(cs))
2184
1.30k
    {
2185
1.30k
        char const c = *cs;
2186
1.30k
        if(zero_first)
2187
1.30k
        {
2188
1.30k
            ++cs;
2189
1.30k
            num.mant = 0;
2190
1.30k
            goto do_num6;
2191
1.30k
        }
2192
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
0
            c >= '1' && c <= '9'))
2194
0
        {
2195
0
            ++cs;
2196
0
            num.mant = c - '0';
2197
0
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
1.30k
    }
2220
0
    else
2221
0
    {
2222
0
        if(BOOST_JSON_UNLIKELY(
2223
0
            ! h_.on_number_part(
2224
0
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
0
            num_buf_.append( begin, cs.used(begin) );
2229
0
        return maybe_suspend(
2230
0
            cs.begin(), state::num1, num);
2231
0
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
0
do_num2:
2239
0
    if(negative || (!stack_empty && num.neg))
2240
0
    {
2241
0
        for(;;)
2242
0
        {
2243
0
            if(BOOST_JSON_UNLIKELY(! cs))
2244
0
            {
2245
0
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
0
                goto finish_int;
2257
0
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
0
    }
2274
0
    else
2275
0
    {
2276
0
        for(;;)
2277
0
        {
2278
0
            if(BOOST_JSON_UNLIKELY(! cs))
2279
0
            {
2280
0
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
0
                goto finish_int;
2292
0
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
0
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
0
do_num3:
2319
0
    for(;;)
2320
0
    {
2321
0
        if(BOOST_JSON_UNLIKELY(! cs))
2322
0
        {
2323
0
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
0
            goto finish_dub;
2335
0
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
0
do_num4:
2373
0
    {
2374
0
        if(BOOST_JSON_UNLIKELY(! cs))
2375
0
        {
2376
0
            if(BOOST_JSON_UNLIKELY(
2377
0
                ! h_.on_number_part(
2378
0
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
0
                num_buf_.append( begin, cs.used(begin) );
2383
0
            return maybe_suspend(
2384
0
                cs.begin(), state::num4, num);
2385
0
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
1.09k
do_num5:
2409
1.09k
    for(;;)
2410
737k
    {
2411
737k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
111
        {
2413
111
            if(BOOST_JSON_UNLIKELY(more_))
2414
111
            {
2415
111
                if(BOOST_JSON_UNLIKELY(
2416
111
                    ! h_.on_number_part(
2417
111
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
111
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
111
                    num_buf_.append( begin, cs.used(begin) );
2422
111
                return suspend(cs.begin(), state::num5, num);
2423
111
            }
2424
0
            goto finish_dub;
2425
111
        }
2426
737k
        char const c = *cs;
2427
737k
        if(BOOST_JSON_LIKELY(
2428
737k
            c >= '0' && c <= '9'))
2429
736k
        {
2430
736k
            ++cs;
2431
736k
        }
2432
984
        else if((c | 32) == 'e')
2433
412
        {
2434
412
            ++cs;
2435
412
            goto do_exp1;
2436
412
        }
2437
572
        else
2438
572
        {
2439
572
            goto finish_dub;
2440
572
        }
2441
737k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
1.30k
do_num6:
2448
1.30k
    {
2449
1.30k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
29
        {
2451
29
            if(BOOST_JSON_UNLIKELY(more_))
2452
29
            {
2453
29
                if(BOOST_JSON_UNLIKELY(
2454
29
                    ! h_.on_number_part(
2455
29
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
29
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
29
                    num_buf_.append( begin, cs.used(begin) );
2460
29
                return suspend(cs.begin(), state::num6, num);
2461
29
            }
2462
0
            goto finish_int;
2463
29
        }
2464
1.27k
        char const c = *cs;
2465
1.27k
        if(BOOST_JSON_LIKELY(
2466
1.27k
            c == '.'))
2467
443
        {
2468
443
            ++cs;
2469
443
        }
2470
836
        else if((c | 32) == 'e')
2471
396
        {
2472
396
            ++cs;
2473
396
            goto do_exp1;
2474
396
        }
2475
440
        else
2476
440
        {
2477
440
            goto finish_int;
2478
440
        }
2479
1.27k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
443
do_num7:
2488
443
    {
2489
443
        if(BOOST_JSON_UNLIKELY(! cs))
2490
4
        {
2491
4
            if(BOOST_JSON_UNLIKELY(more_))
2492
4
            {
2493
4
                if(BOOST_JSON_UNLIKELY(
2494
4
                    ! h_.on_number_part(
2495
4
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
4
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
4
                    num_buf_.append( begin, cs.used(begin) );
2500
4
                return suspend(cs.begin(), state::num7, num);
2501
4
            }
2502
            // digit required
2503
4
            BOOST_STATIC_CONSTEXPR source_location loc
2504
0
                = BOOST_CURRENT_LOCATION;
2505
0
            return fail(cs.begin(), error::syntax, &loc);
2506
4
        }
2507
439
        char const c = *cs;
2508
439
        if(BOOST_JSON_UNLIKELY(
2509
439
            c < '0' || c > '9'))
2510
13
        {
2511
            // digit required
2512
13
            BOOST_STATIC_CONSTEXPR source_location loc
2513
13
                = BOOST_CURRENT_LOCATION;
2514
13
            return fail(cs.begin(), error::syntax, &loc);
2515
13
        }
2516
439
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
2.18k
do_num8:
2525
2.18k
    for(;;)
2526
5.49M
    {
2527
5.49M
        if(BOOST_JSON_UNLIKELY(! cs))
2528
116
        {
2529
116
            if(BOOST_JSON_UNLIKELY(more_))
2530
116
            {
2531
116
                if(BOOST_JSON_UNLIKELY(
2532
116
                    ! h_.on_number_part(
2533
116
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
116
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
116
                    num_buf_.append( begin, cs.used(begin) );
2538
116
                return suspend(cs.begin(), state::num8, num);
2539
116
            }
2540
0
            goto finish_dub;
2541
116
        }
2542
5.49M
        char const c = *cs;
2543
5.49M
        if(BOOST_JSON_LIKELY(
2544
5.49M
            c >= '0' && c <= '9'))
2545
5.49M
        {
2546
5.49M
            ++cs;
2547
5.49M
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
5.49M
                num.mant <= 9007199254740991)) // 2^53-1
2549
5.49M
            {
2550
5.49M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
5.49M
                --num.bias;
2557
5.49M
                num.mant = 10 * num.mant + ( c - '0' );
2558
5.49M
            }
2559
1.09k
            else
2560
1.09k
            {
2561
1.09k
                goto do_num5;
2562
1.09k
            }
2563
5.49M
        }
2564
972
        else if((c | 32) == 'e')
2565
301
        {
2566
301
            ++cs;
2567
301
            goto do_exp1;
2568
301
        }
2569
671
        else
2570
671
        {
2571
671
            goto finish_dub;
2572
671
        }
2573
5.49M
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
3.16k
do_exp1:
2580
3.16k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
18
    {
2582
18
        if(BOOST_JSON_UNLIKELY(
2583
18
            ! h_.on_number_part(
2584
18
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
18
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
18
            num_buf_.append( begin, cs.used(begin) );
2589
18
        return maybe_suspend(
2590
18
            cs.begin(), state::exp1, num);
2591
18
    }
2592
3.14k
    if(*cs == '+')
2593
208
    {
2594
208
        ++cs;
2595
208
    }
2596
2.94k
    else if(*cs == '-')
2597
916
    {
2598
916
        ++cs;
2599
916
        num.frac = true;
2600
916
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
3.14k
do_exp2:
2608
3.14k
    {
2609
3.14k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
10
        {
2611
10
            if(BOOST_JSON_UNLIKELY(more_))
2612
10
            {
2613
10
                if(BOOST_JSON_UNLIKELY(
2614
10
                    ! h_.on_number_part(
2615
10
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
10
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
10
                    num_buf_.append( begin, cs.used(begin) );
2620
10
                return suspend(cs.begin(), state::exp2, num);
2621
10
            }
2622
            // digit required
2623
10
            BOOST_STATIC_CONSTEXPR source_location loc
2624
0
                = BOOST_CURRENT_LOCATION;
2625
0
            return fail(cs.begin(), error::syntax, &loc);
2626
10
        }
2627
3.13k
        char const c = *cs;
2628
3.13k
        if(BOOST_JSON_UNLIKELY(
2629
3.13k
            c < '0' || c > '9'))
2630
23
        {
2631
            // digit required
2632
23
            BOOST_STATIC_CONSTEXPR source_location loc
2633
23
                = BOOST_CURRENT_LOCATION;
2634
23
            return fail(cs.begin(), error::syntax, &loc);
2635
23
        }
2636
3.11k
        ++cs;
2637
3.11k
        num.exp = c - '0';
2638
3.11k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
3.11k
do_exp3:
2646
3.11k
    for(;;)
2647
13.5k
    {
2648
13.5k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
211
        {
2650
211
            if(BOOST_JSON_UNLIKELY(more_))
2651
211
            {
2652
211
                if(BOOST_JSON_UNLIKELY(
2653
211
                    ! h_.on_number_part(
2654
211
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
211
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
211
                    num_buf_.append( begin, cs.used(begin) );
2659
211
                return suspend(cs.begin(), state::exp3, num);
2660
211
            }
2661
211
        }
2662
13.3k
        else
2663
13.3k
        {
2664
13.3k
            char const c = *cs;
2665
13.3k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
10.4k
            {
2667
10.4k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
10.4k
                    num.exp  >  214748364 ||
2670
10.4k
                    (num.exp == 214748364 && c > '7')
2671
10.4k
                ))
2672
1.43k
                    num.exp = INT_MAX;
2673
9.00k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
9.00k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
10.4k
                ++cs;
2677
10.4k
                continue;
2678
10.4k
            }
2679
13.3k
        }
2680
2.90k
        BOOST_ASSERT(num.exp >= 0);
2681
2.90k
        if ( num.frac )
2682
862
        {
2683
862
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
462
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
462
                if(BOOST_JSON_UNLIKELY(
2689
462
                    (num.exp == INT_MAX) &&
2690
462
                    (num.bias < 0) &&
2691
462
                    (num.exp + num.bias < 308) &&
2692
462
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
462
                num.bias = 0;
2700
462
                num.exp = INT_MAX;
2701
462
            }
2702
862
        }
2703
2.04k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
0
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
0
            if(BOOST_JSON_UNLIKELY(
2709
0
                (num.exp == INT_MAX) &&
2710
0
                (num.bias > 0) &&
2711
0
                (num.exp - num.bias < 308) &&
2712
0
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
0
            num.bias = 0;
2720
0
            num.exp = INT_MAX;
2721
0
        }
2722
2.90k
        goto finish_dub;
2723
2.90k
    }
2724
2725
440
finish_int:
2726
440
    if(negative || (!stack_empty && num.neg))
2727
0
    {
2728
0
        if(BOOST_JSON_UNLIKELY(
2729
0
            ! h_.on_int64(static_cast<
2730
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
0
        return cs.begin();
2733
0
    }
2734
440
    if(num.mant <= INT64_MAX)
2735
440
    {
2736
216k
finish_signed:
2737
216k
        if(BOOST_JSON_UNLIKELY(
2738
216k
            ! h_.on_int64(static_cast<
2739
216k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
216k
        return cs.begin();
2742
216k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
6.20k
finish_dub:
2748
6.20k
    double d;
2749
6.20k
    std::size_t const size = cs.used(begin);
2750
6.20k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
6.20k
    {
2753
6.20k
        char const* data = begin;
2754
6.20k
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
6.20k
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
0
        {
2760
0
            data = num_buf_.append( begin, size );
2761
0
            full_size = num_buf_.size();
2762
0
        }
2763
6.20k
        auto const err = detail::charconv::from_chars(
2764
6.20k
            data, data + full_size, d );
2765
6.20k
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
6.20k
        BOOST_ASSERT( err.ptr == data + full_size );
2767
6.20k
        (void)err;
2768
    }
2769
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
6.20k
    if(BOOST_JSON_UNLIKELY(
2778
6.20k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
6.20k
    return cs.begin();
2781
6.20k
}
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>)
Line
Count
Source
2011
7.94k
{
2012
7.94k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
7.94k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
7.94k
    bool const negative = first == '-';
2020
7.94k
    bool const zero_first = first == '0';
2021
7.94k
    bool const nonzero_first = first == '+';
2022
7.94k
    detail::const_stream_wrapper cs(p, end_);
2023
7.94k
    number num;
2024
7.94k
    const char* begin = cs.begin();
2025
7.94k
    if(stack_empty || st_.empty())
2026
7.94k
    {
2027
7.94k
        num.bias = 0;
2028
7.94k
        num.exp = 0;
2029
7.94k
        num.frac = false;
2030
7.94k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
7.94k
        BOOST_ASSERT(cs);
2038
7.94k
        if(negative)
2039
0
            ++cs;
2040
2041
7.94k
        num.neg = negative;
2042
7.94k
        num.frac = false;
2043
7.94k
        num.exp = 0;
2044
7.94k
        num.bias = 0;
2045
2046
        // fast path
2047
7.94k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
7.10k
        {
2049
7.10k
            int n1;
2050
2051
7.10k
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
0
            {
2054
0
                n1 = detail::count_digits( cs.begin() );
2055
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
0
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
0
                else
2075
0
                    num.mant = 0;
2076
2077
0
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
0
                if( n1 == 16 )
2082
0
                {
2083
0
                    goto do_num2;
2084
0
                }
2085
0
            }
2086
7.10k
            else
2087
7.10k
            {
2088
                // 0. floating-point or 0e integer
2089
7.10k
                num.mant = 0;
2090
7.10k
                n1 = 0;
2091
7.10k
                ++cs;
2092
7.10k
            }
2093
2094
7.10k
            {
2095
7.10k
                const char c = *cs;
2096
7.10k
                if(c != '.')
2097
5.15k
                {
2098
5.15k
                    if((c | 32) == 'e')
2099
675
                    {
2100
675
                        ++cs;
2101
675
                        goto do_exp1;
2102
675
                    }
2103
4.48k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
4.48k
                        num.mant = ~num.mant + 1;
2105
4.48k
                    goto finish_signed;
2106
5.15k
                }
2107
7.10k
            }
2108
2109
            // floating-point number
2110
2111
1.95k
            ++cs;
2112
2113
1.95k
            int n2 = detail::count_digits( cs.begin() );
2114
1.95k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
1.95k
            if( n2 == 0 )
2117
2
            {
2118
                // digit required
2119
2
                BOOST_STATIC_CONSTEXPR source_location loc
2120
2
                    = BOOST_CURRENT_LOCATION;
2121
2
                return fail(cs.begin(), error::syntax, &loc);
2122
2
            }
2123
2124
            // floating-point mantissa overflow
2125
1.95k
            if( n1 + n2 >= 19 )
2126
0
            {
2127
0
                goto do_num7;
2128
0
            }
2129
2130
1.95k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
1.95k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
1.95k
            BOOST_ASSERT(num.bias == 0);
2134
2135
1.95k
            num.bias -= n2;
2136
2137
1.95k
            cs += n2;
2138
2139
1.95k
            char ch = *cs;
2140
2141
1.95k
            if( (ch | 32) == 'e' )
2142
517
            {
2143
517
                ++cs;
2144
517
                goto do_exp1;
2145
517
            }
2146
1.43k
            else if( ch >= '0' && ch <= '9' )
2147
817
            {
2148
817
                goto do_num8;
2149
817
            }
2150
2151
616
            goto finish_dub;
2152
1.95k
        }
2153
7.94k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
832
do_num1:
2182
832
    if(zero_first || nonzero_first ||
2183
0
        BOOST_JSON_LIKELY(cs))
2184
832
    {
2185
832
        char const c = *cs;
2186
832
        if(zero_first)
2187
832
        {
2188
832
            ++cs;
2189
832
            num.mant = 0;
2190
832
            goto do_num6;
2191
832
        }
2192
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
0
            c >= '1' && c <= '9'))
2194
0
        {
2195
0
            ++cs;
2196
0
            num.mant = c - '0';
2197
0
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
832
    }
2220
0
    else
2221
0
    {
2222
0
        if(BOOST_JSON_UNLIKELY(
2223
0
            ! h_.on_number_part(
2224
0
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
0
            num_buf_.append( begin, cs.used(begin) );
2229
0
        return maybe_suspend(
2230
0
            cs.begin(), state::num1, num);
2231
0
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
0
do_num2:
2239
0
    if(negative || (!stack_empty && num.neg))
2240
0
    {
2241
0
        for(;;)
2242
0
        {
2243
0
            if(BOOST_JSON_UNLIKELY(! cs))
2244
0
            {
2245
0
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
0
                goto finish_int;
2257
0
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
0
    }
2274
0
    else
2275
0
    {
2276
0
        for(;;)
2277
0
        {
2278
0
            if(BOOST_JSON_UNLIKELY(! cs))
2279
0
            {
2280
0
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
0
                goto finish_int;
2292
0
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
0
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
0
do_num3:
2319
0
    for(;;)
2320
0
    {
2321
0
        if(BOOST_JSON_UNLIKELY(! cs))
2322
0
        {
2323
0
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
0
            goto finish_dub;
2335
0
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
0
do_num4:
2373
0
    {
2374
0
        if(BOOST_JSON_UNLIKELY(! cs))
2375
0
        {
2376
0
            if(BOOST_JSON_UNLIKELY(
2377
0
                ! h_.on_number_part(
2378
0
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
0
                num_buf_.append( begin, cs.used(begin) );
2383
0
            return maybe_suspend(
2384
0
                cs.begin(), state::num4, num);
2385
0
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
937
do_num5:
2409
937
    for(;;)
2410
5.07k
    {
2411
5.07k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
19
        {
2413
19
            if(BOOST_JSON_UNLIKELY(more_))
2414
19
            {
2415
19
                if(BOOST_JSON_UNLIKELY(
2416
19
                    ! h_.on_number_part(
2417
19
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
19
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
19
                    num_buf_.append( begin, cs.used(begin) );
2422
19
                return suspend(cs.begin(), state::num5, num);
2423
19
            }
2424
0
            goto finish_dub;
2425
19
        }
2426
5.05k
        char const c = *cs;
2427
5.05k
        if(BOOST_JSON_LIKELY(
2428
5.05k
            c >= '0' && c <= '9'))
2429
4.13k
        {
2430
4.13k
            ++cs;
2431
4.13k
        }
2432
918
        else if((c | 32) == 'e')
2433
381
        {
2434
381
            ++cs;
2435
381
            goto do_exp1;
2436
381
        }
2437
537
        else
2438
537
        {
2439
537
            goto finish_dub;
2440
537
        }
2441
5.05k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
832
do_num6:
2448
832
    {
2449
832
        if(BOOST_JSON_UNLIKELY(! cs))
2450
18
        {
2451
18
            if(BOOST_JSON_UNLIKELY(more_))
2452
18
            {
2453
18
                if(BOOST_JSON_UNLIKELY(
2454
18
                    ! h_.on_number_part(
2455
18
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
18
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
18
                    num_buf_.append( begin, cs.used(begin) );
2460
18
                return suspend(cs.begin(), state::num6, num);
2461
18
            }
2462
0
            goto finish_int;
2463
18
        }
2464
814
        char const c = *cs;
2465
814
        if(BOOST_JSON_LIKELY(
2466
814
            c == '.'))
2467
137
        {
2468
137
            ++cs;
2469
137
        }
2470
677
        else if((c | 32) == 'e')
2471
223
        {
2472
223
            ++cs;
2473
223
            goto do_exp1;
2474
223
        }
2475
454
        else
2476
454
        {
2477
454
            goto finish_int;
2478
454
        }
2479
814
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
137
do_num7:
2488
137
    {
2489
137
        if(BOOST_JSON_UNLIKELY(! cs))
2490
4
        {
2491
4
            if(BOOST_JSON_UNLIKELY(more_))
2492
4
            {
2493
4
                if(BOOST_JSON_UNLIKELY(
2494
4
                    ! h_.on_number_part(
2495
4
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
4
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
4
                    num_buf_.append( begin, cs.used(begin) );
2500
4
                return suspend(cs.begin(), state::num7, num);
2501
4
            }
2502
            // digit required
2503
4
            BOOST_STATIC_CONSTEXPR source_location loc
2504
0
                = BOOST_CURRENT_LOCATION;
2505
0
            return fail(cs.begin(), error::syntax, &loc);
2506
4
        }
2507
133
        char const c = *cs;
2508
133
        if(BOOST_JSON_UNLIKELY(
2509
133
            c < '0' || c > '9'))
2510
13
        {
2511
            // digit required
2512
13
            BOOST_STATIC_CONSTEXPR source_location loc
2513
13
                = BOOST_CURRENT_LOCATION;
2514
13
            return fail(cs.begin(), error::syntax, &loc);
2515
13
        }
2516
133
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
937
do_num8:
2525
937
    for(;;)
2526
937
    {
2527
937
        if(BOOST_JSON_UNLIKELY(! cs))
2528
0
        {
2529
0
            if(BOOST_JSON_UNLIKELY(more_))
2530
0
            {
2531
0
                if(BOOST_JSON_UNLIKELY(
2532
0
                    ! h_.on_number_part(
2533
0
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
0
                    num_buf_.append( begin, cs.used(begin) );
2538
0
                return suspend(cs.begin(), state::num8, num);
2539
0
            }
2540
0
            goto finish_dub;
2541
0
        }
2542
937
        char const c = *cs;
2543
937
        if(BOOST_JSON_LIKELY(
2544
937
            c >= '0' && c <= '9'))
2545
937
        {
2546
937
            ++cs;
2547
937
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
937
                num.mant <= 9007199254740991)) // 2^53-1
2549
0
            {
2550
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
0
                --num.bias;
2557
0
                num.mant = 10 * num.mant + ( c - '0' );
2558
0
            }
2559
937
            else
2560
937
            {
2561
937
                goto do_num5;
2562
937
            }
2563
937
        }
2564
0
        else if((c | 32) == 'e')
2565
0
        {
2566
0
            ++cs;
2567
0
            goto do_exp1;
2568
0
        }
2569
0
        else
2570
0
        {
2571
0
            goto finish_dub;
2572
0
        }
2573
937
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
1.79k
do_exp1:
2580
1.79k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
16
    {
2582
16
        if(BOOST_JSON_UNLIKELY(
2583
16
            ! h_.on_number_part(
2584
16
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
16
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
16
            num_buf_.append( begin, cs.used(begin) );
2589
16
        return maybe_suspend(
2590
16
            cs.begin(), state::exp1, num);
2591
16
    }
2592
1.78k
    if(*cs == '+')
2593
195
    {
2594
195
        ++cs;
2595
195
    }
2596
1.58k
    else if(*cs == '-')
2597
223
    {
2598
223
        ++cs;
2599
223
        num.frac = true;
2600
223
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
1.78k
do_exp2:
2608
1.78k
    {
2609
1.78k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
12
        {
2611
12
            if(BOOST_JSON_UNLIKELY(more_))
2612
12
            {
2613
12
                if(BOOST_JSON_UNLIKELY(
2614
12
                    ! h_.on_number_part(
2615
12
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
12
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
12
                    num_buf_.append( begin, cs.used(begin) );
2620
12
                return suspend(cs.begin(), state::exp2, num);
2621
12
            }
2622
            // digit required
2623
12
            BOOST_STATIC_CONSTEXPR source_location loc
2624
0
                = BOOST_CURRENT_LOCATION;
2625
0
            return fail(cs.begin(), error::syntax, &loc);
2626
12
        }
2627
1.76k
        char const c = *cs;
2628
1.76k
        if(BOOST_JSON_UNLIKELY(
2629
1.76k
            c < '0' || c > '9'))
2630
19
        {
2631
            // digit required
2632
19
            BOOST_STATIC_CONSTEXPR source_location loc
2633
19
                = BOOST_CURRENT_LOCATION;
2634
19
            return fail(cs.begin(), error::syntax, &loc);
2635
19
        }
2636
1.74k
        ++cs;
2637
1.74k
        num.exp = c - '0';
2638
1.74k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
1.74k
do_exp3:
2646
1.74k
    for(;;)
2647
2.80k
    {
2648
2.80k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
19
        {
2650
19
            if(BOOST_JSON_UNLIKELY(more_))
2651
19
            {
2652
19
                if(BOOST_JSON_UNLIKELY(
2653
19
                    ! h_.on_number_part(
2654
19
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
19
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
19
                    num_buf_.append( begin, cs.used(begin) );
2659
19
                return suspend(cs.begin(), state::exp3, num);
2660
19
            }
2661
19
        }
2662
2.78k
        else
2663
2.78k
        {
2664
2.78k
            char const c = *cs;
2665
2.78k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
1.05k
            {
2667
1.05k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
1.05k
                    num.exp  >  214748364 ||
2670
1.05k
                    (num.exp == 214748364 && c > '7')
2671
1.05k
                ))
2672
0
                    num.exp = INT_MAX;
2673
1.05k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
1.05k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
1.05k
                ++cs;
2677
1.05k
                continue;
2678
1.05k
            }
2679
2.78k
        }
2680
1.73k
        BOOST_ASSERT(num.exp >= 0);
2681
1.73k
        if ( num.frac )
2682
218
        {
2683
218
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
0
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
0
                if(BOOST_JSON_UNLIKELY(
2689
0
                    (num.exp == INT_MAX) &&
2690
0
                    (num.bias < 0) &&
2691
0
                    (num.exp + num.bias < 308) &&
2692
0
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
0
                num.bias = 0;
2700
0
                num.exp = INT_MAX;
2701
0
            }
2702
218
        }
2703
1.51k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
0
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
0
            if(BOOST_JSON_UNLIKELY(
2709
0
                (num.exp == INT_MAX) &&
2710
0
                (num.bias > 0) &&
2711
0
                (num.exp - num.bias < 308) &&
2712
0
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
0
            num.bias = 0;
2720
0
            num.exp = INT_MAX;
2721
0
        }
2722
1.73k
        goto finish_dub;
2723
1.73k
    }
2724
2725
454
finish_int:
2726
454
    if(negative || (!stack_empty && num.neg))
2727
0
    {
2728
0
        if(BOOST_JSON_UNLIKELY(
2729
0
            ! h_.on_int64(static_cast<
2730
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
0
        return cs.begin();
2733
0
    }
2734
454
    if(num.mant <= INT64_MAX)
2735
454
    {
2736
4.93k
finish_signed:
2737
4.93k
        if(BOOST_JSON_UNLIKELY(
2738
4.93k
            ! h_.on_int64(static_cast<
2739
4.93k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
4.93k
        return cs.begin();
2742
4.93k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
2.88k
finish_dub:
2748
2.88k
    double d;
2749
2.88k
    std::size_t const size = cs.used(begin);
2750
2.88k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
2.88k
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
2.88k
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
2.88k
    if(BOOST_JSON_UNLIKELY(
2778
2.88k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
2.88k
    return cs.begin();
2781
2.88k
}
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
2011
60.0k
{
2012
60.0k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
60.0k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
60.0k
    bool const negative = first == '-';
2020
60.0k
    bool const zero_first = first == '0';
2021
60.0k
    bool const nonzero_first = first == '+';
2022
60.0k
    detail::const_stream_wrapper cs(p, end_);
2023
60.0k
    number num;
2024
60.0k
    const char* begin = cs.begin();
2025
60.0k
    if(stack_empty || st_.empty())
2026
60.0k
    {
2027
60.0k
        num.bias = 0;
2028
60.0k
        num.exp = 0;
2029
60.0k
        num.frac = false;
2030
60.0k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
60.0k
        BOOST_ASSERT(cs);
2038
60.0k
        if(negative)
2039
60.0k
            ++cs;
2040
2041
60.0k
        num.neg = negative;
2042
60.0k
        num.frac = false;
2043
60.0k
        num.exp = 0;
2044
60.0k
        num.bias = 0;
2045
2046
        // fast path
2047
60.0k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
57.3k
        {
2049
57.3k
            int n1;
2050
2051
57.3k
            if( nonzero_first ||
2052
57.3k
                (negative && *cs != '0') )
2053
52.0k
            {
2054
52.0k
                n1 = detail::count_digits( cs.begin() );
2055
52.0k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
52.0k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
52.0k
                if( ! nonzero_first && n1 == 0 )
2065
23
                {
2066
                    // digit required
2067
23
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
23
                        = BOOST_CURRENT_LOCATION;
2069
23
                    return fail(cs.begin(), error::syntax, &loc);
2070
23
                }
2071
2072
52.0k
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
52.0k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
52.0k
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
52.0k
                if( n1 == 16 )
2082
11.9k
                {
2083
11.9k
                    goto do_num2;
2084
11.9k
                }
2085
52.0k
            }
2086
5.31k
            else
2087
5.31k
            {
2088
                // 0. floating-point or 0e integer
2089
5.31k
                num.mant = 0;
2090
5.31k
                n1 = 0;
2091
5.31k
                ++cs;
2092
5.31k
            }
2093
2094
45.4k
            {
2095
45.4k
                const char c = *cs;
2096
45.4k
                if(c != '.')
2097
37.7k
                {
2098
37.7k
                    if((c | 32) == 'e')
2099
20.7k
                    {
2100
20.7k
                        ++cs;
2101
20.7k
                        goto do_exp1;
2102
20.7k
                    }
2103
17.0k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
17.0k
                        num.mant = ~num.mant + 1;
2105
17.0k
                    goto finish_signed;
2106
37.7k
                }
2107
45.4k
            }
2108
2109
            // floating-point number
2110
2111
7.65k
            ++cs;
2112
2113
7.65k
            int n2 = detail::count_digits( cs.begin() );
2114
7.65k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
7.65k
            if( n2 == 0 )
2117
6
            {
2118
                // digit required
2119
6
                BOOST_STATIC_CONSTEXPR source_location loc
2120
6
                    = BOOST_CURRENT_LOCATION;
2121
6
                return fail(cs.begin(), error::syntax, &loc);
2122
6
            }
2123
2124
            // floating-point mantissa overflow
2125
7.65k
            if( n1 + n2 >= 19 )
2126
1.32k
            {
2127
1.32k
                goto do_num7;
2128
1.32k
            }
2129
2130
6.32k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
6.32k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
6.32k
            BOOST_ASSERT(num.bias == 0);
2134
2135
6.32k
            num.bias -= n2;
2136
2137
6.32k
            cs += n2;
2138
2139
6.32k
            char ch = *cs;
2140
2141
6.32k
            if( (ch | 32) == 'e' )
2142
1.53k
            {
2143
1.53k
                ++cs;
2144
1.53k
                goto do_exp1;
2145
1.53k
            }
2146
4.79k
            else if( ch >= '0' && ch <= '9' )
2147
1.39k
            {
2148
1.39k
                goto do_num8;
2149
1.39k
            }
2150
2151
3.39k
            goto finish_dub;
2152
6.32k
        }
2153
60.0k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
2.73k
do_num1:
2182
2.73k
    if(zero_first || nonzero_first ||
2183
2.73k
        BOOST_JSON_LIKELY(cs))
2184
2.70k
    {
2185
2.70k
        char const c = *cs;
2186
2.70k
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
2.70k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
2.70k
            c >= '1' && c <= '9'))
2194
2.22k
        {
2195
2.22k
            ++cs;
2196
2.22k
            num.mant = c - '0';
2197
2.22k
        }
2198
483
        else if(BOOST_JSON_UNLIKELY(
2199
483
            c == '0'))
2200
435
        {
2201
435
            ++cs;
2202
435
            num.mant = 0;
2203
435
            goto do_num6;
2204
435
        }
2205
48
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
48
        else
2214
48
        {
2215
48
            BOOST_STATIC_CONSTEXPR source_location loc
2216
48
                = BOOST_CURRENT_LOCATION;
2217
48
            return fail(cs.begin(), error::syntax, &loc);
2218
48
        }
2219
2.70k
    }
2220
28
    else
2221
28
    {
2222
28
        if(BOOST_JSON_UNLIKELY(
2223
28
            ! h_.on_number_part(
2224
28
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
28
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
28
            num_buf_.append( begin, cs.used(begin) );
2229
28
        return maybe_suspend(
2230
28
            cs.begin(), state::num1, num);
2231
28
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
14.1k
do_num2:
2239
14.1k
    if(negative || (!stack_empty && num.neg))
2240
14.1k
    {
2241
14.1k
        for(;;)
2242
46.4k
        {
2243
46.4k
            if(BOOST_JSON_UNLIKELY(! cs))
2244
335
            {
2245
335
                if(BOOST_JSON_UNLIKELY(more_))
2246
192
                {
2247
192
                    if(BOOST_JSON_UNLIKELY(
2248
192
                        ! h_.on_number_part(
2249
192
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
192
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
192
                        num_buf_.append( begin, cs.used(begin) );
2254
192
                    return suspend(cs.begin(), state::num2, num);
2255
192
                }
2256
143
                goto finish_int;
2257
335
            }
2258
46.1k
            char const c = *cs;
2259
46.1k
            if(BOOST_JSON_LIKELY(
2260
46.1k
                c >= '0' && c <= '9'))
2261
37.9k
            {
2262
37.9k
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
37.9k
                if( num.mant  > 922337203685477580 || (
2265
33.5k
                    num.mant == 922337203685477580 && c > '8'))
2266
5.63k
                    break;
2267
32.3k
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
32.3k
                    num.mant = 10 * num.mant + ( c - '0' );
2269
32.3k
                continue;
2270
37.9k
            }
2271
8.15k
            goto do_num6; // [.eE]
2272
46.1k
        }
2273
14.1k
    }
2274
0
    else
2275
0
    {
2276
0
        for(;;)
2277
0
        {
2278
0
            if(BOOST_JSON_UNLIKELY(! cs))
2279
0
            {
2280
0
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
0
                goto finish_int;
2292
0
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
0
    }
2311
5.63k
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
5.63k
do_num3:
2319
5.63k
    for(;;)
2320
13.0M
    {
2321
13.0M
        if(BOOST_JSON_UNLIKELY(! cs))
2322
57
        {
2323
57
            if(BOOST_JSON_UNLIKELY(more_))
2324
27
            {
2325
27
                if(BOOST_JSON_UNLIKELY(
2326
27
                    ! h_.on_number_part(
2327
27
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
27
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
27
                    num_buf_.append( begin, cs.used(begin) );
2332
27
                return suspend(cs.begin(), state::num3, num);
2333
27
            }
2334
30
            goto finish_dub;
2335
57
        }
2336
13.0M
        char const c = *cs;
2337
13.0M
        if(BOOST_JSON_UNLIKELY(
2338
13.0M
            c >= '0' && c <= '9'))
2339
13.0M
        {
2340
13.0M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
13.0M
            ++cs;
2347
13.0M
            ++num.bias;
2348
13.0M
        }
2349
5.57k
        else if(BOOST_JSON_LIKELY(
2350
5.57k
            c == '.'))
2351
1.12k
        {
2352
1.12k
            ++cs;
2353
1.12k
            break;
2354
1.12k
        }
2355
4.44k
        else if((c | 32) == 'e')
2356
1.73k
        {
2357
1.73k
            ++cs;
2358
1.73k
            goto do_exp1;
2359
1.73k
        }
2360
2.71k
        else
2361
2.71k
        {
2362
2.71k
            goto finish_dub;
2363
2.71k
        }
2364
13.0M
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
1.12k
do_num4:
2373
1.12k
    {
2374
1.12k
        if(BOOST_JSON_UNLIKELY(! cs))
2375
4
        {
2376
4
            if(BOOST_JSON_UNLIKELY(
2377
4
                ! h_.on_number_part(
2378
4
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
4
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
4
                num_buf_.append( begin, cs.used(begin) );
2383
4
            return maybe_suspend(
2384
4
                cs.begin(), state::num4, num);
2385
4
        }
2386
1.12k
        char const c = *cs;
2387
1.12k
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
1.12k
            c >= '0' && c <= '9'))
2390
1.10k
        {
2391
1.10k
            ++cs;
2392
1.10k
        }
2393
23
        else
2394
23
        {
2395
            // digit required
2396
23
            BOOST_STATIC_CONSTEXPR source_location loc
2397
23
                = BOOST_CURRENT_LOCATION;
2398
23
            return fail(cs.begin(), error::syntax, &loc);
2399
23
        }
2400
1.12k
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
3.55k
do_num5:
2409
3.55k
    for(;;)
2410
57.1k
    {
2411
57.1k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
56
        {
2413
56
            if(BOOST_JSON_UNLIKELY(more_))
2414
23
            {
2415
23
                if(BOOST_JSON_UNLIKELY(
2416
23
                    ! h_.on_number_part(
2417
23
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
23
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
23
                    num_buf_.append( begin, cs.used(begin) );
2422
23
                return suspend(cs.begin(), state::num5, num);
2423
23
            }
2424
33
            goto finish_dub;
2425
56
        }
2426
57.0k
        char const c = *cs;
2427
57.0k
        if(BOOST_JSON_LIKELY(
2428
57.0k
            c >= '0' && c <= '9'))
2429
53.5k
        {
2430
53.5k
            ++cs;
2431
53.5k
        }
2432
3.49k
        else if((c | 32) == 'e')
2433
1.19k
        {
2434
1.19k
            ++cs;
2435
1.19k
            goto do_exp1;
2436
1.19k
        }
2437
2.30k
        else
2438
2.30k
        {
2439
2.30k
            goto finish_dub;
2440
2.30k
        }
2441
57.0k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
8.59k
do_num6:
2448
8.59k
    {
2449
8.59k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
12
        {
2451
12
            if(BOOST_JSON_UNLIKELY(more_))
2452
6
            {
2453
6
                if(BOOST_JSON_UNLIKELY(
2454
6
                    ! h_.on_number_part(
2455
6
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
6
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
6
                    num_buf_.append( begin, cs.used(begin) );
2460
6
                return suspend(cs.begin(), state::num6, num);
2461
6
            }
2462
6
            goto finish_int;
2463
12
        }
2464
8.58k
        char const c = *cs;
2465
8.58k
        if(BOOST_JSON_LIKELY(
2466
8.58k
            c == '.'))
2467
1.88k
        {
2468
1.88k
            ++cs;
2469
1.88k
        }
2470
6.69k
        else if((c | 32) == 'e')
2471
1.38k
        {
2472
1.38k
            ++cs;
2473
1.38k
            goto do_exp1;
2474
1.38k
        }
2475
5.31k
        else
2476
5.31k
        {
2477
5.31k
            goto finish_int;
2478
5.31k
        }
2479
8.58k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
3.21k
do_num7:
2488
3.21k
    {
2489
3.21k
        if(BOOST_JSON_UNLIKELY(! cs))
2490
8
        {
2491
8
            if(BOOST_JSON_UNLIKELY(more_))
2492
4
            {
2493
4
                if(BOOST_JSON_UNLIKELY(
2494
4
                    ! h_.on_number_part(
2495
4
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
4
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
4
                    num_buf_.append( begin, cs.used(begin) );
2500
4
                return suspend(cs.begin(), state::num7, num);
2501
4
            }
2502
            // digit required
2503
8
            BOOST_STATIC_CONSTEXPR source_location loc
2504
4
                = BOOST_CURRENT_LOCATION;
2505
4
            return fail(cs.begin(), error::syntax, &loc);
2506
8
        }
2507
3.20k
        char const c = *cs;
2508
3.20k
        if(BOOST_JSON_UNLIKELY(
2509
3.20k
            c < '0' || c > '9'))
2510
17
        {
2511
            // digit required
2512
17
            BOOST_STATIC_CONSTEXPR source_location loc
2513
17
                = BOOST_CURRENT_LOCATION;
2514
17
            return fail(cs.begin(), error::syntax, &loc);
2515
17
        }
2516
3.20k
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
4.58k
do_num8:
2525
4.58k
    for(;;)
2526
8.07M
    {
2527
8.07M
        if(BOOST_JSON_UNLIKELY(! cs))
2528
211
        {
2529
211
            if(BOOST_JSON_UNLIKELY(more_))
2530
102
            {
2531
102
                if(BOOST_JSON_UNLIKELY(
2532
102
                    ! h_.on_number_part(
2533
102
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
102
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
102
                    num_buf_.append( begin, cs.used(begin) );
2538
102
                return suspend(cs.begin(), state::num8, num);
2539
102
            }
2540
109
            goto finish_dub;
2541
211
        }
2542
8.07M
        char const c = *cs;
2543
8.07M
        if(BOOST_JSON_LIKELY(
2544
8.07M
            c >= '0' && c <= '9'))
2545
8.07M
        {
2546
8.07M
            ++cs;
2547
8.07M
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
8.07M
                num.mant <= 9007199254740991)) // 2^53-1
2549
8.07M
            {
2550
8.07M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
8.07M
                --num.bias;
2557
8.07M
                num.mant = 10 * num.mant + ( c - '0' );
2558
8.07M
            }
2559
2.45k
            else
2560
2.45k
            {
2561
2.45k
                goto do_num5;
2562
2.45k
            }
2563
8.07M
        }
2564
1.91k
        else if((c | 32) == 'e')
2565
537
        {
2566
537
            ++cs;
2567
537
            goto do_exp1;
2568
537
        }
2569
1.38k
        else
2570
1.38k
        {
2571
1.38k
            goto finish_dub;
2572
1.38k
        }
2573
8.07M
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
27.0k
do_exp1:
2580
27.0k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
56
    {
2582
56
        if(BOOST_JSON_UNLIKELY(
2583
56
            ! h_.on_number_part(
2584
56
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
56
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
56
            num_buf_.append( begin, cs.used(begin) );
2589
56
        return maybe_suspend(
2590
56
            cs.begin(), state::exp1, num);
2591
56
    }
2592
27.0k
    if(*cs == '+')
2593
529
    {
2594
529
        ++cs;
2595
529
    }
2596
26.4k
    else if(*cs == '-')
2597
8.05k
    {
2598
8.05k
        ++cs;
2599
8.05k
        num.frac = true;
2600
8.05k
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
27.0k
do_exp2:
2608
27.0k
    {
2609
27.0k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
26
        {
2611
26
            if(BOOST_JSON_UNLIKELY(more_))
2612
12
            {
2613
12
                if(BOOST_JSON_UNLIKELY(
2614
12
                    ! h_.on_number_part(
2615
12
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
12
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
12
                    num_buf_.append( begin, cs.used(begin) );
2620
12
                return suspend(cs.begin(), state::exp2, num);
2621
12
            }
2622
            // digit required
2623
26
            BOOST_STATIC_CONSTEXPR source_location loc
2624
14
                = BOOST_CURRENT_LOCATION;
2625
14
            return fail(cs.begin(), error::syntax, &loc);
2626
26
        }
2627
27.0k
        char const c = *cs;
2628
27.0k
        if(BOOST_JSON_UNLIKELY(
2629
27.0k
            c < '0' || c > '9'))
2630
50
        {
2631
            // digit required
2632
50
            BOOST_STATIC_CONSTEXPR source_location loc
2633
50
                = BOOST_CURRENT_LOCATION;
2634
50
            return fail(cs.begin(), error::syntax, &loc);
2635
50
        }
2636
26.9k
        ++cs;
2637
26.9k
        num.exp = c - '0';
2638
26.9k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
26.9k
do_exp3:
2646
26.9k
    for(;;)
2647
75.8k
    {
2648
75.8k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
443
        {
2650
443
            if(BOOST_JSON_UNLIKELY(more_))
2651
100
            {
2652
100
                if(BOOST_JSON_UNLIKELY(
2653
100
                    ! h_.on_number_part(
2654
100
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
100
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
100
                    num_buf_.append( begin, cs.used(begin) );
2659
100
                return suspend(cs.begin(), state::exp3, num);
2660
100
            }
2661
443
        }
2662
75.4k
        else
2663
75.4k
        {
2664
75.4k
            char const c = *cs;
2665
75.4k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
48.8k
            {
2667
48.8k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
48.8k
                    num.exp  >  214748364 ||
2670
48.8k
                    (num.exp == 214748364 && c > '7')
2671
48.8k
                ))
2672
9.69k
                    num.exp = INT_MAX;
2673
39.2k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
39.2k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
48.8k
                ++cs;
2677
48.8k
                continue;
2678
48.8k
            }
2679
75.4k
        }
2680
26.8k
        BOOST_ASSERT(num.exp >= 0);
2681
26.8k
        if ( num.frac )
2682
8.04k
        {
2683
8.04k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
919
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
919
                if(BOOST_JSON_UNLIKELY(
2689
919
                    (num.exp == INT_MAX) &&
2690
919
                    (num.bias < 0) &&
2691
919
                    (num.exp + num.bias < 308) &&
2692
919
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
919
                num.bias = 0;
2700
919
                num.exp = INT_MAX;
2701
919
            }
2702
8.04k
        }
2703
18.8k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
967
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
967
            if(BOOST_JSON_UNLIKELY(
2709
967
                (num.exp == INT_MAX) &&
2710
967
                (num.bias > 0) &&
2711
967
                (num.exp - num.bias < 308) &&
2712
967
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
967
            num.bias = 0;
2720
967
            num.exp = INT_MAX;
2721
967
        }
2722
26.8k
        goto finish_dub;
2723
26.8k
    }
2724
2725
5.46k
finish_int:
2726
5.46k
    if(negative || (!stack_empty && num.neg))
2727
5.46k
    {
2728
5.46k
        if(BOOST_JSON_UNLIKELY(
2729
5.46k
            ! h_.on_int64(static_cast<
2730
5.46k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
5.46k
        return cs.begin();
2733
5.46k
    }
2734
0
    if(num.mant <= INT64_MAX)
2735
0
    {
2736
17.0k
finish_signed:
2737
17.0k
        if(BOOST_JSON_UNLIKELY(
2738
17.0k
            ! h_.on_int64(static_cast<
2739
17.0k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
17.0k
        return cs.begin();
2742
17.0k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
36.8k
finish_dub:
2748
36.8k
    double d;
2749
36.8k
    std::size_t const size = cs.used(begin);
2750
36.8k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
36.8k
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
36.8k
        d = 0;
2771
36.8k
    else
2772
36.8k
        d = detail::dec_to_float(
2773
36.8k
            num.mant,
2774
36.8k
            num.bias + (num.frac ?
2775
28.7k
                -num.exp : num.exp),
2776
36.8k
            num.neg);
2777
36.8k
    if(BOOST_JSON_UNLIKELY(
2778
36.8k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
36.8k
    return cs.begin();
2781
36.8k
}
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>)
Line
Count
Source
2011
14.2k
{
2012
14.2k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
14.2k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
14.2k
    bool const negative = first == '-';
2020
14.2k
    bool const zero_first = first == '0';
2021
14.2k
    bool const nonzero_first = first == '+';
2022
14.2k
    detail::const_stream_wrapper cs(p, end_);
2023
14.2k
    number num;
2024
14.2k
    const char* begin = cs.begin();
2025
14.2k
    if(stack_empty || st_.empty())
2026
14.2k
    {
2027
14.2k
        num.bias = 0;
2028
14.2k
        num.exp = 0;
2029
14.2k
        num.frac = false;
2030
14.2k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
14.2k
        BOOST_ASSERT(cs);
2038
14.2k
        if(negative)
2039
14.2k
            ++cs;
2040
2041
14.2k
        num.neg = negative;
2042
14.2k
        num.frac = false;
2043
14.2k
        num.exp = 0;
2044
14.2k
        num.bias = 0;
2045
2046
        // fast path
2047
14.2k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
13.0k
        {
2049
13.0k
            int n1;
2050
2051
13.0k
            if( nonzero_first ||
2052
13.0k
                (negative && *cs != '0') )
2053
8.14k
            {
2054
8.14k
                n1 = detail::count_digits( cs.begin() );
2055
8.14k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
8.14k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
8.14k
                if( ! nonzero_first && n1 == 0 )
2065
5
                {
2066
                    // digit required
2067
5
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
5
                        = BOOST_CURRENT_LOCATION;
2069
5
                    return fail(cs.begin(), error::syntax, &loc);
2070
5
                }
2071
2072
8.14k
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
8.14k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
8.14k
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
8.14k
                if( n1 == 16 )
2082
3.42k
                {
2083
3.42k
                    goto do_num2;
2084
3.42k
                }
2085
8.14k
            }
2086
4.87k
            else
2087
4.87k
            {
2088
                // 0. floating-point or 0e integer
2089
4.87k
                num.mant = 0;
2090
4.87k
                n1 = 0;
2091
4.87k
                ++cs;
2092
4.87k
            }
2093
2094
9.59k
            {
2095
9.59k
                const char c = *cs;
2096
9.59k
                if(c != '.')
2097
6.15k
                {
2098
6.15k
                    if((c | 32) == 'e')
2099
1.16k
                    {
2100
1.16k
                        ++cs;
2101
1.16k
                        goto do_exp1;
2102
1.16k
                    }
2103
4.99k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
4.99k
                        num.mant = ~num.mant + 1;
2105
4.99k
                    goto finish_signed;
2106
6.15k
                }
2107
9.59k
            }
2108
2109
            // floating-point number
2110
2111
3.43k
            ++cs;
2112
2113
3.43k
            int n2 = detail::count_digits( cs.begin() );
2114
3.43k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
3.43k
            if( n2 == 0 )
2117
2
            {
2118
                // digit required
2119
2
                BOOST_STATIC_CONSTEXPR source_location loc
2120
2
                    = BOOST_CURRENT_LOCATION;
2121
2
                return fail(cs.begin(), error::syntax, &loc);
2122
2
            }
2123
2124
            // floating-point mantissa overflow
2125
3.43k
            if( n1 + n2 >= 19 )
2126
867
            {
2127
867
                goto do_num7;
2128
867
            }
2129
2130
2.56k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
2.56k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
2.56k
            BOOST_ASSERT(num.bias == 0);
2134
2135
2.56k
            num.bias -= n2;
2136
2137
2.56k
            cs += n2;
2138
2139
2.56k
            char ch = *cs;
2140
2141
2.56k
            if( (ch | 32) == 'e' )
2142
707
            {
2143
707
                ++cs;
2144
707
                goto do_exp1;
2145
707
            }
2146
1.85k
            else if( ch >= '0' && ch <= '9' )
2147
463
            {
2148
463
                goto do_num8;
2149
463
            }
2150
2151
1.39k
            goto finish_dub;
2152
2.56k
        }
2153
14.2k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
1.21k
do_num1:
2182
1.21k
    if(zero_first || nonzero_first ||
2183
1.21k
        BOOST_JSON_LIKELY(cs))
2184
1.19k
    {
2185
1.19k
        char const c = *cs;
2186
1.19k
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
1.19k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
1.19k
            c >= '1' && c <= '9'))
2194
942
        {
2195
942
            ++cs;
2196
942
            num.mant = c - '0';
2197
942
        }
2198
254
        else if(BOOST_JSON_UNLIKELY(
2199
254
            c == '0'))
2200
224
        {
2201
224
            ++cs;
2202
224
            num.mant = 0;
2203
224
            goto do_num6;
2204
224
        }
2205
30
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
30
        else
2214
30
        {
2215
30
            BOOST_STATIC_CONSTEXPR source_location loc
2216
30
                = BOOST_CURRENT_LOCATION;
2217
30
            return fail(cs.begin(), error::syntax, &loc);
2218
30
        }
2219
1.19k
    }
2220
19
    else
2221
19
    {
2222
19
        if(BOOST_JSON_UNLIKELY(
2223
19
            ! h_.on_number_part(
2224
19
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
19
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
19
            num_buf_.append( begin, cs.used(begin) );
2229
19
        return maybe_suspend(
2230
19
            cs.begin(), state::num1, num);
2231
19
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
4.36k
do_num2:
2239
4.36k
    if(negative || (!stack_empty && num.neg))
2240
4.36k
    {
2241
4.36k
        for(;;)
2242
15.2k
        {
2243
15.2k
            if(BOOST_JSON_UNLIKELY(! cs))
2244
195
            {
2245
195
                if(BOOST_JSON_UNLIKELY(more_))
2246
195
                {
2247
195
                    if(BOOST_JSON_UNLIKELY(
2248
195
                        ! h_.on_number_part(
2249
195
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
195
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
195
                        num_buf_.append( begin, cs.used(begin) );
2254
195
                    return suspend(cs.begin(), state::num2, num);
2255
195
                }
2256
0
                goto finish_int;
2257
195
            }
2258
15.0k
            char const c = *cs;
2259
15.0k
            if(BOOST_JSON_LIKELY(
2260
15.0k
                c >= '0' && c <= '9'))
2261
13.0k
            {
2262
13.0k
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
13.0k
                if( num.mant  > 922337203685477580 || (
2265
11.1k
                    num.mant == 922337203685477580 && c > '8'))
2266
2.16k
                    break;
2267
10.8k
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
10.8k
                    num.mant = 10 * num.mant + ( c - '0' );
2269
10.8k
                continue;
2270
13.0k
            }
2271
2.00k
            goto do_num6; // [.eE]
2272
15.0k
        }
2273
4.36k
    }
2274
0
    else
2275
0
    {
2276
0
        for(;;)
2277
0
        {
2278
0
            if(BOOST_JSON_UNLIKELY(! cs))
2279
0
            {
2280
0
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
0
                goto finish_int;
2292
0
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
0
    }
2311
2.16k
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
2.16k
do_num3:
2319
2.16k
    for(;;)
2320
8.52M
    {
2321
8.52M
        if(BOOST_JSON_UNLIKELY(! cs))
2322
69
        {
2323
69
            if(BOOST_JSON_UNLIKELY(more_))
2324
69
            {
2325
69
                if(BOOST_JSON_UNLIKELY(
2326
69
                    ! h_.on_number_part(
2327
69
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
69
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
69
                    num_buf_.append( begin, cs.used(begin) );
2332
69
                return suspend(cs.begin(), state::num3, num);
2333
69
            }
2334
0
            goto finish_dub;
2335
69
        }
2336
8.52M
        char const c = *cs;
2337
8.52M
        if(BOOST_JSON_UNLIKELY(
2338
8.52M
            c >= '0' && c <= '9'))
2339
8.51M
        {
2340
8.51M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
8.51M
            ++cs;
2347
8.51M
            ++num.bias;
2348
8.51M
        }
2349
2.09k
        else if(BOOST_JSON_LIKELY(
2350
2.09k
            c == '.'))
2351
504
        {
2352
504
            ++cs;
2353
504
            break;
2354
504
        }
2355
1.59k
        else if((c | 32) == 'e')
2356
789
        {
2357
789
            ++cs;
2358
789
            goto do_exp1;
2359
789
        }
2360
804
        else
2361
804
        {
2362
804
            goto finish_dub;
2363
804
        }
2364
8.52M
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
504
do_num4:
2373
504
    {
2374
504
        if(BOOST_JSON_UNLIKELY(! cs))
2375
1
        {
2376
1
            if(BOOST_JSON_UNLIKELY(
2377
1
                ! h_.on_number_part(
2378
1
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
1
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
1
                num_buf_.append( begin, cs.used(begin) );
2383
1
            return maybe_suspend(
2384
1
                cs.begin(), state::num4, num);
2385
1
        }
2386
503
        char const c = *cs;
2387
503
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
503
            c >= '0' && c <= '9'))
2390
496
        {
2391
496
            ++cs;
2392
496
        }
2393
7
        else
2394
7
        {
2395
            // digit required
2396
7
            BOOST_STATIC_CONSTEXPR source_location loc
2397
7
                = BOOST_CURRENT_LOCATION;
2398
7
            return fail(cs.begin(), error::syntax, &loc);
2399
7
        }
2400
503
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
1.95k
do_num5:
2409
1.95k
    for(;;)
2410
3.94M
    {
2411
3.94M
        if(BOOST_JSON_UNLIKELY(! cs))
2412
53
        {
2413
53
            if(BOOST_JSON_UNLIKELY(more_))
2414
53
            {
2415
53
                if(BOOST_JSON_UNLIKELY(
2416
53
                    ! h_.on_number_part(
2417
53
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
53
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
53
                    num_buf_.append( begin, cs.used(begin) );
2422
53
                return suspend(cs.begin(), state::num5, num);
2423
53
            }
2424
0
            goto finish_dub;
2425
53
        }
2426
3.94M
        char const c = *cs;
2427
3.94M
        if(BOOST_JSON_LIKELY(
2428
3.94M
            c >= '0' && c <= '9'))
2429
3.94M
        {
2430
3.94M
            ++cs;
2431
3.94M
        }
2432
1.90k
        else if((c | 32) == 'e')
2433
330
        {
2434
330
            ++cs;
2435
330
            goto do_exp1;
2436
330
        }
2437
1.57k
        else
2438
1.57k
        {
2439
1.57k
            goto finish_dub;
2440
1.57k
        }
2441
3.94M
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
2.23k
do_num6:
2448
2.23k
    {
2449
2.23k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
6
        {
2451
6
            if(BOOST_JSON_UNLIKELY(more_))
2452
6
            {
2453
6
                if(BOOST_JSON_UNLIKELY(
2454
6
                    ! h_.on_number_part(
2455
6
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
6
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
6
                    num_buf_.append( begin, cs.used(begin) );
2460
6
                return suspend(cs.begin(), state::num6, num);
2461
6
            }
2462
0
            goto finish_int;
2463
6
        }
2464
2.22k
        char const c = *cs;
2465
2.22k
        if(BOOST_JSON_LIKELY(
2466
2.22k
            c == '.'))
2467
761
        {
2468
761
            ++cs;
2469
761
        }
2470
1.46k
        else if((c | 32) == 'e')
2471
499
        {
2472
499
            ++cs;
2473
499
            goto do_exp1;
2474
499
        }
2475
966
        else
2476
966
        {
2477
966
            goto finish_int;
2478
966
        }
2479
2.22k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
1.62k
do_num7:
2488
1.62k
    {
2489
1.62k
        if(BOOST_JSON_UNLIKELY(! cs))
2490
6
        {
2491
6
            if(BOOST_JSON_UNLIKELY(more_))
2492
6
            {
2493
6
                if(BOOST_JSON_UNLIKELY(
2494
6
                    ! h_.on_number_part(
2495
6
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
6
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
6
                    num_buf_.append( begin, cs.used(begin) );
2500
6
                return suspend(cs.begin(), state::num7, num);
2501
6
            }
2502
            // digit required
2503
6
            BOOST_STATIC_CONSTEXPR source_location loc
2504
0
                = BOOST_CURRENT_LOCATION;
2505
0
            return fail(cs.begin(), error::syntax, &loc);
2506
6
        }
2507
1.62k
        char const c = *cs;
2508
1.62k
        if(BOOST_JSON_UNLIKELY(
2509
1.62k
            c < '0' || c > '9'))
2510
9
        {
2511
            // digit required
2512
9
            BOOST_STATIC_CONSTEXPR source_location loc
2513
9
                = BOOST_CURRENT_LOCATION;
2514
9
            return fail(cs.begin(), error::syntax, &loc);
2515
9
        }
2516
1.62k
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
2.07k
do_num8:
2525
2.07k
    for(;;)
2526
5.80M
    {
2527
5.80M
        if(BOOST_JSON_UNLIKELY(! cs))
2528
26
        {
2529
26
            if(BOOST_JSON_UNLIKELY(more_))
2530
26
            {
2531
26
                if(BOOST_JSON_UNLIKELY(
2532
26
                    ! h_.on_number_part(
2533
26
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
26
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
26
                    num_buf_.append( begin, cs.used(begin) );
2538
26
                return suspend(cs.begin(), state::num8, num);
2539
26
            }
2540
0
            goto finish_dub;
2541
26
        }
2542
5.80M
        char const c = *cs;
2543
5.80M
        if(BOOST_JSON_LIKELY(
2544
5.80M
            c >= '0' && c <= '9'))
2545
5.79M
        {
2546
5.79M
            ++cs;
2547
5.79M
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
5.79M
                num.mant <= 9007199254740991)) // 2^53-1
2549
5.79M
            {
2550
5.79M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
5.79M
                --num.bias;
2557
5.79M
                num.mant = 10 * num.mant + ( c - '0' );
2558
5.79M
            }
2559
1.46k
            else
2560
1.46k
            {
2561
1.46k
                goto do_num5;
2562
1.46k
            }
2563
5.79M
        }
2564
590
        else if((c | 32) == 'e')
2565
284
        {
2566
284
            ++cs;
2567
284
            goto do_exp1;
2568
284
        }
2569
306
        else
2570
306
        {
2571
306
            goto finish_dub;
2572
306
        }
2573
5.80M
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
3.77k
do_exp1:
2580
3.77k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
24
    {
2582
24
        if(BOOST_JSON_UNLIKELY(
2583
24
            ! h_.on_number_part(
2584
24
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
24
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
24
            num_buf_.append( begin, cs.used(begin) );
2589
24
        return maybe_suspend(
2590
24
            cs.begin(), state::exp1, num);
2591
24
    }
2592
3.74k
    if(*cs == '+')
2593
195
    {
2594
195
        ++cs;
2595
195
    }
2596
3.55k
    else if(*cs == '-')
2597
990
    {
2598
990
        ++cs;
2599
990
        num.frac = true;
2600
990
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
3.74k
do_exp2:
2608
3.74k
    {
2609
3.74k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
10
        {
2611
10
            if(BOOST_JSON_UNLIKELY(more_))
2612
10
            {
2613
10
                if(BOOST_JSON_UNLIKELY(
2614
10
                    ! h_.on_number_part(
2615
10
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
10
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
10
                    num_buf_.append( begin, cs.used(begin) );
2620
10
                return suspend(cs.begin(), state::exp2, num);
2621
10
            }
2622
            // digit required
2623
10
            BOOST_STATIC_CONSTEXPR source_location loc
2624
0
                = BOOST_CURRENT_LOCATION;
2625
0
            return fail(cs.begin(), error::syntax, &loc);
2626
10
        }
2627
3.73k
        char const c = *cs;
2628
3.73k
        if(BOOST_JSON_UNLIKELY(
2629
3.73k
            c < '0' || c > '9'))
2630
12
        {
2631
            // digit required
2632
12
            BOOST_STATIC_CONSTEXPR source_location loc
2633
12
                = BOOST_CURRENT_LOCATION;
2634
12
            return fail(cs.begin(), error::syntax, &loc);
2635
12
        }
2636
3.72k
        ++cs;
2637
3.72k
        num.exp = c - '0';
2638
3.72k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
3.72k
do_exp3:
2646
3.72k
    for(;;)
2647
51.1k
    {
2648
51.1k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
109
        {
2650
109
            if(BOOST_JSON_UNLIKELY(more_))
2651
109
            {
2652
109
                if(BOOST_JSON_UNLIKELY(
2653
109
                    ! h_.on_number_part(
2654
109
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
109
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
109
                    num_buf_.append( begin, cs.used(begin) );
2659
109
                return suspend(cs.begin(), state::exp3, num);
2660
109
            }
2661
109
        }
2662
51.0k
        else
2663
51.0k
        {
2664
51.0k
            char const c = *cs;
2665
51.0k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
47.4k
            {
2667
47.4k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
47.4k
                    num.exp  >  214748364 ||
2670
47.4k
                    (num.exp == 214748364 && c > '7')
2671
47.4k
                ))
2672
9.77k
                    num.exp = INT_MAX;
2673
37.6k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
37.6k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
47.4k
                ++cs;
2677
47.4k
                continue;
2678
47.4k
            }
2679
51.0k
        }
2680
3.61k
        BOOST_ASSERT(num.exp >= 0);
2681
3.61k
        if ( num.frac )
2682
976
        {
2683
976
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
464
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
464
                if(BOOST_JSON_UNLIKELY(
2689
464
                    (num.exp == INT_MAX) &&
2690
464
                    (num.bias < 0) &&
2691
464
                    (num.exp + num.bias < 308) &&
2692
464
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
464
                num.bias = 0;
2700
464
                num.exp = INT_MAX;
2701
464
            }
2702
976
        }
2703
2.63k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
563
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
563
            if(BOOST_JSON_UNLIKELY(
2709
563
                (num.exp == INT_MAX) &&
2710
563
                (num.bias > 0) &&
2711
563
                (num.exp - num.bias < 308) &&
2712
563
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
563
            num.bias = 0;
2720
563
            num.exp = INT_MAX;
2721
563
        }
2722
3.61k
        goto finish_dub;
2723
3.61k
    }
2724
2725
966
finish_int:
2726
966
    if(negative || (!stack_empty && num.neg))
2727
966
    {
2728
966
        if(BOOST_JSON_UNLIKELY(
2729
966
            ! h_.on_int64(static_cast<
2730
966
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
966
        return cs.begin();
2733
966
    }
2734
0
    if(num.mant <= INT64_MAX)
2735
0
    {
2736
4.99k
finish_signed:
2737
4.99k
        if(BOOST_JSON_UNLIKELY(
2738
4.99k
            ! h_.on_int64(static_cast<
2739
4.99k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
4.99k
        return cs.begin();
2742
4.99k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
7.69k
finish_dub:
2748
7.69k
    double d;
2749
7.69k
    std::size_t const size = cs.used(begin);
2750
7.69k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
7.69k
    {
2753
7.69k
        char const* data = begin;
2754
7.69k
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
7.69k
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
0
        {
2760
0
            data = num_buf_.append( begin, size );
2761
0
            full_size = num_buf_.size();
2762
0
        }
2763
7.69k
        auto const err = detail::charconv::from_chars(
2764
7.69k
            data, data + full_size, d );
2765
7.69k
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
7.69k
        BOOST_ASSERT( err.ptr == data + full_size );
2767
7.69k
        (void)err;
2768
    }
2769
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
7.69k
    if(BOOST_JSON_UNLIKELY(
2778
7.69k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
7.69k
    return cs.begin();
2781
7.69k
}
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>)
Line
Count
Source
2011
5.88k
{
2012
5.88k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
5.88k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
5.88k
    bool const negative = first == '-';
2020
5.88k
    bool const zero_first = first == '0';
2021
5.88k
    bool const nonzero_first = first == '+';
2022
5.88k
    detail::const_stream_wrapper cs(p, end_);
2023
5.88k
    number num;
2024
5.88k
    const char* begin = cs.begin();
2025
5.88k
    if(stack_empty || st_.empty())
2026
5.88k
    {
2027
5.88k
        num.bias = 0;
2028
5.88k
        num.exp = 0;
2029
5.88k
        num.frac = false;
2030
5.88k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
5.88k
        BOOST_ASSERT(cs);
2038
5.88k
        if(negative)
2039
5.88k
            ++cs;
2040
2041
5.88k
        num.neg = negative;
2042
5.88k
        num.frac = false;
2043
5.88k
        num.exp = 0;
2044
5.88k
        num.bias = 0;
2045
2046
        // fast path
2047
5.88k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
5.21k
        {
2049
5.21k
            int n1;
2050
2051
5.21k
            if( nonzero_first ||
2052
5.21k
                (negative && *cs != '0') )
2053
4.08k
            {
2054
4.08k
                n1 = detail::count_digits( cs.begin() );
2055
4.08k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
4.08k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
4.08k
                if( ! nonzero_first && n1 == 0 )
2065
2
                {
2066
                    // digit required
2067
2
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
2
                        = BOOST_CURRENT_LOCATION;
2069
2
                    return fail(cs.begin(), error::syntax, &loc);
2070
2
                }
2071
2072
4.08k
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
4.08k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
4.08k
                else
2075
4.08k
                    num.mant = 0;
2076
2077
4.08k
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
4.08k
                if( n1 == 16 )
2082
757
                {
2083
757
                    goto do_num2;
2084
757
                }
2085
4.08k
            }
2086
1.13k
            else
2087
1.13k
            {
2088
                // 0. floating-point or 0e integer
2089
1.13k
                num.mant = 0;
2090
1.13k
                n1 = 0;
2091
1.13k
                ++cs;
2092
1.13k
            }
2093
2094
4.45k
            {
2095
4.45k
                const char c = *cs;
2096
4.45k
                if(c != '.')
2097
3.15k
                {
2098
3.15k
                    if((c | 32) == 'e')
2099
976
                    {
2100
976
                        ++cs;
2101
976
                        goto do_exp1;
2102
976
                    }
2103
2.17k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
2.17k
                        num.mant = ~num.mant + 1;
2105
2.17k
                    goto finish_signed;
2106
3.15k
                }
2107
4.45k
            }
2108
2109
            // floating-point number
2110
2111
1.30k
            ++cs;
2112
2113
1.30k
            int n2 = detail::count_digits( cs.begin() );
2114
1.30k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
1.30k
            if( n2 == 0 )
2117
5
            {
2118
                // digit required
2119
5
                BOOST_STATIC_CONSTEXPR source_location loc
2120
5
                    = BOOST_CURRENT_LOCATION;
2121
5
                return fail(cs.begin(), error::syntax, &loc);
2122
5
            }
2123
2124
            // floating-point mantissa overflow
2125
1.30k
            if( n1 + n2 >= 19 )
2126
198
            {
2127
198
                goto do_num7;
2128
198
            }
2129
2130
1.10k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
1.10k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
1.10k
            BOOST_ASSERT(num.bias == 0);
2134
2135
1.10k
            num.bias -= n2;
2136
2137
1.10k
            cs += n2;
2138
2139
1.10k
            char ch = *cs;
2140
2141
1.10k
            if( (ch | 32) == 'e' )
2142
200
            {
2143
200
                ++cs;
2144
200
                goto do_exp1;
2145
200
            }
2146
902
            else if( ch >= '0' && ch <= '9' )
2147
394
            {
2148
394
                goto do_num8;
2149
394
            }
2150
2151
508
            goto finish_dub;
2152
1.10k
        }
2153
5.88k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
664
do_num1:
2182
664
    if(zero_first || nonzero_first ||
2183
664
        BOOST_JSON_LIKELY(cs))
2184
647
    {
2185
647
        char const c = *cs;
2186
647
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
647
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
647
            c >= '1' && c <= '9'))
2194
455
        {
2195
455
            ++cs;
2196
455
            num.mant = c - '0';
2197
455
        }
2198
192
        else if(BOOST_JSON_UNLIKELY(
2199
192
            c == '0'))
2200
168
        {
2201
168
            ++cs;
2202
168
            num.mant = 0;
2203
168
            goto do_num6;
2204
168
        }
2205
24
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
24
        else
2214
24
        {
2215
24
            BOOST_STATIC_CONSTEXPR source_location loc
2216
24
                = BOOST_CURRENT_LOCATION;
2217
24
            return fail(cs.begin(), error::syntax, &loc);
2218
24
        }
2219
647
    }
2220
17
    else
2221
17
    {
2222
17
        if(BOOST_JSON_UNLIKELY(
2223
17
            ! h_.on_number_part(
2224
17
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
17
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
17
            num_buf_.append( begin, cs.used(begin) );
2229
17
        return maybe_suspend(
2230
17
            cs.begin(), state::num1, num);
2231
17
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
1.21k
do_num2:
2239
1.21k
    if(negative || (!stack_empty && num.neg))
2240
1.21k
    {
2241
1.21k
        for(;;)
2242
2.37k
        {
2243
2.37k
            if(BOOST_JSON_UNLIKELY(! cs))
2244
23
            {
2245
23
                if(BOOST_JSON_UNLIKELY(more_))
2246
23
                {
2247
23
                    if(BOOST_JSON_UNLIKELY(
2248
23
                        ! h_.on_number_part(
2249
23
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
23
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
23
                        num_buf_.append( begin, cs.used(begin) );
2254
23
                    return suspend(cs.begin(), state::num2, num);
2255
23
                }
2256
0
                goto finish_int;
2257
23
            }
2258
2.35k
            char const c = *cs;
2259
2.35k
            if(BOOST_JSON_LIKELY(
2260
2.35k
                c >= '0' && c <= '9'))
2261
1.16k
            {
2262
1.16k
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
1.16k
                if( num.mant  > 922337203685477580 || (
2265
1.16k
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
1.16k
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
1.16k
                    num.mant = 10 * num.mant + ( c - '0' );
2269
1.16k
                continue;
2270
1.16k
            }
2271
1.18k
            goto do_num6; // [.eE]
2272
2.35k
        }
2273
1.21k
    }
2274
0
    else
2275
0
    {
2276
0
        for(;;)
2277
0
        {
2278
0
            if(BOOST_JSON_UNLIKELY(! cs))
2279
0
            {
2280
0
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
0
                goto finish_int;
2292
0
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
0
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
0
do_num3:
2319
0
    for(;;)
2320
0
    {
2321
0
        if(BOOST_JSON_UNLIKELY(! cs))
2322
0
        {
2323
0
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
0
            goto finish_dub;
2335
0
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
0
do_num4:
2373
0
    {
2374
0
        if(BOOST_JSON_UNLIKELY(! cs))
2375
0
        {
2376
0
            if(BOOST_JSON_UNLIKELY(
2377
0
                ! h_.on_number_part(
2378
0
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
0
                num_buf_.append( begin, cs.used(begin) );
2383
0
            return maybe_suspend(
2384
0
                cs.begin(), state::num4, num);
2385
0
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
1.03k
do_num5:
2409
1.03k
    for(;;)
2410
4.60k
    {
2411
4.60k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
25
        {
2413
25
            if(BOOST_JSON_UNLIKELY(more_))
2414
25
            {
2415
25
                if(BOOST_JSON_UNLIKELY(
2416
25
                    ! h_.on_number_part(
2417
25
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
25
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
25
                    num_buf_.append( begin, cs.used(begin) );
2422
25
                return suspend(cs.begin(), state::num5, num);
2423
25
            }
2424
0
            goto finish_dub;
2425
25
        }
2426
4.58k
        char const c = *cs;
2427
4.58k
        if(BOOST_JSON_LIKELY(
2428
4.58k
            c >= '0' && c <= '9'))
2429
3.57k
        {
2430
3.57k
            ++cs;
2431
3.57k
        }
2432
1.01k
        else if((c | 32) == 'e')
2433
202
        {
2434
202
            ++cs;
2435
202
            goto do_exp1;
2436
202
        }
2437
810
        else
2438
810
        {
2439
810
            goto finish_dub;
2440
810
        }
2441
4.58k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
1.35k
do_num6:
2448
1.35k
    {
2449
1.35k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
5
        {
2451
5
            if(BOOST_JSON_UNLIKELY(more_))
2452
5
            {
2453
5
                if(BOOST_JSON_UNLIKELY(
2454
5
                    ! h_.on_number_part(
2455
5
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
5
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
5
                    num_buf_.append( begin, cs.used(begin) );
2460
5
                return suspend(cs.begin(), state::num6, num);
2461
5
            }
2462
0
            goto finish_int;
2463
5
        }
2464
1.35k
        char const c = *cs;
2465
1.35k
        if(BOOST_JSON_LIKELY(
2466
1.35k
            c == '.'))
2467
455
        {
2468
455
            ++cs;
2469
455
        }
2470
897
        else if((c | 32) == 'e')
2471
362
        {
2472
362
            ++cs;
2473
362
            goto do_exp1;
2474
362
        }
2475
535
        else
2476
535
        {
2477
535
            goto finish_int;
2478
535
        }
2479
1.35k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
653
do_num7:
2488
653
    {
2489
653
        if(BOOST_JSON_UNLIKELY(! cs))
2490
5
        {
2491
5
            if(BOOST_JSON_UNLIKELY(more_))
2492
5
            {
2493
5
                if(BOOST_JSON_UNLIKELY(
2494
5
                    ! h_.on_number_part(
2495
5
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
5
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
5
                    num_buf_.append( begin, cs.used(begin) );
2500
5
                return suspend(cs.begin(), state::num7, num);
2501
5
            }
2502
            // digit required
2503
5
            BOOST_STATIC_CONSTEXPR source_location loc
2504
0
                = BOOST_CURRENT_LOCATION;
2505
0
            return fail(cs.begin(), error::syntax, &loc);
2506
5
        }
2507
648
        char const c = *cs;
2508
648
        if(BOOST_JSON_UNLIKELY(
2509
648
            c < '0' || c > '9'))
2510
5
        {
2511
            // digit required
2512
5
            BOOST_STATIC_CONSTEXPR source_location loc
2513
5
                = BOOST_CURRENT_LOCATION;
2514
5
            return fail(cs.begin(), error::syntax, &loc);
2515
5
        }
2516
648
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
1.03k
do_num8:
2525
1.03k
    for(;;)
2526
1.03k
    {
2527
1.03k
        if(BOOST_JSON_UNLIKELY(! cs))
2528
0
        {
2529
0
            if(BOOST_JSON_UNLIKELY(more_))
2530
0
            {
2531
0
                if(BOOST_JSON_UNLIKELY(
2532
0
                    ! h_.on_number_part(
2533
0
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
0
                    num_buf_.append( begin, cs.used(begin) );
2538
0
                return suspend(cs.begin(), state::num8, num);
2539
0
            }
2540
0
            goto finish_dub;
2541
0
        }
2542
1.03k
        char const c = *cs;
2543
1.03k
        if(BOOST_JSON_LIKELY(
2544
1.03k
            c >= '0' && c <= '9'))
2545
1.03k
        {
2546
1.03k
            ++cs;
2547
1.03k
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
1.03k
                num.mant <= 9007199254740991)) // 2^53-1
2549
0
            {
2550
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
0
                --num.bias;
2557
0
                num.mant = 10 * num.mant + ( c - '0' );
2558
0
            }
2559
1.03k
            else
2560
1.03k
            {
2561
1.03k
                goto do_num5;
2562
1.03k
            }
2563
1.03k
        }
2564
0
        else if((c | 32) == 'e')
2565
0
        {
2566
0
            ++cs;
2567
0
            goto do_exp1;
2568
0
        }
2569
0
        else
2570
0
        {
2571
0
            goto finish_dub;
2572
0
        }
2573
1.03k
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
1.74k
do_exp1:
2580
1.74k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
16
    {
2582
16
        if(BOOST_JSON_UNLIKELY(
2583
16
            ! h_.on_number_part(
2584
16
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
16
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
16
            num_buf_.append( begin, cs.used(begin) );
2589
16
        return maybe_suspend(
2590
16
            cs.begin(), state::exp1, num);
2591
16
    }
2592
1.72k
    if(*cs == '+')
2593
194
    {
2594
194
        ++cs;
2595
194
    }
2596
1.53k
    else if(*cs == '-')
2597
223
    {
2598
223
        ++cs;
2599
223
        num.frac = true;
2600
223
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
1.72k
do_exp2:
2608
1.72k
    {
2609
1.72k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
10
        {
2611
10
            if(BOOST_JSON_UNLIKELY(more_))
2612
10
            {
2613
10
                if(BOOST_JSON_UNLIKELY(
2614
10
                    ! h_.on_number_part(
2615
10
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
10
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
10
                    num_buf_.append( begin, cs.used(begin) );
2620
10
                return suspend(cs.begin(), state::exp2, num);
2621
10
            }
2622
            // digit required
2623
10
            BOOST_STATIC_CONSTEXPR source_location loc
2624
0
                = BOOST_CURRENT_LOCATION;
2625
0
            return fail(cs.begin(), error::syntax, &loc);
2626
10
        }
2627
1.71k
        char const c = *cs;
2628
1.71k
        if(BOOST_JSON_UNLIKELY(
2629
1.71k
            c < '0' || c > '9'))
2630
17
        {
2631
            // digit required
2632
17
            BOOST_STATIC_CONSTEXPR source_location loc
2633
17
                = BOOST_CURRENT_LOCATION;
2634
17
            return fail(cs.begin(), error::syntax, &loc);
2635
17
        }
2636
1.69k
        ++cs;
2637
1.69k
        num.exp = c - '0';
2638
1.69k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
1.69k
do_exp3:
2646
1.69k
    for(;;)
2647
2.23k
    {
2648
2.23k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
24
        {
2650
24
            if(BOOST_JSON_UNLIKELY(more_))
2651
24
            {
2652
24
                if(BOOST_JSON_UNLIKELY(
2653
24
                    ! h_.on_number_part(
2654
24
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
24
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
24
                    num_buf_.append( begin, cs.used(begin) );
2659
24
                return suspend(cs.begin(), state::exp3, num);
2660
24
            }
2661
24
        }
2662
2.20k
        else
2663
2.20k
        {
2664
2.20k
            char const c = *cs;
2665
2.20k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
536
            {
2667
536
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
536
                    num.exp  >  214748364 ||
2670
536
                    (num.exp == 214748364 && c > '7')
2671
536
                ))
2672
0
                    num.exp = INT_MAX;
2673
536
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
536
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
536
                ++cs;
2677
536
                continue;
2678
536
            }
2679
2.20k
        }
2680
1.67k
        BOOST_ASSERT(num.exp >= 0);
2681
1.67k
        if ( num.frac )
2682
218
        {
2683
218
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
0
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
0
                if(BOOST_JSON_UNLIKELY(
2689
0
                    (num.exp == INT_MAX) &&
2690
0
                    (num.bias < 0) &&
2691
0
                    (num.exp + num.bias < 308) &&
2692
0
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
0
                num.bias = 0;
2700
0
                num.exp = INT_MAX;
2701
0
            }
2702
218
        }
2703
1.45k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
0
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
0
            if(BOOST_JSON_UNLIKELY(
2709
0
                (num.exp == INT_MAX) &&
2710
0
                (num.bias > 0) &&
2711
0
                (num.exp - num.bias < 308) &&
2712
0
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
0
            num.bias = 0;
2720
0
            num.exp = INT_MAX;
2721
0
        }
2722
1.67k
        goto finish_dub;
2723
1.67k
    }
2724
2725
535
finish_int:
2726
535
    if(negative || (!stack_empty && num.neg))
2727
535
    {
2728
535
        if(BOOST_JSON_UNLIKELY(
2729
535
            ! h_.on_int64(static_cast<
2730
535
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
535
        return cs.begin();
2733
535
    }
2734
0
    if(num.mant <= INT64_MAX)
2735
0
    {
2736
2.17k
finish_signed:
2737
2.17k
        if(BOOST_JSON_UNLIKELY(
2738
2.17k
            ! h_.on_int64(static_cast<
2739
2.17k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
2.17k
        return cs.begin();
2742
2.17k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
2.99k
finish_dub:
2748
2.99k
    double d;
2749
2.99k
    std::size_t const size = cs.used(begin);
2750
2.99k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
2.99k
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
2.99k
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
2.99k
    if(BOOST_JSON_UNLIKELY(
2778
2.99k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
2.99k
    return cs.begin();
2781
2.99k
}
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
2011
11.0M
{
2012
11.0M
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
11.0M
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
11.0M
    bool const negative = first == '-';
2020
11.0M
    bool const zero_first = first == '0';
2021
11.0M
    bool const nonzero_first = first == '+';
2022
11.0M
    detail::const_stream_wrapper cs(p, end_);
2023
11.0M
    number num;
2024
11.0M
    const char* begin = cs.begin();
2025
11.0M
    if(stack_empty || st_.empty())
2026
11.0M
    {
2027
11.0M
        num.bias = 0;
2028
11.0M
        num.exp = 0;
2029
11.0M
        num.frac = false;
2030
11.0M
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
11.0M
        BOOST_ASSERT(cs);
2038
11.0M
        if(negative)
2039
0
            ++cs;
2040
2041
11.0M
        num.neg = negative;
2042
11.0M
        num.frac = false;
2043
11.0M
        num.exp = 0;
2044
11.0M
        num.bias = 0;
2045
2046
        // fast path
2047
11.0M
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
11.0M
        {
2049
11.0M
            int n1;
2050
2051
11.0M
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
11.0M
            {
2054
11.0M
                n1 = detail::count_digits( cs.begin() );
2055
11.0M
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
11.0M
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
11.0M
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
11.0M
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
11.0M
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
11.0M
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
11.0M
                if( n1 == 16 )
2082
80.2k
                {
2083
80.2k
                    goto do_num2;
2084
80.2k
                }
2085
11.0M
            }
2086
0
            else
2087
0
            {
2088
                // 0. floating-point or 0e integer
2089
0
                num.mant = 0;
2090
0
                n1 = 0;
2091
0
                ++cs;
2092
0
            }
2093
2094
10.9M
            {
2095
10.9M
                const char c = *cs;
2096
10.9M
                if(c != '.')
2097
10.9M
                {
2098
10.9M
                    if((c | 32) == 'e')
2099
4.58M
                    {
2100
4.58M
                        ++cs;
2101
4.58M
                        goto do_exp1;
2102
4.58M
                    }
2103
6.36M
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
6.36M
                        num.mant = ~num.mant + 1;
2105
6.36M
                    goto finish_signed;
2106
10.9M
                }
2107
10.9M
            }
2108
2109
            // floating-point number
2110
2111
18.0k
            ++cs;
2112
2113
18.0k
            int n2 = detail::count_digits( cs.begin() );
2114
18.0k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
18.0k
            if( n2 == 0 )
2117
5
            {
2118
                // digit required
2119
5
                BOOST_STATIC_CONSTEXPR source_location loc
2120
5
                    = BOOST_CURRENT_LOCATION;
2121
5
                return fail(cs.begin(), error::syntax, &loc);
2122
5
            }
2123
2124
            // floating-point mantissa overflow
2125
18.0k
            if( n1 + n2 >= 19 )
2126
1.58k
            {
2127
1.58k
                goto do_num7;
2128
1.58k
            }
2129
2130
16.4k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
16.4k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
16.4k
            BOOST_ASSERT(num.bias == 0);
2134
2135
16.4k
            num.bias -= n2;
2136
2137
16.4k
            cs += n2;
2138
2139
16.4k
            char ch = *cs;
2140
2141
16.4k
            if( (ch | 32) == 'e' )
2142
3.35k
            {
2143
3.35k
                ++cs;
2144
3.35k
                goto do_exp1;
2145
3.35k
            }
2146
13.1k
            else if( ch >= '0' && ch <= '9' )
2147
1.65k
            {
2148
1.65k
                goto do_num8;
2149
1.65k
            }
2150
2151
11.4k
            goto finish_dub;
2152
16.4k
        }
2153
11.0M
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
11.1k
do_num1:
2182
11.1k
    if(zero_first || nonzero_first ||
2183
0
        BOOST_JSON_LIKELY(cs))
2184
11.1k
    {
2185
11.1k
        char const c = *cs;
2186
11.1k
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
11.1k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
11.1k
            c >= '1' && c <= '9'))
2194
11.1k
        {
2195
11.1k
            ++cs;
2196
11.1k
            num.mant = c - '0';
2197
11.1k
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
11.1k
    }
2220
0
    else
2221
0
    {
2222
0
        if(BOOST_JSON_UNLIKELY(
2223
0
            ! h_.on_number_part(
2224
0
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
0
            num_buf_.append( begin, cs.used(begin) );
2229
0
        return maybe_suspend(
2230
0
            cs.begin(), state::num1, num);
2231
0
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
91.3k
do_num2:
2239
91.3k
    if(negative || (!stack_empty && num.neg))
2240
0
    {
2241
0
        for(;;)
2242
0
        {
2243
0
            if(BOOST_JSON_UNLIKELY(! cs))
2244
0
            {
2245
0
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
0
                goto finish_int;
2257
0
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
0
    }
2274
91.3k
    else
2275
91.3k
    {
2276
91.3k
        for(;;)
2277
349k
        {
2278
349k
            if(BOOST_JSON_UNLIKELY(! cs))
2279
653
            {
2280
653
                if(BOOST_JSON_UNLIKELY(more_))
2281
360
                {
2282
360
                    if(BOOST_JSON_UNLIKELY(
2283
360
                        ! h_.on_number_part(
2284
360
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
360
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
360
                        num_buf_.append( begin, cs.used(begin) );
2289
360
                    return suspend(cs.begin(), state::num2, num);
2290
360
                }
2291
293
                goto finish_int;
2292
653
            }
2293
349k
            char const c = *cs;
2294
349k
            if(BOOST_JSON_LIKELY(
2295
349k
                c >= '0' && c <= '9'))
2296
274k
            {
2297
274k
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
274k
                if( num.mant  > 1844674407370955161 || (
2300
259k
                    num.mant == 1844674407370955161 && c > '5'))
2301
16.1k
                    break;
2302
258k
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
258k
                    num.mant = 10 * num.mant + ( c - '0' );
2304
258k
            }
2305
74.4k
            else
2306
74.4k
            {
2307
74.4k
                goto do_num6; // [.eE]
2308
74.4k
            }
2309
349k
        }
2310
91.3k
    }
2311
16.1k
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
16.1k
do_num3:
2319
16.1k
    for(;;)
2320
11.6M
    {
2321
11.6M
        if(BOOST_JSON_UNLIKELY(! cs))
2322
63
        {
2323
63
            if(BOOST_JSON_UNLIKELY(more_))
2324
25
            {
2325
25
                if(BOOST_JSON_UNLIKELY(
2326
25
                    ! h_.on_number_part(
2327
25
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
25
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
25
                    num_buf_.append( begin, cs.used(begin) );
2332
25
                return suspend(cs.begin(), state::num3, num);
2333
25
            }
2334
38
            goto finish_dub;
2335
63
        }
2336
11.6M
        char const c = *cs;
2337
11.6M
        if(BOOST_JSON_UNLIKELY(
2338
11.6M
            c >= '0' && c <= '9'))
2339
11.6M
        {
2340
11.6M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
11.6M
            ++cs;
2347
11.6M
            ++num.bias;
2348
11.6M
        }
2349
16.1k
        else if(BOOST_JSON_LIKELY(
2350
16.1k
            c == '.'))
2351
1.24k
        {
2352
1.24k
            ++cs;
2353
1.24k
            break;
2354
1.24k
        }
2355
14.8k
        else if((c | 32) == 'e')
2356
1.67k
        {
2357
1.67k
            ++cs;
2358
1.67k
            goto do_exp1;
2359
1.67k
        }
2360
13.2k
        else
2361
13.2k
        {
2362
13.2k
            goto finish_dub;
2363
13.2k
        }
2364
11.6M
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
1.24k
do_num4:
2373
1.24k
    {
2374
1.24k
        if(BOOST_JSON_UNLIKELY(! cs))
2375
6
        {
2376
6
            if(BOOST_JSON_UNLIKELY(
2377
6
                ! h_.on_number_part(
2378
6
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
6
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
6
                num_buf_.append( begin, cs.used(begin) );
2383
6
            return maybe_suspend(
2384
6
                cs.begin(), state::num4, num);
2385
6
        }
2386
1.24k
        char const c = *cs;
2387
1.24k
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
1.24k
            c >= '0' && c <= '9'))
2390
1.22k
        {
2391
1.22k
            ++cs;
2392
1.22k
        }
2393
21
        else
2394
21
        {
2395
            // digit required
2396
21
            BOOST_STATIC_CONSTEXPR source_location loc
2397
21
                = BOOST_CURRENT_LOCATION;
2398
21
            return fail(cs.begin(), error::syntax, &loc);
2399
21
        }
2400
1.24k
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
9.01k
do_num5:
2409
9.01k
    for(;;)
2410
47.9k
    {
2411
47.9k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
91
        {
2413
91
            if(BOOST_JSON_UNLIKELY(more_))
2414
45
            {
2415
45
                if(BOOST_JSON_UNLIKELY(
2416
45
                    ! h_.on_number_part(
2417
45
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
45
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
45
                    num_buf_.append( begin, cs.used(begin) );
2422
45
                return suspend(cs.begin(), state::num5, num);
2423
45
            }
2424
46
            goto finish_dub;
2425
91
        }
2426
47.8k
        char const c = *cs;
2427
47.8k
        if(BOOST_JSON_LIKELY(
2428
47.8k
            c >= '0' && c <= '9'))
2429
38.9k
        {
2430
38.9k
            ++cs;
2431
38.9k
        }
2432
8.92k
        else if((c | 32) == 'e')
2433
1.11k
        {
2434
1.11k
            ++cs;
2435
1.11k
            goto do_exp1;
2436
1.11k
        }
2437
7.81k
        else
2438
7.81k
        {
2439
7.81k
            goto finish_dub;
2440
7.81k
        }
2441
47.8k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
74.4k
do_num6:
2448
74.4k
    {
2449
74.4k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
0
        {
2451
0
            if(BOOST_JSON_UNLIKELY(more_))
2452
0
            {
2453
0
                if(BOOST_JSON_UNLIKELY(
2454
0
                    ! h_.on_number_part(
2455
0
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
0
                    num_buf_.append( begin, cs.used(begin) );
2460
0
                return suspend(cs.begin(), state::num6, num);
2461
0
            }
2462
0
            goto finish_int;
2463
0
        }
2464
74.4k
        char const c = *cs;
2465
74.4k
        if(BOOST_JSON_LIKELY(
2466
74.4k
            c == '.'))
2467
6.42k
        {
2468
6.42k
            ++cs;
2469
6.42k
        }
2470
68.0k
        else if((c | 32) == 'e')
2471
2.98k
        {
2472
2.98k
            ++cs;
2473
2.98k
            goto do_exp1;
2474
2.98k
        }
2475
65.0k
        else
2476
65.0k
        {
2477
65.0k
            goto finish_int;
2478
65.0k
        }
2479
74.4k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
8.00k
do_num7:
2488
8.00k
    {
2489
8.00k
        if(BOOST_JSON_UNLIKELY(! cs))
2490
8
        {
2491
8
            if(BOOST_JSON_UNLIKELY(more_))
2492
3
            {
2493
3
                if(BOOST_JSON_UNLIKELY(
2494
3
                    ! h_.on_number_part(
2495
3
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
3
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
3
                    num_buf_.append( begin, cs.used(begin) );
2500
3
                return suspend(cs.begin(), state::num7, num);
2501
3
            }
2502
            // digit required
2503
8
            BOOST_STATIC_CONSTEXPR source_location loc
2504
5
                = BOOST_CURRENT_LOCATION;
2505
5
            return fail(cs.begin(), error::syntax, &loc);
2506
8
        }
2507
8.00k
        char const c = *cs;
2508
8.00k
        if(BOOST_JSON_UNLIKELY(
2509
8.00k
            c < '0' || c > '9'))
2510
27
        {
2511
            // digit required
2512
27
            BOOST_STATIC_CONSTEXPR source_location loc
2513
27
                = BOOST_CURRENT_LOCATION;
2514
27
            return fail(cs.begin(), error::syntax, &loc);
2515
27
        }
2516
8.00k
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
9.62k
do_num8:
2525
9.62k
    for(;;)
2526
29.6k
    {
2527
29.6k
        if(BOOST_JSON_UNLIKELY(! cs))
2528
481
        {
2529
481
            if(BOOST_JSON_UNLIKELY(more_))
2530
377
            {
2531
377
                if(BOOST_JSON_UNLIKELY(
2532
377
                    ! h_.on_number_part(
2533
377
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
377
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
377
                    num_buf_.append( begin, cs.used(begin) );
2538
377
                return suspend(cs.begin(), state::num8, num);
2539
377
            }
2540
104
            goto finish_dub;
2541
481
        }
2542
29.1k
        char const c = *cs;
2543
29.1k
        if(BOOST_JSON_LIKELY(
2544
29.1k
            c >= '0' && c <= '9'))
2545
27.8k
        {
2546
27.8k
            ++cs;
2547
27.8k
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
27.8k
                num.mant <= 9007199254740991)) // 2^53-1
2549
20.0k
            {
2550
20.0k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
20.0k
                --num.bias;
2557
20.0k
                num.mant = 10 * num.mant + ( c - '0' );
2558
20.0k
            }
2559
7.79k
            else
2560
7.79k
            {
2561
7.79k
                goto do_num5;
2562
7.79k
            }
2563
27.8k
        }
2564
1.34k
        else if((c | 32) == 'e')
2565
525
        {
2566
525
            ++cs;
2567
525
            goto do_exp1;
2568
525
        }
2569
823
        else
2570
823
        {
2571
823
            goto finish_dub;
2572
823
        }
2573
29.1k
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
4.59M
do_exp1:
2580
4.59M
    if(BOOST_JSON_UNLIKELY(! cs))
2581
60
    {
2582
60
        if(BOOST_JSON_UNLIKELY(
2583
60
            ! h_.on_number_part(
2584
60
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
60
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
60
            num_buf_.append( begin, cs.used(begin) );
2589
60
        return maybe_suspend(
2590
60
            cs.begin(), state::exp1, num);
2591
60
    }
2592
4.59M
    if(*cs == '+')
2593
605
    {
2594
605
        ++cs;
2595
605
    }
2596
4.59M
    else if(*cs == '-')
2597
62.0k
    {
2598
62.0k
        ++cs;
2599
62.0k
        num.frac = true;
2600
62.0k
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
4.59M
do_exp2:
2608
4.59M
    {
2609
4.59M
        if(BOOST_JSON_UNLIKELY(! cs))
2610
22
        {
2611
22
            if(BOOST_JSON_UNLIKELY(more_))
2612
10
            {
2613
10
                if(BOOST_JSON_UNLIKELY(
2614
10
                    ! h_.on_number_part(
2615
10
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
10
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
10
                    num_buf_.append( begin, cs.used(begin) );
2620
10
                return suspend(cs.begin(), state::exp2, num);
2621
10
            }
2622
            // digit required
2623
22
            BOOST_STATIC_CONSTEXPR source_location loc
2624
12
                = BOOST_CURRENT_LOCATION;
2625
12
            return fail(cs.begin(), error::syntax, &loc);
2626
22
        }
2627
4.59M
        char const c = *cs;
2628
4.59M
        if(BOOST_JSON_UNLIKELY(
2629
4.59M
            c < '0' || c > '9'))
2630
57
        {
2631
            // digit required
2632
57
            BOOST_STATIC_CONSTEXPR source_location loc
2633
57
                = BOOST_CURRENT_LOCATION;
2634
57
            return fail(cs.begin(), error::syntax, &loc);
2635
57
        }
2636
4.59M
        ++cs;
2637
4.59M
        num.exp = c - '0';
2638
4.59M
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
4.59M
do_exp3:
2646
4.59M
    for(;;)
2647
9.38M
    {
2648
9.38M
        if(BOOST_JSON_UNLIKELY(! cs))
2649
775
        {
2650
775
            if(BOOST_JSON_UNLIKELY(more_))
2651
384
            {
2652
384
                if(BOOST_JSON_UNLIKELY(
2653
384
                    ! h_.on_number_part(
2654
384
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
384
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
384
                    num_buf_.append( begin, cs.used(begin) );
2659
384
                return suspend(cs.begin(), state::exp3, num);
2660
384
            }
2661
775
        }
2662
9.38M
        else
2663
9.38M
        {
2664
9.38M
            char const c = *cs;
2665
9.38M
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
4.79M
            {
2667
4.79M
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
4.79M
                    num.exp  >  214748364 ||
2670
4.79M
                    (num.exp == 214748364 && c > '7')
2671
4.79M
                ))
2672
134k
                    num.exp = INT_MAX;
2673
4.65M
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
4.65M
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
4.79M
                ++cs;
2677
4.79M
                continue;
2678
4.79M
            }
2679
9.38M
        }
2680
4.59M
        BOOST_ASSERT(num.exp >= 0);
2681
4.59M
        if ( num.frac )
2682
61.8k
        {
2683
61.8k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
923
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
923
                if(BOOST_JSON_UNLIKELY(
2689
923
                    (num.exp == INT_MAX) &&
2690
923
                    (num.bias < 0) &&
2691
923
                    (num.exp + num.bias < 308) &&
2692
923
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
923
                num.bias = 0;
2700
923
                num.exp = INT_MAX;
2701
923
            }
2702
61.8k
        }
2703
4.52M
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
881
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
881
            if(BOOST_JSON_UNLIKELY(
2709
881
                (num.exp == INT_MAX) &&
2710
881
                (num.bias > 0) &&
2711
881
                (num.exp - num.bias < 308) &&
2712
881
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
881
            num.bias = 0;
2720
881
            num.exp = INT_MAX;
2721
881
        }
2722
4.59M
        goto finish_dub;
2723
4.59M
    }
2724
2725
65.3k
finish_int:
2726
65.3k
    if(negative || (!stack_empty && num.neg))
2727
0
    {
2728
0
        if(BOOST_JSON_UNLIKELY(
2729
0
            ! h_.on_int64(static_cast<
2730
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
0
        return cs.begin();
2733
0
    }
2734
65.3k
    if(num.mant <= INT64_MAX)
2735
14.8k
    {
2736
6.38M
finish_signed:
2737
6.38M
        if(BOOST_JSON_UNLIKELY(
2738
6.38M
            ! h_.on_int64(static_cast<
2739
6.38M
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
6.38M
        return cs.begin();
2742
6.38M
    }
2743
50.5k
    if(BOOST_JSON_UNLIKELY(
2744
50.5k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
50.5k
    return cs.begin();
2747
4.62M
finish_dub:
2748
4.62M
    double d;
2749
4.62M
    std::size_t const size = cs.used(begin);
2750
4.62M
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
4.62M
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
4.62M
        d = 0;
2771
4.62M
    else
2772
4.62M
        d = detail::dec_to_float(
2773
4.62M
            num.mant,
2774
4.62M
            num.bias + (num.frac ?
2775
4.56M
                -num.exp : num.exp),
2776
4.62M
            num.neg);
2777
4.62M
    if(BOOST_JSON_UNLIKELY(
2778
4.62M
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
4.62M
    return cs.begin();
2781
4.62M
}
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>)
Line
Count
Source
2011
442k
{
2012
442k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
442k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
442k
    bool const negative = first == '-';
2020
442k
    bool const zero_first = first == '0';
2021
442k
    bool const nonzero_first = first == '+';
2022
442k
    detail::const_stream_wrapper cs(p, end_);
2023
442k
    number num;
2024
442k
    const char* begin = cs.begin();
2025
442k
    if(stack_empty || st_.empty())
2026
442k
    {
2027
442k
        num.bias = 0;
2028
442k
        num.exp = 0;
2029
442k
        num.frac = false;
2030
442k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
442k
        BOOST_ASSERT(cs);
2038
442k
        if(negative)
2039
0
            ++cs;
2040
2041
442k
        num.neg = negative;
2042
442k
        num.frac = false;
2043
442k
        num.exp = 0;
2044
442k
        num.bias = 0;
2045
2046
        // fast path
2047
442k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
437k
        {
2049
437k
            int n1;
2050
2051
437k
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
437k
            {
2054
437k
                n1 = detail::count_digits( cs.begin() );
2055
437k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
437k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
437k
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
437k
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
437k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
437k
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
437k
                if( n1 == 16 )
2082
16.8k
                {
2083
16.8k
                    goto do_num2;
2084
16.8k
                }
2085
437k
            }
2086
0
            else
2087
0
            {
2088
                // 0. floating-point or 0e integer
2089
0
                num.mant = 0;
2090
0
                n1 = 0;
2091
0
                ++cs;
2092
0
            }
2093
2094
420k
            {
2095
420k
                const char c = *cs;
2096
420k
                if(c != '.')
2097
411k
                {
2098
411k
                    if((c | 32) == 'e')
2099
243k
                    {
2100
243k
                        ++cs;
2101
243k
                        goto do_exp1;
2102
243k
                    }
2103
168k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
168k
                        num.mant = ~num.mant + 1;
2105
168k
                    goto finish_signed;
2106
411k
                }
2107
420k
            }
2108
2109
            // floating-point number
2110
2111
8.79k
            ++cs;
2112
2113
8.79k
            int n2 = detail::count_digits( cs.begin() );
2114
8.79k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
8.79k
            if( n2 == 0 )
2117
4
            {
2118
                // digit required
2119
4
                BOOST_STATIC_CONSTEXPR source_location loc
2120
4
                    = BOOST_CURRENT_LOCATION;
2121
4
                return fail(cs.begin(), error::syntax, &loc);
2122
4
            }
2123
2124
            // floating-point mantissa overflow
2125
8.79k
            if( n1 + n2 >= 19 )
2126
1.38k
            {
2127
1.38k
                goto do_num7;
2128
1.38k
            }
2129
2130
7.40k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
7.40k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
7.40k
            BOOST_ASSERT(num.bias == 0);
2134
2135
7.40k
            num.bias -= n2;
2136
2137
7.40k
            cs += n2;
2138
2139
7.40k
            char ch = *cs;
2140
2141
7.40k
            if( (ch | 32) == 'e' )
2142
1.33k
            {
2143
1.33k
                ++cs;
2144
1.33k
                goto do_exp1;
2145
1.33k
            }
2146
6.07k
            else if( ch >= '0' && ch <= '9' )
2147
2.39k
            {
2148
2.39k
                goto do_num8;
2149
2.39k
            }
2150
2151
3.68k
            goto finish_dub;
2152
7.40k
        }
2153
442k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
4.57k
do_num1:
2182
4.57k
    if(zero_first || nonzero_first ||
2183
0
        BOOST_JSON_LIKELY(cs))
2184
4.57k
    {
2185
4.57k
        char const c = *cs;
2186
4.57k
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
4.57k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
4.57k
            c >= '1' && c <= '9'))
2194
4.57k
        {
2195
4.57k
            ++cs;
2196
4.57k
            num.mant = c - '0';
2197
4.57k
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
4.57k
    }
2220
0
    else
2221
0
    {
2222
0
        if(BOOST_JSON_UNLIKELY(
2223
0
            ! h_.on_number_part(
2224
0
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
0
            num_buf_.append( begin, cs.used(begin) );
2229
0
        return maybe_suspend(
2230
0
            cs.begin(), state::num1, num);
2231
0
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
21.3k
do_num2:
2239
21.3k
    if(negative || (!stack_empty && num.neg))
2240
0
    {
2241
0
        for(;;)
2242
0
        {
2243
0
            if(BOOST_JSON_UNLIKELY(! cs))
2244
0
            {
2245
0
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
0
                goto finish_int;
2257
0
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
0
    }
2274
21.3k
    else
2275
21.3k
    {
2276
21.3k
        for(;;)
2277
102k
        {
2278
102k
            if(BOOST_JSON_UNLIKELY(! cs))
2279
330
            {
2280
330
                if(BOOST_JSON_UNLIKELY(more_))
2281
330
                {
2282
330
                    if(BOOST_JSON_UNLIKELY(
2283
330
                        ! h_.on_number_part(
2284
330
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
330
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
330
                        num_buf_.append( begin, cs.used(begin) );
2289
330
                    return suspend(cs.begin(), state::num2, num);
2290
330
                }
2291
0
                goto finish_int;
2292
330
            }
2293
102k
            char const c = *cs;
2294
102k
            if(BOOST_JSON_LIKELY(
2295
102k
                c >= '0' && c <= '9'))
2296
91.0k
            {
2297
91.0k
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
91.0k
                if( num.mant  > 1844674407370955161 || (
2300
82.1k
                    num.mant == 1844674407370955161 && c > '5'))
2301
9.75k
                    break;
2302
81.3k
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
81.3k
                    num.mant = 10 * num.mant + ( c - '0' );
2304
81.3k
            }
2305
11.2k
            else
2306
11.2k
            {
2307
11.2k
                goto do_num6; // [.eE]
2308
11.2k
            }
2309
102k
        }
2310
21.3k
    }
2311
9.75k
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
9.75k
do_num3:
2319
9.75k
    for(;;)
2320
14.4M
    {
2321
14.4M
        if(BOOST_JSON_UNLIKELY(! cs))
2322
456
        {
2323
456
            if(BOOST_JSON_UNLIKELY(more_))
2324
456
            {
2325
456
                if(BOOST_JSON_UNLIKELY(
2326
456
                    ! h_.on_number_part(
2327
456
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
456
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
456
                    num_buf_.append( begin, cs.used(begin) );
2332
456
                return suspend(cs.begin(), state::num3, num);
2333
456
            }
2334
0
            goto finish_dub;
2335
456
        }
2336
14.4M
        char const c = *cs;
2337
14.4M
        if(BOOST_JSON_UNLIKELY(
2338
14.4M
            c >= '0' && c <= '9'))
2339
14.3M
        {
2340
14.3M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
14.3M
            ++cs;
2347
14.3M
            ++num.bias;
2348
14.3M
        }
2349
9.30k
        else if(BOOST_JSON_LIKELY(
2350
9.30k
            c == '.'))
2351
2.64k
        {
2352
2.64k
            ++cs;
2353
2.64k
            break;
2354
2.64k
        }
2355
6.65k
        else if((c | 32) == 'e')
2356
4.23k
        {
2357
4.23k
            ++cs;
2358
4.23k
            goto do_exp1;
2359
4.23k
        }
2360
2.41k
        else
2361
2.41k
        {
2362
2.41k
            goto finish_dub;
2363
2.41k
        }
2364
14.4M
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
2.64k
do_num4:
2373
2.64k
    {
2374
2.64k
        if(BOOST_JSON_UNLIKELY(! cs))
2375
2
        {
2376
2
            if(BOOST_JSON_UNLIKELY(
2377
2
                ! h_.on_number_part(
2378
2
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
2
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
2
                num_buf_.append( begin, cs.used(begin) );
2383
2
            return maybe_suspend(
2384
2
                cs.begin(), state::num4, num);
2385
2
        }
2386
2.64k
        char const c = *cs;
2387
2.64k
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
2.64k
            c >= '0' && c <= '9'))
2390
2.64k
        {
2391
2.64k
            ++cs;
2392
2.64k
        }
2393
3
        else
2394
3
        {
2395
            // digit required
2396
3
            BOOST_STATIC_CONSTEXPR source_location loc
2397
3
                = BOOST_CURRENT_LOCATION;
2398
3
            return fail(cs.begin(), error::syntax, &loc);
2399
3
        }
2400
2.64k
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
8.18k
do_num5:
2409
8.18k
    for(;;)
2410
7.37M
    {
2411
7.37M
        if(BOOST_JSON_UNLIKELY(! cs))
2412
728
        {
2413
728
            if(BOOST_JSON_UNLIKELY(more_))
2414
728
            {
2415
728
                if(BOOST_JSON_UNLIKELY(
2416
728
                    ! h_.on_number_part(
2417
728
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
728
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
728
                    num_buf_.append( begin, cs.used(begin) );
2422
728
                return suspend(cs.begin(), state::num5, num);
2423
728
            }
2424
0
            goto finish_dub;
2425
728
        }
2426
7.37M
        char const c = *cs;
2427
7.37M
        if(BOOST_JSON_LIKELY(
2428
7.37M
            c >= '0' && c <= '9'))
2429
7.36M
        {
2430
7.36M
            ++cs;
2431
7.36M
        }
2432
7.46k
        else if((c | 32) == 'e')
2433
3.28k
        {
2434
3.28k
            ++cs;
2435
3.28k
            goto do_exp1;
2436
3.28k
        }
2437
4.17k
        else
2438
4.17k
        {
2439
4.17k
            goto finish_dub;
2440
4.17k
        }
2441
7.37M
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
11.2k
do_num6:
2448
11.2k
    {
2449
11.2k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
0
        {
2451
0
            if(BOOST_JSON_UNLIKELY(more_))
2452
0
            {
2453
0
                if(BOOST_JSON_UNLIKELY(
2454
0
                    ! h_.on_number_part(
2455
0
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
0
                    num_buf_.append( begin, cs.used(begin) );
2460
0
                return suspend(cs.begin(), state::num6, num);
2461
0
            }
2462
0
            goto finish_int;
2463
0
        }
2464
11.2k
        char const c = *cs;
2465
11.2k
        if(BOOST_JSON_LIKELY(
2466
11.2k
            c == '.'))
2467
2.92k
        {
2468
2.92k
            ++cs;
2469
2.92k
        }
2470
8.37k
        else if((c | 32) == 'e')
2471
1.75k
        {
2472
1.75k
            ++cs;
2473
1.75k
            goto do_exp1;
2474
1.75k
        }
2475
6.62k
        else
2476
6.62k
        {
2477
6.62k
            goto finish_int;
2478
6.62k
        }
2479
11.2k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
4.31k
do_num7:
2488
4.31k
    {
2489
4.31k
        if(BOOST_JSON_UNLIKELY(! cs))
2490
8
        {
2491
8
            if(BOOST_JSON_UNLIKELY(more_))
2492
8
            {
2493
8
                if(BOOST_JSON_UNLIKELY(
2494
8
                    ! h_.on_number_part(
2495
8
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
8
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
8
                    num_buf_.append( begin, cs.used(begin) );
2500
8
                return suspend(cs.begin(), state::num7, num);
2501
8
            }
2502
            // digit required
2503
8
            BOOST_STATIC_CONSTEXPR source_location loc
2504
0
                = BOOST_CURRENT_LOCATION;
2505
0
            return fail(cs.begin(), error::syntax, &loc);
2506
8
        }
2507
4.30k
        char const c = *cs;
2508
4.30k
        if(BOOST_JSON_UNLIKELY(
2509
4.30k
            c < '0' || c > '9'))
2510
19
        {
2511
            // digit required
2512
19
            BOOST_STATIC_CONSTEXPR source_location loc
2513
19
                = BOOST_CURRENT_LOCATION;
2514
19
            return fail(cs.begin(), error::syntax, &loc);
2515
19
        }
2516
4.30k
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
6.67k
do_num8:
2525
6.67k
    for(;;)
2526
24.7k
    {
2527
24.7k
        if(BOOST_JSON_UNLIKELY(! cs))
2528
512
        {
2529
512
            if(BOOST_JSON_UNLIKELY(more_))
2530
512
            {
2531
512
                if(BOOST_JSON_UNLIKELY(
2532
512
                    ! h_.on_number_part(
2533
512
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
512
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
512
                    num_buf_.append( begin, cs.used(begin) );
2538
512
                return suspend(cs.begin(), state::num8, num);
2539
512
            }
2540
0
            goto finish_dub;
2541
512
        }
2542
24.2k
        char const c = *cs;
2543
24.2k
        if(BOOST_JSON_LIKELY(
2544
24.2k
            c >= '0' && c <= '9'))
2545
23.6k
        {
2546
23.6k
            ++cs;
2547
23.6k
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
23.6k
                num.mant <= 9007199254740991)) // 2^53-1
2549
18.0k
            {
2550
18.0k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
18.0k
                --num.bias;
2557
18.0k
                num.mant = 10 * num.mant + ( c - '0' );
2558
18.0k
            }
2559
5.54k
            else
2560
5.54k
            {
2561
5.54k
                goto do_num5;
2562
5.54k
            }
2563
23.6k
        }
2564
616
        else if((c | 32) == 'e')
2565
301
        {
2566
301
            ++cs;
2567
301
            goto do_exp1;
2568
301
        }
2569
315
        else
2570
315
        {
2571
315
            goto finish_dub;
2572
315
        }
2573
24.2k
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
254k
do_exp1:
2580
254k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
24
    {
2582
24
        if(BOOST_JSON_UNLIKELY(
2583
24
            ! h_.on_number_part(
2584
24
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
24
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
24
            num_buf_.append( begin, cs.used(begin) );
2589
24
        return maybe_suspend(
2590
24
            cs.begin(), state::exp1, num);
2591
24
    }
2592
254k
    if(*cs == '+')
2593
218
    {
2594
218
        ++cs;
2595
218
    }
2596
253k
    else if(*cs == '-')
2597
6.79k
    {
2598
6.79k
        ++cs;
2599
6.79k
        num.frac = true;
2600
6.79k
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
254k
do_exp2:
2608
254k
    {
2609
254k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
9
        {
2611
9
            if(BOOST_JSON_UNLIKELY(more_))
2612
9
            {
2613
9
                if(BOOST_JSON_UNLIKELY(
2614
9
                    ! h_.on_number_part(
2615
9
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
9
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
9
                    num_buf_.append( begin, cs.used(begin) );
2620
9
                return suspend(cs.begin(), state::exp2, num);
2621
9
            }
2622
            // digit required
2623
9
            BOOST_STATIC_CONSTEXPR source_location loc
2624
0
                = BOOST_CURRENT_LOCATION;
2625
0
            return fail(cs.begin(), error::syntax, &loc);
2626
9
        }
2627
254k
        char const c = *cs;
2628
254k
        if(BOOST_JSON_UNLIKELY(
2629
254k
            c < '0' || c > '9'))
2630
28
        {
2631
            // digit required
2632
28
            BOOST_STATIC_CONSTEXPR source_location loc
2633
28
                = BOOST_CURRENT_LOCATION;
2634
28
            return fail(cs.begin(), error::syntax, &loc);
2635
28
        }
2636
254k
        ++cs;
2637
254k
        num.exp = c - '0';
2638
254k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
254k
do_exp3:
2646
254k
    for(;;)
2647
538k
    {
2648
538k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
1.16k
        {
2650
1.16k
            if(BOOST_JSON_UNLIKELY(more_))
2651
1.16k
            {
2652
1.16k
                if(BOOST_JSON_UNLIKELY(
2653
1.16k
                    ! h_.on_number_part(
2654
1.16k
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
1.16k
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
1.16k
                    num_buf_.append( begin, cs.used(begin) );
2659
1.16k
                return suspend(cs.begin(), state::exp3, num);
2660
1.16k
            }
2661
1.16k
        }
2662
537k
        else
2663
537k
        {
2664
537k
            char const c = *cs;
2665
537k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
284k
            {
2667
284k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
284k
                    num.exp  >  214748364 ||
2670
284k
                    (num.exp == 214748364 && c > '7')
2671
284k
                ))
2672
8.64k
                    num.exp = INT_MAX;
2673
275k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
275k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
284k
                ++cs;
2677
284k
                continue;
2678
284k
            }
2679
537k
        }
2680
252k
        BOOST_ASSERT(num.exp >= 0);
2681
252k
        if ( num.frac )
2682
6.28k
        {
2683
6.28k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
511
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
511
                if(BOOST_JSON_UNLIKELY(
2689
511
                    (num.exp == INT_MAX) &&
2690
511
                    (num.bias < 0) &&
2691
511
                    (num.exp + num.bias < 308) &&
2692
511
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
511
                num.bias = 0;
2700
511
                num.exp = INT_MAX;
2701
511
            }
2702
6.28k
        }
2703
246k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
430
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
430
            if(BOOST_JSON_UNLIKELY(
2709
430
                (num.exp == INT_MAX) &&
2710
430
                (num.bias > 0) &&
2711
430
                (num.exp - num.bias < 308) &&
2712
430
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
430
            num.bias = 0;
2720
430
            num.exp = INT_MAX;
2721
430
        }
2722
252k
        goto finish_dub;
2723
252k
    }
2724
2725
6.62k
finish_int:
2726
6.62k
    if(negative || (!stack_empty && num.neg))
2727
0
    {
2728
0
        if(BOOST_JSON_UNLIKELY(
2729
0
            ! h_.on_int64(static_cast<
2730
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
0
        return cs.begin();
2733
0
    }
2734
6.62k
    if(num.mant <= INT64_MAX)
2735
2.09k
    {
2736
170k
finish_signed:
2737
170k
        if(BOOST_JSON_UNLIKELY(
2738
170k
            ! h_.on_int64(static_cast<
2739
170k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
170k
        return cs.begin();
2742
170k
    }
2743
4.52k
    if(BOOST_JSON_UNLIKELY(
2744
4.52k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
4.52k
    return cs.begin();
2747
263k
finish_dub:
2748
263k
    double d;
2749
263k
    std::size_t const size = cs.used(begin);
2750
263k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
263k
    {
2753
263k
        char const* data = begin;
2754
263k
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
263k
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
0
        {
2760
0
            data = num_buf_.append( begin, size );
2761
0
            full_size = num_buf_.size();
2762
0
        }
2763
263k
        auto const err = detail::charconv::from_chars(
2764
263k
            data, data + full_size, d );
2765
263k
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
263k
        BOOST_ASSERT( err.ptr == data + full_size );
2767
263k
        (void)err;
2768
    }
2769
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
263k
    if(BOOST_JSON_UNLIKELY(
2778
263k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
263k
    return cs.begin();
2781
263k
}
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>)
Line
Count
Source
2011
94.9k
{
2012
94.9k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
94.9k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
94.9k
    bool const negative = first == '-';
2020
94.9k
    bool const zero_first = first == '0';
2021
94.9k
    bool const nonzero_first = first == '+';
2022
94.9k
    detail::const_stream_wrapper cs(p, end_);
2023
94.9k
    number num;
2024
94.9k
    const char* begin = cs.begin();
2025
94.9k
    if(stack_empty || st_.empty())
2026
94.9k
    {
2027
94.9k
        num.bias = 0;
2028
94.9k
        num.exp = 0;
2029
94.9k
        num.frac = false;
2030
94.9k
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
94.9k
        BOOST_ASSERT(cs);
2038
94.9k
        if(negative)
2039
0
            ++cs;
2040
2041
94.9k
        num.neg = negative;
2042
94.9k
        num.frac = false;
2043
94.9k
        num.exp = 0;
2044
94.9k
        num.bias = 0;
2045
2046
        // fast path
2047
94.9k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
93.5k
        {
2049
93.5k
            int n1;
2050
2051
93.5k
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
93.5k
            {
2054
93.5k
                n1 = detail::count_digits( cs.begin() );
2055
93.5k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
93.5k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
93.5k
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
93.5k
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
93.5k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
93.5k
                else
2075
93.5k
                    num.mant = 0;
2076
2077
93.5k
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
93.5k
                if( n1 == 16 )
2082
2.13k
                {
2083
2.13k
                    goto do_num2;
2084
2.13k
                }
2085
93.5k
            }
2086
0
            else
2087
0
            {
2088
                // 0. floating-point or 0e integer
2089
0
                num.mant = 0;
2090
0
                n1 = 0;
2091
0
                ++cs;
2092
0
            }
2093
2094
91.4k
            {
2095
91.4k
                const char c = *cs;
2096
91.4k
                if(c != '.')
2097
90.0k
                {
2098
90.0k
                    if((c | 32) == 'e')
2099
19.9k
                    {
2100
19.9k
                        ++cs;
2101
19.9k
                        goto do_exp1;
2102
19.9k
                    }
2103
70.0k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
70.0k
                        num.mant = ~num.mant + 1;
2105
70.0k
                    goto finish_signed;
2106
90.0k
                }
2107
91.4k
            }
2108
2109
            // floating-point number
2110
2111
1.44k
            ++cs;
2112
2113
1.44k
            int n2 = detail::count_digits( cs.begin() );
2114
1.44k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
1.44k
            if( n2 == 0 )
2117
1
            {
2118
                // digit required
2119
1
                BOOST_STATIC_CONSTEXPR source_location loc
2120
1
                    = BOOST_CURRENT_LOCATION;
2121
1
                return fail(cs.begin(), error::syntax, &loc);
2122
1
            }
2123
2124
            // floating-point mantissa overflow
2125
1.44k
            if( n1 + n2 >= 19 )
2126
264
            {
2127
264
                goto do_num7;
2128
264
            }
2129
2130
1.18k
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
1.18k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
1.18k
            BOOST_ASSERT(num.bias == 0);
2134
2135
1.18k
            num.bias -= n2;
2136
2137
1.18k
            cs += n2;
2138
2139
1.18k
            char ch = *cs;
2140
2141
1.18k
            if( (ch | 32) == 'e' )
2142
217
            {
2143
217
                ++cs;
2144
217
                goto do_exp1;
2145
217
            }
2146
967
            else if( ch >= '0' && ch <= '9' )
2147
335
            {
2148
335
                goto do_num8;
2149
335
            }
2150
2151
632
            goto finish_dub;
2152
1.18k
        }
2153
94.9k
    }
2154
0
    else
2155
0
    {
2156
0
        num = num_;
2157
0
        state st;
2158
0
        st_.pop(st);
2159
0
        switch(st)
2160
0
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
0
        case state::num1: goto do_num1;
2163
0
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
0
        case state::num5: goto do_num5;
2167
0
        case state::num6: goto do_num6;
2168
0
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
0
        case state::exp1: goto do_exp1;
2171
0
        case state::exp2: goto do_exp2;
2172
0
        case state::exp3: goto do_exp3;
2173
0
        }
2174
0
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
1.36k
do_num1:
2182
1.36k
    if(zero_first || nonzero_first ||
2183
0
        BOOST_JSON_LIKELY(cs))
2184
1.36k
    {
2185
1.36k
        char const c = *cs;
2186
1.36k
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
1.36k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
1.36k
            c >= '1' && c <= '9'))
2194
1.36k
        {
2195
1.36k
            ++cs;
2196
1.36k
            num.mant = c - '0';
2197
1.36k
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
1.36k
    }
2220
0
    else
2221
0
    {
2222
0
        if(BOOST_JSON_UNLIKELY(
2223
0
            ! h_.on_number_part(
2224
0
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
0
            num_buf_.append( begin, cs.used(begin) );
2229
0
        return maybe_suspend(
2230
0
            cs.begin(), state::num1, num);
2231
0
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
3.49k
do_num2:
2239
3.49k
    if(negative || (!stack_empty && num.neg))
2240
0
    {
2241
0
        for(;;)
2242
0
        {
2243
0
            if(BOOST_JSON_UNLIKELY(! cs))
2244
0
            {
2245
0
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
0
                goto finish_int;
2257
0
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
0
    }
2274
3.49k
    else
2275
3.49k
    {
2276
3.49k
        for(;;)
2277
11.4k
        {
2278
11.4k
            if(BOOST_JSON_UNLIKELY(! cs))
2279
70
            {
2280
70
                if(BOOST_JSON_UNLIKELY(more_))
2281
70
                {
2282
70
                    if(BOOST_JSON_UNLIKELY(
2283
70
                        ! h_.on_number_part(
2284
70
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
70
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
70
                        num_buf_.append( begin, cs.used(begin) );
2289
70
                    return suspend(cs.begin(), state::num2, num);
2290
70
                }
2291
0
                goto finish_int;
2292
70
            }
2293
11.3k
            char const c = *cs;
2294
11.3k
            if(BOOST_JSON_LIKELY(
2295
11.3k
                c >= '0' && c <= '9'))
2296
7.94k
            {
2297
7.94k
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
7.94k
                if( num.mant  > 1844674407370955161 || (
2300
7.94k
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
7.94k
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
7.94k
                    num.mant = 10 * num.mant + ( c - '0' );
2304
7.94k
            }
2305
3.42k
            else
2306
3.42k
            {
2307
3.42k
                goto do_num6; // [.eE]
2308
3.42k
            }
2309
11.3k
        }
2310
3.49k
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
0
do_num3:
2319
0
    for(;;)
2320
0
    {
2321
0
        if(BOOST_JSON_UNLIKELY(! cs))
2322
0
        {
2323
0
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
0
            goto finish_dub;
2335
0
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
0
do_num4:
2373
0
    {
2374
0
        if(BOOST_JSON_UNLIKELY(! cs))
2375
0
        {
2376
0
            if(BOOST_JSON_UNLIKELY(
2377
0
                ! h_.on_number_part(
2378
0
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
0
                num_buf_.append( begin, cs.used(begin) );
2383
0
            return maybe_suspend(
2384
0
                cs.begin(), state::num4, num);
2385
0
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
1.06k
do_num5:
2409
1.06k
    for(;;)
2410
4.32k
    {
2411
4.32k
        if(BOOST_JSON_UNLIKELY(! cs))
2412
24
        {
2413
24
            if(BOOST_JSON_UNLIKELY(more_))
2414
24
            {
2415
24
                if(BOOST_JSON_UNLIKELY(
2416
24
                    ! h_.on_number_part(
2417
24
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
24
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
24
                    num_buf_.append( begin, cs.used(begin) );
2422
24
                return suspend(cs.begin(), state::num5, num);
2423
24
            }
2424
0
            goto finish_dub;
2425
24
        }
2426
4.29k
        char const c = *cs;
2427
4.29k
        if(BOOST_JSON_LIKELY(
2428
4.29k
            c >= '0' && c <= '9'))
2429
3.25k
        {
2430
3.25k
            ++cs;
2431
3.25k
        }
2432
1.03k
        else if((c | 32) == 'e')
2433
236
        {
2434
236
            ++cs;
2435
236
            goto do_exp1;
2436
236
        }
2437
803
        else
2438
803
        {
2439
803
            goto finish_dub;
2440
803
        }
2441
4.29k
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
3.42k
do_num6:
2448
3.42k
    {
2449
3.42k
        if(BOOST_JSON_UNLIKELY(! cs))
2450
0
        {
2451
0
            if(BOOST_JSON_UNLIKELY(more_))
2452
0
            {
2453
0
                if(BOOST_JSON_UNLIKELY(
2454
0
                    ! h_.on_number_part(
2455
0
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
0
                    num_buf_.append( begin, cs.used(begin) );
2460
0
                return suspend(cs.begin(), state::num6, num);
2461
0
            }
2462
0
            goto finish_int;
2463
0
        }
2464
3.42k
        char const c = *cs;
2465
3.42k
        if(BOOST_JSON_LIKELY(
2466
3.42k
            c == '.'))
2467
488
        {
2468
488
            ++cs;
2469
488
        }
2470
2.93k
        else if((c | 32) == 'e')
2471
410
        {
2472
410
            ++cs;
2473
410
            goto do_exp1;
2474
410
        }
2475
2.52k
        else
2476
2.52k
        {
2477
2.52k
            goto finish_int;
2478
2.52k
        }
2479
3.42k
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
752
do_num7:
2488
752
    {
2489
752
        if(BOOST_JSON_UNLIKELY(! cs))
2490
5
        {
2491
5
            if(BOOST_JSON_UNLIKELY(more_))
2492
5
            {
2493
5
                if(BOOST_JSON_UNLIKELY(
2494
5
                    ! h_.on_number_part(
2495
5
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
5
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
5
                    num_buf_.append( begin, cs.used(begin) );
2500
5
                return suspend(cs.begin(), state::num7, num);
2501
5
            }
2502
            // digit required
2503
5
            BOOST_STATIC_CONSTEXPR source_location loc
2504
0
                = BOOST_CURRENT_LOCATION;
2505
0
            return fail(cs.begin(), error::syntax, &loc);
2506
5
        }
2507
747
        char const c = *cs;
2508
747
        if(BOOST_JSON_UNLIKELY(
2509
747
            c < '0' || c > '9'))
2510
19
        {
2511
            // digit required
2512
19
            BOOST_STATIC_CONSTEXPR source_location loc
2513
19
                = BOOST_CURRENT_LOCATION;
2514
19
            return fail(cs.begin(), error::syntax, &loc);
2515
19
        }
2516
747
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
1.06k
do_num8:
2525
1.06k
    for(;;)
2526
1.06k
    {
2527
1.06k
        if(BOOST_JSON_UNLIKELY(! cs))
2528
0
        {
2529
0
            if(BOOST_JSON_UNLIKELY(more_))
2530
0
            {
2531
0
                if(BOOST_JSON_UNLIKELY(
2532
0
                    ! h_.on_number_part(
2533
0
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
0
                    num_buf_.append( begin, cs.used(begin) );
2538
0
                return suspend(cs.begin(), state::num8, num);
2539
0
            }
2540
0
            goto finish_dub;
2541
0
        }
2542
1.06k
        char const c = *cs;
2543
1.06k
        if(BOOST_JSON_LIKELY(
2544
1.06k
            c >= '0' && c <= '9'))
2545
1.06k
        {
2546
1.06k
            ++cs;
2547
1.06k
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
1.06k
                num.mant <= 9007199254740991)) // 2^53-1
2549
0
            {
2550
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
0
                --num.bias;
2557
0
                num.mant = 10 * num.mant + ( c - '0' );
2558
0
            }
2559
1.06k
            else
2560
1.06k
            {
2561
1.06k
                goto do_num5;
2562
1.06k
            }
2563
1.06k
        }
2564
0
        else if((c | 32) == 'e')
2565
0
        {
2566
0
            ++cs;
2567
0
            goto do_exp1;
2568
0
        }
2569
0
        else
2570
0
        {
2571
0
            goto finish_dub;
2572
0
        }
2573
1.06k
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
20.8k
do_exp1:
2580
20.8k
    if(BOOST_JSON_UNLIKELY(! cs))
2581
13
    {
2582
13
        if(BOOST_JSON_UNLIKELY(
2583
13
            ! h_.on_number_part(
2584
13
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
13
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
13
            num_buf_.append( begin, cs.used(begin) );
2589
13
        return maybe_suspend(
2590
13
            cs.begin(), state::exp1, num);
2591
13
    }
2592
20.8k
    if(*cs == '+')
2593
194
    {
2594
194
        ++cs;
2595
194
    }
2596
20.6k
    else if(*cs == '-')
2597
1.14k
    {
2598
1.14k
        ++cs;
2599
1.14k
        num.frac = true;
2600
1.14k
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
20.8k
do_exp2:
2608
20.8k
    {
2609
20.8k
        if(BOOST_JSON_UNLIKELY(! cs))
2610
11
        {
2611
11
            if(BOOST_JSON_UNLIKELY(more_))
2612
11
            {
2613
11
                if(BOOST_JSON_UNLIKELY(
2614
11
                    ! h_.on_number_part(
2615
11
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
11
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
11
                    num_buf_.append( begin, cs.used(begin) );
2620
11
                return suspend(cs.begin(), state::exp2, num);
2621
11
            }
2622
            // digit required
2623
11
            BOOST_STATIC_CONSTEXPR source_location loc
2624
0
                = BOOST_CURRENT_LOCATION;
2625
0
            return fail(cs.begin(), error::syntax, &loc);
2626
11
        }
2627
20.8k
        char const c = *cs;
2628
20.8k
        if(BOOST_JSON_UNLIKELY(
2629
20.8k
            c < '0' || c > '9'))
2630
20
        {
2631
            // digit required
2632
20
            BOOST_STATIC_CONSTEXPR source_location loc
2633
20
                = BOOST_CURRENT_LOCATION;
2634
20
            return fail(cs.begin(), error::syntax, &loc);
2635
20
        }
2636
20.7k
        ++cs;
2637
20.7k
        num.exp = c - '0';
2638
20.7k
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
20.7k
do_exp3:
2646
20.7k
    for(;;)
2647
41.6k
    {
2648
41.6k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
27
        {
2650
27
            if(BOOST_JSON_UNLIKELY(more_))
2651
27
            {
2652
27
                if(BOOST_JSON_UNLIKELY(
2653
27
                    ! h_.on_number_part(
2654
27
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
27
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
27
                    num_buf_.append( begin, cs.used(begin) );
2659
27
                return suspend(cs.begin(), state::exp3, num);
2660
27
            }
2661
27
        }
2662
41.5k
        else
2663
41.5k
        {
2664
41.5k
            char const c = *cs;
2665
41.5k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
20.8k
            {
2667
20.8k
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
20.8k
                    num.exp  >  214748364 ||
2670
20.8k
                    (num.exp == 214748364 && c > '7')
2671
20.8k
                ))
2672
0
                    num.exp = INT_MAX;
2673
20.8k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
20.8k
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
20.8k
                ++cs;
2677
20.8k
                continue;
2678
20.8k
            }
2679
41.5k
        }
2680
20.7k
        BOOST_ASSERT(num.exp >= 0);
2681
20.7k
        if ( num.frac )
2682
1.13k
        {
2683
1.13k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
0
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
0
                if(BOOST_JSON_UNLIKELY(
2689
0
                    (num.exp == INT_MAX) &&
2690
0
                    (num.bias < 0) &&
2691
0
                    (num.exp + num.bias < 308) &&
2692
0
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
0
                num.bias = 0;
2700
0
                num.exp = INT_MAX;
2701
0
            }
2702
1.13k
        }
2703
19.6k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
0
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
0
            if(BOOST_JSON_UNLIKELY(
2709
0
                (num.exp == INT_MAX) &&
2710
0
                (num.bias > 0) &&
2711
0
                (num.exp - num.bias < 308) &&
2712
0
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
0
            num.bias = 0;
2720
0
            num.exp = INT_MAX;
2721
0
        }
2722
20.7k
        goto finish_dub;
2723
20.7k
    }
2724
2725
2.52k
finish_int:
2726
2.52k
    if(negative || (!stack_empty && num.neg))
2727
0
    {
2728
0
        if(BOOST_JSON_UNLIKELY(
2729
0
            ! h_.on_int64(static_cast<
2730
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
0
        return cs.begin();
2733
0
    }
2734
2.52k
    if(num.mant <= INT64_MAX)
2735
2.52k
    {
2736
72.5k
finish_signed:
2737
72.5k
        if(BOOST_JSON_UNLIKELY(
2738
72.5k
            ! h_.on_int64(static_cast<
2739
72.5k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
72.5k
        return cs.begin();
2742
72.5k
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
22.1k
finish_dub:
2748
22.1k
    double d;
2749
22.1k
    std::size_t const size = cs.used(begin);
2750
22.1k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
22.1k
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
22.1k
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
22.1k
    if(BOOST_JSON_UNLIKELY(
2778
22.1k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
22.1k
    return cs.begin();
2781
22.1k
}
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
2011
2.06k
{
2012
2.06k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
2.06k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
2.06k
    bool const negative = first == '-';
2020
2.06k
    bool const zero_first = first == '0';
2021
2.06k
    bool const nonzero_first = first == '+';
2022
2.06k
    detail::const_stream_wrapper cs(p, end_);
2023
2.06k
    number num;
2024
2.06k
    const char* begin = cs.begin();
2025
2.06k
    if(stack_empty || st_.empty())
2026
0
    {
2027
0
        num.bias = 0;
2028
0
        num.exp = 0;
2029
0
        num.frac = false;
2030
0
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
0
        BOOST_ASSERT(cs);
2038
0
        if(negative)
2039
0
            ++cs;
2040
2041
0
        num.neg = negative;
2042
0
        num.frac = false;
2043
0
        num.exp = 0;
2044
0
        num.bias = 0;
2045
2046
        // fast path
2047
0
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
0
        {
2049
0
            int n1;
2050
2051
0
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
0
            {
2054
0
                n1 = detail::count_digits( cs.begin() );
2055
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
0
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
0
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
0
                if( n1 == 16 )
2082
0
                {
2083
0
                    goto do_num2;
2084
0
                }
2085
0
            }
2086
0
            else
2087
0
            {
2088
                // 0. floating-point or 0e integer
2089
0
                num.mant = 0;
2090
0
                n1 = 0;
2091
0
                ++cs;
2092
0
            }
2093
2094
0
            {
2095
0
                const char c = *cs;
2096
0
                if(c != '.')
2097
0
                {
2098
0
                    if((c | 32) == 'e')
2099
0
                    {
2100
0
                        ++cs;
2101
0
                        goto do_exp1;
2102
0
                    }
2103
0
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
0
                        num.mant = ~num.mant + 1;
2105
0
                    goto finish_signed;
2106
0
                }
2107
0
            }
2108
2109
            // floating-point number
2110
2111
0
            ++cs;
2112
2113
0
            int n2 = detail::count_digits( cs.begin() );
2114
0
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
0
            if( n2 == 0 )
2117
0
            {
2118
                // digit required
2119
0
                BOOST_STATIC_CONSTEXPR source_location loc
2120
0
                    = BOOST_CURRENT_LOCATION;
2121
0
                return fail(cs.begin(), error::syntax, &loc);
2122
0
            }
2123
2124
            // floating-point mantissa overflow
2125
0
            if( n1 + n2 >= 19 )
2126
0
            {
2127
0
                goto do_num7;
2128
0
            }
2129
2130
0
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
0
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
0
            BOOST_ASSERT(num.bias == 0);
2134
2135
0
            num.bias -= n2;
2136
2137
0
            cs += n2;
2138
2139
0
            char ch = *cs;
2140
2141
0
            if( (ch | 32) == 'e' )
2142
0
            {
2143
0
                ++cs;
2144
0
                goto do_exp1;
2145
0
            }
2146
0
            else if( ch >= '0' && ch <= '9' )
2147
0
            {
2148
0
                goto do_num8;
2149
0
            }
2150
2151
0
            goto finish_dub;
2152
0
        }
2153
0
    }
2154
2.06k
    else
2155
2.06k
    {
2156
2.06k
        num = num_;
2157
2.06k
        state st;
2158
2.06k
        st_.pop(st);
2159
2.06k
        switch(st)
2160
2.06k
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
16
        case state::num1: goto do_num1;
2163
552
        case state::num2: goto do_num2;
2164
52
        case state::num3: goto do_num3;
2165
3
        case state::num4: goto do_num4;
2166
82
        case state::num5: goto do_num5;
2167
32
        case state::num6: goto do_num6;
2168
15
        case state::num7: goto do_num7;
2169
580
        case state::num8: goto do_num8;
2170
74
        case state::exp1: goto do_exp1;
2171
33
        case state::exp2: goto do_exp2;
2172
625
        case state::exp3: goto do_exp3;
2173
2.06k
        }
2174
2.06k
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
16
do_num1:
2182
16
    if(zero_first || nonzero_first ||
2183
16
        BOOST_JSON_LIKELY(cs))
2184
0
    {
2185
0
        char const c = *cs;
2186
0
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
0
            c >= '1' && c <= '9'))
2194
0
        {
2195
0
            ++cs;
2196
0
            num.mant = c - '0';
2197
0
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
0
    }
2220
16
    else
2221
16
    {
2222
16
        if(BOOST_JSON_UNLIKELY(
2223
16
            ! h_.on_number_part(
2224
16
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
16
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
16
            num_buf_.append( begin, cs.used(begin) );
2229
16
        return maybe_suspend(
2230
16
            cs.begin(), state::num1, num);
2231
16
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
552
do_num2:
2239
552
    if(negative || (!stack_empty && num.neg))
2240
192
    {
2241
192
        for(;;)
2242
192
        {
2243
192
            if(BOOST_JSON_UNLIKELY(! cs))
2244
192
            {
2245
192
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
192
                goto finish_int;
2257
192
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
192
    }
2274
360
    else
2275
360
    {
2276
360
        for(;;)
2277
360
        {
2278
360
            if(BOOST_JSON_UNLIKELY(! cs))
2279
360
            {
2280
360
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
360
                goto finish_int;
2292
360
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
360
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
52
do_num3:
2319
52
    for(;;)
2320
52
    {
2321
52
        if(BOOST_JSON_UNLIKELY(! cs))
2322
52
        {
2323
52
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
52
            goto finish_dub;
2335
52
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
3
do_num4:
2373
3
    {
2374
3
        if(BOOST_JSON_UNLIKELY(! cs))
2375
3
        {
2376
3
            if(BOOST_JSON_UNLIKELY(
2377
3
                ! h_.on_number_part(
2378
3
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
3
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
3
                num_buf_.append( begin, cs.used(begin) );
2383
3
            return maybe_suspend(
2384
3
                cs.begin(), state::num4, num);
2385
3
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
82
do_num5:
2409
82
    for(;;)
2410
82
    {
2411
82
        if(BOOST_JSON_UNLIKELY(! cs))
2412
82
        {
2413
82
            if(BOOST_JSON_UNLIKELY(more_))
2414
0
            {
2415
0
                if(BOOST_JSON_UNLIKELY(
2416
0
                    ! h_.on_number_part(
2417
0
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
0
                    num_buf_.append( begin, cs.used(begin) );
2422
0
                return suspend(cs.begin(), state::num5, num);
2423
0
            }
2424
82
            goto finish_dub;
2425
82
        }
2426
0
        char const c = *cs;
2427
0
        if(BOOST_JSON_LIKELY(
2428
0
            c >= '0' && c <= '9'))
2429
0
        {
2430
0
            ++cs;
2431
0
        }
2432
0
        else if((c | 32) == 'e')
2433
0
        {
2434
0
            ++cs;
2435
0
            goto do_exp1;
2436
0
        }
2437
0
        else
2438
0
        {
2439
0
            goto finish_dub;
2440
0
        }
2441
0
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
32
do_num6:
2448
32
    {
2449
32
        if(BOOST_JSON_UNLIKELY(! cs))
2450
32
        {
2451
32
            if(BOOST_JSON_UNLIKELY(more_))
2452
0
            {
2453
0
                if(BOOST_JSON_UNLIKELY(
2454
0
                    ! h_.on_number_part(
2455
0
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
0
                    num_buf_.append( begin, cs.used(begin) );
2460
0
                return suspend(cs.begin(), state::num6, num);
2461
0
            }
2462
32
            goto finish_int;
2463
32
        }
2464
0
        char const c = *cs;
2465
0
        if(BOOST_JSON_LIKELY(
2466
0
            c == '.'))
2467
0
        {
2468
0
            ++cs;
2469
0
        }
2470
0
        else if((c | 32) == 'e')
2471
0
        {
2472
0
            ++cs;
2473
0
            goto do_exp1;
2474
0
        }
2475
0
        else
2476
0
        {
2477
0
            goto finish_int;
2478
0
        }
2479
0
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
15
do_num7:
2488
15
    {
2489
15
        if(BOOST_JSON_UNLIKELY(! cs))
2490
15
        {
2491
15
            if(BOOST_JSON_UNLIKELY(more_))
2492
0
            {
2493
0
                if(BOOST_JSON_UNLIKELY(
2494
0
                    ! h_.on_number_part(
2495
0
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
0
                    num_buf_.append( begin, cs.used(begin) );
2500
0
                return suspend(cs.begin(), state::num7, num);
2501
0
            }
2502
            // digit required
2503
15
            BOOST_STATIC_CONSTEXPR source_location loc
2504
15
                = BOOST_CURRENT_LOCATION;
2505
15
            return fail(cs.begin(), error::syntax, &loc);
2506
15
        }
2507
0
        char const c = *cs;
2508
0
        if(BOOST_JSON_UNLIKELY(
2509
0
            c < '0' || c > '9'))
2510
0
        {
2511
            // digit required
2512
0
            BOOST_STATIC_CONSTEXPR source_location loc
2513
0
                = BOOST_CURRENT_LOCATION;
2514
0
            return fail(cs.begin(), error::syntax, &loc);
2515
0
        }
2516
0
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
580
do_num8:
2525
580
    for(;;)
2526
580
    {
2527
580
        if(BOOST_JSON_UNLIKELY(! cs))
2528
580
        {
2529
580
            if(BOOST_JSON_UNLIKELY(more_))
2530
0
            {
2531
0
                if(BOOST_JSON_UNLIKELY(
2532
0
                    ! h_.on_number_part(
2533
0
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
0
                    num_buf_.append( begin, cs.used(begin) );
2538
0
                return suspend(cs.begin(), state::num8, num);
2539
0
            }
2540
580
            goto finish_dub;
2541
580
        }
2542
0
        char const c = *cs;
2543
0
        if(BOOST_JSON_LIKELY(
2544
0
            c >= '0' && c <= '9'))
2545
0
        {
2546
0
            ++cs;
2547
0
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
0
                num.mant <= 9007199254740991)) // 2^53-1
2549
0
            {
2550
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
0
                --num.bias;
2557
0
                num.mant = 10 * num.mant + ( c - '0' );
2558
0
            }
2559
0
            else
2560
0
            {
2561
0
                goto do_num5;
2562
0
            }
2563
0
        }
2564
0
        else if((c | 32) == 'e')
2565
0
        {
2566
0
            ++cs;
2567
0
            goto do_exp1;
2568
0
        }
2569
0
        else
2570
0
        {
2571
0
            goto finish_dub;
2572
0
        }
2573
0
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
74
do_exp1:
2580
74
    if(BOOST_JSON_UNLIKELY(! cs))
2581
74
    {
2582
74
        if(BOOST_JSON_UNLIKELY(
2583
74
            ! h_.on_number_part(
2584
74
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
74
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
74
            num_buf_.append( begin, cs.used(begin) );
2589
74
        return maybe_suspend(
2590
74
            cs.begin(), state::exp1, num);
2591
74
    }
2592
0
    if(*cs == '+')
2593
0
    {
2594
0
        ++cs;
2595
0
    }
2596
0
    else if(*cs == '-')
2597
0
    {
2598
0
        ++cs;
2599
0
        num.frac = true;
2600
0
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
33
do_exp2:
2608
33
    {
2609
33
        if(BOOST_JSON_UNLIKELY(! cs))
2610
33
        {
2611
33
            if(BOOST_JSON_UNLIKELY(more_))
2612
0
            {
2613
0
                if(BOOST_JSON_UNLIKELY(
2614
0
                    ! h_.on_number_part(
2615
0
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
0
                    num_buf_.append( begin, cs.used(begin) );
2620
0
                return suspend(cs.begin(), state::exp2, num);
2621
0
            }
2622
            // digit required
2623
33
            BOOST_STATIC_CONSTEXPR source_location loc
2624
33
                = BOOST_CURRENT_LOCATION;
2625
33
            return fail(cs.begin(), error::syntax, &loc);
2626
33
        }
2627
0
        char const c = *cs;
2628
0
        if(BOOST_JSON_UNLIKELY(
2629
0
            c < '0' || c > '9'))
2630
0
        {
2631
            // digit required
2632
0
            BOOST_STATIC_CONSTEXPR source_location loc
2633
0
                = BOOST_CURRENT_LOCATION;
2634
0
            return fail(cs.begin(), error::syntax, &loc);
2635
0
        }
2636
0
        ++cs;
2637
0
        num.exp = c - '0';
2638
0
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
625
do_exp3:
2646
625
    for(;;)
2647
625
    {
2648
625
        if(BOOST_JSON_UNLIKELY(! cs))
2649
625
        {
2650
625
            if(BOOST_JSON_UNLIKELY(more_))
2651
0
            {
2652
0
                if(BOOST_JSON_UNLIKELY(
2653
0
                    ! h_.on_number_part(
2654
0
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
0
                    num_buf_.append( begin, cs.used(begin) );
2659
0
                return suspend(cs.begin(), state::exp3, num);
2660
0
            }
2661
625
        }
2662
0
        else
2663
0
        {
2664
0
            char const c = *cs;
2665
0
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
0
            {
2667
0
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
0
                    num.exp  >  214748364 ||
2670
0
                    (num.exp == 214748364 && c > '7')
2671
0
                ))
2672
0
                    num.exp = INT_MAX;
2673
0
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
0
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
0
                ++cs;
2677
0
                continue;
2678
0
            }
2679
0
        }
2680
625
        BOOST_ASSERT(num.exp >= 0);
2681
625
        if ( num.frac )
2682
174
        {
2683
174
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
22
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
22
                if(BOOST_JSON_UNLIKELY(
2689
22
                    (num.exp == INT_MAX) &&
2690
22
                    (num.bias < 0) &&
2691
22
                    (num.exp + num.bias < 308) &&
2692
22
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
22
                num.bias = 0;
2700
22
                num.exp = INT_MAX;
2701
22
            }
2702
174
        }
2703
451
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
36
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
36
            if(BOOST_JSON_UNLIKELY(
2709
36
                (num.exp == INT_MAX) &&
2710
36
                (num.bias > 0) &&
2711
36
                (num.exp - num.bias < 308) &&
2712
36
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
36
            num.bias = 0;
2720
36
            num.exp = INT_MAX;
2721
36
        }
2722
625
        goto finish_dub;
2723
625
    }
2724
2725
584
finish_int:
2726
584
    if(negative || (!stack_empty && num.neg))
2727
198
    {
2728
198
        if(BOOST_JSON_UNLIKELY(
2729
198
            ! h_.on_int64(static_cast<
2730
198
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
198
        return cs.begin();
2733
198
    }
2734
386
    if(num.mant <= INT64_MAX)
2735
283
    {
2736
283
finish_signed:
2737
283
        if(BOOST_JSON_UNLIKELY(
2738
283
            ! h_.on_int64(static_cast<
2739
283
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
283
        return cs.begin();
2742
283
    }
2743
103
    if(BOOST_JSON_UNLIKELY(
2744
103
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
103
    return cs.begin();
2747
1.33k
finish_dub:
2748
1.33k
    double d;
2749
1.33k
    std::size_t const size = cs.used(begin);
2750
1.33k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
1.33k
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
1.33k
        d = 0;
2771
1.33k
    else
2772
1.33k
        d = detail::dec_to_float(
2773
1.33k
            num.mant,
2774
1.33k
            num.bias + (num.frac ?
2775
1.16k
                -num.exp : num.exp),
2776
1.33k
            num.neg);
2777
1.33k
    if(BOOST_JSON_UNLIKELY(
2778
1.33k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
1.33k
    return cs.begin();
2781
1.33k
}
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>)
Line
Count
Source
2011
4.25k
{
2012
4.25k
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
4.25k
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
4.25k
    bool const negative = first == '-';
2020
4.25k
    bool const zero_first = first == '0';
2021
4.25k
    bool const nonzero_first = first == '+';
2022
4.25k
    detail::const_stream_wrapper cs(p, end_);
2023
4.25k
    number num;
2024
4.25k
    const char* begin = cs.begin();
2025
4.25k
    if(stack_empty || st_.empty())
2026
0
    {
2027
0
        num.bias = 0;
2028
0
        num.exp = 0;
2029
0
        num.frac = false;
2030
0
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
0
        BOOST_ASSERT(cs);
2038
0
        if(negative)
2039
0
            ++cs;
2040
2041
0
        num.neg = negative;
2042
0
        num.frac = false;
2043
0
        num.exp = 0;
2044
0
        num.bias = 0;
2045
2046
        // fast path
2047
0
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
0
        {
2049
0
            int n1;
2050
2051
0
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
0
            {
2054
0
                n1 = detail::count_digits( cs.begin() );
2055
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
0
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
                else
2075
                    num.mant = 0;
2076
2077
0
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
0
                if( n1 == 16 )
2082
0
                {
2083
0
                    goto do_num2;
2084
0
                }
2085
0
            }
2086
0
            else
2087
0
            {
2088
                // 0. floating-point or 0e integer
2089
0
                num.mant = 0;
2090
0
                n1 = 0;
2091
0
                ++cs;
2092
0
            }
2093
2094
0
            {
2095
0
                const char c = *cs;
2096
0
                if(c != '.')
2097
0
                {
2098
0
                    if((c | 32) == 'e')
2099
0
                    {
2100
0
                        ++cs;
2101
0
                        goto do_exp1;
2102
0
                    }
2103
0
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
0
                        num.mant = ~num.mant + 1;
2105
0
                    goto finish_signed;
2106
0
                }
2107
0
            }
2108
2109
            // floating-point number
2110
2111
0
            ++cs;
2112
2113
0
            int n2 = detail::count_digits( cs.begin() );
2114
0
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
0
            if( n2 == 0 )
2117
0
            {
2118
                // digit required
2119
0
                BOOST_STATIC_CONSTEXPR source_location loc
2120
0
                    = BOOST_CURRENT_LOCATION;
2121
0
                return fail(cs.begin(), error::syntax, &loc);
2122
0
            }
2123
2124
            // floating-point mantissa overflow
2125
0
            if( n1 + n2 >= 19 )
2126
0
            {
2127
0
                goto do_num7;
2128
0
            }
2129
2130
0
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
0
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
0
            BOOST_ASSERT(num.bias == 0);
2134
2135
0
            num.bias -= n2;
2136
2137
0
            cs += n2;
2138
2139
0
            char ch = *cs;
2140
2141
0
            if( (ch | 32) == 'e' )
2142
0
            {
2143
0
                ++cs;
2144
0
                goto do_exp1;
2145
0
            }
2146
0
            else if( ch >= '0' && ch <= '9' )
2147
0
            {
2148
0
                goto do_num8;
2149
0
            }
2150
2151
0
            goto finish_dub;
2152
0
        }
2153
0
    }
2154
4.25k
    else
2155
4.25k
    {
2156
4.25k
        num = num_;
2157
4.25k
        state st;
2158
4.25k
        st_.pop(st);
2159
4.25k
        switch(st)
2160
4.25k
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
19
        case state::num1: goto do_num1;
2163
525
        case state::num2: goto do_num2;
2164
525
        case state::num3: goto do_num3;
2165
3
        case state::num4: goto do_num4;
2166
892
        case state::num5: goto do_num5;
2167
35
        case state::num6: goto do_num6;
2168
18
        case state::num7: goto do_num7;
2169
654
        case state::num8: goto do_num8;
2170
66
        case state::exp1: goto do_exp1;
2171
29
        case state::exp2: goto do_exp2;
2172
1.48k
        case state::exp3: goto do_exp3;
2173
4.25k
        }
2174
4.25k
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
19
do_num1:
2182
19
    if(zero_first || nonzero_first ||
2183
19
        BOOST_JSON_LIKELY(cs))
2184
0
    {
2185
0
        char const c = *cs;
2186
0
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
0
            c >= '1' && c <= '9'))
2194
0
        {
2195
0
            ++cs;
2196
0
            num.mant = c - '0';
2197
0
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
0
    }
2220
19
    else
2221
19
    {
2222
19
        if(BOOST_JSON_UNLIKELY(
2223
19
            ! h_.on_number_part(
2224
19
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
19
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
19
            num_buf_.append( begin, cs.used(begin) );
2229
19
        return maybe_suspend(
2230
19
            cs.begin(), state::num1, num);
2231
19
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
525
do_num2:
2239
525
    if(negative || (!stack_empty && num.neg))
2240
195
    {
2241
195
        for(;;)
2242
195
        {
2243
195
            if(BOOST_JSON_UNLIKELY(! cs))
2244
195
            {
2245
195
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
195
                goto finish_int;
2257
195
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
195
    }
2274
330
    else
2275
330
    {
2276
330
        for(;;)
2277
330
        {
2278
330
            if(BOOST_JSON_UNLIKELY(! cs))
2279
330
            {
2280
330
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
330
                goto finish_int;
2292
330
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
330
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
525
do_num3:
2319
525
    for(;;)
2320
525
    {
2321
525
        if(BOOST_JSON_UNLIKELY(! cs))
2322
525
        {
2323
525
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
525
            goto finish_dub;
2335
525
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
3
do_num4:
2373
3
    {
2374
3
        if(BOOST_JSON_UNLIKELY(! cs))
2375
3
        {
2376
3
            if(BOOST_JSON_UNLIKELY(
2377
3
                ! h_.on_number_part(
2378
3
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
3
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
3
                num_buf_.append( begin, cs.used(begin) );
2383
3
            return maybe_suspend(
2384
3
                cs.begin(), state::num4, num);
2385
3
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
892
do_num5:
2409
892
    for(;;)
2410
892
    {
2411
892
        if(BOOST_JSON_UNLIKELY(! cs))
2412
892
        {
2413
892
            if(BOOST_JSON_UNLIKELY(more_))
2414
0
            {
2415
0
                if(BOOST_JSON_UNLIKELY(
2416
0
                    ! h_.on_number_part(
2417
0
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
0
                    num_buf_.append( begin, cs.used(begin) );
2422
0
                return suspend(cs.begin(), state::num5, num);
2423
0
            }
2424
892
            goto finish_dub;
2425
892
        }
2426
0
        char const c = *cs;
2427
0
        if(BOOST_JSON_LIKELY(
2428
0
            c >= '0' && c <= '9'))
2429
0
        {
2430
0
            ++cs;
2431
0
        }
2432
0
        else if((c | 32) == 'e')
2433
0
        {
2434
0
            ++cs;
2435
0
            goto do_exp1;
2436
0
        }
2437
0
        else
2438
0
        {
2439
0
            goto finish_dub;
2440
0
        }
2441
0
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
35
do_num6:
2448
35
    {
2449
35
        if(BOOST_JSON_UNLIKELY(! cs))
2450
35
        {
2451
35
            if(BOOST_JSON_UNLIKELY(more_))
2452
0
            {
2453
0
                if(BOOST_JSON_UNLIKELY(
2454
0
                    ! h_.on_number_part(
2455
0
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
0
                    num_buf_.append( begin, cs.used(begin) );
2460
0
                return suspend(cs.begin(), state::num6, num);
2461
0
            }
2462
35
            goto finish_int;
2463
35
        }
2464
0
        char const c = *cs;
2465
0
        if(BOOST_JSON_LIKELY(
2466
0
            c == '.'))
2467
0
        {
2468
0
            ++cs;
2469
0
        }
2470
0
        else if((c | 32) == 'e')
2471
0
        {
2472
0
            ++cs;
2473
0
            goto do_exp1;
2474
0
        }
2475
0
        else
2476
0
        {
2477
0
            goto finish_int;
2478
0
        }
2479
0
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
18
do_num7:
2488
18
    {
2489
18
        if(BOOST_JSON_UNLIKELY(! cs))
2490
18
        {
2491
18
            if(BOOST_JSON_UNLIKELY(more_))
2492
0
            {
2493
0
                if(BOOST_JSON_UNLIKELY(
2494
0
                    ! h_.on_number_part(
2495
0
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
0
                    num_buf_.append( begin, cs.used(begin) );
2500
0
                return suspend(cs.begin(), state::num7, num);
2501
0
            }
2502
            // digit required
2503
18
            BOOST_STATIC_CONSTEXPR source_location loc
2504
18
                = BOOST_CURRENT_LOCATION;
2505
18
            return fail(cs.begin(), error::syntax, &loc);
2506
18
        }
2507
0
        char const c = *cs;
2508
0
        if(BOOST_JSON_UNLIKELY(
2509
0
            c < '0' || c > '9'))
2510
0
        {
2511
            // digit required
2512
0
            BOOST_STATIC_CONSTEXPR source_location loc
2513
0
                = BOOST_CURRENT_LOCATION;
2514
0
            return fail(cs.begin(), error::syntax, &loc);
2515
0
        }
2516
0
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
654
do_num8:
2525
654
    for(;;)
2526
654
    {
2527
654
        if(BOOST_JSON_UNLIKELY(! cs))
2528
654
        {
2529
654
            if(BOOST_JSON_UNLIKELY(more_))
2530
0
            {
2531
0
                if(BOOST_JSON_UNLIKELY(
2532
0
                    ! h_.on_number_part(
2533
0
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
0
                    num_buf_.append( begin, cs.used(begin) );
2538
0
                return suspend(cs.begin(), state::num8, num);
2539
0
            }
2540
654
            goto finish_dub;
2541
654
        }
2542
0
        char const c = *cs;
2543
0
        if(BOOST_JSON_LIKELY(
2544
0
            c >= '0' && c <= '9'))
2545
0
        {
2546
0
            ++cs;
2547
0
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
0
                num.mant <= 9007199254740991)) // 2^53-1
2549
0
            {
2550
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
0
                --num.bias;
2557
0
                num.mant = 10 * num.mant + ( c - '0' );
2558
0
            }
2559
0
            else
2560
0
            {
2561
0
                goto do_num5;
2562
0
            }
2563
0
        }
2564
0
        else if((c | 32) == 'e')
2565
0
        {
2566
0
            ++cs;
2567
0
            goto do_exp1;
2568
0
        }
2569
0
        else
2570
0
        {
2571
0
            goto finish_dub;
2572
0
        }
2573
0
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
66
do_exp1:
2580
66
    if(BOOST_JSON_UNLIKELY(! cs))
2581
66
    {
2582
66
        if(BOOST_JSON_UNLIKELY(
2583
66
            ! h_.on_number_part(
2584
66
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
66
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
66
            num_buf_.append( begin, cs.used(begin) );
2589
66
        return maybe_suspend(
2590
66
            cs.begin(), state::exp1, num);
2591
66
    }
2592
0
    if(*cs == '+')
2593
0
    {
2594
0
        ++cs;
2595
0
    }
2596
0
    else if(*cs == '-')
2597
0
    {
2598
0
        ++cs;
2599
0
        num.frac = true;
2600
0
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
29
do_exp2:
2608
29
    {
2609
29
        if(BOOST_JSON_UNLIKELY(! cs))
2610
29
        {
2611
29
            if(BOOST_JSON_UNLIKELY(more_))
2612
0
            {
2613
0
                if(BOOST_JSON_UNLIKELY(
2614
0
                    ! h_.on_number_part(
2615
0
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
0
                    num_buf_.append( begin, cs.used(begin) );
2620
0
                return suspend(cs.begin(), state::exp2, num);
2621
0
            }
2622
            // digit required
2623
29
            BOOST_STATIC_CONSTEXPR source_location loc
2624
29
                = BOOST_CURRENT_LOCATION;
2625
29
            return fail(cs.begin(), error::syntax, &loc);
2626
29
        }
2627
0
        char const c = *cs;
2628
0
        if(BOOST_JSON_UNLIKELY(
2629
0
            c < '0' || c > '9'))
2630
0
        {
2631
            // digit required
2632
0
            BOOST_STATIC_CONSTEXPR source_location loc
2633
0
                = BOOST_CURRENT_LOCATION;
2634
0
            return fail(cs.begin(), error::syntax, &loc);
2635
0
        }
2636
0
        ++cs;
2637
0
        num.exp = c - '0';
2638
0
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
1.48k
do_exp3:
2646
1.48k
    for(;;)
2647
1.48k
    {
2648
1.48k
        if(BOOST_JSON_UNLIKELY(! cs))
2649
1.48k
        {
2650
1.48k
            if(BOOST_JSON_UNLIKELY(more_))
2651
0
            {
2652
0
                if(BOOST_JSON_UNLIKELY(
2653
0
                    ! h_.on_number_part(
2654
0
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
0
                    num_buf_.append( begin, cs.used(begin) );
2659
0
                return suspend(cs.begin(), state::exp3, num);
2660
0
            }
2661
1.48k
        }
2662
0
        else
2663
0
        {
2664
0
            char const c = *cs;
2665
0
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
0
            {
2667
0
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
0
                    num.exp  >  214748364 ||
2670
0
                    (num.exp == 214748364 && c > '7')
2671
0
                ))
2672
0
                    num.exp = INT_MAX;
2673
0
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
0
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
0
                ++cs;
2677
0
                continue;
2678
0
            }
2679
0
        }
2680
1.48k
        BOOST_ASSERT(num.exp >= 0);
2681
1.48k
        if ( num.frac )
2682
563
        {
2683
563
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
34
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
34
                if(BOOST_JSON_UNLIKELY(
2689
34
                    (num.exp == INT_MAX) &&
2690
34
                    (num.bias < 0) &&
2691
34
                    (num.exp + num.bias < 308) &&
2692
34
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
34
                num.bias = 0;
2700
34
                num.exp = INT_MAX;
2701
34
            }
2702
563
        }
2703
922
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
50
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
50
            if(BOOST_JSON_UNLIKELY(
2709
50
                (num.exp == INT_MAX) &&
2710
50
                (num.bias > 0) &&
2711
50
                (num.exp - num.bias < 308) &&
2712
50
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
50
            num.bias = 0;
2720
50
            num.exp = INT_MAX;
2721
50
        }
2722
1.48k
        goto finish_dub;
2723
1.48k
    }
2724
2725
560
finish_int:
2726
560
    if(negative || (!stack_empty && num.neg))
2727
201
    {
2728
201
        if(BOOST_JSON_UNLIKELY(
2729
201
            ! h_.on_int64(static_cast<
2730
201
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
201
        return cs.begin();
2733
201
    }
2734
359
    if(num.mant <= INT64_MAX)
2735
246
    {
2736
246
finish_signed:
2737
246
        if(BOOST_JSON_UNLIKELY(
2738
246
            ! h_.on_int64(static_cast<
2739
246
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
246
        return cs.begin();
2742
246
    }
2743
113
    if(BOOST_JSON_UNLIKELY(
2744
113
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
113
    return cs.begin();
2747
3.55k
finish_dub:
2748
3.55k
    double d;
2749
3.55k
    std::size_t const size = cs.used(begin);
2750
3.55k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
3.55k
    {
2753
3.55k
        char const* data = begin;
2754
3.55k
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
3.55k
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
3.55k
        {
2760
3.55k
            data = num_buf_.append( begin, size );
2761
3.55k
            full_size = num_buf_.size();
2762
3.55k
        }
2763
3.55k
        auto const err = detail::charconv::from_chars(
2764
3.55k
            data, data + full_size, d );
2765
3.55k
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
3.55k
        BOOST_ASSERT( err.ptr == data + full_size );
2767
3.55k
        (void)err;
2768
    }
2769
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
3.55k
    if(BOOST_JSON_UNLIKELY(
2778
3.55k
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
3.55k
    return cs.begin();
2781
3.55k
}
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>)
Line
Count
Source
2011
363
{
2012
363
    constexpr bool precise_parsing = mode == number_precision::precise;
2013
363
    constexpr bool no_parsing = mode == number_precision::none;
2014
2015
    // only one of these will be true if we are not resuming
2016
    // if negative then !zero_first && !nonzero_first
2017
    // if zero_first then !nonzero_first && !negative
2018
    // if nonzero_first then !zero_first && !negative
2019
363
    bool const negative = first == '-';
2020
363
    bool const zero_first = first == '0';
2021
363
    bool const nonzero_first = first == '+';
2022
363
    detail::const_stream_wrapper cs(p, end_);
2023
363
    number num;
2024
363
    const char* begin = cs.begin();
2025
363
    if(stack_empty || st_.empty())
2026
0
    {
2027
0
        num.bias = 0;
2028
0
        num.exp = 0;
2029
0
        num.frac = false;
2030
0
        num_buf_.clear();
2031
2032
        //----------------------------------
2033
        //
2034
        // '-'
2035
        // leading minus sign
2036
        //
2037
0
        BOOST_ASSERT(cs);
2038
0
        if(negative)
2039
0
            ++cs;
2040
2041
0
        num.neg = negative;
2042
0
        num.frac = false;
2043
0
        num.exp = 0;
2044
0
        num.bias = 0;
2045
2046
        // fast path
2047
0
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2048
0
        {
2049
0
            int n1;
2050
2051
0
            if( nonzero_first ||
2052
0
                (negative && *cs != '0') )
2053
0
            {
2054
0
                n1 = detail::count_digits( cs.begin() );
2055
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2056
2057
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2058
0
                {
2059
0
                    return parse_literal(
2060
0
                        p - 1,
2061
0
                        detail::literals_c<detail::literals::neg_infinity>());
2062
0
                }
2063
2064
0
                if( ! nonzero_first && n1 == 0 )
2065
0
                {
2066
                    // digit required
2067
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2068
0
                        = BOOST_CURRENT_LOCATION;
2069
0
                    return fail(cs.begin(), error::syntax, &loc);
2070
0
                }
2071
2072
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2073
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2074
0
                else
2075
0
                    num.mant = 0;
2076
2077
0
                cs += n1;
2078
2079
                // integer or floating-point with
2080
                // >= 16 leading digits
2081
0
                if( n1 == 16 )
2082
0
                {
2083
0
                    goto do_num2;
2084
0
                }
2085
0
            }
2086
0
            else
2087
0
            {
2088
                // 0. floating-point or 0e integer
2089
0
                num.mant = 0;
2090
0
                n1 = 0;
2091
0
                ++cs;
2092
0
            }
2093
2094
0
            {
2095
0
                const char c = *cs;
2096
0
                if(c != '.')
2097
0
                {
2098
0
                    if((c | 32) == 'e')
2099
0
                    {
2100
0
                        ++cs;
2101
0
                        goto do_exp1;
2102
0
                    }
2103
0
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2104
0
                        num.mant = ~num.mant + 1;
2105
0
                    goto finish_signed;
2106
0
                }
2107
0
            }
2108
2109
            // floating-point number
2110
2111
0
            ++cs;
2112
2113
0
            int n2 = detail::count_digits( cs.begin() );
2114
0
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2115
2116
0
            if( n2 == 0 )
2117
0
            {
2118
                // digit required
2119
0
                BOOST_STATIC_CONSTEXPR source_location loc
2120
0
                    = BOOST_CURRENT_LOCATION;
2121
0
                return fail(cs.begin(), error::syntax, &loc);
2122
0
            }
2123
2124
            // floating-point mantissa overflow
2125
0
            if( n1 + n2 >= 19 )
2126
0
            {
2127
0
                goto do_num7;
2128
0
            }
2129
2130
0
            BOOST_IF_CONSTEXPR( !no_parsing )
2131
0
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2132
2133
0
            BOOST_ASSERT(num.bias == 0);
2134
2135
0
            num.bias -= n2;
2136
2137
0
            cs += n2;
2138
2139
0
            char ch = *cs;
2140
2141
0
            if( (ch | 32) == 'e' )
2142
0
            {
2143
0
                ++cs;
2144
0
                goto do_exp1;
2145
0
            }
2146
0
            else if( ch >= '0' && ch <= '9' )
2147
0
            {
2148
0
                goto do_num8;
2149
0
            }
2150
2151
0
            goto finish_dub;
2152
0
        }
2153
0
    }
2154
363
    else
2155
363
    {
2156
363
        num = num_;
2157
363
        state st;
2158
363
        st_.pop(st);
2159
363
        switch(st)
2160
363
        {
2161
0
        default: BOOST_JSON_UNREACHABLE();
2162
17
        case state::num1: goto do_num1;
2163
93
        case state::num2: goto do_num2;
2164
0
        case state::num3: goto do_num3;
2165
0
        case state::num4: goto do_num4;
2166
68
        case state::num5: goto do_num5;
2167
23
        case state::num6: goto do_num6;
2168
14
        case state::num7: goto do_num7;
2169
0
        case state::num8: goto do_num8;
2170
45
        case state::exp1: goto do_exp1;
2171
33
        case state::exp2: goto do_exp2;
2172
70
        case state::exp3: goto do_exp3;
2173
363
        }
2174
363
    }
2175
2176
    //----------------------------------
2177
    //
2178
    // DIGIT
2179
    // first digit
2180
    //
2181
17
do_num1:
2182
17
    if(zero_first || nonzero_first ||
2183
17
        BOOST_JSON_LIKELY(cs))
2184
0
    {
2185
0
        char const c = *cs;
2186
0
        if(zero_first)
2187
0
        {
2188
0
            ++cs;
2189
0
            num.mant = 0;
2190
0
            goto do_num6;
2191
0
        }
2192
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2193
0
            c >= '1' && c <= '9'))
2194
0
        {
2195
0
            ++cs;
2196
0
            num.mant = c - '0';
2197
0
        }
2198
0
        else if(BOOST_JSON_UNLIKELY(
2199
0
            c == '0'))
2200
0
        {
2201
0
            ++cs;
2202
0
            num.mant = 0;
2203
0
            goto do_num6;
2204
0
        }
2205
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2206
0
        {
2207
0
            st_.push(state::lit1);
2208
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2209
0
            lit_offset_ = 1;
2210
0
            return parse_literal(
2211
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2212
0
        }
2213
0
        else
2214
0
        {
2215
0
            BOOST_STATIC_CONSTEXPR source_location loc
2216
0
                = BOOST_CURRENT_LOCATION;
2217
0
            return fail(cs.begin(), error::syntax, &loc);
2218
0
        }
2219
0
    }
2220
17
    else
2221
17
    {
2222
17
        if(BOOST_JSON_UNLIKELY(
2223
17
            ! h_.on_number_part(
2224
17
                {begin, cs.used(begin)}, ec_)))
2225
0
            return fail(cs.begin());
2226
2227
17
        BOOST_IF_CONSTEXPR( precise_parsing )
2228
17
            num_buf_.append( begin, cs.used(begin) );
2229
17
        return maybe_suspend(
2230
17
            cs.begin(), state::num1, num);
2231
17
    }
2232
2233
    //----------------------------------
2234
    //
2235
    // 1*DIGIT
2236
    // significant digits left of decimal
2237
    //
2238
93
do_num2:
2239
93
    if(negative || (!stack_empty && num.neg))
2240
23
    {
2241
23
        for(;;)
2242
23
        {
2243
23
            if(BOOST_JSON_UNLIKELY(! cs))
2244
23
            {
2245
23
                if(BOOST_JSON_UNLIKELY(more_))
2246
0
                {
2247
0
                    if(BOOST_JSON_UNLIKELY(
2248
0
                        ! h_.on_number_part(
2249
0
                            {begin, cs.used(begin)}, ec_)))
2250
0
                        return fail(cs.begin());
2251
2252
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2253
0
                        num_buf_.append( begin, cs.used(begin) );
2254
0
                    return suspend(cs.begin(), state::num2, num);
2255
0
                }
2256
23
                goto finish_int;
2257
23
            }
2258
0
            char const c = *cs;
2259
0
            if(BOOST_JSON_LIKELY(
2260
0
                c >= '0' && c <= '9'))
2261
0
            {
2262
0
                ++cs;
2263
                //              9223372036854775808 INT64_MIN
2264
0
                if( num.mant  > 922337203685477580 || (
2265
0
                    num.mant == 922337203685477580 && c > '8'))
2266
0
                    break;
2267
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2268
0
                    num.mant = 10 * num.mant + ( c - '0' );
2269
0
                continue;
2270
0
            }
2271
0
            goto do_num6; // [.eE]
2272
0
        }
2273
23
    }
2274
70
    else
2275
70
    {
2276
70
        for(;;)
2277
70
        {
2278
70
            if(BOOST_JSON_UNLIKELY(! cs))
2279
70
            {
2280
70
                if(BOOST_JSON_UNLIKELY(more_))
2281
0
                {
2282
0
                    if(BOOST_JSON_UNLIKELY(
2283
0
                        ! h_.on_number_part(
2284
0
                            {begin, cs.used(begin)}, ec_)))
2285
0
                        return fail(cs.begin());
2286
2287
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2288
0
                        num_buf_.append( begin, cs.used(begin) );
2289
0
                    return suspend(cs.begin(), state::num2, num);
2290
0
                }
2291
70
                goto finish_int;
2292
70
            }
2293
0
            char const c = *cs;
2294
0
            if(BOOST_JSON_LIKELY(
2295
0
                c >= '0' && c <= '9'))
2296
0
            {
2297
0
                ++cs;
2298
                //              18446744073709551615 UINT64_MAX
2299
0
                if( num.mant  > 1844674407370955161 || (
2300
0
                    num.mant == 1844674407370955161 && c > '5'))
2301
0
                    break;
2302
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2303
0
                    num.mant = 10 * num.mant + ( c - '0' );
2304
0
            }
2305
0
            else
2306
0
            {
2307
0
                goto do_num6; // [.eE]
2308
0
            }
2309
0
        }
2310
70
    }
2311
0
    ++num.bias;
2312
2313
    //----------------------------------
2314
    //
2315
    // 1*DIGIT
2316
    // non-significant digits left of decimal
2317
    //
2318
0
do_num3:
2319
0
    for(;;)
2320
0
    {
2321
0
        if(BOOST_JSON_UNLIKELY(! cs))
2322
0
        {
2323
0
            if(BOOST_JSON_UNLIKELY(more_))
2324
0
            {
2325
0
                if(BOOST_JSON_UNLIKELY(
2326
0
                    ! h_.on_number_part(
2327
0
                        {begin, cs.used(begin)}, ec_)))
2328
0
                    return fail(cs.begin());
2329
2330
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2331
0
                    num_buf_.append( begin, cs.used(begin) );
2332
0
                return suspend(cs.begin(), state::num3, num);
2333
0
            }
2334
0
            goto finish_dub;
2335
0
        }
2336
0
        char const c = *cs;
2337
0
        if(BOOST_JSON_UNLIKELY(
2338
0
            c >= '0' && c <= '9'))
2339
0
        {
2340
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2341
0
            {
2342
0
                BOOST_STATIC_CONSTEXPR source_location loc
2343
0
                    = BOOST_CURRENT_LOCATION;
2344
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2345
0
            }
2346
0
            ++cs;
2347
0
            ++num.bias;
2348
0
        }
2349
0
        else if(BOOST_JSON_LIKELY(
2350
0
            c == '.'))
2351
0
        {
2352
0
            ++cs;
2353
0
            break;
2354
0
        }
2355
0
        else if((c | 32) == 'e')
2356
0
        {
2357
0
            ++cs;
2358
0
            goto do_exp1;
2359
0
        }
2360
0
        else
2361
0
        {
2362
0
            goto finish_dub;
2363
0
        }
2364
0
    }
2365
2366
    //----------------------------------
2367
    //
2368
    // DIGIT
2369
    // first non-significant digit
2370
    // to the right of decimal
2371
    //
2372
0
do_num4:
2373
0
    {
2374
0
        if(BOOST_JSON_UNLIKELY(! cs))
2375
0
        {
2376
0
            if(BOOST_JSON_UNLIKELY(
2377
0
                ! h_.on_number_part(
2378
0
                    {begin, cs.used(begin)}, ec_)))
2379
0
                return fail(cs.begin());
2380
2381
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2382
0
                num_buf_.append( begin, cs.used(begin) );
2383
0
            return maybe_suspend(
2384
0
                cs.begin(), state::num4, num);
2385
0
        }
2386
0
        char const c = *cs;
2387
0
        if(BOOST_JSON_LIKELY(
2388
            //static_cast<unsigned char>(c - '0') < 10))
2389
0
            c >= '0' && c <= '9'))
2390
0
        {
2391
0
            ++cs;
2392
0
        }
2393
0
        else
2394
0
        {
2395
            // digit required
2396
0
            BOOST_STATIC_CONSTEXPR source_location loc
2397
0
                = BOOST_CURRENT_LOCATION;
2398
0
            return fail(cs.begin(), error::syntax, &loc);
2399
0
        }
2400
0
    }
2401
2402
    //----------------------------------
2403
    //
2404
    // 1*DIGIT
2405
    // non-significant digits
2406
    // to the right of decimal
2407
    //
2408
68
do_num5:
2409
68
    for(;;)
2410
68
    {
2411
68
        if(BOOST_JSON_UNLIKELY(! cs))
2412
68
        {
2413
68
            if(BOOST_JSON_UNLIKELY(more_))
2414
0
            {
2415
0
                if(BOOST_JSON_UNLIKELY(
2416
0
                    ! h_.on_number_part(
2417
0
                        {begin, cs.used(begin)}, ec_)))
2418
0
                    return fail(cs.begin());
2419
2420
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2421
0
                    num_buf_.append( begin, cs.used(begin) );
2422
0
                return suspend(cs.begin(), state::num5, num);
2423
0
            }
2424
68
            goto finish_dub;
2425
68
        }
2426
0
        char const c = *cs;
2427
0
        if(BOOST_JSON_LIKELY(
2428
0
            c >= '0' && c <= '9'))
2429
0
        {
2430
0
            ++cs;
2431
0
        }
2432
0
        else if((c | 32) == 'e')
2433
0
        {
2434
0
            ++cs;
2435
0
            goto do_exp1;
2436
0
        }
2437
0
        else
2438
0
        {
2439
0
            goto finish_dub;
2440
0
        }
2441
0
    }
2442
2443
    //----------------------------------
2444
    //
2445
    // [.eE]
2446
    //
2447
23
do_num6:
2448
23
    {
2449
23
        if(BOOST_JSON_UNLIKELY(! cs))
2450
23
        {
2451
23
            if(BOOST_JSON_UNLIKELY(more_))
2452
0
            {
2453
0
                if(BOOST_JSON_UNLIKELY(
2454
0
                    ! h_.on_number_part(
2455
0
                        {begin, cs.used(begin)}, ec_)))
2456
0
                    return fail(cs.begin());
2457
2458
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2459
0
                    num_buf_.append( begin, cs.used(begin) );
2460
0
                return suspend(cs.begin(), state::num6, num);
2461
0
            }
2462
23
            goto finish_int;
2463
23
        }
2464
0
        char const c = *cs;
2465
0
        if(BOOST_JSON_LIKELY(
2466
0
            c == '.'))
2467
0
        {
2468
0
            ++cs;
2469
0
        }
2470
0
        else if((c | 32) == 'e')
2471
0
        {
2472
0
            ++cs;
2473
0
            goto do_exp1;
2474
0
        }
2475
0
        else
2476
0
        {
2477
0
            goto finish_int;
2478
0
        }
2479
0
    }
2480
2481
    //----------------------------------
2482
    //
2483
    // DIGIT
2484
    // first significant digit
2485
    // to the right of decimal
2486
    //
2487
14
do_num7:
2488
14
    {
2489
14
        if(BOOST_JSON_UNLIKELY(! cs))
2490
14
        {
2491
14
            if(BOOST_JSON_UNLIKELY(more_))
2492
0
            {
2493
0
                if(BOOST_JSON_UNLIKELY(
2494
0
                    ! h_.on_number_part(
2495
0
                        {begin, cs.used(begin)}, ec_)))
2496
0
                    return fail(cs.begin());
2497
2498
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2499
0
                    num_buf_.append( begin, cs.used(begin) );
2500
0
                return suspend(cs.begin(), state::num7, num);
2501
0
            }
2502
            // digit required
2503
14
            BOOST_STATIC_CONSTEXPR source_location loc
2504
14
                = BOOST_CURRENT_LOCATION;
2505
14
            return fail(cs.begin(), error::syntax, &loc);
2506
14
        }
2507
0
        char const c = *cs;
2508
0
        if(BOOST_JSON_UNLIKELY(
2509
0
            c < '0' || c > '9'))
2510
0
        {
2511
            // digit required
2512
0
            BOOST_STATIC_CONSTEXPR source_location loc
2513
0
                = BOOST_CURRENT_LOCATION;
2514
0
            return fail(cs.begin(), error::syntax, &loc);
2515
0
        }
2516
0
    }
2517
2518
    //----------------------------------
2519
    //
2520
    // 1*DIGIT
2521
    // significant digits
2522
    // to the right of decimal
2523
    //
2524
0
do_num8:
2525
0
    for(;;)
2526
0
    {
2527
0
        if(BOOST_JSON_UNLIKELY(! cs))
2528
0
        {
2529
0
            if(BOOST_JSON_UNLIKELY(more_))
2530
0
            {
2531
0
                if(BOOST_JSON_UNLIKELY(
2532
0
                    ! h_.on_number_part(
2533
0
                        {begin, cs.used(begin)}, ec_)))
2534
0
                    return fail(cs.begin());
2535
2536
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2537
0
                    num_buf_.append( begin, cs.used(begin) );
2538
0
                return suspend(cs.begin(), state::num8, num);
2539
0
            }
2540
0
            goto finish_dub;
2541
0
        }
2542
0
        char const c = *cs;
2543
0
        if(BOOST_JSON_LIKELY(
2544
0
            c >= '0' && c <= '9'))
2545
0
        {
2546
0
            ++cs;
2547
0
            if(!no_parsing && BOOST_JSON_LIKELY(
2548
0
                num.mant <= 9007199254740991)) // 2^53-1
2549
0
            {
2550
0
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2551
0
                {
2552
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2553
0
                        = BOOST_CURRENT_LOCATION;
2554
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2555
0
                }
2556
0
                --num.bias;
2557
0
                num.mant = 10 * num.mant + ( c - '0' );
2558
0
            }
2559
0
            else
2560
0
            {
2561
0
                goto do_num5;
2562
0
            }
2563
0
        }
2564
0
        else if((c | 32) == 'e')
2565
0
        {
2566
0
            ++cs;
2567
0
            goto do_exp1;
2568
0
        }
2569
0
        else
2570
0
        {
2571
0
            goto finish_dub;
2572
0
        }
2573
0
    }
2574
2575
    //----------------------------------
2576
    //
2577
    // *[+-]
2578
    //
2579
45
do_exp1:
2580
45
    if(BOOST_JSON_UNLIKELY(! cs))
2581
45
    {
2582
45
        if(BOOST_JSON_UNLIKELY(
2583
45
            ! h_.on_number_part(
2584
45
                {begin, cs.used(begin)}, ec_)))
2585
0
            return fail(cs.begin());
2586
2587
45
        BOOST_IF_CONSTEXPR( precise_parsing )
2588
45
            num_buf_.append( begin, cs.used(begin) );
2589
45
        return maybe_suspend(
2590
45
            cs.begin(), state::exp1, num);
2591
45
    }
2592
0
    if(*cs == '+')
2593
0
    {
2594
0
        ++cs;
2595
0
    }
2596
0
    else if(*cs == '-')
2597
0
    {
2598
0
        ++cs;
2599
0
        num.frac = true;
2600
0
    }
2601
2602
    //----------------------------------
2603
    //
2604
    // DIGIT
2605
    // first digit of the exponent
2606
    //
2607
33
do_exp2:
2608
33
    {
2609
33
        if(BOOST_JSON_UNLIKELY(! cs))
2610
33
        {
2611
33
            if(BOOST_JSON_UNLIKELY(more_))
2612
0
            {
2613
0
                if(BOOST_JSON_UNLIKELY(
2614
0
                    ! h_.on_number_part(
2615
0
                        {begin, cs.used(begin)}, ec_)))
2616
0
                    return fail(cs.begin());
2617
2618
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2619
0
                    num_buf_.append( begin, cs.used(begin) );
2620
0
                return suspend(cs.begin(), state::exp2, num);
2621
0
            }
2622
            // digit required
2623
33
            BOOST_STATIC_CONSTEXPR source_location loc
2624
33
                = BOOST_CURRENT_LOCATION;
2625
33
            return fail(cs.begin(), error::syntax, &loc);
2626
33
        }
2627
0
        char const c = *cs;
2628
0
        if(BOOST_JSON_UNLIKELY(
2629
0
            c < '0' || c > '9'))
2630
0
        {
2631
            // digit required
2632
0
            BOOST_STATIC_CONSTEXPR source_location loc
2633
0
                = BOOST_CURRENT_LOCATION;
2634
0
            return fail(cs.begin(), error::syntax, &loc);
2635
0
        }
2636
0
        ++cs;
2637
0
        num.exp = c - '0';
2638
0
    }
2639
2640
    //----------------------------------
2641
    //
2642
    // 1*DIGIT
2643
    // subsequent digits in the exponent
2644
    //
2645
70
do_exp3:
2646
70
    for(;;)
2647
70
    {
2648
70
        if(BOOST_JSON_UNLIKELY(! cs))
2649
70
        {
2650
70
            if(BOOST_JSON_UNLIKELY(more_))
2651
0
            {
2652
0
                if(BOOST_JSON_UNLIKELY(
2653
0
                    ! h_.on_number_part(
2654
0
                        {begin, cs.used(begin)}, ec_)))
2655
0
                    return fail(cs.begin());
2656
2657
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2658
0
                    num_buf_.append( begin, cs.used(begin) );
2659
0
                return suspend(cs.begin(), state::exp3, num);
2660
0
            }
2661
70
        }
2662
0
        else
2663
0
        {
2664
0
            char const c = *cs;
2665
0
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2666
0
            {
2667
0
                if(BOOST_JSON_UNLIKELY(
2668
                //              2147483647 INT_MAX
2669
0
                    num.exp  >  214748364 ||
2670
0
                    (num.exp == 214748364 && c > '7')
2671
0
                ))
2672
0
                    num.exp = INT_MAX;
2673
0
                else BOOST_IF_CONSTEXPR( !no_parsing )
2674
0
                    num.exp = 10 * num.exp + ( c - '0' );
2675
2676
0
                ++cs;
2677
0
                continue;
2678
0
            }
2679
0
        }
2680
70
        BOOST_ASSERT(num.exp >= 0);
2681
70
        if ( num.frac )
2682
4
        {
2683
4
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2684
0
            {
2685
                // if exponent overflowed, bias is a very large negative
2686
                // number, and mantissa isn't zero, then we cannot parse the
2687
                // number correctly
2688
0
                if(BOOST_JSON_UNLIKELY(
2689
0
                    (num.exp == INT_MAX) &&
2690
0
                    (num.bias < 0) &&
2691
0
                    (num.exp + num.bias < 308) &&
2692
0
                    num.mant ))
2693
0
                {
2694
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2695
0
                        = BOOST_CURRENT_LOCATION;
2696
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2697
0
                }
2698
2699
0
                num.bias = 0;
2700
0
                num.exp = INT_MAX;
2701
0
            }
2702
4
        }
2703
66
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2704
0
        {
2705
            // if exponent overflowed, bias is a very large positive number,
2706
            // and mantissa isn't zero, then we cannot parse the
2707
            // number correctly
2708
0
            if(BOOST_JSON_UNLIKELY(
2709
0
                (num.exp == INT_MAX) &&
2710
0
                (num.bias > 0) &&
2711
0
                (num.exp - num.bias < 308) &&
2712
0
                num.mant ))
2713
0
            {
2714
0
                BOOST_STATIC_CONSTEXPR source_location loc
2715
0
                    = BOOST_CURRENT_LOCATION;
2716
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2717
0
            }
2718
2719
0
            num.bias = 0;
2720
0
            num.exp = INT_MAX;
2721
0
        }
2722
70
        goto finish_dub;
2723
70
    }
2724
2725
116
finish_int:
2726
116
    if(negative || (!stack_empty && num.neg))
2727
28
    {
2728
28
        if(BOOST_JSON_UNLIKELY(
2729
28
            ! h_.on_int64(static_cast<
2730
28
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2731
0
            return fail(cs.begin());
2732
28
        return cs.begin();
2733
28
    }
2734
88
    if(num.mant <= INT64_MAX)
2735
88
    {
2736
88
finish_signed:
2737
88
        if(BOOST_JSON_UNLIKELY(
2738
88
            ! h_.on_int64(static_cast<
2739
88
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2740
0
            return fail(cs.begin());
2741
88
        return cs.begin();
2742
88
    }
2743
0
    if(BOOST_JSON_UNLIKELY(
2744
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2745
0
        return fail(cs.begin());
2746
0
    return cs.begin();
2747
138
finish_dub:
2748
138
    double d;
2749
138
    std::size_t const size = cs.used(begin);
2750
138
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2751
    BOOST_IF_CONSTEXPR( precise_parsing )
2752
    {
2753
        char const* data = begin;
2754
        std::size_t full_size = size;
2755
         // if we previously suspended or if the current input ends with the
2756
         // number, we need to copy the current part of the number to the
2757
         // temporary buffer
2758
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2759
        {
2760
            data = num_buf_.append( begin, size );
2761
            full_size = num_buf_.size();
2762
        }
2763
        auto const err = detail::charconv::from_chars(
2764
            data, data + full_size, d );
2765
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2766
        BOOST_ASSERT( err.ptr == data + full_size );
2767
        (void)err;
2768
    }
2769
138
    else BOOST_IF_CONSTEXPR( no_parsing )
2770
138
        d = 0;
2771
    else
2772
        d = detail::dec_to_float(
2773
            num.mant,
2774
            num.bias + (num.frac ?
2775
                -num.exp : num.exp),
2776
            num.neg);
2777
138
    if(BOOST_JSON_UNLIKELY(
2778
138
        ! h_.on_double(d, {begin, size}, ec_)))
2779
0
        return fail(cs.begin());
2780
138
    return cs.begin();
2781
138
}
2782
2783
//----------------------------------------------------------
2784
2785
template<class Handler>
2786
template<class... Args>
2787
basic_parser<Handler>::
2788
basic_parser(
2789
    parse_options const& opt,
2790
    Args&&... args)
2791
22.6k
    : h_(std::forward<Args>(args)...)
2792
22.6k
    , opt_(opt)
2793
22.6k
{
2794
22.6k
}
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
2791
13.5k
    : h_(std::forward<Args>(args)...)
2792
13.5k
    , opt_(opt)
2793
13.5k
{
2794
13.5k
}
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
2791
9.14k
    : h_(std::forward<Args>(args)...)
2792
9.14k
    , opt_(opt)
2793
9.14k
{
2794
9.14k
}
2795
2796
//----------------------------------------------------------
2797
2798
template<class Handler>
2799
void
2800
basic_parser<Handler>::
2801
reset() noexcept
2802
36.7k
{
2803
36.7k
    ec_ = {};
2804
36.7k
    st_.clear();
2805
36.7k
    more_ = true;
2806
36.7k
    done_ = false;
2807
36.7k
    clean_ = true;
2808
36.7k
    num_buf_.clear();
2809
36.7k
}
2810
2811
template<class Handler>
2812
void
2813
basic_parser<Handler>::
2814
fail(system::error_code ec) noexcept
2815
2.35k
{
2816
2.35k
    if(! ec)
2817
0
    {
2818
        // assign an arbitrary
2819
        // error code to prevent UB
2820
0
        BOOST_JSON_FAIL(ec_, error::incomplete);
2821
0
    }
2822
2.35k
    else
2823
2.35k
    {
2824
2.35k
        ec_ = ec;
2825
2.35k
    }
2826
2.35k
    done_ = false;
2827
2.35k
}
2828
2829
//----------------------------------------------------------
2830
2831
template<class Handler>
2832
std::size_t
2833
basic_parser<Handler>::
2834
write_some(
2835
    bool more,
2836
    char const* data,
2837
    std::size_t size,
2838
    system::error_code& ec)
2839
33.2k
{
2840
    // see if we exited via exception
2841
    // on the last call to write_some
2842
33.2k
    if(! clean_)
2843
0
    {
2844
        // prevent UB
2845
0
        if(! ec_)
2846
0
        {
2847
0
            BOOST_JSON_FAIL(ec_, error::exception);
2848
0
        }
2849
0
    }
2850
33.2k
    if(ec_)
2851
0
    {
2852
        // error is sticky
2853
0
        ec = ec_;
2854
0
        return 0;
2855
0
    }
2856
33.2k
    clean_ = false;
2857
33.2k
    more_ = more;
2858
33.2k
    end_ = data + size;
2859
33.2k
    const char* p;
2860
33.2k
    if(BOOST_JSON_LIKELY(st_.empty()))
2861
22.6k
    {
2862
        // first time
2863
22.6k
        depth_ = opt_.max_depth;
2864
22.6k
        if(BOOST_JSON_UNLIKELY(
2865
22.6k
            ! h_.on_document_begin(ec_)))
2866
0
        {
2867
0
            ec = ec_;
2868
0
            return 0;
2869
0
        }
2870
22.6k
        p = parse_document(data, std::true_type());
2871
22.6k
    }
2872
10.5k
    else
2873
10.5k
    {
2874
10.5k
        p = parse_document(data, std::false_type());
2875
10.5k
    }
2876
2877
33.2k
    if(BOOST_JSON_LIKELY(p != sentinel()))
2878
11.5k
    {
2879
11.5k
        BOOST_ASSERT(! ec_);
2880
11.5k
        if(! done_)
2881
9.65k
        {
2882
9.65k
            done_ = true;
2883
9.65k
            h_.on_document_end(ec_);
2884
9.65k
        }
2885
11.5k
    }
2886
21.7k
    else
2887
21.7k
    {
2888
21.7k
        if(! ec_)
2889
15.6k
        {
2890
15.6k
            if(! more_)
2891
5.14k
            {
2892
5.14k
                BOOST_JSON_FAIL(ec_, error::incomplete);
2893
5.14k
            }
2894
10.5k
            else if(! st_.empty())
2895
10.5k
            {
2896
                // consume as much trailing whitespace in
2897
                // the JSON document as possible, but still
2898
                // consider the parse complete
2899
10.5k
                state st;
2900
10.5k
                st_.peek(st);
2901
10.5k
                if( st == state::doc3 &&
2902
1.86k
                    ! done_)
2903
1.86k
                {
2904
1.86k
                    done_ = true;
2905
1.86k
                    h_.on_document_end(ec_);
2906
1.86k
                }
2907
10.5k
            }
2908
15.6k
        }
2909
21.7k
        p = end_;
2910
21.7k
    }
2911
33.2k
    ec = ec_;
2912
33.2k
    clean_ = true;
2913
33.2k
    return p - data;
2914
33.2k
}
2915
2916
template<class Handler>
2917
std::size_t
2918
basic_parser<Handler>::
2919
write_some(
2920
    bool more,
2921
    char const* data,
2922
    std::size_t size,
2923
    std::error_code& ec)
2924
{
2925
    system::error_code jec;
2926
    std::size_t const result = write_some(more, data, size, jec);
2927
    ec = jec;
2928
    return result;
2929
}
2930
2931
#endif
2932
2933
} // namespace json
2934
} // namespace boost
2935
2936
#ifdef _MSC_VER
2937
#pragma warning(pop)
2938
#endif
2939
2940
#endif