Coverage Report

Created: 2024-10-29 06:41

/work/stage/include/boost/json/basic_parser_impl.hpp
Line
Count
Source (jump to first uncovered line)
1
//
2
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4
//
5
// Distributed under the Boost Software License, Version 1.0. (See accompanying
6
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7
//
8
// Official repository: https://github.com/boostorg/json
9
//
10
11
#ifndef BOOST_JSON_BASIC_PARSER_IMPL_HPP
12
#define BOOST_JSON_BASIC_PARSER_IMPL_HPP
13
14
#include <boost/json/detail/config.hpp>
15
#include <boost/json/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
82.2k
{
57
82.2k
    static double const tab[618] = {
58
82.2k
                        1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
59
60
82.2k
        1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
61
82.2k
        1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
62
82.2k
        1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
63
82.2k
        1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
64
82.2k
        1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
65
82.2k
        1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
66
82.2k
        1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
67
82.2k
        1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
68
82.2k
        1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
69
82.2k
        1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
70
71
82.2k
        1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
72
82.2k
        1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
73
82.2k
        1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
74
82.2k
        1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
75
82.2k
        1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
76
82.2k
        1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
77
82.2k
        1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
78
82.2k
        1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
79
82.2k
        1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
80
82.2k
        1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
81
82
82.2k
        1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
83
82.2k
        1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
84
82.2k
        1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
85
82.2k
        1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
86
82.2k
        1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
87
82.2k
        1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
88
82.2k
        1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
89
82.2k
        1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
90
82.2k
        1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
91
82.2k
        1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
92
93
82.2k
        1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
94
82.2k
        1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
95
82.2k
        1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
96
82.2k
        1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
97
82.2k
        1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
98
82.2k
        1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
99
82.2k
        1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
100
82.2k
        1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
101
82.2k
        1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
102
82.2k
        1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
103
104
82.2k
        1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
105
82.2k
        1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
106
82.2k
        1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
107
82.2k
        1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
108
82.2k
        1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
109
82.2k
        1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
110
82.2k
        1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
111
82.2k
        1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
112
82.2k
        1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
113
82.2k
        1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
114
115
82.2k
        1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
116
82.2k
        1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
117
82.2k
        1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
118
82.2k
        1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
119
82.2k
        1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
120
82.2k
        1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
121
82.2k
        1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
122
82.2k
        1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
123
82.2k
        1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
124
82.2k
        1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
125
126
82.2k
        1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
127
128
82.2k
    if( exp > 308 )
129
20.9k
    {
130
20.9k
        return std::numeric_limits<double>::infinity();
131
20.9k
    }
132
61.3k
    else if( exp < -308 )
133
6.88k
    {
134
        // due to the way pow10 is used by dec_to_float,
135
        // we can afford to return 0.0 here
136
6.88k
        return 0.0;
137
6.88k
    }
138
54.4k
    else
139
54.4k
    {
140
54.4k
        exp += 308;
141
54.4k
        BOOST_ASSERT(exp >= 0 && exp < 618);
142
0
        return tab[exp];
143
54.4k
    }
144
82.2k
}
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.59M
{
153
    // convert to double explicitly to silence warnings
154
4.59M
    double x = static_cast<double>(m);
155
4.59M
    if(neg)
156
44.5k
        x = -x;
157
158
4.59M
    if(e < -305)
159
18.6k
    {
160
18.6k
        x *= 1e-305 ;
161
18.6k
        e += 305;
162
18.6k
    }
163
164
4.59M
    if(e >= -22 && e < 0)
165
67.7k
        return x / pow10(-e);
166
167
4.53M
    return x * pow10(e);
168
4.59M
}
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.64M
{
181
    // by Peter Dimov
182
3.64M
    if( c >= '0' && c <= '9' )
183
1.89M
        return c - '0';
184
1.74M
    c &= ~0x20;
185
1.74M
    if( c >= 'A' && c <= 'F' )
186
1.74M
        return 10 + c - 'A';
187
1.55k
    return -1;
188
1.74M
}
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
190k
    {
206
190k
        return parser->parse_number(
207
190k
            p,
208
190k
            std::integral_constant<bool, StackEmpty_>(),
209
190k
            std::integral_constant<char, First_>(),
210
190k
            std::integral_constant<
211
190k
                number_precision, static_cast<number_precision>(N)>() );
212
190k
    }
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)48>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
205
15.0k
    {
206
15.0k
        return parser->parse_number(
207
15.0k
            p,
208
15.0k
            std::integral_constant<bool, StackEmpty_>(),
209
15.0k
            std::integral_constant<char, First_>(),
210
15.0k
            std::integral_constant<
211
15.0k
                number_precision, static_cast<number_precision>(N)>() );
212
15.0k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)48>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)48>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)45>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
205
37.5k
    {
206
37.5k
        return parser->parse_number(
207
37.5k
            p,
208
37.5k
            std::integral_constant<bool, StackEmpty_>(),
209
37.5k
            std::integral_constant<char, First_>(),
210
37.5k
            std::integral_constant<
211
37.5k
                number_precision, static_cast<number_precision>(N)>() );
212
37.5k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)45>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)45>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)43>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
205
110k
    {
206
110k
        return parser->parse_number(
207
110k
            p,
208
110k
            std::integral_constant<bool, StackEmpty_>(),
209
110k
            std::integral_constant<char, First_>(),
210
110k
            std::integral_constant<
211
110k
                number_precision, static_cast<number_precision>(N)>() );
212
110k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)43>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<true, (char)43>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<false, (char)0>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<false, (char)0>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number_helper<false, (char)0>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)48>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
205
6.15k
    {
206
6.15k
        return parser->parse_number(
207
6.15k
            p,
208
6.15k
            std::integral_constant<bool, StackEmpty_>(),
209
6.15k
            std::integral_constant<char, First_>(),
210
6.15k
            std::integral_constant<
211
6.15k
                number_precision, static_cast<number_precision>(N)>() );
212
6.15k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)48>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)48>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)45>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
205
8.75k
    {
206
8.75k
        return parser->parse_number(
207
8.75k
            p,
208
8.75k
            std::integral_constant<bool, StackEmpty_>(),
209
8.75k
            std::integral_constant<char, First_>(),
210
8.75k
            std::integral_constant<
211
8.75k
                number_precision, static_cast<number_precision>(N)>() );
212
8.75k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)45>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)45>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)43>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Line
Count
Source
205
13.0k
    {
206
13.0k
        return parser->parse_number(
207
13.0k
            p,
208
13.0k
            std::integral_constant<bool, StackEmpty_>(),
209
13.0k
            std::integral_constant<char, First_>(),
210
13.0k
            std::integral_constant<
211
13.0k
                number_precision, static_cast<number_precision>(N)>() );
212
13.0k
    }
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)43>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<true, (char)43>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<false, (char)0>::operator()<0ul>(std::__1::integral_constant<unsigned long, 0ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<false, (char)0>::operator()<1ul>(std::__1::integral_constant<unsigned long, 1ul>) const
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number_helper<false, (char)0>::operator()<2ul>(std::__1::integral_constant<unsigned long, 2ul>) const
213
};
214
215
//----------------------------------------------------------
216
217
template<class Handler>
218
void
219
basic_parser<Handler>::
220
reserve()
221
0
{
222
0
    if(BOOST_JSON_LIKELY(
223
0
        ! st_.empty()))
224
0
        return;
225
    // Reserve the largest stack we need,
226
    // to avoid reallocation during suspend.
227
0
    st_.reserve(
228
0
        sizeof(state) + // document parsing state
229
0
        (sizeof(state) +
230
0
            sizeof(std::size_t)) * depth() + // array and object state + size
231
0
        sizeof(state) + // value parsing state
232
0
        sizeof(std::size_t) + // string size
233
0
        sizeof(state)); // comment state
234
0
}
Unexecuted instantiation: boost::json::basic_parser<boost::json::detail::into_handler<Object> >::reserve()
Unexecuted instantiation: boost::json::basic_parser<null_parser::handler>::reserve()
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
428k
{
248
    // the "+1" ensures that the returned pointer is unique even if
249
    // the given input buffer borders on this object
250
428k
    return reinterpret_cast<
251
428k
        const char*>(this) + 1;
252
428k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::sentinel()
Line
Count
Source
247
368k
{
248
    // the "+1" ensures that the returned pointer is unique even if
249
    // the given input buffer borders on this object
250
368k
    return reinterpret_cast<
251
368k
        const char*>(this) + 1;
252
368k
}
boost::json::basic_parser<null_parser::handler>::sentinel()
Line
Count
Source
247
60.4k
{
248
    // the "+1" ensures that the returned pointer is unique even if
249
    // the given input buffer borders on this object
250
60.4k
    return reinterpret_cast<
251
60.4k
        const char*>(this) + 1;
252
60.4k
}
253
254
template<class Handler>
255
bool
256
basic_parser<Handler>::
257
incomplete(
258
    const detail::const_stream_wrapper& cs)
259
376k
{
260
376k
    return cs.begin() == sentinel();
261
376k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::incomplete(boost::json::detail::const_stream_wrapper const&)
Line
Count
Source
259
333k
{
260
333k
    return cs.begin() == sentinel();
261
333k
}
boost::json::basic_parser<null_parser::handler>::incomplete(boost::json::detail::const_stream_wrapper const&)
Line
Count
Source
259
42.3k
{
260
42.3k
    return cs.begin() == sentinel();
261
42.3k
}
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
9.95k
{
292
9.95k
    if(BOOST_JSON_LIKELY(
293
9.95k
        ! ec_ && more_))
294
0
    {
295
        // suspend
296
0
        reserve();
297
0
        st_.push_unchecked(n);
298
0
        st_.push_unchecked(st);
299
0
    }
300
9.95k
    return sentinel();
301
9.95k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::suspend_or_fail(boost::json::basic_parser<boost::json::detail::into_handler<Object> >::state, unsigned long)
Line
Count
Source
291
7.32k
{
292
7.32k
    if(BOOST_JSON_LIKELY(
293
7.32k
        ! ec_ && more_))
294
0
    {
295
        // suspend
296
0
        reserve();
297
0
        st_.push_unchecked(n);
298
0
        st_.push_unchecked(st);
299
0
    }
300
7.32k
    return sentinel();
301
7.32k
}
boost::json::basic_parser<null_parser::handler>::suspend_or_fail(boost::json::basic_parser<null_parser::handler>::state, unsigned long)
Line
Count
Source
291
2.62k
{
292
2.62k
    if(BOOST_JSON_LIKELY(
293
2.62k
        ! ec_ && more_))
294
0
    {
295
        // suspend
296
0
        reserve();
297
0
        st_.push_unchecked(n);
298
0
        st_.push_unchecked(st);
299
0
    }
300
2.62k
    return sentinel();
301
2.62k
}
302
303
304
template<class Handler>
305
const char*
306
basic_parser<Handler>::
307
fail(const char* p) noexcept
308
2.26k
{
309
2.26k
    BOOST_ASSERT( p != sentinel() );
310
0
    end_ = p;
311
2.26k
    return sentinel();
312
2.26k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::fail(char const*)
Line
Count
Source
308
2.26k
{
309
2.26k
    BOOST_ASSERT( p != sentinel() );
310
0
    end_ = p;
311
2.26k
    return sentinel();
312
2.26k
}
Unexecuted instantiation: boost::json::basic_parser<null_parser::handler>::fail(char const*)
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
4.56k
{
322
4.56k
    BOOST_ASSERT( p != sentinel() );
323
0
    end_ = p;
324
4.56k
    ec_.assign(ev, loc);
325
4.56k
    return sentinel();
326
4.56k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::fail(char const*, boost::json::error, boost::source_location const*)
Line
Count
Source
321
2.72k
{
322
2.72k
    BOOST_ASSERT( p != sentinel() );
323
0
    end_ = p;
324
2.72k
    ec_.assign(ev, loc);
325
2.72k
    return sentinel();
326
2.72k
}
boost::json::basic_parser<null_parser::handler>::fail(char const*, boost::json::error, boost::source_location const*)
Line
Count
Source
321
1.83k
{
322
1.83k
    BOOST_ASSERT( p != sentinel() );
323
0
    end_ = p;
324
1.83k
    ec_.assign(ev, loc);
325
1.83k
    return sentinel();
326
1.83k
}
327
328
template<class Handler>
329
const char*
330
basic_parser<Handler>::
331
maybe_suspend(
332
    const char* p,
333
    state st)
334
424
{
335
424
    if( p != sentinel() )
336
424
        end_ = p;
337
424
    if(BOOST_JSON_LIKELY(more_))
338
0
    {
339
        // suspend
340
0
        reserve();
341
0
        st_.push_unchecked(st);
342
0
    }
343
424
    return sentinel();
344
424
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::maybe_suspend(char const*, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::state)
Line
Count
Source
334
137
{
335
137
    if( p != sentinel() )
336
137
        end_ = p;
337
137
    if(BOOST_JSON_LIKELY(more_))
338
0
    {
339
        // suspend
340
0
        reserve();
341
0
        st_.push_unchecked(st);
342
0
    }
343
137
    return sentinel();
344
137
}
boost::json::basic_parser<null_parser::handler>::maybe_suspend(char const*, boost::json::basic_parser<null_parser::handler>::state)
Line
Count
Source
334
287
{
335
287
    if( p != sentinel() )
336
287
        end_ = p;
337
287
    if(BOOST_JSON_LIKELY(more_))
338
0
    {
339
        // suspend
340
0
        reserve();
341
0
        st_.push_unchecked(st);
342
0
    }
343
287
    return sentinel();
344
287
}
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
2.84k
{
354
2.84k
    BOOST_ASSERT( p != sentinel() );
355
0
    end_ = p;
356
2.84k
    if(BOOST_JSON_LIKELY(more_))
357
0
    {
358
        // suspend
359
0
        reserve();
360
0
        st_.push_unchecked(n);
361
0
        st_.push_unchecked(st);
362
0
    }
363
2.84k
    return sentinel();
364
2.84k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::maybe_suspend(char const*, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::state, unsigned long)
Line
Count
Source
353
1.69k
{
354
1.69k
    BOOST_ASSERT( p != sentinel() );
355
0
    end_ = p;
356
1.69k
    if(BOOST_JSON_LIKELY(more_))
357
0
    {
358
        // suspend
359
0
        reserve();
360
0
        st_.push_unchecked(n);
361
0
        st_.push_unchecked(st);
362
0
    }
363
1.69k
    return sentinel();
364
1.69k
}
boost::json::basic_parser<null_parser::handler>::maybe_suspend(char const*, boost::json::basic_parser<null_parser::handler>::state, unsigned long)
Line
Count
Source
353
1.15k
{
354
1.15k
    BOOST_ASSERT( p != sentinel() );
355
0
    end_ = p;
356
1.15k
    if(BOOST_JSON_LIKELY(more_))
357
0
    {
358
        // suspend
359
0
        reserve();
360
0
        st_.push_unchecked(n);
361
0
        st_.push_unchecked(st);
362
0
    }
363
1.15k
    return sentinel();
364
1.15k
}
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
169
{
374
169
    BOOST_ASSERT( p != sentinel() );
375
0
    end_ = p;
376
169
    if(BOOST_JSON_LIKELY(more_))
377
0
    {
378
        // suspend
379
0
        num_ = num;
380
0
        reserve();
381
0
        st_.push_unchecked(st);;
382
0
    }
383
169
    return sentinel();
384
169
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::maybe_suspend(char const*, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::state, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::number const&)
Line
Count
Source
373
52
{
374
52
    BOOST_ASSERT( p != sentinel() );
375
0
    end_ = p;
376
52
    if(BOOST_JSON_LIKELY(more_))
377
0
    {
378
        // suspend
379
0
        num_ = num;
380
0
        reserve();
381
0
        st_.push_unchecked(st);;
382
0
    }
383
52
    return sentinel();
384
52
}
boost::json::basic_parser<null_parser::handler>::maybe_suspend(char const*, boost::json::basic_parser<null_parser::handler>::state, boost::json::basic_parser<null_parser::handler>::number const&)
Line
Count
Source
373
117
{
374
117
    BOOST_ASSERT( p != sentinel() );
375
0
    end_ = p;
376
117
    if(BOOST_JSON_LIKELY(more_))
377
0
    {
378
        // suspend
379
0
        num_ = num;
380
0
        reserve();
381
0
        st_.push_unchecked(st);;
382
0
    }
383
117
    return sentinel();
384
117
}
385
386
template<class Handler>
387
const char*
388
basic_parser<Handler>::
389
suspend(
390
    const char* p,
391
    state st)
392
0
{
393
0
    BOOST_ASSERT( p != sentinel() );
394
0
    end_ = p;
395
    // suspend
396
0
    reserve();
397
0
    st_.push_unchecked(st);
398
0
    return sentinel();
399
0
}
Unexecuted instantiation: boost::json::basic_parser<boost::json::detail::into_handler<Object> >::suspend(char const*, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::state)
Unexecuted instantiation: boost::json::basic_parser<null_parser::handler>::suspend(char const*, boost::json::basic_parser<null_parser::handler>::state)
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
0
{
409
0
    BOOST_ASSERT( p != sentinel() );
410
0
    end_ = p;
411
    // suspend
412
0
    num_ = num;
413
0
    reserve();
414
0
    st_.push_unchecked(st);
415
0
    return sentinel();
416
0
}
Unexecuted instantiation: boost::json::basic_parser<boost::json::detail::into_handler<Object> >::suspend(char const*, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::state, boost::json::basic_parser<boost::json::detail::into_handler<Object> >::number const&)
Unexecuted instantiation: boost::json::basic_parser<null_parser::handler>::suspend(char const*, boost::json::basic_parser<null_parser::handler>::state, boost::json::basic_parser<null_parser::handler>::number const&)
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
0
{
428
0
    detail::const_stream_wrapper cs(p, end_);
429
0
    const char* start = cs.begin();
430
0
    std::size_t remain;
431
0
    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
0
    BOOST_ASSERT(*cs == '/');
445
0
    ++cs;
446
0
do_com1:
447
0
    if(BOOST_JSON_UNLIKELY(! cs))
448
0
        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
0
do_com2:
460
        // KRYSTIAN TODO: this is a mess, we have to fix this
461
0
        remain = cs.remain();
462
0
        cs = remain ? static_cast<const char*>(
463
0
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
464
0
        if(! cs.begin())
465
0
            cs = sentinel();
466
0
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
467
0
        {
468
            // if the doc does not terminate
469
            // with a newline, treat it as the
470
            // end of the comment
471
0
            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
0
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479
0
                {start, cs.remain(start)}, ec_)))
480
0
                return fail(cs.end());
481
0
            if(terminal)
482
0
                return suspend(cs.end(), state::com2);
483
0
            return maybe_suspend(cs.end(), state::com2);
484
0
        }
485
0
        break;
486
0
    case '*':
487
0
        do
488
0
        {
489
0
            ++cs;
490
0
do_com3:
491
            // KRYSTIAN TODO: this is a mess, we have to fix this
492
0
            remain = cs.remain();
493
0
            cs = remain ? static_cast<const char*>(
494
0
                std::memchr(cs.begin(), '*', remain)) : sentinel();
495
0
            if(! cs.begin())
496
0
                cs = sentinel();
497
            // stopped inside a c comment
498
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
499
0
            {
500
0
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
501
0
                    {start, cs.remain(start)}, ec_)))
502
0
                    return fail(cs.end());
503
0
                return maybe_suspend(cs.end(), state::com3);
504
0
            }
505
            // found a asterisk, check if the next char is a slash
506
0
            ++cs;
507
0
do_com4:
508
0
            if(BOOST_JSON_UNLIKELY(! cs))
509
0
            {
510
0
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511
0
                    {start, cs.used(start)}, ec_)))
512
0
                    return fail(cs.begin());
513
0
                return maybe_suspend(cs.begin(), state::com4);
514
0
            }
515
0
        }
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
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_comment<true>(char const*, std::__1::integral_constant<bool, true>, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_comment<false>(char const*, std::__1::integral_constant<bool, false>, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_comment<true>(char const*, std::__1::integral_constant<bool, true>, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_comment<false>(char const*, std::__1::integral_constant<bool, false>, bool)
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
12.2k
{
532
12.2k
    detail::const_stream_wrapper cs(p, end_);
533
12.2k
    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
12.2k
do_doc1:
552
12.2k
    cs = detail::count_whitespace(cs.begin(), cs.end());
553
12.2k
    if(BOOST_JSON_UNLIKELY(! cs))
554
48
        return maybe_suspend(cs.begin(), state::doc1);
555
12.1k
do_doc2:
556
12.1k
    switch(+opt_.allow_comments |
557
12.1k
        (opt_.allow_trailing_commas << 1) |
558
12.1k
        (opt_.allow_invalid_utf8 << 2))
559
12.1k
    {
560
    // no extensions
561
12.1k
    default:
562
12.1k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563
12.1k
        break;
564
    // comments
565
0
    case 1:
566
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567
0
        break;
568
    // trailing
569
0
    case 2:
570
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571
0
        break;
572
    // comments & trailing
573
0
    case 3:
574
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575
0
        break;
576
    // skip validation
577
0
    case 4:
578
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579
0
        break;
580
    // comments & skip validation
581
0
    case 5:
582
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583
0
        break;
584
    // trailing & skip validation
585
0
    case 6:
586
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587
0
        break;
588
    // comments & trailing & skip validation
589
0
    case 7:
590
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591
0
        break;
592
12.1k
    }
593
12.1k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594
        // the appropriate state has already been pushed into stack
595
10.2k
        return sentinel();
596
1.94k
do_doc3:
597
1.94k
    cs = detail::count_whitespace(cs.begin(), cs.end());
598
1.94k
    if(BOOST_JSON_UNLIKELY(! cs))
599
1.46k
    {
600
1.46k
        if(more_)
601
0
            return suspend(cs.begin(), state::doc3);
602
1.46k
    }
603
485
    else if(opt_.allow_comments && *cs == '/')
604
0
    {
605
0
do_doc4:
606
0
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
0
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608
0
            return sentinel();
609
0
        goto do_doc3;
610
0
    }
611
1.94k
    return cs.begin();
612
1.94k
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_document<true>(char const*, std::__1::integral_constant<bool, true>)
Line
Count
Source
531
6.93k
{
532
6.93k
    detail::const_stream_wrapper cs(p, end_);
533
6.93k
    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
6.93k
do_doc1:
552
6.93k
    cs = detail::count_whitespace(cs.begin(), cs.end());
553
6.93k
    if(BOOST_JSON_UNLIKELY(! cs))
554
23
        return maybe_suspend(cs.begin(), state::doc1);
555
6.91k
do_doc2:
556
6.91k
    switch(+opt_.allow_comments |
557
6.91k
        (opt_.allow_trailing_commas << 1) |
558
6.91k
        (opt_.allow_invalid_utf8 << 2))
559
6.91k
    {
560
    // no extensions
561
6.91k
    default:
562
6.91k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563
6.91k
        break;
564
    // comments
565
0
    case 1:
566
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567
0
        break;
568
    // trailing
569
0
    case 2:
570
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571
0
        break;
572
    // comments & trailing
573
0
    case 3:
574
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575
0
        break;
576
    // skip validation
577
0
    case 4:
578
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579
0
        break;
580
    // comments & skip validation
581
0
    case 5:
582
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583
0
        break;
584
    // trailing & skip validation
585
0
    case 6:
586
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587
0
        break;
588
    // comments & trailing & skip validation
589
0
    case 7:
590
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591
0
        break;
592
6.91k
    }
593
6.91k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594
        // the appropriate state has already been pushed into stack
595
6.84k
        return sentinel();
596
69
do_doc3:
597
69
    cs = detail::count_whitespace(cs.begin(), cs.end());
598
69
    if(BOOST_JSON_UNLIKELY(! cs))
599
15
    {
600
15
        if(more_)
601
0
            return suspend(cs.begin(), state::doc3);
602
15
    }
603
54
    else if(opt_.allow_comments && *cs == '/')
604
0
    {
605
0
do_doc4:
606
0
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
0
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608
0
            return sentinel();
609
0
        goto do_doc3;
610
0
    }
611
69
    return cs.begin();
612
69
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_document<false>(char const*, std::__1::integral_constant<bool, false>)
char const* boost::json::basic_parser<null_parser::handler>::parse_document<true>(char const*, std::__1::integral_constant<bool, true>)
Line
Count
Source
531
5.27k
{
532
5.27k
    detail::const_stream_wrapper cs(p, end_);
533
5.27k
    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
5.27k
do_doc1:
552
5.27k
    cs = detail::count_whitespace(cs.begin(), cs.end());
553
5.27k
    if(BOOST_JSON_UNLIKELY(! cs))
554
25
        return maybe_suspend(cs.begin(), state::doc1);
555
5.24k
do_doc2:
556
5.24k
    switch(+opt_.allow_comments |
557
5.24k
        (opt_.allow_trailing_commas << 1) |
558
5.24k
        (opt_.allow_invalid_utf8 << 2))
559
5.24k
    {
560
    // no extensions
561
5.24k
    default:
562
5.24k
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563
5.24k
        break;
564
    // comments
565
0
    case 1:
566
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567
0
        break;
568
    // trailing
569
0
    case 2:
570
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571
0
        break;
572
    // comments & trailing
573
0
    case 3:
574
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575
0
        break;
576
    // skip validation
577
0
    case 4:
578
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579
0
        break;
580
    // comments & skip validation
581
0
    case 5:
582
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583
0
        break;
584
    // trailing & skip validation
585
0
    case 6:
586
0
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587
0
        break;
588
    // comments & trailing & skip validation
589
0
    case 7:
590
0
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591
0
        break;
592
5.24k
    }
593
5.24k
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594
        // the appropriate state has already been pushed into stack
595
3.36k
        return sentinel();
596
1.87k
do_doc3:
597
1.87k
    cs = detail::count_whitespace(cs.begin(), cs.end());
598
1.87k
    if(BOOST_JSON_UNLIKELY(! cs))
599
1.44k
    {
600
1.44k
        if(more_)
601
0
            return suspend(cs.begin(), state::doc3);
602
1.44k
    }
603
431
    else if(opt_.allow_comments && *cs == '/')
604
0
    {
605
0
do_doc4:
606
0
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607
0
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608
0
            return sentinel();
609
0
        goto do_doc3;
610
0
    }
611
1.87k
    return cs.begin();
612
1.87k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_document<false>(char const*, std::__1::integral_constant<bool, false>)
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
248k
{
629
248k
    if(stack_empty || st_.empty())
630
248k
    {
631
248k
loop:
632
248k
        switch(*p)
633
248k
        {
634
21.1k
        case '0':
635
21.1k
            return mp11::mp_with_index<3>(
636
21.1k
                static_cast<unsigned char>(opt_.numbers),
637
21.1k
                parse_number_helper<true, '0'>{ this, p });
638
46.3k
        case '-':
639
46.3k
            return mp11::mp_with_index<3>(
640
46.3k
                static_cast<unsigned char>(opt_.numbers),
641
46.3k
                parse_number_helper<true, '-'>{ this, p });
642
54.1k
        case '1': case '2': case '3':
643
97.6k
        case '4': case '5': case '6':
644
123k
        case '7': case '8': case '9':
645
123k
            return mp11::mp_with_index<3>(
646
123k
                static_cast<unsigned char>(opt_.numbers),
647
123k
                parse_number_helper<true, '+'>{ this, p });
648
1.49k
        case 'n':
649
1.49k
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
3.30k
        case 't':
651
3.30k
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
2.20k
        case 'f':
653
2.20k
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
2
        case 'I':
655
2
            if( !opt_.allow_infinity_and_nan )
656
2
            {
657
2
                BOOST_STATIC_CONSTEXPR source_location loc
658
2
                    = BOOST_CURRENT_LOCATION;
659
2
                return fail(p, error::syntax, &loc);
660
2
            }
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
17.8k
        case '"':
671
17.8k
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
19.4k
        case '[':
673
19.4k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
13.1k
        case '{':
675
13.1k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
4
        case '/':
677
4
            if(! allow_comments)
678
4
            {
679
4
                BOOST_STATIC_CONSTEXPR source_location loc
680
4
                    = BOOST_CURRENT_LOCATION;
681
4
                return fail(p, error::syntax, &loc);
682
4
            }
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
            // intentional 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
430
        default:
699
430
            {
700
430
                BOOST_STATIC_CONSTEXPR source_location loc
701
430
                    = BOOST_CURRENT_LOCATION;
702
430
                return fail(p, error::syntax, &loc);
703
0
            }
704
248k
        }
705
248k
    }
706
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
248k
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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
212k
{
629
212k
    if(stack_empty || st_.empty())
630
212k
    {
631
212k
loop:
632
212k
        switch(*p)
633
212k
        {
634
15.0k
        case '0':
635
15.0k
            return mp11::mp_with_index<3>(
636
15.0k
                static_cast<unsigned char>(opt_.numbers),
637
15.0k
                parse_number_helper<true, '0'>{ this, p });
638
37.5k
        case '-':
639
37.5k
            return mp11::mp_with_index<3>(
640
37.5k
                static_cast<unsigned char>(opt_.numbers),
641
37.5k
                parse_number_helper<true, '-'>{ this, p });
642
49.3k
        case '1': case '2': case '3':
643
89.5k
        case '4': case '5': case '6':
644
110k
        case '7': case '8': case '9':
645
110k
            return mp11::mp_with_index<3>(
646
110k
                static_cast<unsigned char>(opt_.numbers),
647
110k
                parse_number_helper<true, '+'>{ this, p });
648
1.05k
        case 'n':
649
1.05k
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
3.02k
        case 't':
651
3.02k
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
1.90k
        case 'f':
653
1.90k
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
1
        case 'I':
655
1
            if( !opt_.allow_infinity_and_nan )
656
1
            {
657
1
                BOOST_STATIC_CONSTEXPR source_location loc
658
1
                    = BOOST_CURRENT_LOCATION;
659
1
                return fail(p, error::syntax, &loc);
660
1
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
1
        case 'N':
663
1
            if( !opt_.allow_infinity_and_nan )
664
1
            {
665
1
                BOOST_STATIC_CONSTEXPR source_location loc
666
1
                    = BOOST_CURRENT_LOCATION;
667
1
                return fail(p, error::syntax, &loc);
668
1
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
16.0k
        case '"':
671
16.0k
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
15.9k
        case '[':
673
15.9k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
11.3k
        case '{':
675
11.3k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
2
        case '/':
677
2
            if(! allow_comments)
678
2
            {
679
2
                BOOST_STATIC_CONSTEXPR source_location loc
680
2
                    = BOOST_CURRENT_LOCATION;
681
2
                return fail(p, error::syntax, &loc);
682
2
            }
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
            // intentional 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
212
        default:
699
212
            {
700
212
                BOOST_STATIC_CONSTEXPR source_location loc
701
212
                    = BOOST_CURRENT_LOCATION;
702
212
                return fail(p, error::syntax, &loc);
703
0
            }
704
212k
        }
705
212k
    }
706
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
212k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_value<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_value<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_value<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool, bool)
char const* boost::json::basic_parser<null_parser::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
36.2k
{
629
36.2k
    if(stack_empty || st_.empty())
630
36.2k
    {
631
36.2k
loop:
632
36.2k
        switch(*p)
633
36.2k
        {
634
6.15k
        case '0':
635
6.15k
            return mp11::mp_with_index<3>(
636
6.15k
                static_cast<unsigned char>(opt_.numbers),
637
6.15k
                parse_number_helper<true, '0'>{ this, p });
638
8.75k
        case '-':
639
8.75k
            return mp11::mp_with_index<3>(
640
8.75k
                static_cast<unsigned char>(opt_.numbers),
641
8.75k
                parse_number_helper<true, '-'>{ this, p });
642
4.83k
        case '1': case '2': case '3':
643
8.06k
        case '4': case '5': case '6':
644
13.0k
        case '7': case '8': case '9':
645
13.0k
            return mp11::mp_with_index<3>(
646
13.0k
                static_cast<unsigned char>(opt_.numbers),
647
13.0k
                parse_number_helper<true, '+'>{ this, p });
648
441
        case 'n':
649
441
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650
281
        case 't':
651
281
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652
307
        case 'f':
653
307
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654
1
        case 'I':
655
1
            if( !opt_.allow_infinity_and_nan )
656
1
            {
657
1
                BOOST_STATIC_CONSTEXPR source_location loc
658
1
                    = BOOST_CURRENT_LOCATION;
659
1
                return fail(p, error::syntax, &loc);
660
1
            }
661
0
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662
3
        case 'N':
663
3
            if( !opt_.allow_infinity_and_nan )
664
3
            {
665
3
                BOOST_STATIC_CONSTEXPR source_location loc
666
3
                    = BOOST_CURRENT_LOCATION;
667
3
                return fail(p, error::syntax, &loc);
668
3
            }
669
0
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670
1.75k
        case '"':
671
1.75k
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672
3.44k
        case '[':
673
3.44k
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674
1.83k
        case '{':
675
1.83k
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676
2
        case '/':
677
2
            if(! allow_comments)
678
2
            {
679
2
                BOOST_STATIC_CONSTEXPR source_location loc
680
2
                    = BOOST_CURRENT_LOCATION;
681
2
                return fail(p, error::syntax, &loc);
682
2
            }
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
            // intentional 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
218
        default:
699
218
            {
700
218
                BOOST_STATIC_CONSTEXPR source_location loc
701
218
                    = BOOST_CURRENT_LOCATION;
702
218
                return fail(p, error::syntax, &loc);
703
0
            }
704
36.2k
        }
705
36.2k
    }
706
0
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707
36.2k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_value<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_value<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_value<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool, bool)
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
0
{
722
0
    state st;
723
0
    st_.peek(st);
724
0
    switch(st)
725
0
    {
726
0
    default: BOOST_JSON_UNREACHABLE();
727
0
    case state::lit1:
728
0
        return parse_literal(p,  detail::literals_c<detail::literals::resume>() );
729
730
0
    case state::str1: case state::str2:
731
0
    case state::str8:
732
0
        return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733
734
0
    case state::arr1: case state::arr2:
735
0
    case state::arr3: case state::arr4:
736
0
    case state::arr5: case state::arr6:
737
0
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738
739
0
    case state::obj1: case state::obj2:
740
0
    case state::obj3: case state::obj4:
741
0
    case state::obj5: case state::obj6:
742
0
    case state::obj7: case state::obj8:
743
0
    case state::obj9: case state::obj10:
744
0
    case state::obj11:
745
0
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746
747
0
    case state::num1: case state::num2:
748
0
    case state::num3: case state::num4:
749
0
    case state::num5: case state::num6:
750
0
    case state::num7: case state::num8:
751
0
    case state::exp1: case state::exp2:
752
0
    case state::exp3:
753
0
        return mp11::mp_with_index<3>(
754
0
            static_cast<unsigned char>(opt_.numbers),
755
0
            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
0
    }
786
0
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::resume_value<false>(char const*, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::resume_value<true>(char const*, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::resume_value<false>(char const*, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::resume_value<true>(char const*, std::__1::integral_constant<bool, true>, bool, bool, bool)
787
788
template<class Handler>
789
template<class Literal>
790
const char*
791
basic_parser<Handler>::
792
parse_literal(const char* p, Literal)
793
7.01k
{
794
7.01k
    using L = detail::literals;
795
796
7.01k
    std::size_t cur_lit;
797
7.01k
    std::size_t offset;
798
799
7.01k
    detail::const_stream_wrapper cs(p, end_);
800
7.01k
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
7.01k
    {
802
7.01k
        constexpr std::size_t index = literal_index(Literal::value);
803
7.01k
        constexpr char const* literal = detail::literal_strings[index];
804
7.01k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
7.01k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
6.84k
        {
808
6.84k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
6.84k
            if( cmp != 0 )
810
92
            {
811
92
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
92
                return fail(cs.begin(), error::syntax, &loc);
813
92
            }
814
815
6.75k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
1.42k
            {
817
1.42k
                if(BOOST_JSON_UNLIKELY(
818
1.42k
                    ! h_.on_null(ec_)))
819
50
                    return fail(cs.begin());
820
1.42k
            }
821
5.33k
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
3.23k
            {
823
3.23k
                if(BOOST_JSON_UNLIKELY(
824
3.23k
                    ! h_.on_bool(true, ec_)))
825
42
                    return fail(cs.begin());
826
3.23k
            }
827
2.09k
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
2.09k
            {
829
2.09k
                if(BOOST_JSON_UNLIKELY(
830
2.09k
                    ! h_.on_bool(false, ec_)))
831
6
                    return fail(cs.begin());
832
2.09k
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
6.65k
            cs += sz;
866
6.65k
            return cs.begin();
867
6.75k
        }
868
869
166
        offset = 0;
870
166
        cur_lit = index;
871
166
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
166
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
166
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
166
    int cmp = 0;
885
166
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
166
        cmp = std::memcmp(
887
166
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
166
    if( cmp != 0 )
889
131
    {
890
131
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
131
        return fail(cs.begin(), error::syntax, &loc);
892
131
    }
893
894
35
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
35
    {
896
35
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
35
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
35
        return maybe_suspend(cs.begin() + size, state::lit1);
901
35
    }
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
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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>)
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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
1.05k
{
794
1.05k
    using L = detail::literals;
795
796
1.05k
    std::size_t cur_lit;
797
1.05k
    std::size_t offset;
798
799
1.05k
    detail::const_stream_wrapper cs(p, end_);
800
1.05k
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
1.05k
    {
802
1.05k
        constexpr std::size_t index = literal_index(Literal::value);
803
1.05k
        constexpr char const* literal = detail::literal_strings[index];
804
1.05k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
1.05k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
1.03k
        {
808
1.03k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
1.03k
            if( cmp != 0 )
810
12
            {
811
12
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
12
                return fail(cs.begin(), error::syntax, &loc);
813
12
            }
814
815
1.01k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
1.01k
            {
817
1.01k
                if(BOOST_JSON_UNLIKELY(
818
1.01k
                    ! h_.on_null(ec_)))
819
50
                    return fail(cs.begin());
820
1.01k
            }
821
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
0
            {
823
0
                if(BOOST_JSON_UNLIKELY(
824
0
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
0
            }
827
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
0
            {
829
0
                if(BOOST_JSON_UNLIKELY(
830
0
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
0
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
968
            cs += sz;
866
968
            return cs.begin();
867
1.01k
        }
868
869
24
        offset = 0;
870
24
        cur_lit = index;
871
24
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
24
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
24
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
24
    int cmp = 0;
885
24
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
24
        cmp = std::memcmp(
887
24
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
24
    if( cmp != 0 )
889
22
    {
890
22
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
22
        return fail(cs.begin(), error::syntax, &loc);
892
22
    }
893
894
2
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
2
    {
896
2
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
2
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
2
        return maybe_suspend(cs.begin() + size, state::lit1);
901
2
    }
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::into_handler<Object> >::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
3.02k
{
794
3.02k
    using L = detail::literals;
795
796
3.02k
    std::size_t cur_lit;
797
3.02k
    std::size_t offset;
798
799
3.02k
    detail::const_stream_wrapper cs(p, end_);
800
3.02k
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
3.02k
    {
802
3.02k
        constexpr std::size_t index = literal_index(Literal::value);
803
3.02k
        constexpr char const* literal = detail::literal_strings[index];
804
3.02k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
3.02k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
2.99k
        {
808
2.99k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
2.99k
            if( cmp != 0 )
810
15
            {
811
15
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
15
                return fail(cs.begin(), error::syntax, &loc);
813
15
            }
814
815
2.97k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
0
            {
817
0
                if(BOOST_JSON_UNLIKELY(
818
0
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
0
            }
821
2.97k
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
2.97k
            {
823
2.97k
                if(BOOST_JSON_UNLIKELY(
824
2.97k
                    ! h_.on_bool(true, ec_)))
825
42
                    return fail(cs.begin());
826
2.97k
            }
827
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
0
            {
829
0
                if(BOOST_JSON_UNLIKELY(
830
0
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
0
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
2.93k
            cs += sz;
866
2.93k
            return cs.begin();
867
2.97k
        }
868
869
36
        offset = 0;
870
36
        cur_lit = index;
871
36
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
36
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
36
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
36
    int cmp = 0;
885
36
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
36
        cmp = std::memcmp(
887
36
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
36
    if( cmp != 0 )
889
33
    {
890
33
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
33
        return fail(cs.begin(), error::syntax, &loc);
892
33
    }
893
894
3
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
3
    {
896
3
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
3
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
3
        return maybe_suspend(cs.begin() + size, state::lit1);
901
3
    }
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::into_handler<Object> >::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
1.90k
{
794
1.90k
    using L = detail::literals;
795
796
1.90k
    std::size_t cur_lit;
797
1.90k
    std::size_t offset;
798
799
1.90k
    detail::const_stream_wrapper cs(p, end_);
800
1.90k
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
1.90k
    {
802
1.90k
        constexpr std::size_t index = literal_index(Literal::value);
803
1.90k
        constexpr char const* literal = detail::literal_strings[index];
804
1.90k
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
1.90k
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
1.86k
        {
808
1.86k
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
1.86k
            if( cmp != 0 )
810
21
            {
811
21
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
21
                return fail(cs.begin(), error::syntax, &loc);
813
21
            }
814
815
1.84k
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
0
            {
817
0
                if(BOOST_JSON_UNLIKELY(
818
0
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
0
            }
821
1.84k
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
0
            {
823
0
                if(BOOST_JSON_UNLIKELY(
824
0
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
0
            }
827
1.84k
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
1.84k
            {
829
1.84k
                if(BOOST_JSON_UNLIKELY(
830
1.84k
                    ! h_.on_bool(false, ec_)))
831
6
                    return fail(cs.begin());
832
1.84k
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
1.83k
            cs += sz;
866
1.83k
            return cs.begin();
867
1.84k
        }
868
869
39
        offset = 0;
870
39
        cur_lit = index;
871
39
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
39
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
39
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
39
    int cmp = 0;
885
39
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
39
        cmp = std::memcmp(
887
39
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
39
    if( cmp != 0 )
889
34
    {
890
34
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
34
        return fail(cs.begin(), error::syntax, &loc);
892
34
    }
893
894
5
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
5
    {
896
5
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
5
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
5
        return maybe_suspend(cs.begin() + size, state::lit1);
901
5
    }
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
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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::into_handler<Object> >::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::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>)
char const* boost::json::basic_parser<null_parser::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
441
{
794
441
    using L = detail::literals;
795
796
441
    std::size_t cur_lit;
797
441
    std::size_t offset;
798
799
441
    detail::const_stream_wrapper cs(p, end_);
800
441
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
441
    {
802
441
        constexpr std::size_t index = literal_index(Literal::value);
803
441
        constexpr char const* literal = detail::literal_strings[index];
804
441
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
441
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
415
        {
808
415
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
415
            if( cmp != 0 )
810
10
            {
811
10
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
10
                return fail(cs.begin(), error::syntax, &loc);
813
10
            }
814
815
405
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
405
            {
817
405
                if(BOOST_JSON_UNLIKELY(
818
405
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
405
            }
821
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
0
            {
823
0
                if(BOOST_JSON_UNLIKELY(
824
0
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
0
            }
827
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
0
            {
829
0
                if(BOOST_JSON_UNLIKELY(
830
0
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
0
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
405
            cs += sz;
866
405
            return cs.begin();
867
405
        }
868
869
26
        offset = 0;
870
26
        cur_lit = index;
871
26
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
26
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
26
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
26
    int cmp = 0;
885
26
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
26
        cmp = std::memcmp(
887
26
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
26
    if( cmp != 0 )
889
18
    {
890
18
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
18
        return fail(cs.begin(), error::syntax, &loc);
892
18
    }
893
894
8
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
8
    {
896
8
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
8
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
8
        return maybe_suspend(cs.begin() + size, state::lit1);
901
8
    }
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<null_parser::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
281
{
794
281
    using L = detail::literals;
795
796
281
    std::size_t cur_lit;
797
281
    std::size_t offset;
798
799
281
    detail::const_stream_wrapper cs(p, end_);
800
281
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
281
    {
802
281
        constexpr std::size_t index = literal_index(Literal::value);
803
281
        constexpr char const* literal = detail::literal_strings[index];
804
281
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
281
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
262
        {
808
262
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
262
            if( cmp != 0 )
810
6
            {
811
6
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
6
                return fail(cs.begin(), error::syntax, &loc);
813
6
            }
814
815
256
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
0
            {
817
0
                if(BOOST_JSON_UNLIKELY(
818
0
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
0
            }
821
256
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
256
            {
823
256
                if(BOOST_JSON_UNLIKELY(
824
256
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
256
            }
827
0
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
0
            {
829
0
                if(BOOST_JSON_UNLIKELY(
830
0
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
0
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
256
            cs += sz;
866
256
            return cs.begin();
867
256
        }
868
869
19
        offset = 0;
870
19
        cur_lit = index;
871
19
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
19
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
19
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
19
    int cmp = 0;
885
19
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
19
        cmp = std::memcmp(
887
19
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
19
    if( cmp != 0 )
889
10
    {
890
10
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
10
        return fail(cs.begin(), error::syntax, &loc);
892
10
    }
893
894
9
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
9
    {
896
9
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
9
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
9
        return maybe_suspend(cs.begin() + size, state::lit1);
901
9
    }
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<null_parser::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
307
{
794
307
    using L = detail::literals;
795
796
307
    std::size_t cur_lit;
797
307
    std::size_t offset;
798
799
307
    detail::const_stream_wrapper cs(p, end_);
800
307
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801
307
    {
802
307
        constexpr std::size_t index = literal_index(Literal::value);
803
307
        constexpr char const* literal = detail::literal_strings[index];
804
307
        constexpr std::size_t sz = detail::literal_sizes[index];
805
806
307
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807
285
        {
808
285
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809
285
            if( cmp != 0 )
810
28
            {
811
28
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812
28
                return fail(cs.begin(), error::syntax, &loc);
813
28
            }
814
815
257
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816
0
            {
817
0
                if(BOOST_JSON_UNLIKELY(
818
0
                    ! h_.on_null(ec_)))
819
0
                    return fail(cs.begin());
820
0
            }
821
257
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822
0
            {
823
0
                if(BOOST_JSON_UNLIKELY(
824
0
                    ! h_.on_bool(true, ec_)))
825
0
                    return fail(cs.begin());
826
0
            }
827
257
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828
257
            {
829
257
                if(BOOST_JSON_UNLIKELY(
830
257
                    ! h_.on_bool(false, ec_)))
831
0
                    return fail(cs.begin());
832
257
            }
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
0
            }
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
0
            }
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
0
            }
860
0
            else
861
0
            {
862
0
                BOOST_JSON_UNREACHABLE();
863
0
            }
864
865
257
            cs += sz;
866
257
            return cs.begin();
867
257
        }
868
869
22
        offset = 0;
870
22
        cur_lit = index;
871
22
    }
872
0
    else
873
0
    {
874
0
        state st;
875
0
        st_.pop(st);
876
0
        BOOST_ASSERT( st == state::lit1 );
877
878
0
        cur_lit = cur_lit_;
879
0
        offset = lit_offset_;
880
0
    }
881
882
22
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883
22
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884
22
    int cmp = 0;
885
22
    if(BOOST_JSON_LIKELY( cs.begin() ))
886
22
        cmp = std::memcmp(
887
22
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888
22
    if( cmp != 0 )
889
14
    {
890
14
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891
14
        return fail(cs.begin(), error::syntax, &loc);
892
14
    }
893
894
8
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895
8
    {
896
8
        BOOST_ASSERT( cur_lit < 256 );
897
0
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898
8
        BOOST_ASSERT( offset + size < 256 );
899
0
        lit_offset_ = static_cast<unsigned char>( offset + size );
900
8
        return maybe_suspend(cs.begin() + size, state::lit1);
901
8
    }
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
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::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<null_parser::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
116k
{
969
116k
    detail::const_stream_wrapper cs(p, end_);
970
116k
    std::size_t total;
971
116k
    char const* start;
972
116k
    std::size_t size;
973
116k
    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
116k
    else
987
116k
    {
988
116k
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
116k
        total = 0;
991
116k
    }
992
993
144k
do_str1:
994
144k
    start = cs.begin();
995
144k
    cs = allow_bad_utf8?
996
0
        detail::count_valid<true>(cs.begin(), cs.end()):
997
144k
        detail::count_valid<false>(cs.begin(), cs.end());
998
144k
    size = cs.used(start);
999
144k
    if(is_key)
1000
108k
    {
1001
108k
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
108k
        if(BOOST_JSON_UNLIKELY(size >
1003
108k
            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
108k
    }
1010
35.6k
    else
1011
35.6k
    {
1012
35.6k
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
35.6k
        if(BOOST_JSON_UNLIKELY(size >
1014
35.6k
            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
35.6k
    }
1021
144k
    total += size;
1022
144k
    if(BOOST_JSON_UNLIKELY(! cs))
1023
892
    {
1024
        // call handler if the string isn't empty
1025
892
        if(BOOST_JSON_LIKELY(size))
1026
474
        {
1027
474
            {
1028
474
                bool r = is_key?
1029
177
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
474
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
474
                if(BOOST_JSON_UNLIKELY(!r))
1033
92
                {
1034
92
                    return fail(cs.begin());
1035
92
                }
1036
474
            }
1037
474
        }
1038
800
        return maybe_suspend(cs.begin(), state::str1, total);
1039
892
    }
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
143k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
30.0k
    {
1045
        // sequence is invalid or incomplete
1046
30.0k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
537
        {
1048
537
            seq_.save(cs.begin(), cs.remain());
1049
537
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
494
            {
1051
494
                BOOST_STATIC_CONSTEXPR source_location loc
1052
494
                    = BOOST_CURRENT_LOCATION;
1053
494
                return fail(cs.begin(), error::syntax, &loc);
1054
494
            }
1055
43
            if(BOOST_JSON_LIKELY(size))
1056
23
            {
1057
23
                bool const r = is_key?
1058
13
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
23
                    h_.on_string_part( {start, size}, total, ec_ );
1060
23
                if(BOOST_JSON_UNLIKELY( !r ))
1061
6
                    return fail( cs.begin() );
1062
23
            }
1063
37
            return maybe_suspend(cs.end(), state::str8, total);
1064
43
        }
1065
29.4k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
29.3k
        {
1067
            // flush unescaped run from input
1068
29.3k
            if(BOOST_JSON_LIKELY(size))
1069
25.8k
            {
1070
25.8k
                bool const r = is_key?
1071
9.68k
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
25.8k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
25.8k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
3
                    return fail( cs.begin() );
1075
25.8k
            }
1076
29.3k
do_str2:
1077
29.3k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
29.3k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
1.23k
                return suspend_or_fail(state::str2, total);
1080
1081
28.0k
            goto do_str1;
1082
29.3k
        }
1083
        // illegal control
1084
169
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
169
        return fail(cs.begin(), error::syntax, &loc);
1086
30.0k
    }
1087
1088
113k
    {
1089
113k
        bool r = is_key?
1090
97.4k
            h_.on_key( {start, size}, total, ec_ ):
1091
113k
            h_.on_string( {start, size}, total, ec_ );
1092
1093
113k
        if(BOOST_JSON_UNLIKELY(!r))
1094
54
        {
1095
54
            return fail(cs.begin());
1096
54
        }
1097
113k
    }
1098
1099
113k
    ++cs;
1100
113k
    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
        bool const r = is_key?
1113
0
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114
0
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115
0
        if(BOOST_JSON_UNLIKELY( !r ))
1116
0
            return fail( cs.begin() );
1117
0
    }
1118
0
    cs += needed;
1119
0
    goto do_str1;
1120
0
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_string<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool, bool)
Line
Count
Source
968
16.0k
{
969
16.0k
    detail::const_stream_wrapper cs(p, end_);
970
16.0k
    std::size_t total;
971
16.0k
    char const* start;
972
16.0k
    std::size_t size;
973
16.0k
    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
16.0k
    else
987
16.0k
    {
988
16.0k
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
16.0k
        total = 0;
991
16.0k
    }
992
993
31.3k
do_str1:
994
31.3k
    start = cs.begin();
995
31.3k
    cs = allow_bad_utf8?
996
0
        detail::count_valid<true>(cs.begin(), cs.end()):
997
31.3k
        detail::count_valid<false>(cs.begin(), cs.end());
998
31.3k
    size = cs.used(start);
999
31.3k
    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
31.3k
    else
1011
31.3k
    {
1012
31.3k
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
31.3k
        if(BOOST_JSON_UNLIKELY(size >
1014
31.3k
            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
31.3k
    }
1021
31.3k
    total += size;
1022
31.3k
    if(BOOST_JSON_UNLIKELY(! cs))
1023
248
    {
1024
        // call handler if the string isn't empty
1025
248
        if(BOOST_JSON_LIKELY(size))
1026
204
        {
1027
204
            {
1028
204
                bool r = is_key?
1029
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
204
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
204
                if(BOOST_JSON_UNLIKELY(!r))
1033
92
                {
1034
92
                    return fail(cs.begin());
1035
92
                }
1036
204
            }
1037
204
        }
1038
156
        return maybe_suspend(cs.begin(), state::str1, total);
1039
248
    }
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
31.1k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
15.9k
    {
1045
        // sequence is invalid or incomplete
1046
15.9k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
145
        {
1048
145
            seq_.save(cs.begin(), cs.remain());
1049
145
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
130
            {
1051
130
                BOOST_STATIC_CONSTEXPR source_location loc
1052
130
                    = BOOST_CURRENT_LOCATION;
1053
130
                return fail(cs.begin(), error::syntax, &loc);
1054
130
            }
1055
15
            if(BOOST_JSON_LIKELY(size))
1056
9
            {
1057
9
                bool const r = is_key?
1058
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
9
                    h_.on_string_part( {start, size}, total, ec_ );
1060
9
                if(BOOST_JSON_UNLIKELY( !r ))
1061
6
                    return fail( cs.begin() );
1062
9
            }
1063
9
            return maybe_suspend(cs.end(), state::str8, total);
1064
15
        }
1065
15.7k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
15.7k
        {
1067
            // flush unescaped run from input
1068
15.7k
            if(BOOST_JSON_LIKELY(size))
1069
14.3k
            {
1070
14.3k
                bool const r = is_key?
1071
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
14.3k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
14.3k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
3
                    return fail( cs.begin() );
1075
14.3k
            }
1076
15.7k
do_str2:
1077
15.7k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
15.7k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
441
                return suspend_or_fail(state::str2, total);
1080
1081
15.2k
            goto do_str1;
1082
15.7k
        }
1083
        // illegal control
1084
36
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
36
        return fail(cs.begin(), error::syntax, &loc);
1086
15.9k
    }
1087
1088
15.2k
    {
1089
15.2k
        bool r = is_key?
1090
0
            h_.on_key( {start, size}, total, ec_ ):
1091
15.2k
            h_.on_string( {start, size}, total, ec_ );
1092
1093
15.2k
        if(BOOST_JSON_UNLIKELY(!r))
1094
54
        {
1095
54
            return fail(cs.begin());
1096
54
        }
1097
15.2k
    }
1098
1099
15.1k
    ++cs;
1100
15.1k
    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
        bool const r = is_key?
1113
0
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114
0
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115
0
        if(BOOST_JSON_UNLIKELY( !r ))
1116
0
            return fail( cs.begin() );
1117
0
    }
1118
0
    cs += needed;
1119
0
    goto do_str1;
1120
0
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_string<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
968
95.8k
{
969
95.8k
    detail::const_stream_wrapper cs(p, end_);
970
95.8k
    std::size_t total;
971
95.8k
    char const* start;
972
95.8k
    std::size_t size;
973
95.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
95.8k
    else
987
95.8k
    {
988
95.8k
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
95.8k
        total = 0;
991
95.8k
    }
992
993
105k
do_str1:
994
105k
    start = cs.begin();
995
105k
    cs = allow_bad_utf8?
996
0
        detail::count_valid<true>(cs.begin(), cs.end()):
997
105k
        detail::count_valid<false>(cs.begin(), cs.end());
998
105k
    size = cs.used(start);
999
105k
    if(is_key)
1000
105k
    {
1001
105k
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
105k
        if(BOOST_JSON_UNLIKELY(size >
1003
105k
            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
105k
    }
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
105k
    total += size;
1022
105k
    if(BOOST_JSON_UNLIKELY(! cs))
1023
203
    {
1024
        // call handler if the string isn't empty
1025
203
        if(BOOST_JSON_LIKELY(size))
1026
132
        {
1027
132
            {
1028
132
                bool r = is_key?
1029
132
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
132
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
132
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
132
            }
1037
132
        }
1038
203
        return maybe_suspend(cs.begin(), state::str1, total);
1039
203
    }
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
105k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
10.0k
    {
1045
        // sequence is invalid or incomplete
1046
10.0k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
159
        {
1048
159
            seq_.save(cs.begin(), cs.remain());
1049
159
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
140
            {
1051
140
                BOOST_STATIC_CONSTEXPR source_location loc
1052
140
                    = BOOST_CURRENT_LOCATION;
1053
140
                return fail(cs.begin(), error::syntax, &loc);
1054
140
            }
1055
19
            if(BOOST_JSON_LIKELY(size))
1056
13
            {
1057
13
                bool const r = is_key?
1058
13
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
13
                    h_.on_string_part( {start, size}, total, ec_ );
1060
13
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
13
            }
1063
19
            return maybe_suspend(cs.end(), state::str8, total);
1064
19
        }
1065
9.90k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
9.82k
        {
1067
            // flush unescaped run from input
1068
9.82k
            if(BOOST_JSON_LIKELY(size))
1069
9.05k
            {
1070
9.05k
                bool const r = is_key?
1071
9.05k
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
9.05k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
9.05k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
9.05k
            }
1076
9.82k
do_str2:
1077
9.82k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
9.82k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
164
                return suspend_or_fail(state::str2, total);
1080
1081
9.66k
            goto do_str1;
1082
9.82k
        }
1083
        // illegal control
1084
82
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
82
        return fail(cs.begin(), error::syntax, &loc);
1086
10.0k
    }
1087
1088
95.2k
    {
1089
95.2k
        bool r = is_key?
1090
95.2k
            h_.on_key( {start, size}, total, ec_ ):
1091
95.2k
            h_.on_string( {start, size}, total, ec_ );
1092
1093
95.2k
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
95.2k
    }
1098
1099
95.2k
    ++cs;
1100
95.2k
    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
        bool const r = is_key?
1113
0
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114
0
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115
0
        if(BOOST_JSON_UNLIKELY( !r ))
1116
0
            return fail( cs.begin() );
1117
0
    }
1118
0
    cs += needed;
1119
0
    goto do_str1;
1120
0
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_string<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_string<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool)
char const* boost::json::basic_parser<null_parser::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
1.75k
{
969
1.75k
    detail::const_stream_wrapper cs(p, end_);
970
1.75k
    std::size_t total;
971
1.75k
    char const* start;
972
1.75k
    std::size_t size;
973
1.75k
    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.75k
    else
987
1.75k
    {
988
1.75k
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
1.75k
        total = 0;
991
1.75k
    }
992
993
4.24k
do_str1:
994
4.24k
    start = cs.begin();
995
4.24k
    cs = allow_bad_utf8?
996
0
        detail::count_valid<true>(cs.begin(), cs.end()):
997
4.24k
        detail::count_valid<false>(cs.begin(), cs.end());
998
4.24k
    size = cs.used(start);
999
4.24k
    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
4.24k
    else
1011
4.24k
    {
1012
4.24k
        BOOST_ASSERT(total <= Handler::max_string_size);
1013
4.24k
        if(BOOST_JSON_UNLIKELY(size >
1014
4.24k
            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
4.24k
    }
1021
4.24k
    total += size;
1022
4.24k
    if(BOOST_JSON_UNLIKELY(! cs))
1023
372
    {
1024
        // call handler if the string isn't empty
1025
372
        if(BOOST_JSON_LIKELY(size))
1026
93
        {
1027
93
            {
1028
93
                bool r = is_key?
1029
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
93
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
93
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
93
            }
1037
93
        }
1038
372
        return maybe_suspend(cs.begin(), state::str1, total);
1039
372
    }
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
3.87k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
3.29k
    {
1045
        // sequence is invalid or incomplete
1046
3.29k
        if((*cs & 0x80) && !allow_bad_utf8)
1047
151
        {
1048
151
            seq_.save(cs.begin(), cs.remain());
1049
151
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
144
            {
1051
144
                BOOST_STATIC_CONSTEXPR source_location loc
1052
144
                    = BOOST_CURRENT_LOCATION;
1053
144
                return fail(cs.begin(), error::syntax, &loc);
1054
144
            }
1055
7
            if(BOOST_JSON_LIKELY(size))
1056
1
            {
1057
1
                bool const r = is_key?
1058
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1059
1
                    h_.on_string_part( {start, size}, total, ec_ );
1060
1
                if(BOOST_JSON_UNLIKELY( !r ))
1061
0
                    return fail( cs.begin() );
1062
1
            }
1063
7
            return maybe_suspend(cs.end(), state::str8, total);
1064
7
        }
1065
3.14k
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
3.10k
        {
1067
            // flush unescaped run from input
1068
3.10k
            if(BOOST_JSON_LIKELY(size))
1069
1.78k
            {
1070
1.78k
                bool const r = is_key?
1071
0
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
1.78k
                    h_.on_string_part( {start, size}, total, ec_ );
1073
1.78k
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
1.78k
            }
1076
3.10k
do_str2:
1077
3.10k
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
3.10k
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
617
                return suspend_or_fail(state::str2, total);
1080
1081
2.49k
            goto do_str1;
1082
3.10k
        }
1083
        // illegal control
1084
37
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
37
        return fail(cs.begin(), error::syntax, &loc);
1086
3.29k
    }
1087
1088
578
    {
1089
578
        bool r = is_key?
1090
0
            h_.on_key( {start, size}, total, ec_ ):
1091
578
            h_.on_string( {start, size}, total, ec_ );
1092
1093
578
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
578
    }
1098
1099
578
    ++cs;
1100
578
    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
        bool const r = is_key?
1113
0
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114
0
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115
0
        if(BOOST_JSON_UNLIKELY( !r ))
1116
0
            return fail( cs.begin() );
1117
0
    }
1118
0
    cs += needed;
1119
0
    goto do_str1;
1120
0
}
char const* boost::json::basic_parser<null_parser::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
2.33k
{
969
2.33k
    detail::const_stream_wrapper cs(p, end_);
970
2.33k
    std::size_t total;
971
2.33k
    char const* start;
972
2.33k
    std::size_t size;
973
2.33k
    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
2.33k
    else
987
2.33k
    {
988
2.33k
        BOOST_ASSERT(*cs == '\x22'); // '"'
989
0
        ++cs;
990
2.33k
        total = 0;
991
2.33k
    }
992
993
2.98k
do_str1:
994
2.98k
    start = cs.begin();
995
2.98k
    cs = allow_bad_utf8?
996
0
        detail::count_valid<true>(cs.begin(), cs.end()):
997
2.98k
        detail::count_valid<false>(cs.begin(), cs.end());
998
2.98k
    size = cs.used(start);
999
2.98k
    if(is_key)
1000
2.98k
    {
1001
2.98k
        BOOST_ASSERT(total <= Handler::max_key_size);
1002
2.98k
        if(BOOST_JSON_UNLIKELY(size >
1003
2.98k
            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
2.98k
    }
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
2.98k
    total += size;
1022
2.98k
    if(BOOST_JSON_UNLIKELY(! cs))
1023
69
    {
1024
        // call handler if the string isn't empty
1025
69
        if(BOOST_JSON_LIKELY(size))
1026
45
        {
1027
45
            {
1028
45
                bool r = is_key?
1029
45
                    h_.on_key_part( {start, size}, total, ec_ ):
1030
45
                    h_.on_string_part( {start, size}, total, ec_ );
1031
1032
45
                if(BOOST_JSON_UNLIKELY(!r))
1033
0
                {
1034
0
                    return fail(cs.begin());
1035
0
                }
1036
45
            }
1037
45
        }
1038
69
        return maybe_suspend(cs.begin(), state::str1, total);
1039
69
    }
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.91k
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044
752
    {
1045
        // sequence is invalid or incomplete
1046
752
        if((*cs & 0x80) && !allow_bad_utf8)
1047
82
        {
1048
82
            seq_.save(cs.begin(), cs.remain());
1049
82
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050
80
            {
1051
80
                BOOST_STATIC_CONSTEXPR source_location loc
1052
80
                    = BOOST_CURRENT_LOCATION;
1053
80
                return fail(cs.begin(), error::syntax, &loc);
1054
80
            }
1055
2
            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
2
            return maybe_suspend(cs.end(), state::str8, total);
1064
2
        }
1065
670
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066
656
        {
1067
            // flush unescaped run from input
1068
656
            if(BOOST_JSON_LIKELY(size))
1069
625
            {
1070
625
                bool const r = is_key?
1071
625
                    h_.on_key_part( {start, size}, total, ec_ ):
1072
625
                    h_.on_string_part( {start, size}, total, ec_ );
1073
625
                if(BOOST_JSON_UNLIKELY( !r ))
1074
0
                    return fail( cs.begin() );
1075
625
            }
1076
656
do_str2:
1077
656
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078
656
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079
12
                return suspend_or_fail(state::str2, total);
1080
1081
644
            goto do_str1;
1082
656
        }
1083
        // illegal control
1084
14
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085
14
        return fail(cs.begin(), error::syntax, &loc);
1086
752
    }
1087
1088
2.16k
    {
1089
2.16k
        bool r = is_key?
1090
2.16k
            h_.on_key( {start, size}, total, ec_ ):
1091
2.16k
            h_.on_string( {start, size}, total, ec_ );
1092
1093
2.16k
        if(BOOST_JSON_UNLIKELY(!r))
1094
0
        {
1095
0
            return fail(cs.begin());
1096
0
        }
1097
2.16k
    }
1098
1099
2.16k
    ++cs;
1100
2.16k
    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
        bool const r = is_key?
1113
0
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114
0
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115
0
        if(BOOST_JSON_UNLIKELY( !r ))
1116
0
            return fail( cs.begin() );
1117
0
    }
1118
0
    cs += needed;
1119
0
    goto do_str1;
1120
0
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_string<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_string<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool)
1121
1122
template<class Handler>
1123
template<bool StackEmpty_>
1124
const char*
1125
basic_parser<Handler>::
1126
parse_escaped(
1127
    const char* p,
1128
    std::size_t& total,
1129
    std::integral_constant<bool, StackEmpty_> stack_empty,
1130
    bool is_key,
1131
    bool allow_bad_utf16)
1132
29.3k
{
1133
29.3k
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1134
29.3k
    auto const ev_too_large = is_key?
1135
18.8k
        error::key_too_large : error::string_too_large;
1136
29.3k
    auto const max_size = is_key?
1137
18.8k
        Handler::max_key_size : Handler::max_string_size;
1138
29.3k
    int digit;
1139
1140
    //---------------------------------------------------------------
1141
    //
1142
    // To handle escapes, a local temporary buffer accumulates
1143
    // the unescaped result. The algorithm attempts to fill the
1144
    // buffer to capacity before invoking the handler.
1145
    // In some cases the temporary buffer needs to be flushed
1146
    // before it is full:
1147
    // * When the closing double quote is seen
1148
    // * When there in no more input (and more is expected later)
1149
    // A goal of the algorithm is to call the handler as few times
1150
    // as possible. Thus, when the first escape is encountered,
1151
    // the algorithm attempts to fill the temporary buffer first.
1152
    //
1153
29.3k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1154
1155
    // Unescaped JSON is never larger than its escaped version.
1156
    // To efficiently process only what will fit in the temporary buffer,
1157
    // the size of the input stream is temporarily "clipped" to the size
1158
    // of the temporary buffer.
1159
    // handle escaped character
1160
29.3k
    detail::clipped_const_stream cs(p, end_);
1161
29.3k
    cs.clip(temp.max_size());
1162
1163
29.3k
    if(! stack_empty && ! st_.empty())
1164
0
    {
1165
0
        state st;
1166
0
        st_.pop(st);
1167
0
        switch(st)
1168
0
        {
1169
0
        default: BOOST_JSON_UNREACHABLE();
1170
0
        case state::str3: goto do_str3;
1171
0
        case state::str4: goto do_str4;
1172
0
        case state::str5: goto do_str5;
1173
0
        case state::str6: goto do_str6;
1174
0
        case state::str7: goto do_str7;
1175
0
        case state::sur1: goto do_sur1;
1176
0
        case state::sur2: goto do_sur2;
1177
0
        case state::sur3: goto do_sur3;
1178
0
        case state::sur4: goto do_sur4;
1179
0
        case state::sur5: goto do_sur5;
1180
0
        case state::sur6: goto do_sur6;
1181
0
        }
1182
0
    }
1183
1184
5.69M
    while(true)
1185
5.69M
    {
1186
5.69M
        BOOST_ASSERT( temp.capacity() );
1187
5.69M
        BOOST_ASSERT(*cs == '\\');
1188
0
        ++cs;
1189
5.69M
do_str3:
1190
5.69M
        if(BOOST_JSON_UNLIKELY(! cs))
1191
1.00k
        {
1192
1.00k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1193
958
            {
1194
958
                BOOST_ASSERT(total <= max_size);
1195
958
                if(BOOST_JSON_UNLIKELY(
1196
958
                    temp.size() > max_size - total))
1197
0
                {
1198
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1199
0
                        = BOOST_CURRENT_LOCATION;
1200
0
                    return fail(cs.begin(), ev_too_large, &loc);
1201
0
                }
1202
958
                total += temp.size();
1203
958
                {
1204
958
                    bool r = is_key
1205
958
                        ? h_.on_key_part(temp.get(), total, ec_)
1206
958
                        : h_.on_string_part(temp.get(), total, ec_);
1207
1208
958
                    if(BOOST_JSON_UNLIKELY(!r))
1209
12
                    {
1210
12
                        return fail(cs.begin());
1211
12
                    }
1212
958
                }
1213
946
                temp.clear();
1214
946
            }
1215
994
            cs.clip(temp.max_size());
1216
994
            if(BOOST_JSON_UNLIKELY(! cs))
1217
132
                return maybe_suspend(cs.begin(), state::str3);
1218
994
        }
1219
5.69M
        switch(*cs)
1220
5.69M
        {
1221
101
        default:
1222
101
            {
1223
101
                BOOST_STATIC_CONSTEXPR source_location loc
1224
101
                    = BOOST_CURRENT_LOCATION;
1225
101
                return fail(cs.begin(), error::syntax, &loc);
1226
0
            }
1227
9.56k
        case '\x22': // '"'
1228
9.56k
            temp.push_back('\x22');
1229
9.56k
            ++cs;
1230
9.56k
            break;
1231
5.34M
        case '\\':
1232
5.34M
            temp.push_back('\\');
1233
5.34M
            ++cs;
1234
5.34M
            break;
1235
4.12k
        case '/':
1236
4.12k
            temp.push_back('/');
1237
4.12k
            ++cs;
1238
4.12k
            break;
1239
112k
        case 'b':
1240
112k
            temp.push_back('\x08');
1241
112k
            ++cs;
1242
112k
            break;
1243
5.14k
        case 'f':
1244
5.14k
            temp.push_back('\x0c');
1245
5.14k
            ++cs;
1246
5.14k
            break;
1247
1.79k
        case 'n':
1248
1.79k
            temp.push_back('\x0a');
1249
1.79k
            ++cs;
1250
1.79k
            break;
1251
966
        case 'r':
1252
966
            temp.push_back('\x0d');
1253
966
            ++cs;
1254
966
            break;
1255
5.11k
        case 't':
1256
5.11k
            temp.push_back('\x09');
1257
5.11k
            ++cs;
1258
5.11k
            break;
1259
219k
        case 'u':
1260
            // utf16 escape
1261
            //
1262
            // fast path only when the buffer
1263
            // is large enough for 2 surrogates
1264
219k
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1265
216k
            {
1266
                // KRYSTIAN TODO: this could be done
1267
                // with fewer instructions
1268
216k
                digit = detail::load_little_endian<4>(
1269
216k
                    cs.begin() + 1);
1270
216k
                int d4 = detail::hex_digit(static_cast<
1271
216k
                    unsigned char>(digit >> 24));
1272
216k
                int d3 = detail::hex_digit(static_cast<
1273
216k
                    unsigned char>(digit >> 16));
1274
216k
                int d2 = detail::hex_digit(static_cast<
1275
216k
                    unsigned char>(digit >> 8));
1276
216k
                int d1 = detail::hex_digit(static_cast<
1277
216k
                    unsigned char>(digit));
1278
216k
                if(BOOST_JSON_UNLIKELY(
1279
216k
                    (d1 | d2 | d3 | d4) == -1))
1280
117
                {
1281
117
                    if(d1 != -1)
1282
57
                        ++cs;
1283
117
                    if(d2 != -1)
1284
51
                        ++cs;
1285
117
                    if(d3 != -1)
1286
42
                        ++cs;
1287
117
                    BOOST_STATIC_CONSTEXPR source_location loc
1288
117
                        = BOOST_CURRENT_LOCATION;
1289
117
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1290
117
                }
1291
                // 32 bit unicode scalar value
1292
216k
                unsigned u1 =
1293
216k
                    (d1 << 12) + (d2 << 8) +
1294
216k
                    (d3 << 4) + d4;
1295
                // valid unicode scalar values are
1296
                // [0, D7FF] and [E000, 10FFFF]
1297
                // values within this range are valid utf-8
1298
                // code points and invalid leading surrogates.
1299
216k
                if(BOOST_JSON_LIKELY(
1300
216k
                    u1 < 0xd800 || u1 > 0xdfff))
1301
85.2k
                {
1302
85.2k
                    cs += 5;
1303
85.2k
                    temp.append_utf8(u1);
1304
85.2k
                    break;
1305
85.2k
                }
1306
131k
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1307
35
                {
1308
                    // If it's an illegal leading surrogate and
1309
                    // the parser does not allow it, return an error.
1310
35
                    if(!allow_bad_utf16)
1311
35
                    {
1312
35
                        BOOST_STATIC_CONSTEXPR source_location loc
1313
35
                            = BOOST_CURRENT_LOCATION;
1314
35
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1315
35
                            &loc);
1316
35
                    }
1317
                    // Otherwise, append the Unicode replacement character
1318
0
                    else
1319
0
                    {
1320
0
                        cs += 5;
1321
0
                        temp.append_utf8(urc);
1322
0
                        break;
1323
0
                    }
1324
35
                }
1325
131k
                cs += 5;
1326
                // KRYSTIAN TODO: this can be a two byte load
1327
                // and a single comparison. We lose error information,
1328
                // but it's faster.
1329
131k
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1330
25
                {
1331
                    // If the next character is not a backslash and
1332
                    // the parser does not allow it, return a syntax error.
1333
25
                    if(!allow_bad_utf16)
1334
25
                    {
1335
25
                        BOOST_STATIC_CONSTEXPR source_location loc
1336
25
                            = BOOST_CURRENT_LOCATION;
1337
25
                        return fail(cs.begin(), error::syntax, &loc);
1338
25
                    }
1339
                    // Otherwise, append the Unicode replacement character since
1340
                    // the first code point is a valid leading surrogate
1341
0
                    else
1342
0
                    {
1343
0
                        temp.append_utf8(urc);
1344
0
                        break;
1345
0
                    }
1346
25
                }
1347
131k
                ++cs;
1348
131k
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1349
16
                {
1350
16
                    if (!allow_bad_utf16)
1351
16
                    {
1352
16
                        BOOST_STATIC_CONSTEXPR source_location loc
1353
16
                            = BOOST_CURRENT_LOCATION;
1354
16
                        return fail(cs.begin(), error::syntax, &loc);
1355
16
                    }
1356
                    // Otherwise, append the Unicode replacement character since
1357
                    // the first code point is a valid leading surrogate
1358
0
                    else
1359
0
                    {
1360
0
                        temp.append_utf8(urc);
1361
0
                        goto do_str3;
1362
0
                    }
1363
16
                }
1364
131k
                ++cs;
1365
131k
                digit = detail::load_little_endian<4>(cs.begin());
1366
131k
                d4 = detail::hex_digit(static_cast<
1367
131k
                    unsigned char>(digit >> 24));
1368
131k
                d3 = detail::hex_digit(static_cast<
1369
131k
                    unsigned char>(digit >> 16));
1370
131k
                d2 = detail::hex_digit(static_cast<
1371
131k
                    unsigned char>(digit >> 8));
1372
131k
                d1 = detail::hex_digit(static_cast<
1373
131k
                    unsigned char>(digit));
1374
131k
                if(BOOST_JSON_UNLIKELY(
1375
131k
                    (d1 | d2 | d3 | d4) == -1))
1376
110
                {
1377
110
                    if(d1 != -1)
1378
42
                        ++cs;
1379
110
                    if(d2 != -1)
1380
30
                        ++cs;
1381
110
                    if(d3 != -1)
1382
42
                        ++cs;
1383
110
                    BOOST_STATIC_CONSTEXPR source_location loc
1384
110
                        = BOOST_CURRENT_LOCATION;
1385
110
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1386
110
                }
1387
131k
                unsigned u2 =
1388
131k
                    (d1 << 12) + (d2 << 8) +
1389
131k
                    (d3 << 4) + d4;
1390
                // Check if the second code point is a valid trailing surrogate.
1391
                // Valid trailing surrogates are [DC00, DFFF]
1392
131k
                if(BOOST_JSON_UNLIKELY(
1393
131k
                    u2 < 0xdc00 || u2 > 0xdfff))
1394
49
                {
1395
                    // If not valid and the parser does not allow it, return an error.
1396
49
                    if(!allow_bad_utf16)
1397
49
                    {
1398
49
                        BOOST_STATIC_CONSTEXPR source_location loc
1399
49
                            = BOOST_CURRENT_LOCATION;
1400
49
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1401
49
                            &loc);
1402
49
                    }
1403
                    // Append the replacement character for the
1404
                    // first leading surrogate.
1405
0
                    cs += 4;
1406
0
                    temp.append_utf8(urc);
1407
                    // Check if the second code point is a
1408
                    // valid unicode scalar value (invalid leading
1409
                    // or trailing surrogate)
1410
0
                    if (u2 < 0xd800 || u2 > 0xdbff)
1411
0
                    {
1412
0
                        temp.append_utf8(u2);
1413
0
                        break;
1414
0
                    }
1415
                    // If it is a valid leading surrogate
1416
0
                    else
1417
0
                    {
1418
0
                        u1_ = u2;
1419
0
                        goto do_sur1;
1420
0
                    }
1421
0
                }
1422
131k
                cs += 4;
1423
                // Calculate the Unicode code point from the surrogate pair and
1424
                // append the UTF-8 representation.
1425
131k
                unsigned cp =
1426
131k
                    ((u1 - 0xd800) << 10) +
1427
131k
                    ((u2 - 0xdc00)) +
1428
131k
                        0x10000;
1429
                // utf-16 surrogate pair
1430
131k
                temp.append_utf8(cp);
1431
131k
                break;
1432
131k
            }
1433
            // flush
1434
2.47k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1435
2.00k
            {
1436
2.00k
                BOOST_ASSERT(total <= max_size);
1437
2.00k
                if(BOOST_JSON_UNLIKELY(
1438
2.00k
                    temp.size() > max_size - total))
1439
0
                {
1440
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1441
0
                        = BOOST_CURRENT_LOCATION;
1442
0
                    return fail(cs.begin(), ev_too_large, &loc);
1443
0
                }
1444
2.00k
                total += temp.size();
1445
2.00k
                {
1446
2.00k
                    bool r = is_key
1447
2.00k
                        ? h_.on_key_part(temp.get(), total, ec_)
1448
2.00k
                        : h_.on_string_part(temp.get(), total, ec_);
1449
1450
2.00k
                    if(BOOST_JSON_UNLIKELY(!r))
1451
8
                    {
1452
8
                        return fail(cs.begin());
1453
8
                    }
1454
2.00k
                }
1455
2.00k
                temp.clear();
1456
2.00k
                cs.clip(temp.max_size());
1457
2.00k
            }
1458
2.46k
            ++cs;
1459
            // utf-16 escape
1460
2.46k
    do_str4:
1461
2.46k
            if(BOOST_JSON_UNLIKELY(! cs))
1462
43
                return maybe_suspend(cs.begin(), state::str4);
1463
2.41k
            digit = detail::hex_digit(*cs);
1464
2.41k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1465
43
            {
1466
43
                BOOST_STATIC_CONSTEXPR source_location loc
1467
43
                    = BOOST_CURRENT_LOCATION;
1468
43
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1469
43
            }
1470
2.37k
            ++cs;
1471
2.37k
            u1_ = digit << 12;
1472
2.37k
    do_str5:
1473
2.37k
            if(BOOST_JSON_UNLIKELY(! cs))
1474
24
                return maybe_suspend(cs.begin(), state::str5);
1475
2.35k
            digit = detail::hex_digit(*cs);
1476
2.35k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1477
32
            {
1478
32
                BOOST_STATIC_CONSTEXPR source_location loc
1479
32
                    = BOOST_CURRENT_LOCATION;
1480
32
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1481
32
            }
1482
2.32k
            ++cs;
1483
2.32k
            u1_ += digit << 8;
1484
2.32k
    do_str6:
1485
2.32k
            if(BOOST_JSON_UNLIKELY(! cs))
1486
30
                return maybe_suspend(cs.begin(), state::str6);
1487
2.29k
            digit = detail::hex_digit(*cs);
1488
2.29k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1489
37
            {
1490
37
                BOOST_STATIC_CONSTEXPR source_location loc
1491
37
                    = BOOST_CURRENT_LOCATION;
1492
37
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1493
37
            }
1494
2.25k
            ++cs;
1495
2.25k
            u1_ += digit << 4;
1496
2.25k
    do_str7:
1497
2.25k
            if(BOOST_JSON_UNLIKELY(! cs))
1498
26
                return maybe_suspend(cs.begin(), state::str7);
1499
2.22k
            digit = detail::hex_digit(*cs);
1500
2.22k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1501
32
            {
1502
32
                BOOST_STATIC_CONSTEXPR source_location loc
1503
32
                    = BOOST_CURRENT_LOCATION;
1504
32
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1505
32
            }
1506
2.19k
            ++cs;
1507
2.19k
            u1_ += digit;
1508
2.19k
            if(BOOST_JSON_LIKELY(
1509
2.19k
                u1_ < 0xd800 || u1_ > 0xdfff))
1510
843
            {
1511
843
                BOOST_ASSERT(temp.empty());
1512
                // utf-8 codepoint
1513
0
                temp.append_utf8(u1_);
1514
843
                break;
1515
843
            }
1516
1.35k
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1517
21
            {
1518
                // If it's an illegal leading surrogate and
1519
                // the parser does not allow it, return an error.
1520
21
                if(!allow_bad_utf16)
1521
21
                {
1522
21
                    BOOST_STATIC_CONSTEXPR source_location loc
1523
21
                        = BOOST_CURRENT_LOCATION;
1524
21
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1525
21
                }
1526
                // Otherwise, append the Unicode replacement character
1527
0
                else
1528
0
                {
1529
0
                    BOOST_ASSERT(temp.empty());
1530
0
                    temp.append_utf8(urc);
1531
0
                    break;
1532
0
                }
1533
21
            }
1534
1.33k
    do_sur1:
1535
1.33k
            if(BOOST_JSON_UNLIKELY(! cs))
1536
19
                return maybe_suspend(cs.begin(), state::sur1);
1537
1.31k
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1538
9
            {
1539
                // If the next character is not a backslash and
1540
                // the parser does not allow it, return a syntax error.
1541
9
                if(!allow_bad_utf16)
1542
9
                {
1543
9
                    BOOST_STATIC_CONSTEXPR source_location loc
1544
9
                        = BOOST_CURRENT_LOCATION;
1545
9
                    return fail(cs.begin(), error::syntax, &loc);
1546
9
                }
1547
                // Otherwise, append the Unicode replacement character since
1548
                // the first code point is a valid leading surrogate
1549
0
                else
1550
0
                {
1551
0
                    temp.append_utf8(urc);
1552
0
                    break;
1553
0
                }
1554
9
            }
1555
1.30k
            ++cs;
1556
1.30k
    do_sur2:
1557
1.30k
            if(BOOST_JSON_UNLIKELY(! cs))
1558
5
                return maybe_suspend(cs.begin(), state::sur2);
1559
1.29k
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1560
13
            {
1561
13
                if (!allow_bad_utf16)
1562
13
                {
1563
13
                    BOOST_STATIC_CONSTEXPR source_location loc
1564
13
                        = BOOST_CURRENT_LOCATION;
1565
13
                    return fail(cs.begin(), error::syntax, &loc);
1566
13
                }
1567
                // Otherwise, append the Unicode replacement character since
1568
                // the first code point is a valid leading surrogate
1569
0
                else
1570
0
                {
1571
0
                    temp.append_utf8(urc);
1572
0
                    goto do_str3;
1573
0
                }
1574
13
            }
1575
1.28k
            ++cs;
1576
1.28k
    do_sur3:
1577
1.28k
            if(BOOST_JSON_UNLIKELY(! cs))
1578
2
                return maybe_suspend(cs.begin(), state::sur3);
1579
1.28k
            digit = detail::hex_digit(*cs);
1580
1.28k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1581
22
            {
1582
22
                BOOST_STATIC_CONSTEXPR source_location loc
1583
22
                    = BOOST_CURRENT_LOCATION;
1584
22
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1585
22
            }
1586
1.26k
            ++cs;
1587
1.26k
            u2_ = digit << 12;
1588
1.26k
    do_sur4:
1589
1.26k
            if(BOOST_JSON_UNLIKELY(! cs))
1590
20
                return maybe_suspend(cs.begin(), state::sur4);
1591
1.24k
            digit = detail::hex_digit(*cs);
1592
1.24k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1593
27
            {
1594
27
                BOOST_STATIC_CONSTEXPR source_location loc
1595
27
                    = BOOST_CURRENT_LOCATION;
1596
27
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1597
27
            }
1598
1.21k
            ++cs;
1599
1.21k
            u2_ += digit << 8;
1600
1.21k
    do_sur5:
1601
1.21k
            if(BOOST_JSON_UNLIKELY(! cs))
1602
17
                return maybe_suspend(cs.begin(), state::sur5);
1603
1.19k
            digit = detail::hex_digit(*cs);
1604
1.19k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1605
29
            {
1606
29
                BOOST_STATIC_CONSTEXPR source_location loc
1607
29
                    = BOOST_CURRENT_LOCATION;
1608
29
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1609
29
            }
1610
1.16k
            ++cs;
1611
1.16k
            u2_ += digit << 4;
1612
1.16k
    do_sur6:
1613
1.16k
            if(BOOST_JSON_UNLIKELY(! cs))
1614
23
                return maybe_suspend(cs.begin(), state::sur6);
1615
1.14k
            digit = detail::hex_digit(*cs);
1616
1.14k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1617
12
            {
1618
12
                BOOST_STATIC_CONSTEXPR source_location loc
1619
12
                    = BOOST_CURRENT_LOCATION;
1620
12
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1621
12
            }
1622
1.13k
            ++cs;
1623
1.13k
            u2_ += digit;
1624
            // Check if the second code point is a valid trailing surrogate.
1625
            // Valid trailing surrogates are [DC00, DFFF]
1626
1.13k
            if(BOOST_JSON_UNLIKELY(
1627
1.13k
                u2_ < 0xdc00 || u2_ > 0xdfff))
1628
28
            {
1629
                // If not valid and the parser does not allow it, return an error.
1630
28
                if(!allow_bad_utf16)
1631
28
                {
1632
28
                    BOOST_STATIC_CONSTEXPR source_location loc
1633
28
                        = BOOST_CURRENT_LOCATION;
1634
28
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1635
28
                }
1636
                // Append the replacement character for the
1637
                // first leading surrogate.
1638
0
                temp.append_utf8(urc);
1639
                // Check if the second code point is a
1640
                // valid unicode scalar value (invalid leading
1641
                // or trailing surrogate)
1642
0
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1643
0
                {
1644
0
                    temp.append_utf8(u2_);
1645
0
                    break;
1646
0
                }
1647
                // If it is a valid leading surrogate
1648
0
                else
1649
0
                {
1650
0
                    u1_ = u2_;
1651
0
                    goto do_sur1;
1652
0
                }
1653
0
            }
1654
            // Calculate the Unicode code point from the surrogate pair and
1655
            // append the UTF-8 representation.
1656
1.10k
            unsigned cp =
1657
1.10k
                ((u1_ - 0xd800) << 10) +
1658
1.10k
                ((u2_ - 0xdc00)) +
1659
1.10k
                    0x10000;
1660
            // utf-16 surrogate pair
1661
1.10k
            temp.append_utf8(cp);
1662
5.69M
        }
1663
1664
        // flush
1665
5.69M
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1666
28.2k
            break;
1667
5.69M
    }
1668
1669
28.2k
    if(BOOST_JSON_LIKELY( temp.size() ))
1670
28.2k
    {
1671
28.2k
        BOOST_ASSERT(total <= max_size);
1672
28.2k
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1673
0
        {
1674
0
            BOOST_STATIC_CONSTEXPR source_location loc
1675
0
                = BOOST_CURRENT_LOCATION;
1676
0
            return fail(cs.begin(), ev_too_large, &loc);
1677
0
        }
1678
1679
28.2k
        total += temp.size();
1680
28.2k
        bool const r = is_key
1681
28.2k
            ? h_.on_key_part(temp.get(), total, ec_)
1682
28.2k
            : h_.on_string_part(temp.get(), total, ec_);
1683
28.2k
        if(BOOST_JSON_UNLIKELY( !r ))
1684
115
            return fail( cs.begin() );
1685
28.2k
    }
1686
1687
28.0k
    return cs.begin();
1688
28.2k
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_escaped<true>(char const*, unsigned long&, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1132
25.5k
{
1133
25.5k
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1134
25.5k
    auto const ev_too_large = is_key?
1135
15.7k
        error::key_too_large : error::string_too_large;
1136
25.5k
    auto const max_size = is_key?
1137
15.7k
        Handler::max_key_size : Handler::max_string_size;
1138
25.5k
    int digit;
1139
1140
    //---------------------------------------------------------------
1141
    //
1142
    // To handle escapes, a local temporary buffer accumulates
1143
    // the unescaped result. The algorithm attempts to fill the
1144
    // buffer to capacity before invoking the handler.
1145
    // In some cases the temporary buffer needs to be flushed
1146
    // before it is full:
1147
    // * When the closing double quote is seen
1148
    // * When there in no more input (and more is expected later)
1149
    // A goal of the algorithm is to call the handler as few times
1150
    // as possible. Thus, when the first escape is encountered,
1151
    // the algorithm attempts to fill the temporary buffer first.
1152
    //
1153
25.5k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1154
1155
    // Unescaped JSON is never larger than its escaped version.
1156
    // To efficiently process only what will fit in the temporary buffer,
1157
    // the size of the input stream is temporarily "clipped" to the size
1158
    // of the temporary buffer.
1159
    // handle escaped character
1160
25.5k
    detail::clipped_const_stream cs(p, end_);
1161
25.5k
    cs.clip(temp.max_size());
1162
1163
25.5k
    if(! stack_empty && ! st_.empty())
1164
0
    {
1165
0
        state st;
1166
0
        st_.pop(st);
1167
0
        switch(st)
1168
0
        {
1169
0
        default: BOOST_JSON_UNREACHABLE();
1170
0
        case state::str3: goto do_str3;
1171
0
        case state::str4: goto do_str4;
1172
0
        case state::str5: goto do_str5;
1173
0
        case state::str6: goto do_str6;
1174
0
        case state::str7: goto do_str7;
1175
0
        case state::sur1: goto do_sur1;
1176
0
        case state::sur2: goto do_sur2;
1177
0
        case state::sur3: goto do_sur3;
1178
0
        case state::sur4: goto do_sur4;
1179
0
        case state::sur5: goto do_sur5;
1180
0
        case state::sur6: goto do_sur6;
1181
0
        }
1182
0
    }
1183
1184
1.06M
    while(true)
1185
1.06M
    {
1186
1.06M
        BOOST_ASSERT( temp.capacity() );
1187
1.06M
        BOOST_ASSERT(*cs == '\\');
1188
0
        ++cs;
1189
1.06M
do_str3:
1190
1.06M
        if(BOOST_JSON_UNLIKELY(! cs))
1191
274
        {
1192
274
            if(BOOST_JSON_LIKELY(! temp.empty()))
1193
254
            {
1194
254
                BOOST_ASSERT(total <= max_size);
1195
254
                if(BOOST_JSON_UNLIKELY(
1196
254
                    temp.size() > max_size - total))
1197
0
                {
1198
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1199
0
                        = BOOST_CURRENT_LOCATION;
1200
0
                    return fail(cs.begin(), ev_too_large, &loc);
1201
0
                }
1202
254
                total += temp.size();
1203
254
                {
1204
254
                    bool r = is_key
1205
254
                        ? h_.on_key_part(temp.get(), total, ec_)
1206
254
                        : h_.on_string_part(temp.get(), total, ec_);
1207
1208
254
                    if(BOOST_JSON_UNLIKELY(!r))
1209
12
                    {
1210
12
                        return fail(cs.begin());
1211
12
                    }
1212
254
                }
1213
242
                temp.clear();
1214
242
            }
1215
262
            cs.clip(temp.max_size());
1216
262
            if(BOOST_JSON_UNLIKELY(! cs))
1217
48
                return maybe_suspend(cs.begin(), state::str3);
1218
262
        }
1219
1.06M
        switch(*cs)
1220
1.06M
        {
1221
46
        default:
1222
46
            {
1223
46
                BOOST_STATIC_CONSTEXPR source_location loc
1224
46
                    = BOOST_CURRENT_LOCATION;
1225
46
                return fail(cs.begin(), error::syntax, &loc);
1226
0
            }
1227
3.53k
        case '\x22': // '"'
1228
3.53k
            temp.push_back('\x22');
1229
3.53k
            ++cs;
1230
3.53k
            break;
1231
981k
        case '\\':
1232
981k
            temp.push_back('\\');
1233
981k
            ++cs;
1234
981k
            break;
1235
647
        case '/':
1236
647
            temp.push_back('/');
1237
647
            ++cs;
1238
647
            break;
1239
794
        case 'b':
1240
794
            temp.push_back('\x08');
1241
794
            ++cs;
1242
794
            break;
1243
3.51k
        case 'f':
1244
3.51k
            temp.push_back('\x0c');
1245
3.51k
            ++cs;
1246
3.51k
            break;
1247
1.49k
        case 'n':
1248
1.49k
            temp.push_back('\x0a');
1249
1.49k
            ++cs;
1250
1.49k
            break;
1251
557
        case 'r':
1252
557
            temp.push_back('\x0d');
1253
557
            ++cs;
1254
557
            break;
1255
4.43k
        case 't':
1256
4.43k
            temp.push_back('\x09');
1257
4.43k
            ++cs;
1258
4.43k
            break;
1259
65.9k
        case 'u':
1260
            // utf16 escape
1261
            //
1262
            // fast path only when the buffer
1263
            // is large enough for 2 surrogates
1264
65.9k
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1265
65.3k
            {
1266
                // KRYSTIAN TODO: this could be done
1267
                // with fewer instructions
1268
65.3k
                digit = detail::load_little_endian<4>(
1269
65.3k
                    cs.begin() + 1);
1270
65.3k
                int d4 = detail::hex_digit(static_cast<
1271
65.3k
                    unsigned char>(digit >> 24));
1272
65.3k
                int d3 = detail::hex_digit(static_cast<
1273
65.3k
                    unsigned char>(digit >> 16));
1274
65.3k
                int d2 = detail::hex_digit(static_cast<
1275
65.3k
                    unsigned char>(digit >> 8));
1276
65.3k
                int d1 = detail::hex_digit(static_cast<
1277
65.3k
                    unsigned char>(digit));
1278
65.3k
                if(BOOST_JSON_UNLIKELY(
1279
65.3k
                    (d1 | d2 | d3 | d4) == -1))
1280
68
                {
1281
68
                    if(d1 != -1)
1282
38
                        ++cs;
1283
68
                    if(d2 != -1)
1284
34
                        ++cs;
1285
68
                    if(d3 != -1)
1286
29
                        ++cs;
1287
68
                    BOOST_STATIC_CONSTEXPR source_location loc
1288
68
                        = BOOST_CURRENT_LOCATION;
1289
68
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1290
68
                }
1291
                // 32 bit unicode scalar value
1292
65.3k
                unsigned u1 =
1293
65.3k
                    (d1 << 12) + (d2 << 8) +
1294
65.3k
                    (d3 << 4) + d4;
1295
                // valid unicode scalar values are
1296
                // [0, D7FF] and [E000, 10FFFF]
1297
                // values within this range are valid utf-8
1298
                // code points and invalid leading surrogates.
1299
65.3k
                if(BOOST_JSON_LIKELY(
1300
65.3k
                    u1 < 0xd800 || u1 > 0xdfff))
1301
7.11k
                {
1302
7.11k
                    cs += 5;
1303
7.11k
                    temp.append_utf8(u1);
1304
7.11k
                    break;
1305
7.11k
                }
1306
58.2k
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1307
20
                {
1308
                    // If it's an illegal leading surrogate and
1309
                    // the parser does not allow it, return an error.
1310
20
                    if(!allow_bad_utf16)
1311
20
                    {
1312
20
                        BOOST_STATIC_CONSTEXPR source_location loc
1313
20
                            = BOOST_CURRENT_LOCATION;
1314
20
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1315
20
                            &loc);
1316
20
                    }
1317
                    // Otherwise, append the Unicode replacement character
1318
0
                    else
1319
0
                    {
1320
0
                        cs += 5;
1321
0
                        temp.append_utf8(urc);
1322
0
                        break;
1323
0
                    }
1324
20
                }
1325
58.1k
                cs += 5;
1326
                // KRYSTIAN TODO: this can be a two byte load
1327
                // and a single comparison. We lose error information,
1328
                // but it's faster.
1329
58.1k
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1330
14
                {
1331
                    // If the next character is not a backslash and
1332
                    // the parser does not allow it, return a syntax error.
1333
14
                    if(!allow_bad_utf16)
1334
14
                    {
1335
14
                        BOOST_STATIC_CONSTEXPR source_location loc
1336
14
                            = BOOST_CURRENT_LOCATION;
1337
14
                        return fail(cs.begin(), error::syntax, &loc);
1338
14
                    }
1339
                    // Otherwise, append the Unicode replacement character since
1340
                    // the first code point is a valid leading surrogate
1341
0
                    else
1342
0
                    {
1343
0
                        temp.append_utf8(urc);
1344
0
                        break;
1345
0
                    }
1346
14
                }
1347
58.1k
                ++cs;
1348
58.1k
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1349
13
                {
1350
13
                    if (!allow_bad_utf16)
1351
13
                    {
1352
13
                        BOOST_STATIC_CONSTEXPR source_location loc
1353
13
                            = BOOST_CURRENT_LOCATION;
1354
13
                        return fail(cs.begin(), error::syntax, &loc);
1355
13
                    }
1356
                    // Otherwise, append the Unicode replacement character since
1357
                    // the first code point is a valid leading surrogate
1358
0
                    else
1359
0
                    {
1360
0
                        temp.append_utf8(urc);
1361
0
                        goto do_str3;
1362
0
                    }
1363
13
                }
1364
58.1k
                ++cs;
1365
58.1k
                digit = detail::load_little_endian<4>(cs.begin());
1366
58.1k
                d4 = detail::hex_digit(static_cast<
1367
58.1k
                    unsigned char>(digit >> 24));
1368
58.1k
                d3 = detail::hex_digit(static_cast<
1369
58.1k
                    unsigned char>(digit >> 16));
1370
58.1k
                d2 = detail::hex_digit(static_cast<
1371
58.1k
                    unsigned char>(digit >> 8));
1372
58.1k
                d1 = detail::hex_digit(static_cast<
1373
58.1k
                    unsigned char>(digit));
1374
58.1k
                if(BOOST_JSON_UNLIKELY(
1375
58.1k
                    (d1 | d2 | d3 | d4) == -1))
1376
51
                {
1377
51
                    if(d1 != -1)
1378
19
                        ++cs;
1379
51
                    if(d2 != -1)
1380
17
                        ++cs;
1381
51
                    if(d3 != -1)
1382
20
                        ++cs;
1383
51
                    BOOST_STATIC_CONSTEXPR source_location loc
1384
51
                        = BOOST_CURRENT_LOCATION;
1385
51
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1386
51
                }
1387
58.1k
                unsigned u2 =
1388
58.1k
                    (d1 << 12) + (d2 << 8) +
1389
58.1k
                    (d3 << 4) + d4;
1390
                // Check if the second code point is a valid trailing surrogate.
1391
                // Valid trailing surrogates are [DC00, DFFF]
1392
58.1k
                if(BOOST_JSON_UNLIKELY(
1393
58.1k
                    u2 < 0xdc00 || u2 > 0xdfff))
1394
22
                {
1395
                    // If not valid and the parser does not allow it, return an error.
1396
22
                    if(!allow_bad_utf16)
1397
22
                    {
1398
22
                        BOOST_STATIC_CONSTEXPR source_location loc
1399
22
                            = BOOST_CURRENT_LOCATION;
1400
22
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1401
22
                            &loc);
1402
22
                    }
1403
                    // Append the replacement character for the
1404
                    // first leading surrogate.
1405
0
                    cs += 4;
1406
0
                    temp.append_utf8(urc);
1407
                    // Check if the second code point is a
1408
                    // valid unicode scalar value (invalid leading
1409
                    // or trailing surrogate)
1410
0
                    if (u2 < 0xd800 || u2 > 0xdbff)
1411
0
                    {
1412
0
                        temp.append_utf8(u2);
1413
0
                        break;
1414
0
                    }
1415
                    // If it is a valid leading surrogate
1416
0
                    else
1417
0
                    {
1418
0
                        u1_ = u2;
1419
0
                        goto do_sur1;
1420
0
                    }
1421
0
                }
1422
58.0k
                cs += 4;
1423
                // Calculate the Unicode code point from the surrogate pair and
1424
                // append the UTF-8 representation.
1425
58.0k
                unsigned cp =
1426
58.0k
                    ((u1 - 0xd800) << 10) +
1427
58.0k
                    ((u2 - 0xdc00)) +
1428
58.0k
                        0x10000;
1429
                // utf-16 surrogate pair
1430
58.0k
                temp.append_utf8(cp);
1431
58.0k
                break;
1432
58.1k
            }
1433
            // flush
1434
521
            if(BOOST_JSON_LIKELY(! temp.empty()))
1435
310
            {
1436
310
                BOOST_ASSERT(total <= max_size);
1437
310
                if(BOOST_JSON_UNLIKELY(
1438
310
                    temp.size() > max_size - total))
1439
0
                {
1440
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1441
0
                        = BOOST_CURRENT_LOCATION;
1442
0
                    return fail(cs.begin(), ev_too_large, &loc);
1443
0
                }
1444
310
                total += temp.size();
1445
310
                {
1446
310
                    bool r = is_key
1447
310
                        ? h_.on_key_part(temp.get(), total, ec_)
1448
310
                        : h_.on_string_part(temp.get(), total, ec_);
1449
1450
310
                    if(BOOST_JSON_UNLIKELY(!r))
1451
8
                    {
1452
8
                        return fail(cs.begin());
1453
8
                    }
1454
310
                }
1455
302
                temp.clear();
1456
302
                cs.clip(temp.max_size());
1457
302
            }
1458
513
            ++cs;
1459
            // utf-16 escape
1460
513
    do_str4:
1461
513
            if(BOOST_JSON_UNLIKELY(! cs))
1462
11
                return maybe_suspend(cs.begin(), state::str4);
1463
502
            digit = detail::hex_digit(*cs);
1464
502
            if(BOOST_JSON_UNLIKELY(digit == -1))
1465
24
            {
1466
24
                BOOST_STATIC_CONSTEXPR source_location loc
1467
24
                    = BOOST_CURRENT_LOCATION;
1468
24
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1469
24
            }
1470
478
            ++cs;
1471
478
            u1_ = digit << 12;
1472
478
    do_str5:
1473
478
            if(BOOST_JSON_UNLIKELY(! cs))
1474
7
                return maybe_suspend(cs.begin(), state::str5);
1475
471
            digit = detail::hex_digit(*cs);
1476
471
            if(BOOST_JSON_UNLIKELY(digit == -1))
1477
18
            {
1478
18
                BOOST_STATIC_CONSTEXPR source_location loc
1479
18
                    = BOOST_CURRENT_LOCATION;
1480
18
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1481
18
            }
1482
453
            ++cs;
1483
453
            u1_ += digit << 8;
1484
453
    do_str6:
1485
453
            if(BOOST_JSON_UNLIKELY(! cs))
1486
7
                return maybe_suspend(cs.begin(), state::str6);
1487
446
            digit = detail::hex_digit(*cs);
1488
446
            if(BOOST_JSON_UNLIKELY(digit == -1))
1489
18
            {
1490
18
                BOOST_STATIC_CONSTEXPR source_location loc
1491
18
                    = BOOST_CURRENT_LOCATION;
1492
18
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1493
18
            }
1494
428
            ++cs;
1495
428
            u1_ += digit << 4;
1496
428
    do_str7:
1497
428
            if(BOOST_JSON_UNLIKELY(! cs))
1498
8
                return maybe_suspend(cs.begin(), state::str7);
1499
420
            digit = detail::hex_digit(*cs);
1500
420
            if(BOOST_JSON_UNLIKELY(digit == -1))
1501
18
            {
1502
18
                BOOST_STATIC_CONSTEXPR source_location loc
1503
18
                    = BOOST_CURRENT_LOCATION;
1504
18
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1505
18
            }
1506
402
            ++cs;
1507
402
            u1_ += digit;
1508
402
            if(BOOST_JSON_LIKELY(
1509
402
                u1_ < 0xd800 || u1_ > 0xdfff))
1510
82
            {
1511
82
                BOOST_ASSERT(temp.empty());
1512
                // utf-8 codepoint
1513
0
                temp.append_utf8(u1_);
1514
82
                break;
1515
82
            }
1516
320
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1517
10
            {
1518
                // If it's an illegal leading surrogate and
1519
                // the parser does not allow it, return an error.
1520
10
                if(!allow_bad_utf16)
1521
10
                {
1522
10
                    BOOST_STATIC_CONSTEXPR source_location loc
1523
10
                        = BOOST_CURRENT_LOCATION;
1524
10
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1525
10
                }
1526
                // Otherwise, append the Unicode replacement character
1527
0
                else
1528
0
                {
1529
0
                    BOOST_ASSERT(temp.empty());
1530
0
                    temp.append_utf8(urc);
1531
0
                    break;
1532
0
                }
1533
10
            }
1534
310
    do_sur1:
1535
310
            if(BOOST_JSON_UNLIKELY(! cs))
1536
4
                return maybe_suspend(cs.begin(), state::sur1);
1537
306
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1538
7
            {
1539
                // If the next character is not a backslash and
1540
                // the parser does not allow it, return a syntax error.
1541
7
                if(!allow_bad_utf16)
1542
7
                {
1543
7
                    BOOST_STATIC_CONSTEXPR source_location loc
1544
7
                        = BOOST_CURRENT_LOCATION;
1545
7
                    return fail(cs.begin(), error::syntax, &loc);
1546
7
                }
1547
                // Otherwise, append the Unicode replacement character since
1548
                // the first code point is a valid leading surrogate
1549
0
                else
1550
0
                {
1551
0
                    temp.append_utf8(urc);
1552
0
                    break;
1553
0
                }
1554
7
            }
1555
299
            ++cs;
1556
299
    do_sur2:
1557
299
            if(BOOST_JSON_UNLIKELY(! cs))
1558
3
                return maybe_suspend(cs.begin(), state::sur2);
1559
296
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1560
2
            {
1561
2
                if (!allow_bad_utf16)
1562
2
                {
1563
2
                    BOOST_STATIC_CONSTEXPR source_location loc
1564
2
                        = BOOST_CURRENT_LOCATION;
1565
2
                    return fail(cs.begin(), error::syntax, &loc);
1566
2
                }
1567
                // Otherwise, append the Unicode replacement character since
1568
                // the first code point is a valid leading surrogate
1569
0
                else
1570
0
                {
1571
0
                    temp.append_utf8(urc);
1572
0
                    goto do_str3;
1573
0
                }
1574
2
            }
1575
294
            ++cs;
1576
294
    do_sur3:
1577
294
            if(BOOST_JSON_UNLIKELY(! cs))
1578
1
                return maybe_suspend(cs.begin(), state::sur3);
1579
293
            digit = detail::hex_digit(*cs);
1580
293
            if(BOOST_JSON_UNLIKELY(digit == -1))
1581
7
            {
1582
7
                BOOST_STATIC_CONSTEXPR source_location loc
1583
7
                    = BOOST_CURRENT_LOCATION;
1584
7
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1585
7
            }
1586
286
            ++cs;
1587
286
            u2_ = digit << 12;
1588
286
    do_sur4:
1589
286
            if(BOOST_JSON_UNLIKELY(! cs))
1590
6
                return maybe_suspend(cs.begin(), state::sur4);
1591
280
            digit = detail::hex_digit(*cs);
1592
280
            if(BOOST_JSON_UNLIKELY(digit == -1))
1593
11
            {
1594
11
                BOOST_STATIC_CONSTEXPR source_location loc
1595
11
                    = BOOST_CURRENT_LOCATION;
1596
11
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1597
11
            }
1598
269
            ++cs;
1599
269
            u2_ += digit << 8;
1600
269
    do_sur5:
1601
269
            if(BOOST_JSON_UNLIKELY(! cs))
1602
6
                return maybe_suspend(cs.begin(), state::sur5);
1603
263
            digit = detail::hex_digit(*cs);
1604
263
            if(BOOST_JSON_UNLIKELY(digit == -1))
1605
12
            {
1606
12
                BOOST_STATIC_CONSTEXPR source_location loc
1607
12
                    = BOOST_CURRENT_LOCATION;
1608
12
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1609
12
            }
1610
251
            ++cs;
1611
251
            u2_ += digit << 4;
1612
251
    do_sur6:
1613
251
            if(BOOST_JSON_UNLIKELY(! cs))
1614
3
                return maybe_suspend(cs.begin(), state::sur6);
1615
248
            digit = detail::hex_digit(*cs);
1616
248
            if(BOOST_JSON_UNLIKELY(digit == -1))
1617
2
            {
1618
2
                BOOST_STATIC_CONSTEXPR source_location loc
1619
2
                    = BOOST_CURRENT_LOCATION;
1620
2
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1621
2
            }
1622
246
            ++cs;
1623
246
            u2_ += digit;
1624
            // Check if the second code point is a valid trailing surrogate.
1625
            // Valid trailing surrogates are [DC00, DFFF]
1626
246
            if(BOOST_JSON_UNLIKELY(
1627
246
                u2_ < 0xdc00 || u2_ > 0xdfff))
1628
3
            {
1629
                // If not valid and the parser does not allow it, return an error.
1630
3
                if(!allow_bad_utf16)
1631
3
                {
1632
3
                    BOOST_STATIC_CONSTEXPR source_location loc
1633
3
                        = BOOST_CURRENT_LOCATION;
1634
3
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1635
3
                }
1636
                // Append the replacement character for the
1637
                // first leading surrogate.
1638
0
                temp.append_utf8(urc);
1639
                // Check if the second code point is a
1640
                // valid unicode scalar value (invalid leading
1641
                // or trailing surrogate)
1642
0
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1643
0
                {
1644
0
                    temp.append_utf8(u2_);
1645
0
                    break;
1646
0
                }
1647
                // If it is a valid leading surrogate
1648
0
                else
1649
0
                {
1650
0
                    u1_ = u2_;
1651
0
                    goto do_sur1;
1652
0
                }
1653
0
            }
1654
            // Calculate the Unicode code point from the surrogate pair and
1655
            // append the UTF-8 representation.
1656
243
            unsigned cp =
1657
243
                ((u1_ - 0xd800) << 10) +
1658
243
                ((u2_ - 0xdc00)) +
1659
243
                    0x10000;
1660
            // utf-16 surrogate pair
1661
243
            temp.append_utf8(cp);
1662
1.06M
        }
1663
1664
        // flush
1665
1.06M
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1666
25.0k
            break;
1667
1.06M
    }
1668
1669
25.0k
    if(BOOST_JSON_LIKELY( temp.size() ))
1670
25.0k
    {
1671
25.0k
        BOOST_ASSERT(total <= max_size);
1672
25.0k
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1673
0
        {
1674
0
            BOOST_STATIC_CONSTEXPR source_location loc
1675
0
                = BOOST_CURRENT_LOCATION;
1676
0
            return fail(cs.begin(), ev_too_large, &loc);
1677
0
        }
1678
1679
25.0k
        total += temp.size();
1680
25.0k
        bool const r = is_key
1681
25.0k
            ? h_.on_key_part(temp.get(), total, ec_)
1682
25.0k
            : h_.on_string_part(temp.get(), total, ec_);
1683
25.0k
        if(BOOST_JSON_UNLIKELY( !r ))
1684
115
            return fail( cs.begin() );
1685
25.0k
    }
1686
1687
24.9k
    return cs.begin();
1688
25.0k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_escaped<false>(char const*, unsigned long&, std::__1::integral_constant<bool, false>, bool, bool)
char const* boost::json::basic_parser<null_parser::handler>::parse_escaped<true>(char const*, unsigned long&, std::__1::integral_constant<bool, true>, bool, bool)
Line
Count
Source
1132
3.76k
{
1133
3.76k
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1134
3.76k
    auto const ev_too_large = is_key?
1135
3.10k
        error::key_too_large : error::string_too_large;
1136
3.76k
    auto const max_size = is_key?
1137
3.10k
        Handler::max_key_size : Handler::max_string_size;
1138
3.76k
    int digit;
1139
1140
    //---------------------------------------------------------------
1141
    //
1142
    // To handle escapes, a local temporary buffer accumulates
1143
    // the unescaped result. The algorithm attempts to fill the
1144
    // buffer to capacity before invoking the handler.
1145
    // In some cases the temporary buffer needs to be flushed
1146
    // before it is full:
1147
    // * When the closing double quote is seen
1148
    // * When there in no more input (and more is expected later)
1149
    // A goal of the algorithm is to call the handler as few times
1150
    // as possible. Thus, when the first escape is encountered,
1151
    // the algorithm attempts to fill the temporary buffer first.
1152
    //
1153
3.76k
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1154
1155
    // Unescaped JSON is never larger than its escaped version.
1156
    // To efficiently process only what will fit in the temporary buffer,
1157
    // the size of the input stream is temporarily "clipped" to the size
1158
    // of the temporary buffer.
1159
    // handle escaped character
1160
3.76k
    detail::clipped_const_stream cs(p, end_);
1161
3.76k
    cs.clip(temp.max_size());
1162
1163
3.76k
    if(! stack_empty && ! st_.empty())
1164
0
    {
1165
0
        state st;
1166
0
        st_.pop(st);
1167
0
        switch(st)
1168
0
        {
1169
0
        default: BOOST_JSON_UNREACHABLE();
1170
0
        case state::str3: goto do_str3;
1171
0
        case state::str4: goto do_str4;
1172
0
        case state::str5: goto do_str5;
1173
0
        case state::str6: goto do_str6;
1174
0
        case state::str7: goto do_str7;
1175
0
        case state::sur1: goto do_sur1;
1176
0
        case state::sur2: goto do_sur2;
1177
0
        case state::sur3: goto do_sur3;
1178
0
        case state::sur4: goto do_sur4;
1179
0
        case state::sur5: goto do_sur5;
1180
0
        case state::sur6: goto do_sur6;
1181
0
        }
1182
0
    }
1183
1184
4.63M
    while(true)
1185
4.63M
    {
1186
4.63M
        BOOST_ASSERT( temp.capacity() );
1187
4.63M
        BOOST_ASSERT(*cs == '\\');
1188
0
        ++cs;
1189
4.63M
do_str3:
1190
4.63M
        if(BOOST_JSON_UNLIKELY(! cs))
1191
732
        {
1192
732
            if(BOOST_JSON_LIKELY(! temp.empty()))
1193
704
            {
1194
704
                BOOST_ASSERT(total <= max_size);
1195
704
                if(BOOST_JSON_UNLIKELY(
1196
704
                    temp.size() > max_size - total))
1197
0
                {
1198
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1199
0
                        = BOOST_CURRENT_LOCATION;
1200
0
                    return fail(cs.begin(), ev_too_large, &loc);
1201
0
                }
1202
704
                total += temp.size();
1203
704
                {
1204
704
                    bool r = is_key
1205
704
                        ? h_.on_key_part(temp.get(), total, ec_)
1206
704
                        : h_.on_string_part(temp.get(), total, ec_);
1207
1208
704
                    if(BOOST_JSON_UNLIKELY(!r))
1209
0
                    {
1210
0
                        return fail(cs.begin());
1211
0
                    }
1212
704
                }
1213
704
                temp.clear();
1214
704
            }
1215
732
            cs.clip(temp.max_size());
1216
732
            if(BOOST_JSON_UNLIKELY(! cs))
1217
84
                return maybe_suspend(cs.begin(), state::str3);
1218
732
        }
1219
4.63M
        switch(*cs)
1220
4.63M
        {
1221
55
        default:
1222
55
            {
1223
55
                BOOST_STATIC_CONSTEXPR source_location loc
1224
55
                    = BOOST_CURRENT_LOCATION;
1225
55
                return fail(cs.begin(), error::syntax, &loc);
1226
0
            }
1227
6.03k
        case '\x22': // '"'
1228
6.03k
            temp.push_back('\x22');
1229
6.03k
            ++cs;
1230
6.03k
            break;
1231
4.35M
        case '\\':
1232
4.35M
            temp.push_back('\\');
1233
4.35M
            ++cs;
1234
4.35M
            break;
1235
3.47k
        case '/':
1236
3.47k
            temp.push_back('/');
1237
3.47k
            ++cs;
1238
3.47k
            break;
1239
111k
        case 'b':
1240
111k
            temp.push_back('\x08');
1241
111k
            ++cs;
1242
111k
            break;
1243
1.62k
        case 'f':
1244
1.62k
            temp.push_back('\x0c');
1245
1.62k
            ++cs;
1246
1.62k
            break;
1247
298
        case 'n':
1248
298
            temp.push_back('\x0a');
1249
298
            ++cs;
1250
298
            break;
1251
409
        case 'r':
1252
409
            temp.push_back('\x0d');
1253
409
            ++cs;
1254
409
            break;
1255
678
        case 't':
1256
678
            temp.push_back('\x09');
1257
678
            ++cs;
1258
678
            break;
1259
153k
        case 'u':
1260
            // utf16 escape
1261
            //
1262
            // fast path only when the buffer
1263
            // is large enough for 2 surrogates
1264
153k
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1265
151k
            {
1266
                // KRYSTIAN TODO: this could be done
1267
                // with fewer instructions
1268
151k
                digit = detail::load_little_endian<4>(
1269
151k
                    cs.begin() + 1);
1270
151k
                int d4 = detail::hex_digit(static_cast<
1271
151k
                    unsigned char>(digit >> 24));
1272
151k
                int d3 = detail::hex_digit(static_cast<
1273
151k
                    unsigned char>(digit >> 16));
1274
151k
                int d2 = detail::hex_digit(static_cast<
1275
151k
                    unsigned char>(digit >> 8));
1276
151k
                int d1 = detail::hex_digit(static_cast<
1277
151k
                    unsigned char>(digit));
1278
151k
                if(BOOST_JSON_UNLIKELY(
1279
151k
                    (d1 | d2 | d3 | d4) == -1))
1280
49
                {
1281
49
                    if(d1 != -1)
1282
19
                        ++cs;
1283
49
                    if(d2 != -1)
1284
17
                        ++cs;
1285
49
                    if(d3 != -1)
1286
13
                        ++cs;
1287
49
                    BOOST_STATIC_CONSTEXPR source_location loc
1288
49
                        = BOOST_CURRENT_LOCATION;
1289
49
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1290
49
                }
1291
                // 32 bit unicode scalar value
1292
151k
                unsigned u1 =
1293
151k
                    (d1 << 12) + (d2 << 8) +
1294
151k
                    (d3 << 4) + d4;
1295
                // valid unicode scalar values are
1296
                // [0, D7FF] and [E000, 10FFFF]
1297
                // values within this range are valid utf-8
1298
                // code points and invalid leading surrogates.
1299
151k
                if(BOOST_JSON_LIKELY(
1300
151k
                    u1 < 0xd800 || u1 > 0xdfff))
1301
78.1k
                {
1302
78.1k
                    cs += 5;
1303
78.1k
                    temp.append_utf8(u1);
1304
78.1k
                    break;
1305
78.1k
                }
1306
73.1k
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1307
15
                {
1308
                    // If it's an illegal leading surrogate and
1309
                    // the parser does not allow it, return an error.
1310
15
                    if(!allow_bad_utf16)
1311
15
                    {
1312
15
                        BOOST_STATIC_CONSTEXPR source_location loc
1313
15
                            = BOOST_CURRENT_LOCATION;
1314
15
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1315
15
                            &loc);
1316
15
                    }
1317
                    // Otherwise, append the Unicode replacement character
1318
0
                    else
1319
0
                    {
1320
0
                        cs += 5;
1321
0
                        temp.append_utf8(urc);
1322
0
                        break;
1323
0
                    }
1324
15
                }
1325
73.0k
                cs += 5;
1326
                // KRYSTIAN TODO: this can be a two byte load
1327
                // and a single comparison. We lose error information,
1328
                // but it's faster.
1329
73.0k
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1330
11
                {
1331
                    // If the next character is not a backslash and
1332
                    // the parser does not allow it, return a syntax error.
1333
11
                    if(!allow_bad_utf16)
1334
11
                    {
1335
11
                        BOOST_STATIC_CONSTEXPR source_location loc
1336
11
                            = BOOST_CURRENT_LOCATION;
1337
11
                        return fail(cs.begin(), error::syntax, &loc);
1338
11
                    }
1339
                    // Otherwise, append the Unicode replacement character since
1340
                    // the first code point is a valid leading surrogate
1341
0
                    else
1342
0
                    {
1343
0
                        temp.append_utf8(urc);
1344
0
                        break;
1345
0
                    }
1346
11
                }
1347
73.0k
                ++cs;
1348
73.0k
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1349
3
                {
1350
3
                    if (!allow_bad_utf16)
1351
3
                    {
1352
3
                        BOOST_STATIC_CONSTEXPR source_location loc
1353
3
                            = BOOST_CURRENT_LOCATION;
1354
3
                        return fail(cs.begin(), error::syntax, &loc);
1355
3
                    }
1356
                    // Otherwise, append the Unicode replacement character since
1357
                    // the first code point is a valid leading surrogate
1358
0
                    else
1359
0
                    {
1360
0
                        temp.append_utf8(urc);
1361
0
                        goto do_str3;
1362
0
                    }
1363
3
                }
1364
73.0k
                ++cs;
1365
73.0k
                digit = detail::load_little_endian<4>(cs.begin());
1366
73.0k
                d4 = detail::hex_digit(static_cast<
1367
73.0k
                    unsigned char>(digit >> 24));
1368
73.0k
                d3 = detail::hex_digit(static_cast<
1369
73.0k
                    unsigned char>(digit >> 16));
1370
73.0k
                d2 = detail::hex_digit(static_cast<
1371
73.0k
                    unsigned char>(digit >> 8));
1372
73.0k
                d1 = detail::hex_digit(static_cast<
1373
73.0k
                    unsigned char>(digit));
1374
73.0k
                if(BOOST_JSON_UNLIKELY(
1375
73.0k
                    (d1 | d2 | d3 | d4) == -1))
1376
59
                {
1377
59
                    if(d1 != -1)
1378
23
                        ++cs;
1379
59
                    if(d2 != -1)
1380
13
                        ++cs;
1381
59
                    if(d3 != -1)
1382
22
                        ++cs;
1383
59
                    BOOST_STATIC_CONSTEXPR source_location loc
1384
59
                        = BOOST_CURRENT_LOCATION;
1385
59
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1386
59
                }
1387
73.0k
                unsigned u2 =
1388
73.0k
                    (d1 << 12) + (d2 << 8) +
1389
73.0k
                    (d3 << 4) + d4;
1390
                // Check if the second code point is a valid trailing surrogate.
1391
                // Valid trailing surrogates are [DC00, DFFF]
1392
73.0k
                if(BOOST_JSON_UNLIKELY(
1393
73.0k
                    u2 < 0xdc00 || u2 > 0xdfff))
1394
27
                {
1395
                    // If not valid and the parser does not allow it, return an error.
1396
27
                    if(!allow_bad_utf16)
1397
27
                    {
1398
27
                        BOOST_STATIC_CONSTEXPR source_location loc
1399
27
                            = BOOST_CURRENT_LOCATION;
1400
27
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1401
27
                            &loc);
1402
27
                    }
1403
                    // Append the replacement character for the
1404
                    // first leading surrogate.
1405
0
                    cs += 4;
1406
0
                    temp.append_utf8(urc);
1407
                    // Check if the second code point is a
1408
                    // valid unicode scalar value (invalid leading
1409
                    // or trailing surrogate)
1410
0
                    if (u2 < 0xd800 || u2 > 0xdbff)
1411
0
                    {
1412
0
                        temp.append_utf8(u2);
1413
0
                        break;
1414
0
                    }
1415
                    // If it is a valid leading surrogate
1416
0
                    else
1417
0
                    {
1418
0
                        u1_ = u2;
1419
0
                        goto do_sur1;
1420
0
                    }
1421
0
                }
1422
72.9k
                cs += 4;
1423
                // Calculate the Unicode code point from the surrogate pair and
1424
                // append the UTF-8 representation.
1425
72.9k
                unsigned cp =
1426
72.9k
                    ((u1 - 0xd800) << 10) +
1427
72.9k
                    ((u2 - 0xdc00)) +
1428
72.9k
                        0x10000;
1429
                // utf-16 surrogate pair
1430
72.9k
                temp.append_utf8(cp);
1431
72.9k
                break;
1432
73.0k
            }
1433
            // flush
1434
1.94k
            if(BOOST_JSON_LIKELY(! temp.empty()))
1435
1.69k
            {
1436
1.69k
                BOOST_ASSERT(total <= max_size);
1437
1.69k
                if(BOOST_JSON_UNLIKELY(
1438
1.69k
                    temp.size() > max_size - total))
1439
0
                {
1440
0
                    BOOST_STATIC_CONSTEXPR source_location loc
1441
0
                        = BOOST_CURRENT_LOCATION;
1442
0
                    return fail(cs.begin(), ev_too_large, &loc);
1443
0
                }
1444
1.69k
                total += temp.size();
1445
1.69k
                {
1446
1.69k
                    bool r = is_key
1447
1.69k
                        ? h_.on_key_part(temp.get(), total, ec_)
1448
1.69k
                        : h_.on_string_part(temp.get(), total, ec_);
1449
1450
1.69k
                    if(BOOST_JSON_UNLIKELY(!r))
1451
0
                    {
1452
0
                        return fail(cs.begin());
1453
0
                    }
1454
1.69k
                }
1455
1.69k
                temp.clear();
1456
1.69k
                cs.clip(temp.max_size());
1457
1.69k
            }
1458
1.94k
            ++cs;
1459
            // utf-16 escape
1460
1.94k
    do_str4:
1461
1.94k
            if(BOOST_JSON_UNLIKELY(! cs))
1462
32
                return maybe_suspend(cs.begin(), state::str4);
1463
1.91k
            digit = detail::hex_digit(*cs);
1464
1.91k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1465
19
            {
1466
19
                BOOST_STATIC_CONSTEXPR source_location loc
1467
19
                    = BOOST_CURRENT_LOCATION;
1468
19
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1469
19
            }
1470
1.89k
            ++cs;
1471
1.89k
            u1_ = digit << 12;
1472
1.89k
    do_str5:
1473
1.89k
            if(BOOST_JSON_UNLIKELY(! cs))
1474
17
                return maybe_suspend(cs.begin(), state::str5);
1475
1.88k
            digit = detail::hex_digit(*cs);
1476
1.88k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1477
14
            {
1478
14
                BOOST_STATIC_CONSTEXPR source_location loc
1479
14
                    = BOOST_CURRENT_LOCATION;
1480
14
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1481
14
            }
1482
1.86k
            ++cs;
1483
1.86k
            u1_ += digit << 8;
1484
1.86k
    do_str6:
1485
1.86k
            if(BOOST_JSON_UNLIKELY(! cs))
1486
23
                return maybe_suspend(cs.begin(), state::str6);
1487
1.84k
            digit = detail::hex_digit(*cs);
1488
1.84k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1489
19
            {
1490
19
                BOOST_STATIC_CONSTEXPR source_location loc
1491
19
                    = BOOST_CURRENT_LOCATION;
1492
19
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1493
19
            }
1494
1.82k
            ++cs;
1495
1.82k
            u1_ += digit << 4;
1496
1.82k
    do_str7:
1497
1.82k
            if(BOOST_JSON_UNLIKELY(! cs))
1498
18
                return maybe_suspend(cs.begin(), state::str7);
1499
1.80k
            digit = detail::hex_digit(*cs);
1500
1.80k
            if(BOOST_JSON_UNLIKELY(digit == -1))
1501
14
            {
1502
14
                BOOST_STATIC_CONSTEXPR source_location loc
1503
14
                    = BOOST_CURRENT_LOCATION;
1504
14
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1505
14
            }
1506
1.79k
            ++cs;
1507
1.79k
            u1_ += digit;
1508
1.79k
            if(BOOST_JSON_LIKELY(
1509
1.79k
                u1_ < 0xd800 || u1_ > 0xdfff))
1510
761
            {
1511
761
                BOOST_ASSERT(temp.empty());
1512
                // utf-8 codepoint
1513
0
                temp.append_utf8(u1_);
1514
761
                break;
1515
761
            }
1516
1.03k
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1517
11
            {
1518
                // If it's an illegal leading surrogate and
1519
                // the parser does not allow it, return an error.
1520
11
                if(!allow_bad_utf16)
1521
11
                {
1522
11
                    BOOST_STATIC_CONSTEXPR source_location loc
1523
11
                        = BOOST_CURRENT_LOCATION;
1524
11
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1525
11
                }
1526
                // Otherwise, append the Unicode replacement character
1527
0
                else
1528
0
                {
1529
0
                    BOOST_ASSERT(temp.empty());
1530
0
                    temp.append_utf8(urc);
1531
0
                    break;
1532
0
                }
1533
11
            }
1534
1.02k
    do_sur1:
1535
1.02k
            if(BOOST_JSON_UNLIKELY(! cs))
1536
15
                return maybe_suspend(cs.begin(), state::sur1);
1537
1.00k
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1538
2
            {
1539
                // If the next character is not a backslash and
1540
                // the parser does not allow it, return a syntax error.
1541
2
                if(!allow_bad_utf16)
1542
2
                {
1543
2
                    BOOST_STATIC_CONSTEXPR source_location loc
1544
2
                        = BOOST_CURRENT_LOCATION;
1545
2
                    return fail(cs.begin(), error::syntax, &loc);
1546
2
                }
1547
                // Otherwise, append the Unicode replacement character since
1548
                // the first code point is a valid leading surrogate
1549
0
                else
1550
0
                {
1551
0
                    temp.append_utf8(urc);
1552
0
                    break;
1553
0
                }
1554
2
            }
1555
1.00k
            ++cs;
1556
1.00k
    do_sur2:
1557
1.00k
            if(BOOST_JSON_UNLIKELY(! cs))
1558
2
                return maybe_suspend(cs.begin(), state::sur2);
1559
1.00k
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1560
11
            {
1561
11
                if (!allow_bad_utf16)
1562
11
                {
1563
11
                    BOOST_STATIC_CONSTEXPR source_location loc
1564
11
                        = BOOST_CURRENT_LOCATION;
1565
11
                    return fail(cs.begin(), error::syntax, &loc);
1566
11
                }
1567
                // Otherwise, append the Unicode replacement character since
1568
                // the first code point is a valid leading surrogate
1569
0
                else
1570
0
                {
1571
0
                    temp.append_utf8(urc);
1572
0
                    goto do_str3;
1573
0
                }
1574
11
            }
1575
991
            ++cs;
1576
991
    do_sur3:
1577
991
            if(BOOST_JSON_UNLIKELY(! cs))
1578
1
                return maybe_suspend(cs.begin(), state::sur3);
1579
990
            digit = detail::hex_digit(*cs);
1580
990
            if(BOOST_JSON_UNLIKELY(digit == -1))
1581
15
            {
1582
15
                BOOST_STATIC_CONSTEXPR source_location loc
1583
15
                    = BOOST_CURRENT_LOCATION;
1584
15
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1585
15
            }
1586
975
            ++cs;
1587
975
            u2_ = digit << 12;
1588
975
    do_sur4:
1589
975
            if(BOOST_JSON_UNLIKELY(! cs))
1590
14
                return maybe_suspend(cs.begin(), state::sur4);
1591
961
            digit = detail::hex_digit(*cs);
1592
961
            if(BOOST_JSON_UNLIKELY(digit == -1))
1593
16
            {
1594
16
                BOOST_STATIC_CONSTEXPR source_location loc
1595
16
                    = BOOST_CURRENT_LOCATION;
1596
16
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1597
16
            }
1598
945
            ++cs;
1599
945
            u2_ += digit << 8;
1600
945
    do_sur5:
1601
945
            if(BOOST_JSON_UNLIKELY(! cs))
1602
11
                return maybe_suspend(cs.begin(), state::sur5);
1603
934
            digit = detail::hex_digit(*cs);
1604
934
            if(BOOST_JSON_UNLIKELY(digit == -1))
1605
17
            {
1606
17
                BOOST_STATIC_CONSTEXPR source_location loc
1607
17
                    = BOOST_CURRENT_LOCATION;
1608
17
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1609
17
            }
1610
917
            ++cs;
1611
917
            u2_ += digit << 4;
1612
917
    do_sur6:
1613
917
            if(BOOST_JSON_UNLIKELY(! cs))
1614
20
                return maybe_suspend(cs.begin(), state::sur6);
1615
897
            digit = detail::hex_digit(*cs);
1616
897
            if(BOOST_JSON_UNLIKELY(digit == -1))
1617
10
            {
1618
10
                BOOST_STATIC_CONSTEXPR source_location loc
1619
10
                    = BOOST_CURRENT_LOCATION;
1620
10
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1621
10
            }
1622
887
            ++cs;
1623
887
            u2_ += digit;
1624
            // Check if the second code point is a valid trailing surrogate.
1625
            // Valid trailing surrogates are [DC00, DFFF]
1626
887
            if(BOOST_JSON_UNLIKELY(
1627
887
                u2_ < 0xdc00 || u2_ > 0xdfff))
1628
25
            {
1629
                // If not valid and the parser does not allow it, return an error.
1630
25
                if(!allow_bad_utf16)
1631
25
                {
1632
25
                    BOOST_STATIC_CONSTEXPR source_location loc
1633
25
                        = BOOST_CURRENT_LOCATION;
1634
25
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1635
25
                }
1636
                // Append the replacement character for the
1637
                // first leading surrogate.
1638
0
                temp.append_utf8(urc);
1639
                // Check if the second code point is a
1640
                // valid unicode scalar value (invalid leading
1641
                // or trailing surrogate)
1642
0
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1643
0
                {
1644
0
                    temp.append_utf8(u2_);
1645
0
                    break;
1646
0
                }
1647
                // If it is a valid leading surrogate
1648
0
                else
1649
0
                {
1650
0
                    u1_ = u2_;
1651
0
                    goto do_sur1;
1652
0
                }
1653
0
            }
1654
            // Calculate the Unicode code point from the surrogate pair and
1655
            // append the UTF-8 representation.
1656
862
            unsigned cp =
1657
862
                ((u1_ - 0xd800) << 10) +
1658
862
                ((u2_ - 0xdc00)) +
1659
862
                    0x10000;
1660
            // utf-16 surrogate pair
1661
862
            temp.append_utf8(cp);
1662
4.63M
        }
1663
1664
        // flush
1665
4.63M
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1666
3.13k
            break;
1667
4.63M
    }
1668
1669
3.13k
    if(BOOST_JSON_LIKELY( temp.size() ))
1670
3.13k
    {
1671
3.13k
        BOOST_ASSERT(total <= max_size);
1672
3.13k
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1673
0
        {
1674
0
            BOOST_STATIC_CONSTEXPR source_location loc
1675
0
                = BOOST_CURRENT_LOCATION;
1676
0
            return fail(cs.begin(), ev_too_large, &loc);
1677
0
        }
1678
1679
3.13k
        total += temp.size();
1680
3.13k
        bool const r = is_key
1681
3.13k
            ? h_.on_key_part(temp.get(), total, ec_)
1682
3.13k
            : h_.on_string_part(temp.get(), total, ec_);
1683
3.13k
        if(BOOST_JSON_UNLIKELY( !r ))
1684
0
            return fail( cs.begin() );
1685
3.13k
    }
1686
1687
3.13k
    return cs.begin();
1688
3.13k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_escaped<false>(char const*, unsigned long&, std::__1::integral_constant<bool, false>, bool, bool)
1689
1690
//----------------------------------------------------------
1691
1692
template<class Handler>
1693
template<
1694
    bool StackEmpty_,
1695
    bool AllowComments_/*,
1696
    bool AllowTrailing_,
1697
    bool AllowBadUTF8_*/>
1698
const char*
1699
basic_parser<Handler>::
1700
parse_object(const char* p,
1701
    std::integral_constant<bool, StackEmpty_> stack_empty,
1702
    std::integral_constant<bool, AllowComments_> allow_comments,
1703
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1704
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1705
    bool allow_bad_utf16)
1706
13.1k
{
1707
13.1k
    detail::const_stream_wrapper cs(p, end_);
1708
13.1k
    std::size_t size;
1709
13.1k
    if(! stack_empty && ! st_.empty())
1710
0
    {
1711
        // resume
1712
0
        state st;
1713
0
        st_.pop(st);
1714
0
        st_.pop(size);
1715
0
        switch(st)
1716
0
        {
1717
0
        default: BOOST_JSON_UNREACHABLE();
1718
0
        case state::obj1: goto do_obj1;
1719
0
        case state::obj2: goto do_obj2;
1720
0
        case state::obj3: goto do_obj3;
1721
0
        case state::obj4: goto do_obj4;
1722
0
        case state::obj5: goto do_obj5;
1723
0
        case state::obj6: goto do_obj6;
1724
0
        case state::obj7: goto do_obj7;
1725
0
        case state::obj8: goto do_obj8;
1726
0
        case state::obj9: goto do_obj9;
1727
0
        case state::obj10: goto do_obj10;
1728
0
        case state::obj11: goto do_obj11;
1729
0
        }
1730
0
    }
1731
13.1k
    BOOST_ASSERT(*cs == '{');
1732
0
    size = 0;
1733
13.1k
    if(BOOST_JSON_UNLIKELY(! depth_))
1734
6
    {
1735
6
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1736
6
        return fail(cs.begin(), error::too_deep, &loc);
1737
6
    }
1738
13.1k
    --depth_;
1739
13.1k
    if(BOOST_JSON_UNLIKELY(
1740
13.1k
        ! h_.on_object_begin(ec_)))
1741
59
        return fail(cs.begin());
1742
13.0k
    ++cs;
1743
    // object:
1744
    //     '{' *ws '}'
1745
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1746
13.0k
do_obj1:
1747
13.0k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1748
13.0k
    if(BOOST_JSON_UNLIKELY(! cs))
1749
65
        return maybe_suspend(cs.begin(), state::obj1, size);
1750
13.0k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1751
10.9k
    {
1752
10.9k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1753
113
        {
1754
113
            if(allow_comments && *cs == '/')
1755
0
            {
1756
0
do_obj2:
1757
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1758
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1759
0
                    return suspend_or_fail(state::obj2, size);
1760
0
                goto do_obj1;
1761
0
            }
1762
113
            BOOST_STATIC_CONSTEXPR source_location loc
1763
113
                = BOOST_CURRENT_LOCATION;
1764
113
            return fail(cs.begin(), error::syntax, &loc);
1765
113
        }
1766
98.1k
loop:
1767
98.1k
        if(BOOST_JSON_UNLIKELY(++size >
1768
98.1k
            Handler::max_object_size))
1769
0
        {
1770
0
            BOOST_STATIC_CONSTEXPR source_location loc
1771
0
                = BOOST_CURRENT_LOCATION;
1772
0
            return fail(cs.begin(), error::object_too_large, &loc);
1773
0
        }
1774
98.1k
do_obj3:
1775
98.1k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1776
98.1k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1777
785
            return suspend_or_fail(state::obj3, size);
1778
97.4k
do_obj4:
1779
97.4k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1780
97.4k
        if(BOOST_JSON_UNLIKELY(! cs))
1781
208
            return maybe_suspend(cs.begin(), state::obj4, size);
1782
97.1k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1783
256
        {
1784
256
            if(allow_comments && *cs == '/')
1785
0
            {
1786
0
do_obj5:
1787
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1788
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1789
0
                    return suspend_or_fail(state::obj5, size);
1790
0
                goto do_obj4;
1791
0
            }
1792
256
            BOOST_STATIC_CONSTEXPR source_location loc
1793
256
                = BOOST_CURRENT_LOCATION;
1794
256
            return fail(cs.begin(), error::syntax, &loc);
1795
256
        }
1796
96.9k
        ++cs;
1797
96.9k
do_obj6:
1798
96.9k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1799
96.9k
        if(BOOST_JSON_UNLIKELY(! cs))
1800
61
            return maybe_suspend(cs.begin(), state::obj6, size);
1801
96.8k
do_obj7:
1802
96.8k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1803
96.8k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1804
4.30k
            return suspend_or_fail(state::obj7, size);
1805
92.5k
do_obj8:
1806
92.5k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1807
92.5k
        if(BOOST_JSON_UNLIKELY(! cs))
1808
593
            return maybe_suspend(cs.begin(), state::obj8, size);
1809
91.9k
        if(BOOST_JSON_LIKELY(*cs == ','))
1810
87.6k
        {
1811
87.6k
            ++cs;
1812
87.6k
do_obj9:
1813
87.6k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1814
87.6k
            if(BOOST_JSON_UNLIKELY(! cs))
1815
88
                return maybe_suspend(cs.begin(), state::obj9, size);
1816
1817
            // loop for next element
1818
87.5k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1819
87.3k
                goto loop;
1820
186
            if(! allow_trailing || *cs != '}')
1821
186
            {
1822
186
                if(allow_comments && *cs == '/')
1823
0
                {
1824
0
do_obj10:
1825
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1826
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1827
0
                        return suspend_or_fail(state::obj10, size);
1828
0
                    goto do_obj9;
1829
0
                }
1830
186
                BOOST_STATIC_CONSTEXPR source_location loc
1831
186
                    = BOOST_CURRENT_LOCATION;
1832
186
                return fail(cs.begin(), error::syntax, &loc);
1833
186
            }
1834
186
        }
1835
4.33k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1836
732
        {
1837
732
            if(allow_comments && *cs == '/')
1838
0
            {
1839
0
do_obj11:
1840
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1841
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1842
0
                    return suspend_or_fail(state::obj11, size);
1843
0
                goto do_obj8;
1844
0
            }
1845
732
            BOOST_STATIC_CONSTEXPR source_location loc
1846
732
                = BOOST_CURRENT_LOCATION;
1847
732
            return fail(cs.begin(), error::syntax, &loc);
1848
732
        }
1849
        // got closing brace, fall through
1850
91.9k
    }
1851
5.68k
    if(BOOST_JSON_UNLIKELY(
1852
5.68k
        ! h_.on_object_end(size, ec_)))
1853
12
        return fail(cs.begin());
1854
5.67k
    ++depth_;
1855
5.67k
    ++cs;
1856
5.67k
    return cs.begin();
1857
5.68k
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_object<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Line
Count
Source
1706
11.3k
{
1707
11.3k
    detail::const_stream_wrapper cs(p, end_);
1708
11.3k
    std::size_t size;
1709
11.3k
    if(! stack_empty && ! st_.empty())
1710
0
    {
1711
        // resume
1712
0
        state st;
1713
0
        st_.pop(st);
1714
0
        st_.pop(size);
1715
0
        switch(st)
1716
0
        {
1717
0
        default: BOOST_JSON_UNREACHABLE();
1718
0
        case state::obj1: goto do_obj1;
1719
0
        case state::obj2: goto do_obj2;
1720
0
        case state::obj3: goto do_obj3;
1721
0
        case state::obj4: goto do_obj4;
1722
0
        case state::obj5: goto do_obj5;
1723
0
        case state::obj6: goto do_obj6;
1724
0
        case state::obj7: goto do_obj7;
1725
0
        case state::obj8: goto do_obj8;
1726
0
        case state::obj9: goto do_obj9;
1727
0
        case state::obj10: goto do_obj10;
1728
0
        case state::obj11: goto do_obj11;
1729
0
        }
1730
0
    }
1731
11.3k
    BOOST_ASSERT(*cs == '{');
1732
0
    size = 0;
1733
11.3k
    if(BOOST_JSON_UNLIKELY(! depth_))
1734
1
    {
1735
1
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1736
1
        return fail(cs.begin(), error::too_deep, &loc);
1737
1
    }
1738
11.3k
    --depth_;
1739
11.3k
    if(BOOST_JSON_UNLIKELY(
1740
11.3k
        ! h_.on_object_begin(ec_)))
1741
59
        return fail(cs.begin());
1742
11.2k
    ++cs;
1743
    // object:
1744
    //     '{' *ws '}'
1745
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1746
11.2k
do_obj1:
1747
11.2k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1748
11.2k
    if(BOOST_JSON_UNLIKELY(! cs))
1749
27
        return maybe_suspend(cs.begin(), state::obj1, size);
1750
11.2k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1751
9.61k
    {
1752
9.61k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1753
50
        {
1754
50
            if(allow_comments && *cs == '/')
1755
0
            {
1756
0
do_obj2:
1757
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1758
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1759
0
                    return suspend_or_fail(state::obj2, size);
1760
0
                goto do_obj1;
1761
0
            }
1762
50
            BOOST_STATIC_CONSTEXPR source_location loc
1763
50
                = BOOST_CURRENT_LOCATION;
1764
50
            return fail(cs.begin(), error::syntax, &loc);
1765
50
        }
1766
95.8k
loop:
1767
95.8k
        if(BOOST_JSON_UNLIKELY(++size >
1768
95.8k
            Handler::max_object_size))
1769
0
        {
1770
0
            BOOST_STATIC_CONSTEXPR source_location loc
1771
0
                = BOOST_CURRENT_LOCATION;
1772
0
            return fail(cs.begin(), error::object_too_large, &loc);
1773
0
        }
1774
95.8k
do_obj3:
1775
95.8k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1776
95.8k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1777
608
            return suspend_or_fail(state::obj3, size);
1778
95.2k
do_obj4:
1779
95.2k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1780
95.2k
        if(BOOST_JSON_UNLIKELY(! cs))
1781
177
            return maybe_suspend(cs.begin(), state::obj4, size);
1782
95.0k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1783
195
        {
1784
195
            if(allow_comments && *cs == '/')
1785
0
            {
1786
0
do_obj5:
1787
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1788
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1789
0
                    return suspend_or_fail(state::obj5, size);
1790
0
                goto do_obj4;
1791
0
            }
1792
195
            BOOST_STATIC_CONSTEXPR source_location loc
1793
195
                = BOOST_CURRENT_LOCATION;
1794
195
            return fail(cs.begin(), error::syntax, &loc);
1795
195
        }
1796
94.8k
        ++cs;
1797
94.8k
do_obj6:
1798
94.8k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1799
94.8k
        if(BOOST_JSON_UNLIKELY(! cs))
1800
28
            return maybe_suspend(cs.begin(), state::obj6, size);
1801
94.8k
do_obj7:
1802
94.8k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1803
94.8k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1804
3.75k
            return suspend_or_fail(state::obj7, size);
1805
91.0k
do_obj8:
1806
91.0k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1807
91.0k
        if(BOOST_JSON_UNLIKELY(! cs))
1808
563
            return maybe_suspend(cs.begin(), state::obj8, size);
1809
90.5k
        if(BOOST_JSON_LIKELY(*cs == ','))
1810
86.4k
        {
1811
86.4k
            ++cs;
1812
86.4k
do_obj9:
1813
86.4k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1814
86.4k
            if(BOOST_JSON_UNLIKELY(! cs))
1815
62
                return maybe_suspend(cs.begin(), state::obj9, size);
1816
1817
            // loop for next element
1818
86.4k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1819
86.2k
                goto loop;
1820
138
            if(! allow_trailing || *cs != '}')
1821
138
            {
1822
138
                if(allow_comments && *cs == '/')
1823
0
                {
1824
0
do_obj10:
1825
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1826
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1827
0
                        return suspend_or_fail(state::obj10, size);
1828
0
                    goto do_obj9;
1829
0
                }
1830
138
                BOOST_STATIC_CONSTEXPR source_location loc
1831
138
                    = BOOST_CURRENT_LOCATION;
1832
138
                return fail(cs.begin(), error::syntax, &loc);
1833
138
            }
1834
138
        }
1835
4.03k
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1836
661
        {
1837
661
            if(allow_comments && *cs == '/')
1838
0
            {
1839
0
do_obj11:
1840
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1841
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1842
0
                    return suspend_or_fail(state::obj11, size);
1843
0
                goto do_obj8;
1844
0
            }
1845
661
            BOOST_STATIC_CONSTEXPR source_location loc
1846
661
                = BOOST_CURRENT_LOCATION;
1847
661
            return fail(cs.begin(), error::syntax, &loc);
1848
661
        }
1849
        // got closing brace, fall through
1850
90.5k
    }
1851
4.98k
    if(BOOST_JSON_UNLIKELY(
1852
4.98k
        ! h_.on_object_end(size, ec_)))
1853
12
        return fail(cs.begin());
1854
4.97k
    ++depth_;
1855
4.97k
    ++cs;
1856
4.97k
    return cs.begin();
1857
4.98k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_object<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_object<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_object<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool, bool)
char const* boost::json::basic_parser<null_parser::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
1706
1.83k
{
1707
1.83k
    detail::const_stream_wrapper cs(p, end_);
1708
1.83k
    std::size_t size;
1709
1.83k
    if(! stack_empty && ! st_.empty())
1710
0
    {
1711
        // resume
1712
0
        state st;
1713
0
        st_.pop(st);
1714
0
        st_.pop(size);
1715
0
        switch(st)
1716
0
        {
1717
0
        default: BOOST_JSON_UNREACHABLE();
1718
0
        case state::obj1: goto do_obj1;
1719
0
        case state::obj2: goto do_obj2;
1720
0
        case state::obj3: goto do_obj3;
1721
0
        case state::obj4: goto do_obj4;
1722
0
        case state::obj5: goto do_obj5;
1723
0
        case state::obj6: goto do_obj6;
1724
0
        case state::obj7: goto do_obj7;
1725
0
        case state::obj8: goto do_obj8;
1726
0
        case state::obj9: goto do_obj9;
1727
0
        case state::obj10: goto do_obj10;
1728
0
        case state::obj11: goto do_obj11;
1729
0
        }
1730
0
    }
1731
1.83k
    BOOST_ASSERT(*cs == '{');
1732
0
    size = 0;
1733
1.83k
    if(BOOST_JSON_UNLIKELY(! depth_))
1734
5
    {
1735
5
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1736
5
        return fail(cs.begin(), error::too_deep, &loc);
1737
5
    }
1738
1.82k
    --depth_;
1739
1.82k
    if(BOOST_JSON_UNLIKELY(
1740
1.82k
        ! h_.on_object_begin(ec_)))
1741
0
        return fail(cs.begin());
1742
1.82k
    ++cs;
1743
    // object:
1744
    //     '{' *ws '}'
1745
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1746
1.82k
do_obj1:
1747
1.82k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1748
1.82k
    if(BOOST_JSON_UNLIKELY(! cs))
1749
38
        return maybe_suspend(cs.begin(), state::obj1, size);
1750
1.78k
    if(BOOST_JSON_LIKELY(*cs != '}'))
1751
1.31k
    {
1752
1.31k
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1753
63
        {
1754
63
            if(allow_comments && *cs == '/')
1755
0
            {
1756
0
do_obj2:
1757
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1758
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1759
0
                    return suspend_or_fail(state::obj2, size);
1760
0
                goto do_obj1;
1761
0
            }
1762
63
            BOOST_STATIC_CONSTEXPR source_location loc
1763
63
                = BOOST_CURRENT_LOCATION;
1764
63
            return fail(cs.begin(), error::syntax, &loc);
1765
63
        }
1766
2.33k
loop:
1767
2.33k
        if(BOOST_JSON_UNLIKELY(++size >
1768
2.33k
            Handler::max_object_size))
1769
0
        {
1770
0
            BOOST_STATIC_CONSTEXPR source_location loc
1771
0
                = BOOST_CURRENT_LOCATION;
1772
0
            return fail(cs.begin(), error::object_too_large, &loc);
1773
0
        }
1774
2.33k
do_obj3:
1775
2.33k
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1776
2.33k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1777
177
            return suspend_or_fail(state::obj3, size);
1778
2.16k
do_obj4:
1779
2.16k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1780
2.16k
        if(BOOST_JSON_UNLIKELY(! cs))
1781
31
            return maybe_suspend(cs.begin(), state::obj4, size);
1782
2.13k
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1783
61
        {
1784
61
            if(allow_comments && *cs == '/')
1785
0
            {
1786
0
do_obj5:
1787
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1788
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1789
0
                    return suspend_or_fail(state::obj5, size);
1790
0
                goto do_obj4;
1791
0
            }
1792
61
            BOOST_STATIC_CONSTEXPR source_location loc
1793
61
                = BOOST_CURRENT_LOCATION;
1794
61
            return fail(cs.begin(), error::syntax, &loc);
1795
61
        }
1796
2.06k
        ++cs;
1797
2.06k
do_obj6:
1798
2.06k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1799
2.06k
        if(BOOST_JSON_UNLIKELY(! cs))
1800
33
            return maybe_suspend(cs.begin(), state::obj6, size);
1801
2.03k
do_obj7:
1802
2.03k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1803
2.03k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1804
548
            return suspend_or_fail(state::obj7, size);
1805
1.48k
do_obj8:
1806
1.48k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1807
1.48k
        if(BOOST_JSON_UNLIKELY(! cs))
1808
30
            return maybe_suspend(cs.begin(), state::obj8, size);
1809
1.45k
        if(BOOST_JSON_LIKELY(*cs == ','))
1810
1.15k
        {
1811
1.15k
            ++cs;
1812
1.15k
do_obj9:
1813
1.15k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1814
1.15k
            if(BOOST_JSON_UNLIKELY(! cs))
1815
26
                return maybe_suspend(cs.begin(), state::obj9, size);
1816
1817
            // loop for next element
1818
1.13k
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1819
1.08k
                goto loop;
1820
48
            if(! allow_trailing || *cs != '}')
1821
48
            {
1822
48
                if(allow_comments && *cs == '/')
1823
0
                {
1824
0
do_obj10:
1825
0
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1826
0
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1827
0
                        return suspend_or_fail(state::obj10, size);
1828
0
                    goto do_obj9;
1829
0
                }
1830
48
                BOOST_STATIC_CONSTEXPR source_location loc
1831
48
                    = BOOST_CURRENT_LOCATION;
1832
48
                return fail(cs.begin(), error::syntax, &loc);
1833
48
            }
1834
48
        }
1835
299
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1836
71
        {
1837
71
            if(allow_comments && *cs == '/')
1838
0
            {
1839
0
do_obj11:
1840
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1841
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1842
0
                    return suspend_or_fail(state::obj11, size);
1843
0
                goto do_obj8;
1844
0
            }
1845
71
            BOOST_STATIC_CONSTEXPR source_location loc
1846
71
                = BOOST_CURRENT_LOCATION;
1847
71
            return fail(cs.begin(), error::syntax, &loc);
1848
71
        }
1849
        // got closing brace, fall through
1850
1.45k
    }
1851
701
    if(BOOST_JSON_UNLIKELY(
1852
701
        ! h_.on_object_end(size, ec_)))
1853
0
        return fail(cs.begin());
1854
701
    ++depth_;
1855
701
    ++cs;
1856
701
    return cs.begin();
1857
701
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_object<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_object<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_object<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool, bool)
1858
1859
//----------------------------------------------------------
1860
1861
template<class Handler>
1862
template<
1863
    bool StackEmpty_,
1864
    bool AllowComments_/*,
1865
    bool AllowTrailing_,
1866
    bool AllowBadUTF8_*/>
1867
const char*
1868
basic_parser<Handler>::
1869
parse_array(const char* p,
1870
    std::integral_constant<bool, StackEmpty_> stack_empty,
1871
    std::integral_constant<bool, AllowComments_> allow_comments,
1872
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1873
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1874
    bool allow_bad_utf16)
1875
19.4k
{
1876
19.4k
    detail::const_stream_wrapper cs(p, end_);
1877
19.4k
    std::size_t size;
1878
19.4k
    if(! stack_empty && ! st_.empty())
1879
0
    {
1880
        // resume
1881
0
        state st;
1882
0
        st_.pop(st);
1883
0
        st_.pop(size);
1884
0
        switch(st)
1885
0
        {
1886
0
        default: BOOST_JSON_UNREACHABLE();
1887
0
        case state::arr1: goto do_arr1;
1888
0
        case state::arr2: goto do_arr2;
1889
0
        case state::arr3: goto do_arr3;
1890
0
        case state::arr4: goto do_arr4;
1891
0
        case state::arr5: goto do_arr5;
1892
0
        case state::arr6: goto do_arr6;
1893
0
        }
1894
0
    }
1895
19.4k
    BOOST_ASSERT(*cs == '[');
1896
0
    size = 0;
1897
19.4k
    if(BOOST_JSON_UNLIKELY(! depth_))
1898
5
    {
1899
5
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1900
5
        return fail(cs.begin(), error::too_deep, &loc);
1901
5
    }
1902
19.4k
    --depth_;
1903
19.4k
    if(BOOST_JSON_UNLIKELY(
1904
19.4k
        ! h_.on_array_begin(ec_)))
1905
49
        return fail(cs.begin());
1906
19.3k
    ++cs;
1907
    // array:
1908
    //     '[' *ws ']'
1909
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1910
19.3k
do_arr1:
1911
19.3k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1912
19.3k
    if(BOOST_JSON_UNLIKELY(! cs))
1913
91
        return maybe_suspend(cs.begin(), state::arr1, size);
1914
19.2k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1915
14.5k
    {
1916
139k
loop:
1917
139k
        if(allow_comments && *cs == '/')
1918
0
        {
1919
0
do_arr2:
1920
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1921
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1922
0
                return suspend_or_fail(state::arr2, size);
1923
0
            goto do_arr1;
1924
0
        }
1925
139k
        if(BOOST_JSON_UNLIKELY(++size >
1926
139k
            Handler::max_array_size))
1927
0
        {
1928
0
            BOOST_STATIC_CONSTEXPR source_location loc
1929
0
                = BOOST_CURRENT_LOCATION;
1930
0
            return fail(cs.begin(), error::array_too_large, &loc);
1931
0
        }
1932
139k
do_arr3:
1933
        // array is not empty, value required
1934
139k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1935
139k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1936
3.62k
            return suspend_or_fail(state::arr3, size);
1937
135k
do_arr4:
1938
135k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1939
135k
        if(BOOST_JSON_UNLIKELY(! cs))
1940
790
            return maybe_suspend(cs.begin(), state::arr4, size);
1941
135k
        if(BOOST_JSON_LIKELY(*cs == ','))
1942
125k
        {
1943
125k
            ++cs;
1944
125k
do_arr5:
1945
125k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1946
125k
            if(BOOST_JSON_UNLIKELY(! cs))
1947
108
                return maybe_suspend(cs.begin(), state::arr5, size);
1948
            // loop for next element
1949
124k
            if(! allow_trailing || *cs != ']')
1950
124k
                goto loop;
1951
124k
        }
1952
10.0k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1953
758
        {
1954
758
            if(allow_comments && *cs == '/')
1955
0
            {
1956
0
do_arr6:
1957
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1958
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1959
0
                    return suspend_or_fail(state::arr6, size);
1960
0
                goto do_arr4;
1961
0
            }
1962
758
            BOOST_STATIC_CONSTEXPR source_location loc
1963
758
                = BOOST_CURRENT_LOCATION;
1964
758
            return fail(cs.begin(), error::syntax, &loc);
1965
758
        }
1966
        // got closing bracket; fall through
1967
135k
    }
1968
13.9k
    if(BOOST_JSON_UNLIKELY(
1969
13.9k
        ! h_.on_array_end(size, ec_)))
1970
33
        return fail(cs.begin());
1971
13.9k
    ++depth_;
1972
13.9k
    ++cs;
1973
13.9k
    return cs.begin();
1974
13.9k
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_array<true, false>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Line
Count
Source
1875
15.9k
{
1876
15.9k
    detail::const_stream_wrapper cs(p, end_);
1877
15.9k
    std::size_t size;
1878
15.9k
    if(! stack_empty && ! st_.empty())
1879
0
    {
1880
        // resume
1881
0
        state st;
1882
0
        st_.pop(st);
1883
0
        st_.pop(size);
1884
0
        switch(st)
1885
0
        {
1886
0
        default: BOOST_JSON_UNREACHABLE();
1887
0
        case state::arr1: goto do_arr1;
1888
0
        case state::arr2: goto do_arr2;
1889
0
        case state::arr3: goto do_arr3;
1890
0
        case state::arr4: goto do_arr4;
1891
0
        case state::arr5: goto do_arr5;
1892
0
        case state::arr6: goto do_arr6;
1893
0
        }
1894
0
    }
1895
15.9k
    BOOST_ASSERT(*cs == '[');
1896
0
    size = 0;
1897
15.9k
    if(BOOST_JSON_UNLIKELY(! depth_))
1898
3
    {
1899
3
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1900
3
        return fail(cs.begin(), error::too_deep, &loc);
1901
3
    }
1902
15.9k
    --depth_;
1903
15.9k
    if(BOOST_JSON_UNLIKELY(
1904
15.9k
        ! h_.on_array_begin(ec_)))
1905
49
        return fail(cs.begin());
1906
15.9k
    ++cs;
1907
    // array:
1908
    //     '[' *ws ']'
1909
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1910
15.9k
do_arr1:
1911
15.9k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1912
15.9k
    if(BOOST_JSON_UNLIKELY(! cs))
1913
49
        return maybe_suspend(cs.begin(), state::arr1, size);
1914
15.8k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1915
11.3k
    {
1916
110k
loop:
1917
110k
        if(allow_comments && *cs == '/')
1918
0
        {
1919
0
do_arr2:
1920
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1921
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1922
0
                return suspend_or_fail(state::arr2, size);
1923
0
            goto do_arr1;
1924
0
        }
1925
110k
        if(BOOST_JSON_UNLIKELY(++size >
1926
110k
            Handler::max_array_size))
1927
0
        {
1928
0
            BOOST_STATIC_CONSTEXPR source_location loc
1929
0
                = BOOST_CURRENT_LOCATION;
1930
0
            return fail(cs.begin(), error::array_too_large, &loc);
1931
0
        }
1932
110k
do_arr3:
1933
        // array is not empty, value required
1934
110k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1935
110k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1936
2.35k
            return suspend_or_fail(state::arr3, size);
1937
108k
do_arr4:
1938
108k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1939
108k
        if(BOOST_JSON_UNLIKELY(! cs))
1940
363
            return maybe_suspend(cs.begin(), state::arr4, size);
1941
107k
        if(BOOST_JSON_LIKELY(*cs == ','))
1942
99.2k
        {
1943
99.2k
            ++cs;
1944
99.2k
do_arr5:
1945
99.2k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1946
99.2k
            if(BOOST_JSON_UNLIKELY(! cs))
1947
34
                return maybe_suspend(cs.begin(), state::arr5, size);
1948
            // loop for next element
1949
99.2k
            if(! allow_trailing || *cs != ']')
1950
99.2k
                goto loop;
1951
99.2k
        }
1952
8.59k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1953
387
        {
1954
387
            if(allow_comments && *cs == '/')
1955
0
            {
1956
0
do_arr6:
1957
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1958
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1959
0
                    return suspend_or_fail(state::arr6, size);
1960
0
                goto do_arr4;
1961
0
            }
1962
387
            BOOST_STATIC_CONSTEXPR source_location loc
1963
387
                = BOOST_CURRENT_LOCATION;
1964
387
            return fail(cs.begin(), error::syntax, &loc);
1965
387
        }
1966
        // got closing bracket; fall through
1967
107k
    }
1968
12.7k
    if(BOOST_JSON_UNLIKELY(
1969
12.7k
        ! h_.on_array_end(size, ec_)))
1970
33
        return fail(cs.begin());
1971
12.6k
    ++depth_;
1972
12.6k
    ++cs;
1973
12.6k
    return cs.begin();
1974
12.7k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_array<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_array<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_array<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool, bool)
char const* boost::json::basic_parser<null_parser::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
1875
3.44k
{
1876
3.44k
    detail::const_stream_wrapper cs(p, end_);
1877
3.44k
    std::size_t size;
1878
3.44k
    if(! stack_empty && ! st_.empty())
1879
0
    {
1880
        // resume
1881
0
        state st;
1882
0
        st_.pop(st);
1883
0
        st_.pop(size);
1884
0
        switch(st)
1885
0
        {
1886
0
        default: BOOST_JSON_UNREACHABLE();
1887
0
        case state::arr1: goto do_arr1;
1888
0
        case state::arr2: goto do_arr2;
1889
0
        case state::arr3: goto do_arr3;
1890
0
        case state::arr4: goto do_arr4;
1891
0
        case state::arr5: goto do_arr5;
1892
0
        case state::arr6: goto do_arr6;
1893
0
        }
1894
0
    }
1895
3.44k
    BOOST_ASSERT(*cs == '[');
1896
0
    size = 0;
1897
3.44k
    if(BOOST_JSON_UNLIKELY(! depth_))
1898
2
    {
1899
2
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1900
2
        return fail(cs.begin(), error::too_deep, &loc);
1901
2
    }
1902
3.44k
    --depth_;
1903
3.44k
    if(BOOST_JSON_UNLIKELY(
1904
3.44k
        ! h_.on_array_begin(ec_)))
1905
0
        return fail(cs.begin());
1906
3.44k
    ++cs;
1907
    // array:
1908
    //     '[' *ws ']'
1909
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1910
3.44k
do_arr1:
1911
3.44k
    cs = detail::count_whitespace(cs.begin(), cs.end());
1912
3.44k
    if(BOOST_JSON_UNLIKELY(! cs))
1913
42
        return maybe_suspend(cs.begin(), state::arr1, size);
1914
3.40k
    if(BOOST_JSON_LIKELY(*cs != ']'))
1915
3.18k
    {
1916
28.9k
loop:
1917
28.9k
        if(allow_comments && *cs == '/')
1918
0
        {
1919
0
do_arr2:
1920
0
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1921
0
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1922
0
                return suspend_or_fail(state::arr2, size);
1923
0
            goto do_arr1;
1924
0
        }
1925
28.9k
        if(BOOST_JSON_UNLIKELY(++size >
1926
28.9k
            Handler::max_array_size))
1927
0
        {
1928
0
            BOOST_STATIC_CONSTEXPR source_location loc
1929
0
                = BOOST_CURRENT_LOCATION;
1930
0
            return fail(cs.begin(), error::array_too_large, &loc);
1931
0
        }
1932
28.9k
do_arr3:
1933
        // array is not empty, value required
1934
28.9k
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1935
28.9k
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1936
1.26k
            return suspend_or_fail(state::arr3, size);
1937
27.7k
do_arr4:
1938
27.7k
        cs = detail::count_whitespace(cs.begin(), cs.end());
1939
27.7k
        if(BOOST_JSON_UNLIKELY(! cs))
1940
427
            return maybe_suspend(cs.begin(), state::arr4, size);
1941
27.2k
        if(BOOST_JSON_LIKELY(*cs == ','))
1942
25.8k
        {
1943
25.8k
            ++cs;
1944
25.8k
do_arr5:
1945
25.8k
            cs = detail::count_whitespace(cs.begin(), cs.end());
1946
25.8k
            if(BOOST_JSON_UNLIKELY(! cs))
1947
74
                return maybe_suspend(cs.begin(), state::arr5, size);
1948
            // loop for next element
1949
25.7k
            if(! allow_trailing || *cs != ']')
1950
25.7k
                goto loop;
1951
25.7k
        }
1952
1.42k
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1953
371
        {
1954
371
            if(allow_comments && *cs == '/')
1955
0
            {
1956
0
do_arr6:
1957
0
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1958
0
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1959
0
                    return suspend_or_fail(state::arr6, size);
1960
0
                goto do_arr4;
1961
0
            }
1962
371
            BOOST_STATIC_CONSTEXPR source_location loc
1963
371
                = BOOST_CURRENT_LOCATION;
1964
371
            return fail(cs.begin(), error::syntax, &loc);
1965
371
        }
1966
        // got closing bracket; fall through
1967
27.2k
    }
1968
1.26k
    if(BOOST_JSON_UNLIKELY(
1969
1.26k
        ! h_.on_array_end(size, ec_)))
1970
0
        return fail(cs.begin());
1971
1.26k
    ++depth_;
1972
1.26k
    ++cs;
1973
1.26k
    return cs.begin();
1974
1.26k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_array<true, true>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<bool, true>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_array<false, false>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, false>, bool, bool, bool)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_array<false, true>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<bool, true>, bool, bool, bool)
1975
1976
//----------------------------------------------------------
1977
1978
template<class Handler>
1979
template<bool StackEmpty_, char First_, number_precision Numbers_>
1980
const char*
1981
basic_parser<Handler>::
1982
parse_number(const char* p,
1983
    std::integral_constant<bool, StackEmpty_> stack_empty,
1984
    std::integral_constant<char, First_> first,
1985
    std::integral_constant<number_precision, Numbers_> mode)
1986
190k
{
1987
190k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
190k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
190k
    bool const negative = first == '-';
1995
190k
    bool const zero_first = first == '0';
1996
190k
    bool const nonzero_first = first == '+';
1997
190k
    detail::const_stream_wrapper cs(p, end_);
1998
190k
    number num;
1999
190k
    const char* begin = cs.begin();
2000
190k
    if(stack_empty || st_.empty())
2001
190k
    {
2002
190k
        num.bias = 0;
2003
190k
        num.exp = 0;
2004
190k
        num.frac = false;
2005
190k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
190k
        BOOST_ASSERT(cs);
2013
190k
        if(negative)
2014
46.3k
            ++cs;
2015
2016
190k
        num.neg = negative;
2017
190k
        num.frac = false;
2018
190k
        num.exp = 0;
2019
190k
        num.bias = 0;
2020
2021
        // fast path
2022
190k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
180k
        {
2024
180k
            int n1;
2025
2026
180k
            if( nonzero_first ||
2027
180k
                (negative && *cs != '0') )
2028
156k
            {
2029
156k
                n1 = detail::count_digits( cs.begin() );
2030
156k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
156k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
156k
                if( ! nonzero_first && n1 == 0 )
2040
18
                {
2041
                    // digit required
2042
18
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
18
                        = BOOST_CURRENT_LOCATION;
2044
18
                    return fail(cs.begin(), error::syntax, &loc);
2045
18
                }
2046
2047
156k
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
156k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
156k
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
156k
                if( n1 == 16 )
2057
42.4k
                {
2058
42.4k
                    goto do_num2;
2059
42.4k
                }
2060
156k
            }
2061
23.5k
            else
2062
23.5k
            {
2063
                // 0. floating-point or 0e integer
2064
23.5k
                num.mant = 0;
2065
23.5k
                n1 = 0;
2066
23.5k
                ++cs;
2067
23.5k
            }
2068
2069
137k
            {
2070
137k
                const char c = *cs;
2071
137k
                if(c != '.')
2072
100k
                {
2073
100k
                    if((c | 32) == 'e')
2074
11.1k
                    {
2075
11.1k
                        ++cs;
2076
11.1k
                        goto do_exp1;
2077
11.1k
                    }
2078
89.7k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
24.8k
                        num.mant = ~num.mant + 1;
2080
89.7k
                    goto finish_signed;
2081
100k
                }
2082
137k
            }
2083
2084
            // floating-point number
2085
2086
36.6k
            ++cs;
2087
2088
36.6k
            int n2 = detail::count_digits( cs.begin() );
2089
36.6k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
36.6k
            if( n2 == 0 )
2092
21
            {
2093
                // digit required
2094
21
                BOOST_STATIC_CONSTEXPR source_location loc
2095
21
                    = BOOST_CURRENT_LOCATION;
2096
21
                return fail(cs.begin(), error::syntax, &loc);
2097
21
            }
2098
2099
            // floating-point mantissa overflow
2100
36.5k
            if( n1 + n2 >= 19 )
2101
2.54k
            {
2102
2.54k
                goto do_num7;
2103
2.54k
            }
2104
2105
34.0k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
34.0k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
34.0k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
34.0k
            cs += n2;
2113
2114
34.0k
            char ch = *cs;
2115
2116
34.0k
            if( (ch | 32) == 'e' )
2117
9.61k
            {
2118
9.61k
                ++cs;
2119
9.61k
                goto do_exp1;
2120
9.61k
            }
2121
24.4k
            else if( ch >= '0' && ch <= '9' )
2122
5.09k
            {
2123
5.09k
                goto do_num8;
2124
5.09k
            }
2125
2126
19.3k
            goto finish_dub;
2127
34.0k
        }
2128
190k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
10.7k
do_num1:
2157
10.7k
    if(zero_first || nonzero_first ||
2158
10.7k
        BOOST_JSON_LIKELY(cs))
2159
10.6k
    {
2160
10.6k
        char const c = *cs;
2161
10.6k
        if(zero_first)
2162
1.87k
        {
2163
1.87k
            ++cs;
2164
1.87k
            num.mant = 0;
2165
1.87k
            goto do_num6;
2166
1.87k
        }
2167
8.76k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
8.76k
            c >= '1' && c <= '9'))
2169
8.44k
        {
2170
8.44k
            ++cs;
2171
8.44k
            num.mant = c - '0';
2172
8.44k
        }
2173
324
        else if(BOOST_JSON_UNLIKELY(
2174
324
            c == '0'))
2175
282
        {
2176
282
            ++cs;
2177
282
            num.mant = 0;
2178
282
            goto do_num6;
2179
282
        }
2180
42
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
42
        else
2189
42
        {
2190
42
            BOOST_STATIC_CONSTEXPR source_location loc
2191
42
                = BOOST_CURRENT_LOCATION;
2192
42
            return fail(cs.begin(), error::syntax, &loc);
2193
42
        }
2194
10.6k
    }
2195
56
    else
2196
56
    {
2197
56
        if(BOOST_JSON_UNLIKELY(
2198
56
            ! h_.on_number_part(
2199
56
                {begin, cs.used(begin)}, ec_)))
2200
24
            return fail(cs.begin());
2201
2202
32
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
32
        return maybe_suspend(
2205
32
            cs.begin(), state::num1, num);
2206
56
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
50.9k
do_num2:
2214
50.9k
    if(negative || (!stack_empty && num.neg))
2215
11.7k
    {
2216
11.7k
        for(;;)
2217
41.3k
        {
2218
41.3k
            if(BOOST_JSON_UNLIKELY(! cs))
2219
350
            {
2220
350
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
350
                goto finish_int;
2232
350
            }
2233
40.9k
            char const c = *cs;
2234
40.9k
            if(BOOST_JSON_LIKELY(
2235
40.9k
                c >= '0' && c <= '9'))
2236
35.7k
            {
2237
35.7k
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
35.7k
                if( num.mant  > 922337203685477580 || (
2240
30.2k
                    num.mant == 922337203685477580 && c > '8'))
2241
6.08k
                    break;
2242
29.6k
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
29.6k
                    num.mant = 10 * num.mant + ( c - '0' );
2244
29.6k
                continue;
2245
35.7k
            }
2246
5.27k
            goto do_num6; // [.eE]
2247
40.9k
        }
2248
11.7k
    }
2249
39.1k
    else
2250
39.1k
    {
2251
39.1k
        for(;;)
2252
132k
        {
2253
132k
            if(BOOST_JSON_UNLIKELY(! cs))
2254
918
            {
2255
918
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
918
                goto finish_int;
2267
918
            }
2268
131k
            char const c = *cs;
2269
131k
            if(BOOST_JSON_LIKELY(
2270
131k
                c >= '0' && c <= '9'))
2271
107k
            {
2272
107k
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
107k
                if( num.mant  > 1844674407370955161 || (
2275
96.9k
                    num.mant == 1844674407370955161 && c > '5'))
2276
14.3k
                    break;
2277
93.0k
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
93.0k
                    num.mant = 10 * num.mant + ( c - '0' );
2279
93.0k
            }
2280
23.9k
            else
2281
23.9k
            {
2282
23.9k
                goto do_num6; // [.eE]
2283
23.9k
            }
2284
131k
        }
2285
39.1k
    }
2286
20.4k
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
20.4k
do_num3:
2294
20.4k
    for(;;)
2295
12.6M
    {
2296
12.6M
        if(BOOST_JSON_UNLIKELY(! cs))
2297
120
        {
2298
120
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
120
            goto finish_dub;
2310
120
        }
2311
12.6M
        char const c = *cs;
2312
12.6M
        if(BOOST_JSON_UNLIKELY(
2313
12.6M
            c >= '0' && c <= '9'))
2314
12.6M
        {
2315
12.6M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
12.6M
            ++cs;
2322
12.6M
            ++num.bias;
2323
12.6M
        }
2324
20.2k
        else if(BOOST_JSON_LIKELY(
2325
20.2k
            c == '.'))
2326
4.68k
        {
2327
4.68k
            ++cs;
2328
4.68k
            break;
2329
4.68k
        }
2330
15.6k
        else if((c | 32) == 'e')
2331
3.58k
        {
2332
3.58k
            ++cs;
2333
3.58k
            goto do_exp1;
2334
3.58k
        }
2335
12.0k
        else
2336
12.0k
        {
2337
12.0k
            goto finish_dub;
2338
12.0k
        }
2339
12.6M
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
4.68k
do_num4:
2348
4.68k
    {
2349
4.68k
        if(BOOST_JSON_UNLIKELY(! cs))
2350
16
        {
2351
16
            if(BOOST_JSON_UNLIKELY(
2352
16
                ! h_.on_number_part(
2353
16
                    {begin, cs.used(begin)}, ec_)))
2354
3
                return fail(cs.begin());
2355
2356
13
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
13
            return maybe_suspend(
2359
13
                cs.begin(), state::num4, num);
2360
16
        }
2361
4.66k
        char const c = *cs;
2362
4.66k
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
4.66k
            c >= '0' && c <= '9'))
2365
4.62k
        {
2366
4.62k
            ++cs;
2367
4.62k
        }
2368
42
        else
2369
42
        {
2370
            // digit required
2371
42
            BOOST_STATIC_CONSTEXPR source_location loc
2372
42
                = BOOST_CURRENT_LOCATION;
2373
42
            return fail(cs.begin(), error::syntax, &loc);
2374
42
        }
2375
4.66k
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
15.4k
do_num5:
2384
15.4k
    for(;;)
2385
171k
    {
2386
171k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
171
        {
2388
171
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
171
            goto finish_dub;
2400
171
        }
2401
171k
        char const c = *cs;
2402
171k
        if(BOOST_JSON_LIKELY(
2403
171k
            c >= '0' && c <= '9'))
2404
156k
        {
2405
156k
            ++cs;
2406
156k
        }
2407
15.3k
        else if((c | 32) == 'e')
2408
6.37k
        {
2409
6.37k
            ++cs;
2410
6.37k
            goto do_exp1;
2411
6.37k
        }
2412
8.92k
        else
2413
8.92k
        {
2414
8.92k
            goto finish_dub;
2415
8.92k
        }
2416
171k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
31.3k
do_num6:
2423
31.3k
    {
2424
31.3k
        if(BOOST_JSON_UNLIKELY(! cs))
2425
59
        {
2426
59
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
59
            goto finish_int;
2438
59
        }
2439
31.3k
        char const c = *cs;
2440
31.3k
        if(BOOST_JSON_LIKELY(
2441
31.3k
            c == '.'))
2442
11.6k
        {
2443
11.6k
            ++cs;
2444
11.6k
        }
2445
19.6k
        else if((c | 32) == 'e')
2446
2.99k
        {
2447
2.99k
            ++cs;
2448
2.99k
            goto do_exp1;
2449
2.99k
        }
2450
16.6k
        else
2451
16.6k
        {
2452
16.6k
            goto finish_int;
2453
16.6k
        }
2454
31.3k
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
14.1k
do_num7:
2463
14.1k
    {
2464
14.1k
        if(BOOST_JSON_UNLIKELY(! cs))
2465
30
        {
2466
30
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
30
            BOOST_STATIC_CONSTEXPR source_location loc
2479
30
                = BOOST_CURRENT_LOCATION;
2480
30
            return fail(cs.begin(), error::syntax, &loc);
2481
30
        }
2482
14.1k
        char const c = *cs;
2483
14.1k
        if(BOOST_JSON_UNLIKELY(
2484
14.1k
            c < '0' || c > '9'))
2485
67
        {
2486
            // digit required
2487
67
            BOOST_STATIC_CONSTEXPR source_location loc
2488
67
                = BOOST_CURRENT_LOCATION;
2489
67
            return fail(cs.begin(), error::syntax, &loc);
2490
67
        }
2491
14.1k
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
19.1k
do_num8:
2500
19.1k
    for(;;)
2501
9.57M
    {
2502
9.57M
        if(BOOST_JSON_UNLIKELY(! cs))
2503
499
        {
2504
499
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
499
            goto finish_dub;
2516
499
        }
2517
9.57M
        char const c = *cs;
2518
9.57M
        if(BOOST_JSON_LIKELY(
2519
9.57M
            c >= '0' && c <= '9'))
2520
9.56M
        {
2521
9.56M
            ++cs;
2522
9.56M
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
9.56M
                num.mant <= 9007199254740991)) // 2^53-1
2524
9.55M
            {
2525
9.55M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
9.55M
                --num.bias;
2532
9.55M
                num.mant = 10 * num.mant + ( c - '0' );
2533
9.55M
            }
2534
10.8k
            else
2535
10.8k
            {
2536
10.8k
                goto do_num5;
2537
10.8k
            }
2538
9.56M
        }
2539
7.82k
        else if((c | 32) == 'e')
2540
5.18k
        {
2541
5.18k
            ++cs;
2542
5.18k
            goto do_exp1;
2543
5.18k
        }
2544
2.64k
        else
2545
2.64k
        {
2546
2.64k
            goto finish_dub;
2547
2.64k
        }
2548
9.57M
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
38.9k
do_exp1:
2555
38.9k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
151
    {
2557
151
        if(BOOST_JSON_UNLIKELY(
2558
151
            ! h_.on_number_part(
2559
151
                {begin, cs.used(begin)}, ec_)))
2560
27
            return fail(cs.begin());
2561
2562
124
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
124
        return maybe_suspend(
2565
124
            cs.begin(), state::exp1, num);
2566
151
    }
2567
38.7k
    if(*cs == '+')
2568
1.49k
    {
2569
1.49k
        ++cs;
2570
1.49k
    }
2571
37.2k
    else if(*cs == '-')
2572
8.42k
    {
2573
8.42k
        ++cs;
2574
8.42k
        num.frac = true;
2575
8.42k
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
38.7k
do_exp2:
2583
38.7k
    {
2584
38.7k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
66
        {
2586
66
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
66
            BOOST_STATIC_CONSTEXPR source_location loc
2599
66
                = BOOST_CURRENT_LOCATION;
2600
66
            return fail(cs.begin(), error::syntax, &loc);
2601
66
        }
2602
38.6k
        char const c = *cs;
2603
38.6k
        if(BOOST_JSON_UNLIKELY(
2604
38.6k
            c < '0' || c > '9'))
2605
138
        {
2606
            // digit required
2607
138
            BOOST_STATIC_CONSTEXPR source_location loc
2608
138
                = BOOST_CURRENT_LOCATION;
2609
138
            return fail(cs.begin(), error::syntax, &loc);
2610
138
        }
2611
38.5k
        ++cs;
2612
38.5k
        num.exp = c - '0';
2613
38.5k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
38.5k
do_exp3:
2621
38.5k
    for(;;)
2622
338k
    {
2623
338k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
1.20k
        {
2625
1.20k
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
1.20k
        }
2637
337k
        else
2638
337k
        {
2639
337k
            char const c = *cs;
2640
337k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
299k
            {
2642
299k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
299k
                    num.exp  >  214748364 ||
2645
299k
                    (num.exp == 214748364 && c > '7')
2646
299k
                ))
2647
67.7k
                    num.exp = INT_MAX;
2648
232k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
232k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
299k
                ++cs;
2652
299k
                continue;
2653
299k
            }
2654
337k
        }
2655
38.5k
        BOOST_ASSERT(num.exp >= 0);
2656
38.5k
        if ( num.frac )
2657
8.39k
        {
2658
8.39k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
4.46k
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
4.46k
                if(BOOST_JSON_UNLIKELY(
2664
4.46k
                    (num.exp == INT_MAX) &&
2665
4.46k
                    (num.bias < 0) &&
2666
4.46k
                    (num.exp + num.bias < 308) &&
2667
4.46k
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
4.46k
                num.bias = 0;
2675
4.46k
                num.exp = INT_MAX;
2676
4.46k
            }
2677
8.39k
        }
2678
30.1k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
4.33k
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
4.33k
            if(BOOST_JSON_UNLIKELY(
2684
4.33k
                (num.exp == INT_MAX) &&
2685
4.33k
                (num.bias > 0) &&
2686
4.33k
                (num.exp - num.bias < 308) &&
2687
4.33k
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
4.33k
            num.bias = 0;
2695
4.33k
            num.exp = INT_MAX;
2696
4.33k
        }
2697
38.5k
        goto finish_dub;
2698
38.5k
    }
2699
2700
18.0k
finish_int:
2701
18.0k
    if(negative || (!stack_empty && num.neg))
2702
2.31k
    {
2703
2.31k
        if(BOOST_JSON_UNLIKELY(
2704
2.31k
            ! h_.on_int64(static_cast<
2705
2.31k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
274
            return fail(cs.begin());
2707
2.03k
        return cs.begin();
2708
2.31k
    }
2709
15.7k
    if(num.mant <= INT64_MAX)
2710
8.53k
    {
2711
98.3k
finish_signed:
2712
98.3k
        if(BOOST_JSON_UNLIKELY(
2713
98.3k
            ! h_.on_int64(static_cast<
2714
98.3k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
143
            return fail(cs.begin());
2716
98.1k
        return cs.begin();
2717
98.3k
    }
2718
7.16k
    if(BOOST_JSON_UNLIKELY(
2719
7.16k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
364
        return fail(cs.begin());
2721
6.80k
    return cs.begin();
2722
82.2k
finish_dub:
2723
82.2k
    double d;
2724
82.2k
    std::size_t const size = cs.used(begin);
2725
82.2k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
82.2k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
82.2k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
82.2k
    else
2747
82.2k
        d = detail::dec_to_float(
2748
82.2k
            num.mant,
2749
82.2k
            num.bias + (num.frac ?
2750
73.8k
                -num.exp : num.exp),
2751
82.2k
            num.neg);
2752
82.2k
    if(BOOST_JSON_UNLIKELY(
2753
82.2k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
887
        return fail(cs.begin());
2755
81.3k
    return cs.begin();
2756
82.2k
}
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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
1986
15.0k
{
1987
15.0k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
15.0k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
15.0k
    bool const negative = first == '-';
1995
15.0k
    bool const zero_first = first == '0';
1996
15.0k
    bool const nonzero_first = first == '+';
1997
15.0k
    detail::const_stream_wrapper cs(p, end_);
1998
15.0k
    number num;
1999
15.0k
    const char* begin = cs.begin();
2000
15.0k
    if(stack_empty || st_.empty())
2001
15.0k
    {
2002
15.0k
        num.bias = 0;
2003
15.0k
        num.exp = 0;
2004
15.0k
        num.frac = false;
2005
15.0k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
15.0k
        BOOST_ASSERT(cs);
2013
15.0k
        if(negative)
2014
0
            ++cs;
2015
2016
15.0k
        num.neg = negative;
2017
15.0k
        num.frac = false;
2018
15.0k
        num.exp = 0;
2019
15.0k
        num.bias = 0;
2020
2021
        // fast path
2022
15.0k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
14.1k
        {
2024
14.1k
            int n1;
2025
2026
14.1k
            if( nonzero_first ||
2027
14.1k
                (negative && *cs != '0') )
2028
0
            {
2029
0
                n1 = detail::count_digits( cs.begin() );
2030
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
0
                if( ! nonzero_first && n1 == 0 )
2040
0
                {
2041
                    // digit required
2042
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
0
                        = BOOST_CURRENT_LOCATION;
2044
0
                    return fail(cs.begin(), error::syntax, &loc);
2045
0
                }
2046
2047
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
0
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
0
                if( n1 == 16 )
2057
0
                {
2058
0
                    goto do_num2;
2059
0
                }
2060
0
            }
2061
14.1k
            else
2062
14.1k
            {
2063
                // 0. floating-point or 0e integer
2064
14.1k
                num.mant = 0;
2065
14.1k
                n1 = 0;
2066
14.1k
                ++cs;
2067
14.1k
            }
2068
2069
14.1k
            {
2070
14.1k
                const char c = *cs;
2071
14.1k
                if(c != '.')
2072
6.66k
                {
2073
6.66k
                    if((c | 32) == 'e')
2074
2.44k
                    {
2075
2.44k
                        ++cs;
2076
2.44k
                        goto do_exp1;
2077
2.44k
                    }
2078
4.22k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
0
                        num.mant = ~num.mant + 1;
2080
4.22k
                    goto finish_signed;
2081
6.66k
                }
2082
14.1k
            }
2083
2084
            // floating-point number
2085
2086
7.50k
            ++cs;
2087
2088
7.50k
            int n2 = detail::count_digits( cs.begin() );
2089
7.50k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
7.50k
            if( n2 == 0 )
2092
3
            {
2093
                // digit required
2094
3
                BOOST_STATIC_CONSTEXPR source_location loc
2095
3
                    = BOOST_CURRENT_LOCATION;
2096
3
                return fail(cs.begin(), error::syntax, &loc);
2097
3
            }
2098
2099
            // floating-point mantissa overflow
2100
7.50k
            if( n1 + n2 >= 19 )
2101
0
            {
2102
0
                goto do_num7;
2103
0
            }
2104
2105
7.50k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
7.50k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
7.50k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
7.50k
            cs += n2;
2113
2114
7.50k
            char ch = *cs;
2115
2116
7.50k
            if( (ch | 32) == 'e' )
2117
2.99k
            {
2118
2.99k
                ++cs;
2119
2.99k
                goto do_exp1;
2120
2.99k
            }
2121
4.50k
            else if( ch >= '0' && ch <= '9' )
2122
1.69k
            {
2123
1.69k
                goto do_num8;
2124
1.69k
            }
2125
2126
2.81k
            goto finish_dub;
2127
7.50k
        }
2128
15.0k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
860
do_num1:
2157
860
    if(zero_first || nonzero_first ||
2158
860
        BOOST_JSON_LIKELY(cs))
2159
860
    {
2160
860
        char const c = *cs;
2161
860
        if(zero_first)
2162
860
        {
2163
860
            ++cs;
2164
860
            num.mant = 0;
2165
860
            goto do_num6;
2166
860
        }
2167
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
0
            c >= '1' && c <= '9'))
2169
0
        {
2170
0
            ++cs;
2171
0
            num.mant = c - '0';
2172
0
        }
2173
0
        else if(BOOST_JSON_UNLIKELY(
2174
0
            c == '0'))
2175
0
        {
2176
0
            ++cs;
2177
0
            num.mant = 0;
2178
0
            goto do_num6;
2179
0
        }
2180
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
0
        else
2189
0
        {
2190
0
            BOOST_STATIC_CONSTEXPR source_location loc
2191
0
                = BOOST_CURRENT_LOCATION;
2192
0
            return fail(cs.begin(), error::syntax, &loc);
2193
0
        }
2194
860
    }
2195
0
    else
2196
0
    {
2197
0
        if(BOOST_JSON_UNLIKELY(
2198
0
            ! h_.on_number_part(
2199
0
                {begin, cs.used(begin)}, ec_)))
2200
0
            return fail(cs.begin());
2201
2202
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
0
        return maybe_suspend(
2205
0
            cs.begin(), state::num1, num);
2206
0
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
0
do_num2:
2214
0
    if(negative || (!stack_empty && num.neg))
2215
0
    {
2216
0
        for(;;)
2217
0
        {
2218
0
            if(BOOST_JSON_UNLIKELY(! cs))
2219
0
            {
2220
0
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
0
                goto finish_int;
2232
0
            }
2233
0
            char const c = *cs;
2234
0
            if(BOOST_JSON_LIKELY(
2235
0
                c >= '0' && c <= '9'))
2236
0
            {
2237
0
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
0
                if( num.mant  > 922337203685477580 || (
2240
0
                    num.mant == 922337203685477580 && c > '8'))
2241
0
                    break;
2242
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
0
                    num.mant = 10 * num.mant + ( c - '0' );
2244
0
                continue;
2245
0
            }
2246
0
            goto do_num6; // [.eE]
2247
0
        }
2248
0
    }
2249
0
    else
2250
0
    {
2251
0
        for(;;)
2252
0
        {
2253
0
            if(BOOST_JSON_UNLIKELY(! cs))
2254
0
            {
2255
0
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
0
                goto finish_int;
2267
0
            }
2268
0
            char const c = *cs;
2269
0
            if(BOOST_JSON_LIKELY(
2270
0
                c >= '0' && c <= '9'))
2271
0
            {
2272
0
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
0
                if( num.mant  > 1844674407370955161 || (
2275
0
                    num.mant == 1844674407370955161 && c > '5'))
2276
0
                    break;
2277
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
0
                    num.mant = 10 * num.mant + ( c - '0' );
2279
0
            }
2280
0
            else
2281
0
            {
2282
0
                goto do_num6; // [.eE]
2283
0
            }
2284
0
        }
2285
0
    }
2286
0
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
0
do_num3:
2294
0
    for(;;)
2295
0
    {
2296
0
        if(BOOST_JSON_UNLIKELY(! cs))
2297
0
        {
2298
0
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
0
            goto finish_dub;
2310
0
        }
2311
0
        char const c = *cs;
2312
0
        if(BOOST_JSON_UNLIKELY(
2313
0
            c >= '0' && c <= '9'))
2314
0
        {
2315
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
0
            ++cs;
2322
0
            ++num.bias;
2323
0
        }
2324
0
        else if(BOOST_JSON_LIKELY(
2325
0
            c == '.'))
2326
0
        {
2327
0
            ++cs;
2328
0
            break;
2329
0
        }
2330
0
        else if((c | 32) == 'e')
2331
0
        {
2332
0
            ++cs;
2333
0
            goto do_exp1;
2334
0
        }
2335
0
        else
2336
0
        {
2337
0
            goto finish_dub;
2338
0
        }
2339
0
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
0
do_num4:
2348
0
    {
2349
0
        if(BOOST_JSON_UNLIKELY(! cs))
2350
0
        {
2351
0
            if(BOOST_JSON_UNLIKELY(
2352
0
                ! h_.on_number_part(
2353
0
                    {begin, cs.used(begin)}, ec_)))
2354
0
                return fail(cs.begin());
2355
2356
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
0
            return maybe_suspend(
2359
0
                cs.begin(), state::num4, num);
2360
0
        }
2361
0
        char const c = *cs;
2362
0
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
0
            c >= '0' && c <= '9'))
2365
0
        {
2366
0
            ++cs;
2367
0
        }
2368
0
        else
2369
0
        {
2370
            // digit required
2371
0
            BOOST_STATIC_CONSTEXPR source_location loc
2372
0
                = BOOST_CURRENT_LOCATION;
2373
0
            return fail(cs.begin(), error::syntax, &loc);
2374
0
        }
2375
0
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
982
do_num5:
2384
982
    for(;;)
2385
6.12k
    {
2386
6.12k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
18
        {
2388
18
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
18
            goto finish_dub;
2400
18
        }
2401
6.10k
        char const c = *cs;
2402
6.10k
        if(BOOST_JSON_LIKELY(
2403
6.10k
            c >= '0' && c <= '9'))
2404
5.14k
        {
2405
5.14k
            ++cs;
2406
5.14k
        }
2407
964
        else if((c | 32) == 'e')
2408
306
        {
2409
306
            ++cs;
2410
306
            goto do_exp1;
2411
306
        }
2412
658
        else
2413
658
        {
2414
658
            goto finish_dub;
2415
658
        }
2416
6.10k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
860
do_num6:
2423
860
    {
2424
860
        if(BOOST_JSON_UNLIKELY(! cs))
2425
35
        {
2426
35
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
35
            goto finish_int;
2438
35
        }
2439
825
        char const c = *cs;
2440
825
        if(BOOST_JSON_LIKELY(
2441
825
            c == '.'))
2442
252
        {
2443
252
            ++cs;
2444
252
        }
2445
573
        else if((c | 32) == 'e')
2446
260
        {
2447
260
            ++cs;
2448
260
            goto do_exp1;
2449
260
        }
2450
313
        else
2451
313
        {
2452
313
            goto finish_int;
2453
313
        }
2454
825
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
252
do_num7:
2463
252
    {
2464
252
        if(BOOST_JSON_UNLIKELY(! cs))
2465
2
        {
2466
2
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
2
            BOOST_STATIC_CONSTEXPR source_location loc
2479
2
                = BOOST_CURRENT_LOCATION;
2480
2
            return fail(cs.begin(), error::syntax, &loc);
2481
2
        }
2482
250
        char const c = *cs;
2483
250
        if(BOOST_JSON_UNLIKELY(
2484
250
            c < '0' || c > '9'))
2485
8
        {
2486
            // digit required
2487
8
            BOOST_STATIC_CONSTEXPR source_location loc
2488
8
                = BOOST_CURRENT_LOCATION;
2489
8
            return fail(cs.begin(), error::syntax, &loc);
2490
8
        }
2491
250
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
1.93k
do_num8:
2500
1.93k
    for(;;)
2501
6.87k
    {
2502
6.87k
        if(BOOST_JSON_UNLIKELY(! cs))
2503
53
        {
2504
53
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
53
            goto finish_dub;
2516
53
        }
2517
6.81k
        char const c = *cs;
2518
6.81k
        if(BOOST_JSON_LIKELY(
2519
6.81k
            c >= '0' && c <= '9'))
2520
5.91k
        {
2521
5.91k
            ++cs;
2522
5.91k
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
5.91k
                num.mant <= 9007199254740991)) // 2^53-1
2524
4.93k
            {
2525
4.93k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
4.93k
                --num.bias;
2532
4.93k
                num.mant = 10 * num.mant + ( c - '0' );
2533
4.93k
            }
2534
982
            else
2535
982
            {
2536
982
                goto do_num5;
2537
982
            }
2538
5.91k
        }
2539
899
        else if((c | 32) == 'e')
2540
329
        {
2541
329
            ++cs;
2542
329
            goto do_exp1;
2543
329
        }
2544
570
        else
2545
570
        {
2546
570
            goto finish_dub;
2547
570
        }
2548
6.81k
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
6.34k
do_exp1:
2555
6.34k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
20
    {
2557
20
        if(BOOST_JSON_UNLIKELY(
2558
20
            ! h_.on_number_part(
2559
20
                {begin, cs.used(begin)}, ec_)))
2560
8
            return fail(cs.begin());
2561
2562
12
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
12
        return maybe_suspend(
2565
12
            cs.begin(), state::exp1, num);
2566
20
    }
2567
6.32k
    if(*cs == '+')
2568
306
    {
2569
306
        ++cs;
2570
306
    }
2571
6.01k
    else if(*cs == '-')
2572
2.17k
    {
2573
2.17k
        ++cs;
2574
2.17k
        num.frac = true;
2575
2.17k
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
6.32k
do_exp2:
2583
6.32k
    {
2584
6.32k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
7
        {
2586
7
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
7
            BOOST_STATIC_CONSTEXPR source_location loc
2599
7
                = BOOST_CURRENT_LOCATION;
2600
7
            return fail(cs.begin(), error::syntax, &loc);
2601
7
        }
2602
6.31k
        char const c = *cs;
2603
6.31k
        if(BOOST_JSON_UNLIKELY(
2604
6.31k
            c < '0' || c > '9'))
2605
27
        {
2606
            // digit required
2607
27
            BOOST_STATIC_CONSTEXPR source_location loc
2608
27
                = BOOST_CURRENT_LOCATION;
2609
27
            return fail(cs.begin(), error::syntax, &loc);
2610
27
        }
2611
6.28k
        ++cs;
2612
6.28k
        num.exp = c - '0';
2613
6.28k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
6.28k
do_exp3:
2621
6.28k
    for(;;)
2622
51.7k
    {
2623
51.7k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
129
        {
2625
129
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
129
        }
2637
51.5k
        else
2638
51.5k
        {
2639
51.5k
            char const c = *cs;
2640
51.5k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
45.4k
            {
2642
45.4k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
45.4k
                    num.exp  >  214748364 ||
2645
45.4k
                    (num.exp == 214748364 && c > '7')
2646
45.4k
                ))
2647
10.5k
                    num.exp = INT_MAX;
2648
34.8k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
34.8k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
45.4k
                ++cs;
2652
45.4k
                continue;
2653
45.4k
            }
2654
51.5k
        }
2655
6.28k
        BOOST_ASSERT(num.exp >= 0);
2656
6.28k
        if ( num.frac )
2657
2.17k
        {
2658
2.17k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
1.31k
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
1.31k
                if(BOOST_JSON_UNLIKELY(
2664
1.31k
                    (num.exp == INT_MAX) &&
2665
1.31k
                    (num.bias < 0) &&
2666
1.31k
                    (num.exp + num.bias < 308) &&
2667
1.31k
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
1.31k
                num.bias = 0;
2675
1.31k
                num.exp = INT_MAX;
2676
1.31k
            }
2677
2.17k
        }
2678
4.10k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
0
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
0
            if(BOOST_JSON_UNLIKELY(
2684
0
                (num.exp == INT_MAX) &&
2685
0
                (num.bias > 0) &&
2686
0
                (num.exp - num.bias < 308) &&
2687
0
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
0
            num.bias = 0;
2695
0
            num.exp = INT_MAX;
2696
0
        }
2697
6.28k
        goto finish_dub;
2698
6.28k
    }
2699
2700
348
finish_int:
2701
348
    if(negative || (!stack_empty && num.neg))
2702
0
    {
2703
0
        if(BOOST_JSON_UNLIKELY(
2704
0
            ! h_.on_int64(static_cast<
2705
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
0
            return fail(cs.begin());
2707
0
        return cs.begin();
2708
0
    }
2709
348
    if(num.mant <= INT64_MAX)
2710
348
    {
2711
4.56k
finish_signed:
2712
4.56k
        if(BOOST_JSON_UNLIKELY(
2713
4.56k
            ! h_.on_int64(static_cast<
2714
4.56k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
24
            return fail(cs.begin());
2716
4.54k
        return cs.begin();
2717
4.56k
    }
2718
0
    if(BOOST_JSON_UNLIKELY(
2719
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
0
        return fail(cs.begin());
2721
0
    return cs.begin();
2722
10.4k
finish_dub:
2723
10.4k
    double d;
2724
10.4k
    std::size_t const size = cs.used(begin);
2725
10.4k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
10.4k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
10.4k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
10.4k
    else
2747
10.4k
        d = detail::dec_to_float(
2748
10.4k
            num.mant,
2749
10.4k
            num.bias + (num.frac ?
2750
8.22k
                -num.exp : num.exp),
2751
10.4k
            num.neg);
2752
10.4k
    if(BOOST_JSON_UNLIKELY(
2753
10.4k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
231
        return fail(cs.begin());
2755
10.1k
    return cs.begin();
2756
10.4k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number<true, (char)48, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number<true, (char)48, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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
1986
37.5k
{
1987
37.5k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
37.5k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
37.5k
    bool const negative = first == '-';
1995
37.5k
    bool const zero_first = first == '0';
1996
37.5k
    bool const nonzero_first = first == '+';
1997
37.5k
    detail::const_stream_wrapper cs(p, end_);
1998
37.5k
    number num;
1999
37.5k
    const char* begin = cs.begin();
2000
37.5k
    if(stack_empty || st_.empty())
2001
37.5k
    {
2002
37.5k
        num.bias = 0;
2003
37.5k
        num.exp = 0;
2004
37.5k
        num.frac = false;
2005
37.5k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
37.5k
        BOOST_ASSERT(cs);
2013
37.5k
        if(negative)
2014
37.5k
            ++cs;
2015
2016
37.5k
        num.neg = negative;
2017
37.5k
        num.frac = false;
2018
37.5k
        num.exp = 0;
2019
37.5k
        num.bias = 0;
2020
2021
        // fast path
2022
37.5k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
36.4k
        {
2024
36.4k
            int n1;
2025
2026
36.4k
            if( nonzero_first ||
2027
36.4k
                (negative && *cs != '0') )
2028
33.6k
            {
2029
33.6k
                n1 = detail::count_digits( cs.begin() );
2030
33.6k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
33.6k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
33.6k
                if( ! nonzero_first && n1 == 0 )
2040
9
                {
2041
                    // digit required
2042
9
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
9
                        = BOOST_CURRENT_LOCATION;
2044
9
                    return fail(cs.begin(), error::syntax, &loc);
2045
9
                }
2046
2047
33.6k
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
33.6k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
33.6k
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
33.6k
                if( n1 == 16 )
2057
6.81k
                {
2058
6.81k
                    goto do_num2;
2059
6.81k
                }
2060
33.6k
            }
2061
2.76k
            else
2062
2.76k
            {
2063
                // 0. floating-point or 0e integer
2064
2.76k
                num.mant = 0;
2065
2.76k
                n1 = 0;
2066
2.76k
                ++cs;
2067
2.76k
            }
2068
2069
29.5k
            {
2070
29.5k
                const char c = *cs;
2071
29.5k
                if(c != '.')
2072
24.6k
                {
2073
24.6k
                    if((c | 32) == 'e')
2074
949
                    {
2075
949
                        ++cs;
2076
949
                        goto do_exp1;
2077
949
                    }
2078
23.6k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
23.6k
                        num.mant = ~num.mant + 1;
2080
23.6k
                    goto finish_signed;
2081
24.6k
                }
2082
29.5k
            }
2083
2084
            // floating-point number
2085
2086
4.96k
            ++cs;
2087
2088
4.96k
            int n2 = detail::count_digits( cs.begin() );
2089
4.96k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
4.96k
            if( n2 == 0 )
2092
2
            {
2093
                // digit required
2094
2
                BOOST_STATIC_CONSTEXPR source_location loc
2095
2
                    = BOOST_CURRENT_LOCATION;
2096
2
                return fail(cs.begin(), error::syntax, &loc);
2097
2
            }
2098
2099
            // floating-point mantissa overflow
2100
4.96k
            if( n1 + n2 >= 19 )
2101
573
            {
2102
573
                goto do_num7;
2103
573
            }
2104
2105
4.38k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
4.38k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
4.38k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
4.38k
            cs += n2;
2113
2114
4.38k
            char ch = *cs;
2115
2116
4.38k
            if( (ch | 32) == 'e' )
2117
651
            {
2118
651
                ++cs;
2119
651
                goto do_exp1;
2120
651
            }
2121
3.73k
            else if( ch >= '0' && ch <= '9' )
2122
1.13k
            {
2123
1.13k
                goto do_num8;
2124
1.13k
            }
2125
2126
2.59k
            goto finish_dub;
2127
4.38k
        }
2128
37.5k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
1.12k
do_num1:
2157
1.12k
    if(zero_first || nonzero_first ||
2158
1.12k
        BOOST_JSON_LIKELY(cs))
2159
1.08k
    {
2160
1.08k
        char const c = *cs;
2161
1.08k
        if(zero_first)
2162
0
        {
2163
0
            ++cs;
2164
0
            num.mant = 0;
2165
0
            goto do_num6;
2166
0
        }
2167
1.08k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
1.08k
            c >= '1' && c <= '9'))
2169
967
        {
2170
967
            ++cs;
2171
967
            num.mant = c - '0';
2172
967
        }
2173
121
        else if(BOOST_JSON_UNLIKELY(
2174
121
            c == '0'))
2175
104
        {
2176
104
            ++cs;
2177
104
            num.mant = 0;
2178
104
            goto do_num6;
2179
104
        }
2180
17
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
17
        else
2189
17
        {
2190
17
            BOOST_STATIC_CONSTEXPR source_location loc
2191
17
                = BOOST_CURRENT_LOCATION;
2192
17
            return fail(cs.begin(), error::syntax, &loc);
2193
17
        }
2194
1.08k
    }
2195
40
    else
2196
40
    {
2197
40
        if(BOOST_JSON_UNLIKELY(
2198
40
            ! h_.on_number_part(
2199
40
                {begin, cs.used(begin)}, ec_)))
2200
24
            return fail(cs.begin());
2201
2202
16
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
16
        return maybe_suspend(
2205
16
            cs.begin(), state::num1, num);
2206
40
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
7.77k
do_num2:
2214
7.77k
    if(negative || (!stack_empty && num.neg))
2215
7.77k
    {
2216
7.77k
        for(;;)
2217
28.8k
        {
2218
28.8k
            if(BOOST_JSON_UNLIKELY(! cs))
2219
204
            {
2220
204
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
204
                goto finish_int;
2232
204
            }
2233
28.6k
            char const c = *cs;
2234
28.6k
            if(BOOST_JSON_LIKELY(
2235
28.6k
                c >= '0' && c <= '9'))
2236
25.6k
            {
2237
25.6k
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
25.6k
                if( num.mant  > 922337203685477580 || (
2240
21.4k
                    num.mant == 922337203685477580 && c > '8'))
2241
4.63k
                    break;
2242
21.0k
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
21.0k
                    num.mant = 10 * num.mant + ( c - '0' );
2244
21.0k
                continue;
2245
25.6k
            }
2246
2.93k
            goto do_num6; // [.eE]
2247
28.6k
        }
2248
7.77k
    }
2249
0
    else
2250
0
    {
2251
0
        for(;;)
2252
0
        {
2253
0
            if(BOOST_JSON_UNLIKELY(! cs))
2254
0
            {
2255
0
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
0
                goto finish_int;
2267
0
            }
2268
0
            char const c = *cs;
2269
0
            if(BOOST_JSON_LIKELY(
2270
0
                c >= '0' && c <= '9'))
2271
0
            {
2272
0
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
0
                if( num.mant  > 1844674407370955161 || (
2275
0
                    num.mant == 1844674407370955161 && c > '5'))
2276
0
                    break;
2277
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
0
                    num.mant = 10 * num.mant + ( c - '0' );
2279
0
            }
2280
0
            else
2281
0
            {
2282
0
                goto do_num6; // [.eE]
2283
0
            }
2284
0
        }
2285
0
    }
2286
4.63k
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
4.63k
do_num3:
2294
4.63k
    for(;;)
2295
345k
    {
2296
345k
        if(BOOST_JSON_UNLIKELY(! cs))
2297
16
        {
2298
16
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
16
            goto finish_dub;
2310
16
        }
2311
345k
        char const c = *cs;
2312
345k
        if(BOOST_JSON_UNLIKELY(
2313
345k
            c >= '0' && c <= '9'))
2314
341k
        {
2315
341k
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
341k
            ++cs;
2322
341k
            ++num.bias;
2323
341k
        }
2324
4.62k
        else if(BOOST_JSON_LIKELY(
2325
4.62k
            c == '.'))
2326
782
        {
2327
782
            ++cs;
2328
782
            break;
2329
782
        }
2330
3.84k
        else if((c | 32) == 'e')
2331
1.44k
        {
2332
1.44k
            ++cs;
2333
1.44k
            goto do_exp1;
2334
1.44k
        }
2335
2.39k
        else
2336
2.39k
        {
2337
2.39k
            goto finish_dub;
2338
2.39k
        }
2339
345k
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
782
do_num4:
2348
782
    {
2349
782
        if(BOOST_JSON_UNLIKELY(! cs))
2350
2
        {
2351
2
            if(BOOST_JSON_UNLIKELY(
2352
2
                ! h_.on_number_part(
2353
2
                    {begin, cs.used(begin)}, ec_)))
2354
1
                return fail(cs.begin());
2355
2356
1
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
1
            return maybe_suspend(
2359
1
                cs.begin(), state::num4, num);
2360
2
        }
2361
780
        char const c = *cs;
2362
780
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
780
            c >= '0' && c <= '9'))
2365
774
        {
2366
774
            ++cs;
2367
774
        }
2368
6
        else
2369
6
        {
2370
            // digit required
2371
6
            BOOST_STATIC_CONSTEXPR source_location loc
2372
6
                = BOOST_CURRENT_LOCATION;
2373
6
            return fail(cs.begin(), error::syntax, &loc);
2374
6
        }
2375
780
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
3.03k
do_num5:
2384
3.03k
    for(;;)
2385
19.6k
    {
2386
19.6k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
24
        {
2388
24
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
24
            goto finish_dub;
2400
24
        }
2401
19.6k
        char const c = *cs;
2402
19.6k
        if(BOOST_JSON_LIKELY(
2403
19.6k
            c >= '0' && c <= '9'))
2404
16.6k
        {
2405
16.6k
            ++cs;
2406
16.6k
        }
2407
3.01k
        else if((c | 32) == 'e')
2408
718
        {
2409
718
            ++cs;
2410
718
            goto do_exp1;
2411
718
        }
2412
2.29k
        else
2413
2.29k
        {
2414
2.29k
            goto finish_dub;
2415
2.29k
        }
2416
19.6k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
3.03k
do_num6:
2423
3.03k
    {
2424
3.03k
        if(BOOST_JSON_UNLIKELY(! cs))
2425
5
        {
2426
5
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
5
            goto finish_int;
2438
5
        }
2439
3.03k
        char const c = *cs;
2440
3.03k
        if(BOOST_JSON_LIKELY(
2441
3.03k
            c == '.'))
2442
1.25k
        {
2443
1.25k
            ++cs;
2444
1.25k
        }
2445
1.77k
        else if((c | 32) == 'e')
2446
693
        {
2447
693
            ++cs;
2448
693
            goto do_exp1;
2449
693
        }
2450
1.08k
        else
2451
1.08k
        {
2452
1.08k
            goto finish_int;
2453
1.08k
        }
2454
3.03k
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
1.83k
do_num7:
2463
1.83k
    {
2464
1.83k
        if(BOOST_JSON_UNLIKELY(! cs))
2465
5
        {
2466
5
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
5
            BOOST_STATIC_CONSTEXPR source_location loc
2479
5
                = BOOST_CURRENT_LOCATION;
2480
5
            return fail(cs.begin(), error::syntax, &loc);
2481
5
        }
2482
1.82k
        char const c = *cs;
2483
1.82k
        if(BOOST_JSON_UNLIKELY(
2484
1.82k
            c < '0' || c > '9'))
2485
12
        {
2486
            // digit required
2487
12
            BOOST_STATIC_CONSTEXPR source_location loc
2488
12
                = BOOST_CURRENT_LOCATION;
2489
12
            return fail(cs.begin(), error::syntax, &loc);
2490
12
        }
2491
1.82k
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
2.95k
do_num8:
2500
2.95k
    for(;;)
2501
81.7k
    {
2502
81.7k
        if(BOOST_JSON_UNLIKELY(! cs))
2503
39
        {
2504
39
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
39
            goto finish_dub;
2516
39
        }
2517
81.7k
        char const c = *cs;
2518
81.7k
        if(BOOST_JSON_LIKELY(
2519
81.7k
            c >= '0' && c <= '9'))
2520
81.0k
        {
2521
81.0k
            ++cs;
2522
81.0k
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
81.0k
                num.mant <= 9007199254740991)) // 2^53-1
2524
78.8k
            {
2525
78.8k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
78.8k
                --num.bias;
2532
78.8k
                num.mant = 10 * num.mant + ( c - '0' );
2533
78.8k
            }
2534
2.26k
            else
2535
2.26k
            {
2536
2.26k
                goto do_num5;
2537
2.26k
            }
2538
81.0k
        }
2539
649
        else if((c | 32) == 'e')
2540
314
        {
2541
314
            ++cs;
2542
314
            goto do_exp1;
2543
314
        }
2544
335
        else
2545
335
        {
2546
335
            goto finish_dub;
2547
335
        }
2548
81.7k
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
4.77k
do_exp1:
2555
4.77k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
14
    {
2557
14
        if(BOOST_JSON_UNLIKELY(
2558
14
            ! h_.on_number_part(
2559
14
                {begin, cs.used(begin)}, ec_)))
2560
5
            return fail(cs.begin());
2561
2562
9
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
9
        return maybe_suspend(
2565
9
            cs.begin(), state::exp1, num);
2566
14
    }
2567
4.75k
    if(*cs == '+')
2568
340
    {
2569
340
        ++cs;
2570
340
    }
2571
4.41k
    else if(*cs == '-')
2572
1.24k
    {
2573
1.24k
        ++cs;
2574
1.24k
        num.frac = true;
2575
1.24k
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
4.75k
do_exp2:
2583
4.75k
    {
2584
4.75k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
9
        {
2586
9
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
9
            BOOST_STATIC_CONSTEXPR source_location loc
2599
9
                = BOOST_CURRENT_LOCATION;
2600
9
            return fail(cs.begin(), error::syntax, &loc);
2601
9
        }
2602
4.74k
        char const c = *cs;
2603
4.74k
        if(BOOST_JSON_UNLIKELY(
2604
4.74k
            c < '0' || c > '9'))
2605
17
        {
2606
            // digit required
2607
17
            BOOST_STATIC_CONSTEXPR source_location loc
2608
17
                = BOOST_CURRENT_LOCATION;
2609
17
            return fail(cs.begin(), error::syntax, &loc);
2610
17
        }
2611
4.73k
        ++cs;
2612
4.73k
        num.exp = c - '0';
2613
4.73k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
4.73k
do_exp3:
2621
4.73k
    for(;;)
2622
42.3k
    {
2623
42.3k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
122
        {
2625
122
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
122
        }
2637
42.1k
        else
2638
42.1k
        {
2639
42.1k
            char const c = *cs;
2640
42.1k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
37.5k
            {
2642
37.5k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
37.5k
                    num.exp  >  214748364 ||
2645
37.5k
                    (num.exp == 214748364 && c > '7')
2646
37.5k
                ))
2647
7.76k
                    num.exp = INT_MAX;
2648
29.8k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
29.8k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
37.5k
                ++cs;
2652
37.5k
                continue;
2653
37.5k
            }
2654
42.1k
        }
2655
4.73k
        BOOST_ASSERT(num.exp >= 0);
2656
4.73k
        if ( num.frac )
2657
1.24k
        {
2658
1.24k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
647
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
647
                if(BOOST_JSON_UNLIKELY(
2664
647
                    (num.exp == INT_MAX) &&
2665
647
                    (num.bias < 0) &&
2666
647
                    (num.exp + num.bias < 308) &&
2667
647
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
647
                num.bias = 0;
2675
647
                num.exp = INT_MAX;
2676
647
            }
2677
1.24k
        }
2678
3.48k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
937
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
937
            if(BOOST_JSON_UNLIKELY(
2684
937
                (num.exp == INT_MAX) &&
2685
937
                (num.bias > 0) &&
2686
937
                (num.exp - num.bias < 308) &&
2687
937
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
937
            num.bias = 0;
2695
937
            num.exp = INT_MAX;
2696
937
        }
2697
4.73k
        goto finish_dub;
2698
4.73k
    }
2699
2700
1.29k
finish_int:
2701
1.29k
    if(negative || (!stack_empty && num.neg))
2702
1.29k
    {
2703
1.29k
        if(BOOST_JSON_UNLIKELY(
2704
1.29k
            ! h_.on_int64(static_cast<
2705
1.29k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
274
            return fail(cs.begin());
2707
1.01k
        return cs.begin();
2708
1.29k
    }
2709
0
    if(num.mant <= INT64_MAX)
2710
0
    {
2711
23.6k
finish_signed:
2712
23.6k
        if(BOOST_JSON_UNLIKELY(
2713
23.6k
            ! h_.on_int64(static_cast<
2714
23.6k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
27
            return fail(cs.begin());
2716
23.6k
        return cs.begin();
2717
23.6k
    }
2718
0
    if(BOOST_JSON_UNLIKELY(
2719
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
0
        return fail(cs.begin());
2721
0
    return cs.begin();
2722
12.4k
finish_dub:
2723
12.4k
    double d;
2724
12.4k
    std::size_t const size = cs.used(begin);
2725
12.4k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
12.4k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
12.4k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
12.4k
    else
2747
12.4k
        d = detail::dec_to_float(
2748
12.4k
            num.mant,
2749
12.4k
            num.bias + (num.frac ?
2750
11.1k
                -num.exp : num.exp),
2751
12.4k
            num.neg);
2752
12.4k
    if(BOOST_JSON_UNLIKELY(
2753
12.4k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
302
        return fail(cs.begin());
2755
12.1k
    return cs.begin();
2756
12.4k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number<true, (char)45, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number<true, (char)45, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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
1986
110k
{
1987
110k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
110k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
110k
    bool const negative = first == '-';
1995
110k
    bool const zero_first = first == '0';
1996
110k
    bool const nonzero_first = first == '+';
1997
110k
    detail::const_stream_wrapper cs(p, end_);
1998
110k
    number num;
1999
110k
    const char* begin = cs.begin();
2000
110k
    if(stack_empty || st_.empty())
2001
110k
    {
2002
110k
        num.bias = 0;
2003
110k
        num.exp = 0;
2004
110k
        num.frac = false;
2005
110k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
110k
        BOOST_ASSERT(cs);
2013
110k
        if(negative)
2014
0
            ++cs;
2015
2016
110k
        num.neg = negative;
2017
110k
        num.frac = false;
2018
110k
        num.exp = 0;
2019
110k
        num.bias = 0;
2020
2021
        // fast path
2022
110k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
106k
        {
2024
106k
            int n1;
2025
2026
106k
            if( nonzero_first ||
2027
106k
                (negative && *cs != '0') )
2028
106k
            {
2029
106k
                n1 = detail::count_digits( cs.begin() );
2030
106k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
106k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
106k
                if( ! nonzero_first && n1 == 0 )
2040
0
                {
2041
                    // digit required
2042
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
0
                        = BOOST_CURRENT_LOCATION;
2044
0
                    return fail(cs.begin(), error::syntax, &loc);
2045
0
                }
2046
2047
106k
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
106k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
106k
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
106k
                if( n1 == 16 )
2057
29.6k
                {
2058
29.6k
                    goto do_num2;
2059
29.6k
                }
2060
106k
            }
2061
0
            else
2062
0
            {
2063
                // 0. floating-point or 0e integer
2064
0
                num.mant = 0;
2065
0
                n1 = 0;
2066
0
                ++cs;
2067
0
            }
2068
2069
76.5k
            {
2070
76.5k
                const char c = *cs;
2071
76.5k
                if(c != '.')
2072
60.4k
                {
2073
60.4k
                    if((c | 32) == 'e')
2074
4.52k
                    {
2075
4.52k
                        ++cs;
2076
4.52k
                        goto do_exp1;
2077
4.52k
                    }
2078
55.8k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
0
                        num.mant = ~num.mant + 1;
2080
55.8k
                    goto finish_signed;
2081
60.4k
                }
2082
76.5k
            }
2083
2084
            // floating-point number
2085
2086
16.0k
            ++cs;
2087
2088
16.0k
            int n2 = detail::count_digits( cs.begin() );
2089
16.0k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
16.0k
            if( n2 == 0 )
2092
7
            {
2093
                // digit required
2094
7
                BOOST_STATIC_CONSTEXPR source_location loc
2095
7
                    = BOOST_CURRENT_LOCATION;
2096
7
                return fail(cs.begin(), error::syntax, &loc);
2097
7
            }
2098
2099
            // floating-point mantissa overflow
2100
16.0k
            if( n1 + n2 >= 19 )
2101
1.54k
            {
2102
1.54k
                goto do_num7;
2103
1.54k
            }
2104
2105
14.5k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
14.5k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
14.5k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
14.5k
            cs += n2;
2113
2114
14.5k
            char ch = *cs;
2115
2116
14.5k
            if( (ch | 32) == 'e' )
2117
4.18k
            {
2118
4.18k
                ++cs;
2119
4.18k
                goto do_exp1;
2120
4.18k
            }
2121
10.3k
            else if( ch >= '0' && ch <= '9' )
2122
738
            {
2123
738
                goto do_num8;
2124
738
            }
2125
2126
9.60k
            goto finish_dub;
2127
14.5k
        }
2128
110k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
4.05k
do_num1:
2157
4.05k
    if(zero_first || nonzero_first ||
2158
4.05k
        BOOST_JSON_LIKELY(cs))
2159
4.05k
    {
2160
4.05k
        char const c = *cs;
2161
4.05k
        if(zero_first)
2162
0
        {
2163
0
            ++cs;
2164
0
            num.mant = 0;
2165
0
            goto do_num6;
2166
0
        }
2167
4.05k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
4.05k
            c >= '1' && c <= '9'))
2169
4.05k
        {
2170
4.05k
            ++cs;
2171
4.05k
            num.mant = c - '0';
2172
4.05k
        }
2173
0
        else if(BOOST_JSON_UNLIKELY(
2174
0
            c == '0'))
2175
0
        {
2176
0
            ++cs;
2177
0
            num.mant = 0;
2178
0
            goto do_num6;
2179
0
        }
2180
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
0
        else
2189
0
        {
2190
0
            BOOST_STATIC_CONSTEXPR source_location loc
2191
0
                = BOOST_CURRENT_LOCATION;
2192
0
            return fail(cs.begin(), error::syntax, &loc);
2193
0
        }
2194
4.05k
    }
2195
0
    else
2196
0
    {
2197
0
        if(BOOST_JSON_UNLIKELY(
2198
0
            ! h_.on_number_part(
2199
0
                {begin, cs.used(begin)}, ec_)))
2200
0
            return fail(cs.begin());
2201
2202
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
0
        return maybe_suspend(
2205
0
            cs.begin(), state::num1, num);
2206
0
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
33.6k
do_num2:
2214
33.6k
    if(negative || (!stack_empty && num.neg))
2215
0
    {
2216
0
        for(;;)
2217
0
        {
2218
0
            if(BOOST_JSON_UNLIKELY(! cs))
2219
0
            {
2220
0
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
0
                goto finish_int;
2232
0
            }
2233
0
            char const c = *cs;
2234
0
            if(BOOST_JSON_LIKELY(
2235
0
                c >= '0' && c <= '9'))
2236
0
            {
2237
0
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
0
                if( num.mant  > 922337203685477580 || (
2240
0
                    num.mant == 922337203685477580 && c > '8'))
2241
0
                    break;
2242
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
0
                    num.mant = 10 * num.mant + ( c - '0' );
2244
0
                continue;
2245
0
            }
2246
0
            goto do_num6; // [.eE]
2247
0
        }
2248
0
    }
2249
33.6k
    else
2250
33.6k
    {
2251
33.6k
        for(;;)
2252
114k
        {
2253
114k
            if(BOOST_JSON_UNLIKELY(! cs))
2254
644
            {
2255
644
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
644
                goto finish_int;
2267
644
            }
2268
113k
            char const c = *cs;
2269
113k
            if(BOOST_JSON_LIKELY(
2270
113k
                c >= '0' && c <= '9'))
2271
93.7k
            {
2272
93.7k
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
93.7k
                if( num.mant  > 1844674407370955161 || (
2275
84.6k
                    num.mant == 1844674407370955161 && c > '5'))
2276
12.7k
                    break;
2277
80.9k
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
80.9k
                    num.mant = 10 * num.mant + ( c - '0' );
2279
80.9k
            }
2280
20.2k
            else
2281
20.2k
            {
2282
20.2k
                goto do_num6; // [.eE]
2283
20.2k
            }
2284
113k
        }
2285
33.6k
    }
2286
12.7k
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
12.7k
do_num3:
2294
12.7k
    for(;;)
2295
478k
    {
2296
478k
        if(BOOST_JSON_UNLIKELY(! cs))
2297
19
        {
2298
19
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
19
            goto finish_dub;
2310
19
        }
2311
478k
        char const c = *cs;
2312
478k
        if(BOOST_JSON_UNLIKELY(
2313
478k
            c >= '0' && c <= '9'))
2314
465k
        {
2315
465k
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
465k
            ++cs;
2322
465k
            ++num.bias;
2323
465k
        }
2324
12.7k
        else if(BOOST_JSON_LIKELY(
2325
12.7k
            c == '.'))
2326
3.31k
        {
2327
3.31k
            ++cs;
2328
3.31k
            break;
2329
3.31k
        }
2330
9.45k
        else if((c | 32) == 'e')
2331
815
        {
2332
815
            ++cs;
2333
815
            goto do_exp1;
2334
815
        }
2335
8.64k
        else
2336
8.64k
        {
2337
8.64k
            goto finish_dub;
2338
8.64k
        }
2339
478k
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
3.31k
do_num4:
2348
3.31k
    {
2349
3.31k
        if(BOOST_JSON_UNLIKELY(! cs))
2350
3
        {
2351
3
            if(BOOST_JSON_UNLIKELY(
2352
3
                ! h_.on_number_part(
2353
3
                    {begin, cs.used(begin)}, ec_)))
2354
2
                return fail(cs.begin());
2355
2356
1
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
1
            return maybe_suspend(
2359
1
                cs.begin(), state::num4, num);
2360
3
        }
2361
3.30k
        char const c = *cs;
2362
3.30k
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
3.30k
            c >= '0' && c <= '9'))
2365
3.29k
        {
2366
3.29k
            ++cs;
2367
3.29k
        }
2368
8
        else
2369
8
        {
2370
            // digit required
2371
8
            BOOST_STATIC_CONSTEXPR source_location loc
2372
8
                = BOOST_CURRENT_LOCATION;
2373
8
            return fail(cs.begin(), error::syntax, &loc);
2374
8
        }
2375
3.30k
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
8.79k
do_num5:
2384
8.79k
    for(;;)
2385
78.2k
    {
2386
78.2k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
38
        {
2388
38
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
38
            goto finish_dub;
2400
38
        }
2401
78.2k
        char const c = *cs;
2402
78.2k
        if(BOOST_JSON_LIKELY(
2403
78.2k
            c >= '0' && c <= '9'))
2404
69.4k
        {
2405
69.4k
            ++cs;
2406
69.4k
        }
2407
8.75k
        else if((c | 32) == 'e')
2408
4.75k
        {
2409
4.75k
            ++cs;
2410
4.75k
            goto do_exp1;
2411
4.75k
        }
2412
3.99k
        else
2413
3.99k
        {
2414
3.99k
            goto finish_dub;
2415
3.99k
        }
2416
78.2k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
20.2k
do_num6:
2423
20.2k
    {
2424
20.2k
        if(BOOST_JSON_UNLIKELY(! cs))
2425
0
        {
2426
0
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
0
            goto finish_int;
2438
0
        }
2439
20.2k
        char const c = *cs;
2440
20.2k
        if(BOOST_JSON_LIKELY(
2441
20.2k
            c == '.'))
2442
7.53k
        {
2443
7.53k
            ++cs;
2444
7.53k
        }
2445
12.6k
        else if((c | 32) == 'e')
2446
595
        {
2447
595
            ++cs;
2448
595
            goto do_exp1;
2449
595
        }
2450
12.1k
        else
2451
12.1k
        {
2452
12.1k
            goto finish_int;
2453
12.1k
        }
2454
20.2k
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
9.08k
do_num7:
2463
9.08k
    {
2464
9.08k
        if(BOOST_JSON_UNLIKELY(! cs))
2465
3
        {
2466
3
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
3
            BOOST_STATIC_CONSTEXPR source_location loc
2479
3
                = BOOST_CURRENT_LOCATION;
2480
3
            return fail(cs.begin(), error::syntax, &loc);
2481
3
        }
2482
9.08k
        char const c = *cs;
2483
9.08k
        if(BOOST_JSON_UNLIKELY(
2484
9.08k
            c < '0' || c > '9'))
2485
13
        {
2486
            // digit required
2487
13
            BOOST_STATIC_CONSTEXPR source_location loc
2488
13
                = BOOST_CURRENT_LOCATION;
2489
13
            return fail(cs.begin(), error::syntax, &loc);
2490
13
        }
2491
9.08k
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
9.80k
do_num8:
2500
9.80k
    for(;;)
2501
26.7k
    {
2502
26.7k
        if(BOOST_JSON_UNLIKELY(! cs))
2503
77
        {
2504
77
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
77
            goto finish_dub;
2516
77
        }
2517
26.6k
        char const c = *cs;
2518
26.6k
        if(BOOST_JSON_LIKELY(
2519
26.6k
            c >= '0' && c <= '9'))
2520
22.4k
        {
2521
22.4k
            ++cs;
2522
22.4k
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
22.4k
                num.mant <= 9007199254740991)) // 2^53-1
2524
16.9k
            {
2525
16.9k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
16.9k
                --num.bias;
2532
16.9k
                num.mant = 10 * num.mant + ( c - '0' );
2533
16.9k
            }
2534
5.49k
            else
2535
5.49k
            {
2536
5.49k
                goto do_num5;
2537
5.49k
            }
2538
22.4k
        }
2539
4.23k
        else if((c | 32) == 'e')
2540
3.73k
        {
2541
3.73k
            ++cs;
2542
3.73k
            goto do_exp1;
2543
3.73k
        }
2544
507
        else
2545
507
        {
2546
507
            goto finish_dub;
2547
507
        }
2548
26.6k
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
18.6k
do_exp1:
2555
18.6k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
27
    {
2557
27
        if(BOOST_JSON_UNLIKELY(
2558
27
            ! h_.on_number_part(
2559
27
                {begin, cs.used(begin)}, ec_)))
2560
14
            return fail(cs.begin());
2561
2562
13
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
13
        return maybe_suspend(
2565
13
            cs.begin(), state::exp1, num);
2566
27
    }
2567
18.5k
    if(*cs == '+')
2568
266
    {
2569
266
        ++cs;
2570
266
    }
2571
18.3k
    else if(*cs == '-')
2572
2.68k
    {
2573
2.68k
        ++cs;
2574
2.68k
        num.frac = true;
2575
2.68k
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
18.5k
do_exp2:
2583
18.5k
    {
2584
18.5k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
5
        {
2586
5
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
5
            BOOST_STATIC_CONSTEXPR source_location loc
2599
5
                = BOOST_CURRENT_LOCATION;
2600
5
            return fail(cs.begin(), error::syntax, &loc);
2601
5
        }
2602
18.5k
        char const c = *cs;
2603
18.5k
        if(BOOST_JSON_UNLIKELY(
2604
18.5k
            c < '0' || c > '9'))
2605
23
        {
2606
            // digit required
2607
23
            BOOST_STATIC_CONSTEXPR source_location loc
2608
23
                = BOOST_CURRENT_LOCATION;
2609
23
            return fail(cs.begin(), error::syntax, &loc);
2610
23
        }
2611
18.5k
        ++cs;
2612
18.5k
        num.exp = c - '0';
2613
18.5k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
18.5k
do_exp3:
2621
18.5k
    for(;;)
2622
199k
    {
2623
199k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
156
        {
2625
156
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
156
        }
2637
198k
        else
2638
198k
        {
2639
198k
            char const c = *cs;
2640
198k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
180k
            {
2642
180k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
180k
                    num.exp  >  214748364 ||
2645
180k
                    (num.exp == 214748364 && c > '7')
2646
180k
                ))
2647
41.7k
                    num.exp = INT_MAX;
2648
138k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
138k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
180k
                ++cs;
2652
180k
                continue;
2653
180k
            }
2654
198k
        }
2655
18.5k
        BOOST_ASSERT(num.exp >= 0);
2656
18.5k
        if ( num.frac )
2657
2.68k
        {
2658
2.68k
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
1.22k
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
1.22k
                if(BOOST_JSON_UNLIKELY(
2664
1.22k
                    (num.exp == INT_MAX) &&
2665
1.22k
                    (num.bias < 0) &&
2666
1.22k
                    (num.exp + num.bias < 308) &&
2667
1.22k
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
1.22k
                num.bias = 0;
2675
1.22k
                num.exp = INT_MAX;
2676
1.22k
            }
2677
2.68k
        }
2678
15.8k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
2.47k
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
2.47k
            if(BOOST_JSON_UNLIKELY(
2684
2.47k
                (num.exp == INT_MAX) &&
2685
2.47k
                (num.bias > 0) &&
2686
2.47k
                (num.exp - num.bias < 308) &&
2687
2.47k
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
2.47k
            num.bias = 0;
2695
2.47k
            num.exp = INT_MAX;
2696
2.47k
        }
2697
18.5k
        goto finish_dub;
2698
18.5k
    }
2699
2700
12.7k
finish_int:
2701
12.7k
    if(negative || (!stack_empty && num.neg))
2702
0
    {
2703
0
        if(BOOST_JSON_UNLIKELY(
2704
0
            ! h_.on_int64(static_cast<
2705
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
0
            return fail(cs.begin());
2707
0
        return cs.begin();
2708
0
    }
2709
12.7k
    if(num.mant <= INT64_MAX)
2710
6.06k
    {
2711
61.9k
finish_signed:
2712
61.9k
        if(BOOST_JSON_UNLIKELY(
2713
61.9k
            ! h_.on_int64(static_cast<
2714
61.9k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
92
            return fail(cs.begin());
2716
61.8k
        return cs.begin();
2717
61.9k
    }
2718
6.67k
    if(BOOST_JSON_UNLIKELY(
2719
6.67k
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
364
        return fail(cs.begin());
2721
6.31k
    return cs.begin();
2722
41.4k
finish_dub:
2723
41.4k
    double d;
2724
41.4k
    std::size_t const size = cs.used(begin);
2725
41.4k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
41.4k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
41.4k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
41.4k
    else
2747
41.4k
        d = detail::dec_to_float(
2748
41.4k
            num.mant,
2749
41.4k
            num.bias + (num.frac ?
2750
38.7k
                -num.exp : num.exp),
2751
41.4k
            num.neg);
2752
41.4k
    if(BOOST_JSON_UNLIKELY(
2753
41.4k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
354
        return fail(cs.begin());
2755
41.0k
    return cs.begin();
2756
41.4k
}
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number<true, (char)43, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)43>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::parse_number<false, (char)0, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<char, (char)0>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<boost::json::detail::into_handler<Object> >::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>)
char const* boost::json::basic_parser<null_parser::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
1986
6.15k
{
1987
6.15k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
6.15k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
6.15k
    bool const negative = first == '-';
1995
6.15k
    bool const zero_first = first == '0';
1996
6.15k
    bool const nonzero_first = first == '+';
1997
6.15k
    detail::const_stream_wrapper cs(p, end_);
1998
6.15k
    number num;
1999
6.15k
    const char* begin = cs.begin();
2000
6.15k
    if(stack_empty || st_.empty())
2001
6.15k
    {
2002
6.15k
        num.bias = 0;
2003
6.15k
        num.exp = 0;
2004
6.15k
        num.frac = false;
2005
6.15k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
6.15k
        BOOST_ASSERT(cs);
2013
6.15k
        if(negative)
2014
0
            ++cs;
2015
2016
6.15k
        num.neg = negative;
2017
6.15k
        num.frac = false;
2018
6.15k
        num.exp = 0;
2019
6.15k
        num.bias = 0;
2020
2021
        // fast path
2022
6.15k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
5.13k
        {
2024
5.13k
            int n1;
2025
2026
5.13k
            if( nonzero_first ||
2027
5.13k
                (negative && *cs != '0') )
2028
0
            {
2029
0
                n1 = detail::count_digits( cs.begin() );
2030
0
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
0
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
0
                if( ! nonzero_first && n1 == 0 )
2040
0
                {
2041
                    // digit required
2042
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
0
                        = BOOST_CURRENT_LOCATION;
2044
0
                    return fail(cs.begin(), error::syntax, &loc);
2045
0
                }
2046
2047
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
0
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
0
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
0
                if( n1 == 16 )
2057
0
                {
2058
0
                    goto do_num2;
2059
0
                }
2060
0
            }
2061
5.13k
            else
2062
5.13k
            {
2063
                // 0. floating-point or 0e integer
2064
5.13k
                num.mant = 0;
2065
5.13k
                n1 = 0;
2066
5.13k
                ++cs;
2067
5.13k
            }
2068
2069
5.13k
            {
2070
5.13k
                const char c = *cs;
2071
5.13k
                if(c != '.')
2072
1.71k
                {
2073
1.71k
                    if((c | 32) == 'e')
2074
1.05k
                    {
2075
1.05k
                        ++cs;
2076
1.05k
                        goto do_exp1;
2077
1.05k
                    }
2078
664
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
0
                        num.mant = ~num.mant + 1;
2080
664
                    goto finish_signed;
2081
1.71k
                }
2082
5.13k
            }
2083
2084
            // floating-point number
2085
2086
3.41k
            ++cs;
2087
2088
3.41k
            int n2 = detail::count_digits( cs.begin() );
2089
3.41k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
3.41k
            if( n2 == 0 )
2092
5
            {
2093
                // digit required
2094
5
                BOOST_STATIC_CONSTEXPR source_location loc
2095
5
                    = BOOST_CURRENT_LOCATION;
2096
5
                return fail(cs.begin(), error::syntax, &loc);
2097
5
            }
2098
2099
            // floating-point mantissa overflow
2100
3.41k
            if( n1 + n2 >= 19 )
2101
0
            {
2102
0
                goto do_num7;
2103
0
            }
2104
2105
3.41k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
3.41k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
3.41k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
3.41k
            cs += n2;
2113
2114
3.41k
            char ch = *cs;
2115
2116
3.41k
            if( (ch | 32) == 'e' )
2117
606
            {
2118
606
                ++cs;
2119
606
                goto do_exp1;
2120
606
            }
2121
2.80k
            else if( ch >= '0' && ch <= '9' )
2122
1.05k
            {
2123
1.05k
                goto do_num8;
2124
1.05k
            }
2125
2126
1.75k
            goto finish_dub;
2127
3.41k
        }
2128
6.15k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
1.01k
do_num1:
2157
1.01k
    if(zero_first || nonzero_first ||
2158
1.01k
        BOOST_JSON_LIKELY(cs))
2159
1.01k
    {
2160
1.01k
        char const c = *cs;
2161
1.01k
        if(zero_first)
2162
1.01k
        {
2163
1.01k
            ++cs;
2164
1.01k
            num.mant = 0;
2165
1.01k
            goto do_num6;
2166
1.01k
        }
2167
0
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
0
            c >= '1' && c <= '9'))
2169
0
        {
2170
0
            ++cs;
2171
0
            num.mant = c - '0';
2172
0
        }
2173
0
        else if(BOOST_JSON_UNLIKELY(
2174
0
            c == '0'))
2175
0
        {
2176
0
            ++cs;
2177
0
            num.mant = 0;
2178
0
            goto do_num6;
2179
0
        }
2180
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
0
        else
2189
0
        {
2190
0
            BOOST_STATIC_CONSTEXPR source_location loc
2191
0
                = BOOST_CURRENT_LOCATION;
2192
0
            return fail(cs.begin(), error::syntax, &loc);
2193
0
        }
2194
1.01k
    }
2195
0
    else
2196
0
    {
2197
0
        if(BOOST_JSON_UNLIKELY(
2198
0
            ! h_.on_number_part(
2199
0
                {begin, cs.used(begin)}, ec_)))
2200
0
            return fail(cs.begin());
2201
2202
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
0
        return maybe_suspend(
2205
0
            cs.begin(), state::num1, num);
2206
0
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
0
do_num2:
2214
0
    if(negative || (!stack_empty && num.neg))
2215
0
    {
2216
0
        for(;;)
2217
0
        {
2218
0
            if(BOOST_JSON_UNLIKELY(! cs))
2219
0
            {
2220
0
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
0
                goto finish_int;
2232
0
            }
2233
0
            char const c = *cs;
2234
0
            if(BOOST_JSON_LIKELY(
2235
0
                c >= '0' && c <= '9'))
2236
0
            {
2237
0
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
0
                if( num.mant  > 922337203685477580 || (
2240
0
                    num.mant == 922337203685477580 && c > '8'))
2241
0
                    break;
2242
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
0
                    num.mant = 10 * num.mant + ( c - '0' );
2244
0
                continue;
2245
0
            }
2246
0
            goto do_num6; // [.eE]
2247
0
        }
2248
0
    }
2249
0
    else
2250
0
    {
2251
0
        for(;;)
2252
0
        {
2253
0
            if(BOOST_JSON_UNLIKELY(! cs))
2254
0
            {
2255
0
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
0
                goto finish_int;
2267
0
            }
2268
0
            char const c = *cs;
2269
0
            if(BOOST_JSON_LIKELY(
2270
0
                c >= '0' && c <= '9'))
2271
0
            {
2272
0
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
0
                if( num.mant  > 1844674407370955161 || (
2275
0
                    num.mant == 1844674407370955161 && c > '5'))
2276
0
                    break;
2277
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
0
                    num.mant = 10 * num.mant + ( c - '0' );
2279
0
            }
2280
0
            else
2281
0
            {
2282
0
                goto do_num6; // [.eE]
2283
0
            }
2284
0
        }
2285
0
    }
2286
0
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
0
do_num3:
2294
0
    for(;;)
2295
0
    {
2296
0
        if(BOOST_JSON_UNLIKELY(! cs))
2297
0
        {
2298
0
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
0
            goto finish_dub;
2310
0
        }
2311
0
        char const c = *cs;
2312
0
        if(BOOST_JSON_UNLIKELY(
2313
0
            c >= '0' && c <= '9'))
2314
0
        {
2315
0
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
0
            ++cs;
2322
0
            ++num.bias;
2323
0
        }
2324
0
        else if(BOOST_JSON_LIKELY(
2325
0
            c == '.'))
2326
0
        {
2327
0
            ++cs;
2328
0
            break;
2329
0
        }
2330
0
        else if((c | 32) == 'e')
2331
0
        {
2332
0
            ++cs;
2333
0
            goto do_exp1;
2334
0
        }
2335
0
        else
2336
0
        {
2337
0
            goto finish_dub;
2338
0
        }
2339
0
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
0
do_num4:
2348
0
    {
2349
0
        if(BOOST_JSON_UNLIKELY(! cs))
2350
0
        {
2351
0
            if(BOOST_JSON_UNLIKELY(
2352
0
                ! h_.on_number_part(
2353
0
                    {begin, cs.used(begin)}, ec_)))
2354
0
                return fail(cs.begin());
2355
2356
0
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
0
            return maybe_suspend(
2359
0
                cs.begin(), state::num4, num);
2360
0
        }
2361
0
        char const c = *cs;
2362
0
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
0
            c >= '0' && c <= '9'))
2365
0
        {
2366
0
            ++cs;
2367
0
        }
2368
0
        else
2369
0
        {
2370
            // digit required
2371
0
            BOOST_STATIC_CONSTEXPR source_location loc
2372
0
                = BOOST_CURRENT_LOCATION;
2373
0
            return fail(cs.begin(), error::syntax, &loc);
2374
0
        }
2375
0
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
511
do_num5:
2384
511
    for(;;)
2385
33.6k
    {
2386
33.6k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
14
        {
2388
14
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
14
            goto finish_dub;
2400
14
        }
2401
33.5k
        char const c = *cs;
2402
33.5k
        if(BOOST_JSON_LIKELY(
2403
33.5k
            c >= '0' && c <= '9'))
2404
33.0k
        {
2405
33.0k
            ++cs;
2406
33.0k
        }
2407
497
        else if((c | 32) == 'e')
2408
197
        {
2409
197
            ++cs;
2410
197
            goto do_exp1;
2411
197
        }
2412
300
        else
2413
300
        {
2414
300
            goto finish_dub;
2415
300
        }
2416
33.5k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
1.01k
do_num6:
2423
1.01k
    {
2424
1.01k
        if(BOOST_JSON_UNLIKELY(! cs))
2425
14
        {
2426
14
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
14
            goto finish_int;
2438
14
        }
2439
1.00k
        char const c = *cs;
2440
1.00k
        if(BOOST_JSON_LIKELY(
2441
1.00k
            c == '.'))
2442
327
        {
2443
327
            ++cs;
2444
327
        }
2445
677
        else if((c | 32) == 'e')
2446
397
        {
2447
397
            ++cs;
2448
397
            goto do_exp1;
2449
397
        }
2450
280
        else
2451
280
        {
2452
280
            goto finish_int;
2453
280
        }
2454
1.00k
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
327
do_num7:
2463
327
    {
2464
327
        if(BOOST_JSON_UNLIKELY(! cs))
2465
6
        {
2466
6
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
6
            BOOST_STATIC_CONSTEXPR source_location loc
2479
6
                = BOOST_CURRENT_LOCATION;
2480
6
            return fail(cs.begin(), error::syntax, &loc);
2481
6
        }
2482
321
        char const c = *cs;
2483
321
        if(BOOST_JSON_UNLIKELY(
2484
321
            c < '0' || c > '9'))
2485
20
        {
2486
            // digit required
2487
20
            BOOST_STATIC_CONSTEXPR source_location loc
2488
20
                = BOOST_CURRENT_LOCATION;
2489
20
            return fail(cs.begin(), error::syntax, &loc);
2490
20
        }
2491
321
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
1.35k
do_num8:
2500
1.35k
    for(;;)
2501
5.40M
    {
2502
5.40M
        if(BOOST_JSON_UNLIKELY(! cs))
2503
88
        {
2504
88
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
88
            goto finish_dub;
2516
88
        }
2517
5.40M
        char const c = *cs;
2518
5.40M
        if(BOOST_JSON_LIKELY(
2519
5.40M
            c >= '0' && c <= '9'))
2520
5.40M
        {
2521
5.40M
            ++cs;
2522
5.40M
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
5.40M
                num.mant <= 9007199254740991)) // 2^53-1
2524
5.40M
            {
2525
5.40M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
5.40M
                --num.bias;
2532
5.40M
                num.mant = 10 * num.mant + ( c - '0' );
2533
5.40M
            }
2534
511
            else
2535
511
            {
2536
511
                goto do_num5;
2537
511
            }
2538
5.40M
        }
2539
752
        else if((c | 32) == 'e')
2540
281
        {
2541
281
            ++cs;
2542
281
            goto do_exp1;
2543
281
        }
2544
471
        else
2545
471
        {
2546
471
            goto finish_dub;
2547
471
        }
2548
5.40M
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
2.53k
do_exp1:
2555
2.53k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
22
    {
2557
22
        if(BOOST_JSON_UNLIKELY(
2558
22
            ! h_.on_number_part(
2559
22
                {begin, cs.used(begin)}, ec_)))
2560
0
            return fail(cs.begin());
2561
2562
22
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
22
        return maybe_suspend(
2565
22
            cs.begin(), state::exp1, num);
2566
22
    }
2567
2.51k
    if(*cs == '+')
2568
195
    {
2569
195
        ++cs;
2570
195
    }
2571
2.31k
    else if(*cs == '-')
2572
791
    {
2573
791
        ++cs;
2574
791
        num.frac = true;
2575
791
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
2.51k
do_exp2:
2583
2.51k
    {
2584
2.51k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
15
        {
2586
15
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
15
            BOOST_STATIC_CONSTEXPR source_location loc
2599
15
                = BOOST_CURRENT_LOCATION;
2600
15
            return fail(cs.begin(), error::syntax, &loc);
2601
15
        }
2602
2.49k
        char const c = *cs;
2603
2.49k
        if(BOOST_JSON_UNLIKELY(
2604
2.49k
            c < '0' || c > '9'))
2605
27
        {
2606
            // digit required
2607
27
            BOOST_STATIC_CONSTEXPR source_location loc
2608
27
                = BOOST_CURRENT_LOCATION;
2609
27
            return fail(cs.begin(), error::syntax, &loc);
2610
27
        }
2611
2.47k
        ++cs;
2612
2.47k
        num.exp = c - '0';
2613
2.47k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
2.47k
do_exp3:
2621
2.47k
    for(;;)
2622
14.4k
    {
2623
14.4k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
222
        {
2625
222
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
222
        }
2637
14.1k
        else
2638
14.1k
        {
2639
14.1k
            char const c = *cs;
2640
14.1k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
11.9k
            {
2642
11.9k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
11.9k
                    num.exp  >  214748364 ||
2645
11.9k
                    (num.exp == 214748364 && c > '7')
2646
11.9k
                ))
2647
5.43k
                    num.exp = INT_MAX;
2648
6.50k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
6.50k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
11.9k
                ++cs;
2652
11.9k
                continue;
2653
11.9k
            }
2654
14.1k
        }
2655
2.47k
        BOOST_ASSERT(num.exp >= 0);
2656
2.47k
        if ( num.frac )
2657
783
        {
2658
783
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
434
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
434
                if(BOOST_JSON_UNLIKELY(
2664
434
                    (num.exp == INT_MAX) &&
2665
434
                    (num.bias < 0) &&
2666
434
                    (num.exp + num.bias < 308) &&
2667
434
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
434
                num.bias = 0;
2675
434
                num.exp = INT_MAX;
2676
434
            }
2677
783
        }
2678
1.68k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
0
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
0
            if(BOOST_JSON_UNLIKELY(
2684
0
                (num.exp == INT_MAX) &&
2685
0
                (num.bias > 0) &&
2686
0
                (num.exp - num.bias < 308) &&
2687
0
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
0
            num.bias = 0;
2695
0
            num.exp = INT_MAX;
2696
0
        }
2697
2.47k
        goto finish_dub;
2698
2.47k
    }
2699
2700
294
finish_int:
2701
294
    if(negative || (!stack_empty && num.neg))
2702
0
    {
2703
0
        if(BOOST_JSON_UNLIKELY(
2704
0
            ! h_.on_int64(static_cast<
2705
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
0
            return fail(cs.begin());
2707
0
        return cs.begin();
2708
0
    }
2709
294
    if(num.mant <= INT64_MAX)
2710
294
    {
2711
958
finish_signed:
2712
958
        if(BOOST_JSON_UNLIKELY(
2713
958
            ! h_.on_int64(static_cast<
2714
958
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
0
            return fail(cs.begin());
2716
958
        return cs.begin();
2717
958
    }
2718
0
    if(BOOST_JSON_UNLIKELY(
2719
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
0
        return fail(cs.begin());
2721
0
    return cs.begin();
2722
5.10k
finish_dub:
2723
5.10k
    double d;
2724
5.10k
    std::size_t const size = cs.used(begin);
2725
5.10k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
5.10k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
5.10k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
5.10k
    else
2747
5.10k
        d = detail::dec_to_float(
2748
5.10k
            num.mant,
2749
5.10k
            num.bias + (num.frac ?
2750
4.31k
                -num.exp : num.exp),
2751
5.10k
            num.neg);
2752
5.10k
    if(BOOST_JSON_UNLIKELY(
2753
5.10k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
0
        return fail(cs.begin());
2755
5.10k
    return cs.begin();
2756
5.10k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number<true, (char)48, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number<true, (char)48, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)48>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<null_parser::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
1986
8.75k
{
1987
8.75k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
8.75k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
8.75k
    bool const negative = first == '-';
1995
8.75k
    bool const zero_first = first == '0';
1996
8.75k
    bool const nonzero_first = first == '+';
1997
8.75k
    detail::const_stream_wrapper cs(p, end_);
1998
8.75k
    number num;
1999
8.75k
    const char* begin = cs.begin();
2000
8.75k
    if(stack_empty || st_.empty())
2001
8.75k
    {
2002
8.75k
        num.bias = 0;
2003
8.75k
        num.exp = 0;
2004
8.75k
        num.frac = false;
2005
8.75k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
8.75k
        BOOST_ASSERT(cs);
2013
8.75k
        if(negative)
2014
8.75k
            ++cs;
2015
2016
8.75k
        num.neg = negative;
2017
8.75k
        num.frac = false;
2018
8.75k
        num.exp = 0;
2019
8.75k
        num.bias = 0;
2020
2021
        // fast path
2022
8.75k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
7.54k
        {
2024
7.54k
            int n1;
2025
2026
7.54k
            if( nonzero_first ||
2027
7.54k
                (negative && *cs != '0') )
2028
6.09k
            {
2029
6.09k
                n1 = detail::count_digits( cs.begin() );
2030
6.09k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
6.09k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
6.09k
                if( ! nonzero_first && n1 == 0 )
2040
9
                {
2041
                    // digit required
2042
9
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
9
                        = BOOST_CURRENT_LOCATION;
2044
9
                    return fail(cs.begin(), error::syntax, &loc);
2045
9
                }
2046
2047
6.08k
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
6.08k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
6.08k
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
6.08k
                if( n1 == 16 )
2057
2.93k
                {
2058
2.93k
                    goto do_num2;
2059
2.93k
                }
2060
6.08k
            }
2061
1.45k
            else
2062
1.45k
            {
2063
                // 0. floating-point or 0e integer
2064
1.45k
                num.mant = 0;
2065
1.45k
                n1 = 0;
2066
1.45k
                ++cs;
2067
1.45k
            }
2068
2069
4.59k
            {
2070
4.59k
                const char c = *cs;
2071
4.59k
                if(c != '.')
2072
2.29k
                {
2073
2.29k
                    if((c | 32) == 'e')
2074
1.11k
                    {
2075
1.11k
                        ++cs;
2076
1.11k
                        goto do_exp1;
2077
1.11k
                    }
2078
1.18k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
1.18k
                        num.mant = ~num.mant + 1;
2080
1.18k
                    goto finish_signed;
2081
2.29k
                }
2082
4.59k
            }
2083
2084
            // floating-point number
2085
2086
2.30k
            ++cs;
2087
2088
2.30k
            int n2 = detail::count_digits( cs.begin() );
2089
2.30k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
2.30k
            if( n2 == 0 )
2092
3
            {
2093
                // digit required
2094
3
                BOOST_STATIC_CONSTEXPR source_location loc
2095
3
                    = BOOST_CURRENT_LOCATION;
2096
3
                return fail(cs.begin(), error::syntax, &loc);
2097
3
            }
2098
2099
            // floating-point mantissa overflow
2100
2.30k
            if( n1 + n2 >= 19 )
2101
202
            {
2102
202
                goto do_num7;
2103
202
            }
2104
2105
2.10k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
2.10k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
2.10k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
2.10k
            cs += n2;
2113
2114
2.10k
            char ch = *cs;
2115
2116
2.10k
            if( (ch | 32) == 'e' )
2117
583
            {
2118
583
                ++cs;
2119
583
                goto do_exp1;
2120
583
            }
2121
1.52k
            else if( ch >= '0' && ch <= '9' )
2122
268
            {
2123
268
                goto do_num8;
2124
268
            }
2125
2126
1.25k
            goto finish_dub;
2127
2.10k
        }
2128
8.75k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
1.21k
do_num1:
2157
1.21k
    if(zero_first || nonzero_first ||
2158
1.21k
        BOOST_JSON_LIKELY(cs))
2159
1.19k
    {
2160
1.19k
        char const c = *cs;
2161
1.19k
        if(zero_first)
2162
0
        {
2163
0
            ++cs;
2164
0
            num.mant = 0;
2165
0
            goto do_num6;
2166
0
        }
2167
1.19k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
1.19k
            c >= '1' && c <= '9'))
2169
993
        {
2170
993
            ++cs;
2171
993
            num.mant = c - '0';
2172
993
        }
2173
203
        else if(BOOST_JSON_UNLIKELY(
2174
203
            c == '0'))
2175
178
        {
2176
178
            ++cs;
2177
178
            num.mant = 0;
2178
178
            goto do_num6;
2179
178
        }
2180
25
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
25
        else
2189
25
        {
2190
25
            BOOST_STATIC_CONSTEXPR source_location loc
2191
25
                = BOOST_CURRENT_LOCATION;
2192
25
            return fail(cs.begin(), error::syntax, &loc);
2193
25
        }
2194
1.19k
    }
2195
16
    else
2196
16
    {
2197
16
        if(BOOST_JSON_UNLIKELY(
2198
16
            ! h_.on_number_part(
2199
16
                {begin, cs.used(begin)}, ec_)))
2200
0
            return fail(cs.begin());
2201
2202
16
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
16
        return maybe_suspend(
2205
16
            cs.begin(), state::num1, num);
2206
16
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
3.93k
do_num2:
2214
3.93k
    if(negative || (!stack_empty && num.neg))
2215
3.93k
    {
2216
3.93k
        for(;;)
2217
12.5k
        {
2218
12.5k
            if(BOOST_JSON_UNLIKELY(! cs))
2219
146
            {
2220
146
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
146
                goto finish_int;
2232
146
            }
2233
12.3k
            char const c = *cs;
2234
12.3k
            if(BOOST_JSON_LIKELY(
2235
12.3k
                c >= '0' && c <= '9'))
2236
10.0k
            {
2237
10.0k
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
10.0k
                if( num.mant  > 922337203685477580 || (
2240
8.83k
                    num.mant == 922337203685477580 && c > '8'))
2241
1.44k
                    break;
2242
8.59k
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
8.59k
                    num.mant = 10 * num.mant + ( c - '0' );
2244
8.59k
                continue;
2245
10.0k
            }
2246
2.33k
            goto do_num6; // [.eE]
2247
12.3k
        }
2248
3.93k
    }
2249
0
    else
2250
0
    {
2251
0
        for(;;)
2252
0
        {
2253
0
            if(BOOST_JSON_UNLIKELY(! cs))
2254
0
            {
2255
0
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
0
                goto finish_int;
2267
0
            }
2268
0
            char const c = *cs;
2269
0
            if(BOOST_JSON_LIKELY(
2270
0
                c >= '0' && c <= '9'))
2271
0
            {
2272
0
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
0
                if( num.mant  > 1844674407370955161 || (
2275
0
                    num.mant == 1844674407370955161 && c > '5'))
2276
0
                    break;
2277
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
0
                    num.mant = 10 * num.mant + ( c - '0' );
2279
0
            }
2280
0
            else
2281
0
            {
2282
0
                goto do_num6; // [.eE]
2283
0
            }
2284
0
        }
2285
0
    }
2286
1.44k
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
1.44k
do_num3:
2294
1.44k
    for(;;)
2295
5.85M
    {
2296
5.85M
        if(BOOST_JSON_UNLIKELY(! cs))
2297
43
        {
2298
43
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
43
            goto finish_dub;
2310
43
        }
2311
5.85M
        char const c = *cs;
2312
5.85M
        if(BOOST_JSON_UNLIKELY(
2313
5.85M
            c >= '0' && c <= '9'))
2314
5.85M
        {
2315
5.85M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
5.85M
            ++cs;
2322
5.85M
            ++num.bias;
2323
5.85M
        }
2324
1.40k
        else if(BOOST_JSON_LIKELY(
2325
1.40k
            c == '.'))
2326
231
        {
2327
231
            ++cs;
2328
231
            break;
2329
231
        }
2330
1.17k
        else if((c | 32) == 'e')
2331
660
        {
2332
660
            ++cs;
2333
660
            goto do_exp1;
2334
660
        }
2335
513
        else
2336
513
        {
2337
513
            goto finish_dub;
2338
513
        }
2339
5.85M
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
231
do_num4:
2348
231
    {
2349
231
        if(BOOST_JSON_UNLIKELY(! cs))
2350
5
        {
2351
5
            if(BOOST_JSON_UNLIKELY(
2352
5
                ! h_.on_number_part(
2353
5
                    {begin, cs.used(begin)}, ec_)))
2354
0
                return fail(cs.begin());
2355
2356
5
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
5
            return maybe_suspend(
2359
5
                cs.begin(), state::num4, num);
2360
5
        }
2361
226
        char const c = *cs;
2362
226
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
226
            c >= '0' && c <= '9'))
2365
212
        {
2366
212
            ++cs;
2367
212
        }
2368
14
        else
2369
14
        {
2370
            // digit required
2371
14
            BOOST_STATIC_CONSTEXPR source_location loc
2372
14
                = BOOST_CURRENT_LOCATION;
2373
14
            return fail(cs.begin(), error::syntax, &loc);
2374
14
        }
2375
226
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
946
do_num5:
2384
946
    for(;;)
2385
32.1k
    {
2386
32.1k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
33
        {
2388
33
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
33
            goto finish_dub;
2400
33
        }
2401
32.1k
        char const c = *cs;
2402
32.1k
        if(BOOST_JSON_LIKELY(
2403
32.1k
            c >= '0' && c <= '9'))
2404
31.2k
        {
2405
31.2k
            ++cs;
2406
31.2k
        }
2407
913
        else if((c | 32) == 'e')
2408
201
        {
2409
201
            ++cs;
2410
201
            goto do_exp1;
2411
201
        }
2412
712
        else
2413
712
        {
2414
712
            goto finish_dub;
2415
712
        }
2416
32.1k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
2.51k
do_num6:
2423
2.51k
    {
2424
2.51k
        if(BOOST_JSON_UNLIKELY(! cs))
2425
5
        {
2426
5
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
5
            goto finish_int;
2438
5
        }
2439
2.51k
        char const c = *cs;
2440
2.51k
        if(BOOST_JSON_LIKELY(
2441
2.51k
            c == '.'))
2442
1.14k
        {
2443
1.14k
            ++cs;
2444
1.14k
        }
2445
1.36k
        else if((c | 32) == 'e')
2446
500
        {
2447
500
            ++cs;
2448
500
            goto do_exp1;
2449
500
        }
2450
868
        else
2451
868
        {
2452
868
            goto finish_int;
2453
868
        }
2454
2.51k
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
1.34k
do_num7:
2463
1.34k
    {
2464
1.34k
        if(BOOST_JSON_UNLIKELY(! cs))
2465
8
        {
2466
8
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
8
            BOOST_STATIC_CONSTEXPR source_location loc
2479
8
                = BOOST_CURRENT_LOCATION;
2480
8
            return fail(cs.begin(), error::syntax, &loc);
2481
8
        }
2482
1.33k
        char const c = *cs;
2483
1.33k
        if(BOOST_JSON_UNLIKELY(
2484
1.33k
            c < '0' || c > '9'))
2485
7
        {
2486
            // digit required
2487
7
            BOOST_STATIC_CONSTEXPR source_location loc
2488
7
                = BOOST_CURRENT_LOCATION;
2489
7
            return fail(cs.begin(), error::syntax, &loc);
2490
7
        }
2491
1.33k
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
1.59k
do_num8:
2500
1.59k
    for(;;)
2501
4.05M
    {
2502
4.05M
        if(BOOST_JSON_UNLIKELY(! cs))
2503
121
        {
2504
121
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
121
            goto finish_dub;
2516
121
        }
2517
4.05M
        char const c = *cs;
2518
4.05M
        if(BOOST_JSON_LIKELY(
2519
4.05M
            c >= '0' && c <= '9'))
2520
4.05M
        {
2521
4.05M
            ++cs;
2522
4.05M
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
4.05M
                num.mant <= 9007199254740991)) // 2^53-1
2524
4.05M
            {
2525
4.05M
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
4.05M
                --num.bias;
2532
4.05M
                num.mant = 10 * num.mant + ( c - '0' );
2533
4.05M
            }
2534
734
            else
2535
734
            {
2536
734
                goto do_num5;
2537
734
            }
2538
4.05M
        }
2539
743
        else if((c | 32) == 'e')
2540
274
        {
2541
274
            ++cs;
2542
274
            goto do_exp1;
2543
274
        }
2544
469
        else
2545
469
        {
2546
469
            goto finish_dub;
2547
469
        }
2548
4.05M
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
3.32k
do_exp1:
2555
3.32k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
34
    {
2557
34
        if(BOOST_JSON_UNLIKELY(
2558
34
            ! h_.on_number_part(
2559
34
                {begin, cs.used(begin)}, ec_)))
2560
0
            return fail(cs.begin());
2561
2562
34
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
34
        return maybe_suspend(
2565
34
            cs.begin(), state::exp1, num);
2566
34
    }
2567
3.29k
    if(*cs == '+')
2568
197
    {
2569
197
        ++cs;
2570
197
    }
2571
3.09k
    else if(*cs == '-')
2572
779
    {
2573
779
        ++cs;
2574
779
        num.frac = true;
2575
779
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
3.29k
do_exp2:
2583
3.29k
    {
2584
3.29k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
15
        {
2586
15
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
15
            BOOST_STATIC_CONSTEXPR source_location loc
2599
15
                = BOOST_CURRENT_LOCATION;
2600
15
            return fail(cs.begin(), error::syntax, &loc);
2601
15
        }
2602
3.28k
        char const c = *cs;
2603
3.28k
        if(BOOST_JSON_UNLIKELY(
2604
3.28k
            c < '0' || c > '9'))
2605
23
        {
2606
            // digit required
2607
23
            BOOST_STATIC_CONSTEXPR source_location loc
2608
23
                = BOOST_CURRENT_LOCATION;
2609
23
            return fail(cs.begin(), error::syntax, &loc);
2610
23
        }
2611
3.25k
        ++cs;
2612
3.25k
        num.exp = c - '0';
2613
3.25k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
3.25k
do_exp3:
2621
3.25k
    for(;;)
2622
16.2k
    {
2623
16.2k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
286
        {
2625
286
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
286
        }
2637
16.0k
        else
2638
16.0k
        {
2639
16.0k
            char const c = *cs;
2640
16.0k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
13.0k
            {
2642
13.0k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
13.0k
                    num.exp  >  214748364 ||
2645
13.0k
                    (num.exp == 214748364 && c > '7')
2646
13.0k
                ))
2647
1.30k
                    num.exp = INT_MAX;
2648
11.7k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
11.7k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
13.0k
                ++cs;
2652
13.0k
                continue;
2653
13.0k
            }
2654
16.0k
        }
2655
3.25k
        BOOST_ASSERT(num.exp >= 0);
2656
3.25k
        if ( num.frac )
2657
770
        {
2658
770
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
435
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
435
                if(BOOST_JSON_UNLIKELY(
2664
435
                    (num.exp == INT_MAX) &&
2665
435
                    (num.bias < 0) &&
2666
435
                    (num.exp + num.bias < 308) &&
2667
435
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
435
                num.bias = 0;
2675
435
                num.exp = INT_MAX;
2676
435
            }
2677
770
        }
2678
2.48k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
462
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
462
            if(BOOST_JSON_UNLIKELY(
2684
462
                (num.exp == INT_MAX) &&
2685
462
                (num.bias > 0) &&
2686
462
                (num.exp - num.bias < 308) &&
2687
462
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
462
            num.bias = 0;
2695
462
            num.exp = INT_MAX;
2696
462
        }
2697
3.25k
        goto finish_dub;
2698
3.25k
    }
2699
2700
1.01k
finish_int:
2701
1.01k
    if(negative || (!stack_empty && num.neg))
2702
1.01k
    {
2703
1.01k
        if(BOOST_JSON_UNLIKELY(
2704
1.01k
            ! h_.on_int64(static_cast<
2705
1.01k
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
0
            return fail(cs.begin());
2707
1.01k
        return cs.begin();
2708
1.01k
    }
2709
0
    if(num.mant <= INT64_MAX)
2710
0
    {
2711
1.18k
finish_signed:
2712
1.18k
        if(BOOST_JSON_UNLIKELY(
2713
1.18k
            ! h_.on_int64(static_cast<
2714
1.18k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
0
            return fail(cs.begin());
2716
1.18k
        return cs.begin();
2717
1.18k
    }
2718
0
    if(BOOST_JSON_UNLIKELY(
2719
0
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
0
        return fail(cs.begin());
2721
0
    return cs.begin();
2722
6.40k
finish_dub:
2723
6.40k
    double d;
2724
6.40k
    std::size_t const size = cs.used(begin);
2725
6.40k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
6.40k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
6.40k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
6.40k
    else
2747
6.40k
        d = detail::dec_to_float(
2748
6.40k
            num.mant,
2749
6.40k
            num.bias + (num.frac ?
2750
5.63k
                -num.exp : num.exp),
2751
6.40k
            num.neg);
2752
6.40k
    if(BOOST_JSON_UNLIKELY(
2753
6.40k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
0
        return fail(cs.begin());
2755
6.40k
    return cs.begin();
2756
6.40k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number<true, (char)45, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number<true, (char)45, (boost::json::number_precision)2>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)45>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)2>)
char const* boost::json::basic_parser<null_parser::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
1986
13.0k
{
1987
13.0k
    constexpr bool precise_parsing = mode == number_precision::precise;
1988
13.0k
    constexpr bool no_parsing = mode == number_precision::none;
1989
1990
    // only one of these will be true if we are not resuming
1991
    // if negative then !zero_first && !nonzero_first
1992
    // if zero_first then !nonzero_first && !negative
1993
    // if nonzero_first then !zero_first && !negative
1994
13.0k
    bool const negative = first == '-';
1995
13.0k
    bool const zero_first = first == '0';
1996
13.0k
    bool const nonzero_first = first == '+';
1997
13.0k
    detail::const_stream_wrapper cs(p, end_);
1998
13.0k
    number num;
1999
13.0k
    const char* begin = cs.begin();
2000
13.0k
    if(stack_empty || st_.empty())
2001
13.0k
    {
2002
13.0k
        num.bias = 0;
2003
13.0k
        num.exp = 0;
2004
13.0k
        num.frac = false;
2005
13.0k
        num_buf_.clear();
2006
2007
        //----------------------------------
2008
        //
2009
        // '-'
2010
        // leading minus sign
2011
        //
2012
13.0k
        BOOST_ASSERT(cs);
2013
13.0k
        if(negative)
2014
0
            ++cs;
2015
2016
13.0k
        num.neg = negative;
2017
13.0k
        num.frac = false;
2018
13.0k
        num.exp = 0;
2019
13.0k
        num.bias = 0;
2020
2021
        // fast path
2022
13.0k
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023
10.6k
        {
2024
10.6k
            int n1;
2025
2026
10.6k
            if( nonzero_first ||
2027
10.6k
                (negative && *cs != '0') )
2028
10.6k
            {
2029
10.6k
                n1 = detail::count_digits( cs.begin() );
2030
10.6k
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031
2032
10.6k
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033
0
                {
2034
0
                    return parse_literal(
2035
0
                        p - 1,
2036
0
                        detail::literals_c<detail::literals::neg_infinity>());
2037
0
                }
2038
2039
10.6k
                if( ! nonzero_first && n1 == 0 )
2040
0
                {
2041
                    // digit required
2042
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2043
0
                        = BOOST_CURRENT_LOCATION;
2044
0
                    return fail(cs.begin(), error::syntax, &loc);
2045
0
                }
2046
2047
10.6k
                BOOST_IF_CONSTEXPR( !no_parsing )
2048
10.6k
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049
0
                else
2050
0
                    num.mant = 0;
2051
2052
10.6k
                cs += n1;
2053
2054
                // integer or floating-point with
2055
                // >= 16 leading digits
2056
10.6k
                if( n1 == 16 )
2057
3.09k
                {
2058
3.09k
                    goto do_num2;
2059
3.09k
                }
2060
10.6k
            }
2061
0
            else
2062
0
            {
2063
                // 0. floating-point or 0e integer
2064
0
                num.mant = 0;
2065
0
                n1 = 0;
2066
0
                ++cs;
2067
0
            }
2068
2069
7.52k
            {
2070
7.52k
                const char c = *cs;
2071
7.52k
                if(c != '.')
2072
5.20k
                {
2073
5.20k
                    if((c | 32) == 'e')
2074
1.05k
                    {
2075
1.05k
                        ++cs;
2076
1.05k
                        goto do_exp1;
2077
1.05k
                    }
2078
4.14k
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079
0
                        num.mant = ~num.mant + 1;
2080
4.14k
                    goto finish_signed;
2081
5.20k
                }
2082
7.52k
            }
2083
2084
            // floating-point number
2085
2086
2.31k
            ++cs;
2087
2088
2.31k
            int n2 = detail::count_digits( cs.begin() );
2089
2.31k
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090
2091
2.31k
            if( n2 == 0 )
2092
1
            {
2093
                // digit required
2094
1
                BOOST_STATIC_CONSTEXPR source_location loc
2095
1
                    = BOOST_CURRENT_LOCATION;
2096
1
                return fail(cs.begin(), error::syntax, &loc);
2097
1
            }
2098
2099
            // floating-point mantissa overflow
2100
2.31k
            if( n1 + n2 >= 19 )
2101
216
            {
2102
216
                goto do_num7;
2103
216
            }
2104
2105
2.10k
            BOOST_IF_CONSTEXPR( !no_parsing )
2106
2.10k
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107
2108
2.10k
            BOOST_ASSERT(num.bias == 0);
2109
2110
0
            num.bias -= n2;
2111
2112
2.10k
            cs += n2;
2113
2114
2.10k
            char ch = *cs;
2115
2116
2.10k
            if( (ch | 32) == 'e' )
2117
584
            {
2118
584
                ++cs;
2119
584
                goto do_exp1;
2120
584
            }
2121
1.51k
            else if( ch >= '0' && ch <= '9' )
2122
204
            {
2123
204
                goto do_num8;
2124
204
            }
2125
2126
1.31k
            goto finish_dub;
2127
2.10k
        }
2128
13.0k
    }
2129
0
    else
2130
0
    {
2131
0
        num = num_;
2132
0
        state st;
2133
0
        st_.pop(st);
2134
0
        switch(st)
2135
0
        {
2136
0
        default: BOOST_JSON_UNREACHABLE();
2137
0
        case state::num1: goto do_num1;
2138
0
        case state::num2: goto do_num2;
2139
0
        case state::num3: goto do_num3;
2140
0
        case state::num4: goto do_num4;
2141
0
        case state::num5: goto do_num5;
2142
0
        case state::num6: goto do_num6;
2143
0
        case state::num7: goto do_num7;
2144
0
        case state::num8: goto do_num8;
2145
0
        case state::exp1: goto do_exp1;
2146
0
        case state::exp2: goto do_exp2;
2147
0
        case state::exp3: goto do_exp3;
2148
0
        }
2149
0
    }
2150
2151
    //----------------------------------
2152
    //
2153
    // DIGIT
2154
    // first digit
2155
    //
2156
2.43k
do_num1:
2157
2.43k
    if(zero_first || nonzero_first ||
2158
2.43k
        BOOST_JSON_LIKELY(cs))
2159
2.43k
    {
2160
2.43k
        char const c = *cs;
2161
2.43k
        if(zero_first)
2162
0
        {
2163
0
            ++cs;
2164
0
            num.mant = 0;
2165
0
            goto do_num6;
2166
0
        }
2167
2.43k
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168
2.43k
            c >= '1' && c <= '9'))
2169
2.43k
        {
2170
2.43k
            ++cs;
2171
2.43k
            num.mant = c - '0';
2172
2.43k
        }
2173
0
        else if(BOOST_JSON_UNLIKELY(
2174
0
            c == '0'))
2175
0
        {
2176
0
            ++cs;
2177
0
            num.mant = 0;
2178
0
            goto do_num6;
2179
0
        }
2180
0
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181
0
        {
2182
0
            st_.push(state::lit1);
2183
0
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184
0
            lit_offset_ = 1;
2185
0
            return parse_literal(
2186
0
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187
0
        }
2188
0
        else
2189
0
        {
2190
0
            BOOST_STATIC_CONSTEXPR source_location loc
2191
0
                = BOOST_CURRENT_LOCATION;
2192
0
            return fail(cs.begin(), error::syntax, &loc);
2193
0
        }
2194
2.43k
    }
2195
0
    else
2196
0
    {
2197
0
        if(BOOST_JSON_UNLIKELY(
2198
0
            ! h_.on_number_part(
2199
0
                {begin, cs.used(begin)}, ec_)))
2200
0
            return fail(cs.begin());
2201
2202
0
        BOOST_IF_CONSTEXPR( precise_parsing )
2203
0
            num_buf_.append( begin, cs.used(begin) );
2204
0
        return maybe_suspend(
2205
0
            cs.begin(), state::num1, num);
2206
0
    }
2207
2208
    //----------------------------------
2209
    //
2210
    // 1*DIGIT
2211
    // significant digits left of decimal
2212
    //
2213
5.52k
do_num2:
2214
5.52k
    if(negative || (!stack_empty && num.neg))
2215
0
    {
2216
0
        for(;;)
2217
0
        {
2218
0
            if(BOOST_JSON_UNLIKELY(! cs))
2219
0
            {
2220
0
                if(BOOST_JSON_UNLIKELY(more_))
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 suspend(cs.begin(), state::num2, num);
2230
0
                }
2231
0
                goto finish_int;
2232
0
            }
2233
0
            char const c = *cs;
2234
0
            if(BOOST_JSON_LIKELY(
2235
0
                c >= '0' && c <= '9'))
2236
0
            {
2237
0
                ++cs;
2238
                //              9223372036854775808 INT64_MIN
2239
0
                if( num.mant  > 922337203685477580 || (
2240
0
                    num.mant == 922337203685477580 && c > '8'))
2241
0
                    break;
2242
0
                BOOST_IF_CONSTEXPR( !no_parsing )
2243
0
                    num.mant = 10 * num.mant + ( c - '0' );
2244
0
                continue;
2245
0
            }
2246
0
            goto do_num6; // [.eE]
2247
0
        }
2248
0
    }
2249
5.52k
    else
2250
5.52k
    {
2251
5.52k
        for(;;)
2252
17.6k
        {
2253
17.6k
            if(BOOST_JSON_UNLIKELY(! cs))
2254
274
            {
2255
274
                if(BOOST_JSON_UNLIKELY(more_))
2256
0
                {
2257
0
                    if(BOOST_JSON_UNLIKELY(
2258
0
                        ! h_.on_number_part(
2259
0
                            {begin, cs.used(begin)}, ec_)))
2260
0
                        return fail(cs.begin());
2261
2262
0
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263
0
                        num_buf_.append( begin, cs.used(begin) );
2264
0
                    return suspend(cs.begin(), state::num2, num);
2265
0
                }
2266
274
                goto finish_int;
2267
274
            }
2268
17.3k
            char const c = *cs;
2269
17.3k
            if(BOOST_JSON_LIKELY(
2270
17.3k
                c >= '0' && c <= '9'))
2271
13.6k
            {
2272
13.6k
                ++cs;
2273
                //              18446744073709551615 UINT64_MAX
2274
13.6k
                if( num.mant  > 1844674407370955161 || (
2275
12.3k
                    num.mant == 1844674407370955161 && c > '5'))
2276
1.54k
                    break;
2277
12.1k
                BOOST_IF_CONSTEXPR( !no_parsing )
2278
12.1k
                    num.mant = 10 * num.mant + ( c - '0' );
2279
12.1k
            }
2280
3.71k
            else
2281
3.71k
            {
2282
3.71k
                goto do_num6; // [.eE]
2283
3.71k
            }
2284
17.3k
        }
2285
5.52k
    }
2286
1.54k
    ++num.bias;
2287
2288
    //----------------------------------
2289
    //
2290
    // 1*DIGIT
2291
    // non-significant digits left of decimal
2292
    //
2293
1.54k
do_num3:
2294
1.54k
    for(;;)
2295
5.99M
    {
2296
5.99M
        if(BOOST_JSON_UNLIKELY(! cs))
2297
42
        {
2298
42
            if(BOOST_JSON_UNLIKELY(more_))
2299
0
            {
2300
0
                if(BOOST_JSON_UNLIKELY(
2301
0
                    ! h_.on_number_part(
2302
0
                        {begin, cs.used(begin)}, ec_)))
2303
0
                    return fail(cs.begin());
2304
2305
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2306
0
                    num_buf_.append( begin, cs.used(begin) );
2307
0
                return suspend(cs.begin(), state::num3, num);
2308
0
            }
2309
42
            goto finish_dub;
2310
42
        }
2311
5.99M
        char const c = *cs;
2312
5.99M
        if(BOOST_JSON_UNLIKELY(
2313
5.99M
            c >= '0' && c <= '9'))
2314
5.99M
        {
2315
5.99M
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316
0
            {
2317
0
                BOOST_STATIC_CONSTEXPR source_location loc
2318
0
                    = BOOST_CURRENT_LOCATION;
2319
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320
0
            }
2321
5.99M
            ++cs;
2322
5.99M
            ++num.bias;
2323
5.99M
        }
2324
1.50k
        else if(BOOST_JSON_LIKELY(
2325
1.50k
            c == '.'))
2326
360
        {
2327
360
            ++cs;
2328
360
            break;
2329
360
        }
2330
1.14k
        else if((c | 32) == 'e')
2331
666
        {
2332
666
            ++cs;
2333
666
            goto do_exp1;
2334
666
        }
2335
475
        else
2336
475
        {
2337
475
            goto finish_dub;
2338
475
        }
2339
5.99M
    }
2340
2341
    //----------------------------------
2342
    //
2343
    // DIGIT
2344
    // first non-significant digit
2345
    // to the right of decimal
2346
    //
2347
360
do_num4:
2348
360
    {
2349
360
        if(BOOST_JSON_UNLIKELY(! cs))
2350
6
        {
2351
6
            if(BOOST_JSON_UNLIKELY(
2352
6
                ! h_.on_number_part(
2353
6
                    {begin, cs.used(begin)}, ec_)))
2354
0
                return fail(cs.begin());
2355
2356
6
            BOOST_IF_CONSTEXPR( precise_parsing )
2357
0
                num_buf_.append( begin, cs.used(begin) );
2358
6
            return maybe_suspend(
2359
6
                cs.begin(), state::num4, num);
2360
6
        }
2361
354
        char const c = *cs;
2362
354
        if(BOOST_JSON_LIKELY(
2363
            //static_cast<unsigned char>(c - '0') < 10))
2364
354
            c >= '0' && c <= '9'))
2365
340
        {
2366
340
            ++cs;
2367
340
        }
2368
14
        else
2369
14
        {
2370
            // digit required
2371
14
            BOOST_STATIC_CONSTEXPR source_location loc
2372
14
                = BOOST_CURRENT_LOCATION;
2373
14
            return fail(cs.begin(), error::syntax, &loc);
2374
14
        }
2375
354
    }
2376
2377
    //----------------------------------
2378
    //
2379
    // 1*DIGIT
2380
    // non-significant digits
2381
    // to the right of decimal
2382
    //
2383
1.20k
do_num5:
2384
1.20k
    for(;;)
2385
1.74k
    {
2386
1.74k
        if(BOOST_JSON_UNLIKELY(! cs))
2387
44
        {
2388
44
            if(BOOST_JSON_UNLIKELY(more_))
2389
0
            {
2390
0
                if(BOOST_JSON_UNLIKELY(
2391
0
                    ! h_.on_number_part(
2392
0
                        {begin, cs.used(begin)}, ec_)))
2393
0
                    return fail(cs.begin());
2394
2395
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2396
0
                    num_buf_.append( begin, cs.used(begin) );
2397
0
                return suspend(cs.begin(), state::num5, num);
2398
0
            }
2399
44
            goto finish_dub;
2400
44
        }
2401
1.69k
        char const c = *cs;
2402
1.69k
        if(BOOST_JSON_LIKELY(
2403
1.69k
            c >= '0' && c <= '9'))
2404
539
        {
2405
539
            ++cs;
2406
539
        }
2407
1.15k
        else if((c | 32) == 'e')
2408
198
        {
2409
198
            ++cs;
2410
198
            goto do_exp1;
2411
198
        }
2412
960
        else
2413
960
        {
2414
960
            goto finish_dub;
2415
960
        }
2416
1.69k
    }
2417
2418
    //----------------------------------
2419
    //
2420
    // [.eE]
2421
    //
2422
3.71k
do_num6:
2423
3.71k
    {
2424
3.71k
        if(BOOST_JSON_UNLIKELY(! cs))
2425
0
        {
2426
0
            if(BOOST_JSON_UNLIKELY(more_))
2427
0
            {
2428
0
                if(BOOST_JSON_UNLIKELY(
2429
0
                    ! h_.on_number_part(
2430
0
                        {begin, cs.used(begin)}, ec_)))
2431
0
                    return fail(cs.begin());
2432
2433
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2434
0
                    num_buf_.append( begin, cs.used(begin) );
2435
0
                return suspend(cs.begin(), state::num6, num);
2436
0
            }
2437
0
            goto finish_int;
2438
0
        }
2439
3.71k
        char const c = *cs;
2440
3.71k
        if(BOOST_JSON_LIKELY(
2441
3.71k
            c == '.'))
2442
1.12k
        {
2443
1.12k
            ++cs;
2444
1.12k
        }
2445
2.59k
        else if((c | 32) == 'e')
2446
552
        {
2447
552
            ++cs;
2448
552
            goto do_exp1;
2449
552
        }
2450
2.04k
        else
2451
2.04k
        {
2452
2.04k
            goto finish_int;
2453
2.04k
        }
2454
3.71k
    }
2455
2456
    //----------------------------------
2457
    //
2458
    // DIGIT
2459
    // first significant digit
2460
    // to the right of decimal
2461
    //
2462
1.33k
do_num7:
2463
1.33k
    {
2464
1.33k
        if(BOOST_JSON_UNLIKELY(! cs))
2465
6
        {
2466
6
            if(BOOST_JSON_UNLIKELY(more_))
2467
0
            {
2468
0
                if(BOOST_JSON_UNLIKELY(
2469
0
                    ! h_.on_number_part(
2470
0
                        {begin, cs.used(begin)}, ec_)))
2471
0
                    return fail(cs.begin());
2472
2473
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2474
0
                    num_buf_.append( begin, cs.used(begin) );
2475
0
                return suspend(cs.begin(), state::num7, num);
2476
0
            }
2477
            // digit required
2478
6
            BOOST_STATIC_CONSTEXPR source_location loc
2479
6
                = BOOST_CURRENT_LOCATION;
2480
6
            return fail(cs.begin(), error::syntax, &loc);
2481
6
        }
2482
1.33k
        char const c = *cs;
2483
1.33k
        if(BOOST_JSON_UNLIKELY(
2484
1.33k
            c < '0' || c > '9'))
2485
7
        {
2486
            // digit required
2487
7
            BOOST_STATIC_CONSTEXPR source_location loc
2488
7
                = BOOST_CURRENT_LOCATION;
2489
7
            return fail(cs.begin(), error::syntax, &loc);
2490
7
        }
2491
1.33k
    }
2492
2493
    //----------------------------------
2494
    //
2495
    // 1*DIGIT
2496
    // significant digits
2497
    // to the right of decimal
2498
    //
2499
1.52k
do_num8:
2500
1.52k
    for(;;)
2501
5.04k
    {
2502
5.04k
        if(BOOST_JSON_UNLIKELY(! cs))
2503
121
        {
2504
121
            if(BOOST_JSON_UNLIKELY(more_))
2505
0
            {
2506
0
                if(BOOST_JSON_UNLIKELY(
2507
0
                    ! h_.on_number_part(
2508
0
                        {begin, cs.used(begin)}, ec_)))
2509
0
                    return fail(cs.begin());
2510
2511
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2512
0
                    num_buf_.append( begin, cs.used(begin) );
2513
0
                return suspend(cs.begin(), state::num8, num);
2514
0
            }
2515
121
            goto finish_dub;
2516
121
        }
2517
4.92k
        char const c = *cs;
2518
4.92k
        if(BOOST_JSON_LIKELY(
2519
4.92k
            c >= '0' && c <= '9'))
2520
4.38k
        {
2521
4.38k
            ++cs;
2522
4.38k
            if(!no_parsing && BOOST_JSON_LIKELY(
2523
4.38k
                num.mant <= 9007199254740991)) // 2^53-1
2524
3.52k
            {
2525
3.52k
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526
0
                {
2527
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2528
0
                        = BOOST_CURRENT_LOCATION;
2529
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530
0
                }
2531
3.52k
                --num.bias;
2532
3.52k
                num.mant = 10 * num.mant + ( c - '0' );
2533
3.52k
            }
2534
862
            else
2535
862
            {
2536
862
                goto do_num5;
2537
862
            }
2538
4.38k
        }
2539
544
        else if((c | 32) == 'e')
2540
251
        {
2541
251
            ++cs;
2542
251
            goto do_exp1;
2543
251
        }
2544
293
        else
2545
293
        {
2546
293
            goto finish_dub;
2547
293
        }
2548
4.92k
    }
2549
2550
    //----------------------------------
2551
    //
2552
    // *[+-]
2553
    //
2554
3.31k
do_exp1:
2555
3.31k
    if(BOOST_JSON_UNLIKELY(! cs))
2556
34
    {
2557
34
        if(BOOST_JSON_UNLIKELY(
2558
34
            ! h_.on_number_part(
2559
34
                {begin, cs.used(begin)}, ec_)))
2560
0
            return fail(cs.begin());
2561
2562
34
        BOOST_IF_CONSTEXPR( precise_parsing )
2563
0
            num_buf_.append( begin, cs.used(begin) );
2564
34
        return maybe_suspend(
2565
34
            cs.begin(), state::exp1, num);
2566
34
    }
2567
3.27k
    if(*cs == '+')
2568
195
    {
2569
195
        ++cs;
2570
195
    }
2571
3.08k
    else if(*cs == '-')
2572
745
    {
2573
745
        ++cs;
2574
745
        num.frac = true;
2575
745
    }
2576
2577
    //----------------------------------
2578
    //
2579
    // DIGIT
2580
    // first digit of the exponent
2581
    //
2582
3.27k
do_exp2:
2583
3.27k
    {
2584
3.27k
        if(BOOST_JSON_UNLIKELY(! cs))
2585
15
        {
2586
15
            if(BOOST_JSON_UNLIKELY(more_))
2587
0
            {
2588
0
                if(BOOST_JSON_UNLIKELY(
2589
0
                    ! h_.on_number_part(
2590
0
                        {begin, cs.used(begin)}, ec_)))
2591
0
                    return fail(cs.begin());
2592
2593
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2594
0
                    num_buf_.append( begin, cs.used(begin) );
2595
0
                return suspend(cs.begin(), state::exp2, num);
2596
0
            }
2597
            // digit required
2598
15
            BOOST_STATIC_CONSTEXPR source_location loc
2599
15
                = BOOST_CURRENT_LOCATION;
2600
15
            return fail(cs.begin(), error::syntax, &loc);
2601
15
        }
2602
3.26k
        char const c = *cs;
2603
3.26k
        if(BOOST_JSON_UNLIKELY(
2604
3.26k
            c < '0' || c > '9'))
2605
21
        {
2606
            // digit required
2607
21
            BOOST_STATIC_CONSTEXPR source_location loc
2608
21
                = BOOST_CURRENT_LOCATION;
2609
21
            return fail(cs.begin(), error::syntax, &loc);
2610
21
        }
2611
3.24k
        ++cs;
2612
3.24k
        num.exp = c - '0';
2613
3.24k
    }
2614
2615
    //----------------------------------
2616
    //
2617
    // 1*DIGIT
2618
    // subsequent digits in the exponent
2619
    //
2620
3.24k
do_exp3:
2621
3.24k
    for(;;)
2622
14.5k
    {
2623
14.5k
        if(BOOST_JSON_UNLIKELY(! cs))
2624
291
        {
2625
291
            if(BOOST_JSON_UNLIKELY(more_))
2626
0
            {
2627
0
                if(BOOST_JSON_UNLIKELY(
2628
0
                    ! h_.on_number_part(
2629
0
                        {begin, cs.used(begin)}, ec_)))
2630
0
                    return fail(cs.begin());
2631
2632
0
                BOOST_IF_CONSTEXPR( precise_parsing )
2633
0
                    num_buf_.append( begin, cs.used(begin) );
2634
0
                return suspend(cs.begin(), state::exp3, num);
2635
0
            }
2636
291
        }
2637
14.2k
        else
2638
14.2k
        {
2639
14.2k
            char const c = *cs;
2640
14.2k
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641
11.2k
            {
2642
11.2k
                if(BOOST_JSON_UNLIKELY(
2643
                //              2147483647 INT_MAX
2644
11.2k
                    num.exp  >  214748364 ||
2645
11.2k
                    (num.exp == 214748364 && c > '7')
2646
11.2k
                ))
2647
957
                    num.exp = INT_MAX;
2648
10.3k
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649
10.3k
                    num.exp = 10 * num.exp + ( c - '0' );
2650
2651
11.2k
                ++cs;
2652
11.2k
                continue;
2653
11.2k
            }
2654
14.2k
        }
2655
3.24k
        BOOST_ASSERT(num.exp >= 0);
2656
3.24k
        if ( num.frac )
2657
738
        {
2658
738
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659
403
            {
2660
                // if exponent overflowed, bias is a very large negative
2661
                // number, and mantissa isn't zero, then we cannot parse the
2662
                // number correctly
2663
403
                if(BOOST_JSON_UNLIKELY(
2664
403
                    (num.exp == INT_MAX) &&
2665
403
                    (num.bias < 0) &&
2666
403
                    (num.exp + num.bias < 308) &&
2667
403
                    num.mant ))
2668
0
                {
2669
0
                    BOOST_STATIC_CONSTEXPR source_location loc
2670
0
                        = BOOST_CURRENT_LOCATION;
2671
0
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672
0
                }
2673
2674
403
                num.bias = 0;
2675
403
                num.exp = INT_MAX;
2676
403
            }
2677
738
        }
2678
2.50k
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679
463
        {
2680
            // if exponent overflowed, bias is a very large positive number,
2681
            // and mantissa isn't zero, then we cannot parse the
2682
            // number correctly
2683
463
            if(BOOST_JSON_UNLIKELY(
2684
463
                (num.exp == INT_MAX) &&
2685
463
                (num.bias > 0) &&
2686
463
                (num.exp - num.bias < 308) &&
2687
463
                num.mant ))
2688
0
            {
2689
0
                BOOST_STATIC_CONSTEXPR source_location loc
2690
0
                    = BOOST_CURRENT_LOCATION;
2691
0
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692
0
            }
2693
2694
463
            num.bias = 0;
2695
463
            num.exp = INT_MAX;
2696
463
        }
2697
3.24k
        goto finish_dub;
2698
3.24k
    }
2699
2700
2.31k
finish_int:
2701
2.31k
    if(negative || (!stack_empty && num.neg))
2702
0
    {
2703
0
        if(BOOST_JSON_UNLIKELY(
2704
0
            ! h_.on_int64(static_cast<
2705
0
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706
0
            return fail(cs.begin());
2707
0
        return cs.begin();
2708
0
    }
2709
2.31k
    if(num.mant <= INT64_MAX)
2710
1.82k
    {
2711
5.97k
finish_signed:
2712
5.97k
        if(BOOST_JSON_UNLIKELY(
2713
5.97k
            ! h_.on_int64(static_cast<
2714
5.97k
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715
0
            return fail(cs.begin());
2716
5.97k
        return cs.begin();
2717
5.97k
    }
2718
487
    if(BOOST_JSON_UNLIKELY(
2719
487
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720
0
        return fail(cs.begin());
2721
487
    return cs.begin();
2722
6.48k
finish_dub:
2723
6.48k
    double d;
2724
6.48k
    std::size_t const size = cs.used(begin);
2725
6.48k
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726
6.48k
    BOOST_IF_CONSTEXPR( precise_parsing )
2727
0
    {
2728
0
        char const* data = begin;
2729
0
        std::size_t full_size = size;
2730
         // if we previously suspended or if the current input ends with the
2731
         // number, we need to copy the current part of the number to the
2732
         // temporary buffer
2733
0
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734
0
        {
2735
0
            data = num_buf_.append( begin, size );
2736
0
            full_size = num_buf_.size();
2737
0
        }
2738
0
        auto const err = detail::charconv::from_chars(
2739
0
            data, data + full_size, d );
2740
0
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741
0
        BOOST_ASSERT( err.ptr == data + full_size );
2742
0
        (void)err;
2743
0
    }
2744
6.48k
    else BOOST_IF_CONSTEXPR( no_parsing )
2745
0
        d = 0;
2746
6.48k
    else
2747
6.48k
        d = detail::dec_to_float(
2748
6.48k
            num.mant,
2749
6.48k
            num.bias + (num.frac ?
2750
5.75k
                -num.exp : num.exp),
2751
6.48k
            num.neg);
2752
6.48k
    if(BOOST_JSON_UNLIKELY(
2753
6.48k
        ! h_.on_double(d, {begin, size}, ec_)))
2754
0
        return fail(cs.begin());
2755
6.48k
    return cs.begin();
2756
6.48k
}
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number<true, (char)43, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, true>, std::__1::integral_constant<char, (char)43>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::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>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::handler>::parse_number<false, (char)0, (boost::json::number_precision)1>(char const*, std::__1::integral_constant<bool, false>, std::__1::integral_constant<char, (char)0>, std::__1::integral_constant<boost::json::number_precision, (boost::json::number_precision)1>)
Unexecuted instantiation: char const* boost::json::basic_parser<null_parser::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>)
2757
2758
//----------------------------------------------------------
2759
2760
template<class Handler>
2761
template<class... Args>
2762
basic_parser<Handler>::
2763
basic_parser(
2764
    parse_options const& opt,
2765
    Args&&... args)
2766
    : h_(std::forward<Args>(args)...)
2767
    , opt_(opt)
2768
12.2k
{
2769
12.2k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::basic_parser<Object*>(boost::json::parse_options const&, Object*&&)
Line
Count
Source
2768
6.93k
{
2769
6.93k
}
boost::json::basic_parser<null_parser::handler>::basic_parser<>(boost::json::parse_options const&)
Line
Count
Source
2768
5.27k
{
2769
5.27k
}
2770
2771
//----------------------------------------------------------
2772
2773
template<class Handler>
2774
void
2775
basic_parser<Handler>::
2776
reset() noexcept
2777
{
2778
    ec_ = {};
2779
    st_.clear();
2780
    more_ = true;
2781
    done_ = false;
2782
    clean_ = true;
2783
    num_buf_.clear();
2784
}
2785
2786
template<class Handler>
2787
void
2788
basic_parser<Handler>::
2789
fail(system::error_code ec) noexcept
2790
{
2791
    if(! ec)
2792
    {
2793
        // assign an arbitrary
2794
        // error code to prevent UB
2795
        BOOST_JSON_FAIL(ec_, error::incomplete);
2796
    }
2797
    else
2798
    {
2799
        ec_ = ec;
2800
    }
2801
    done_ = false;
2802
}
2803
2804
//----------------------------------------------------------
2805
2806
template<class Handler>
2807
std::size_t
2808
basic_parser<Handler>::
2809
write_some(
2810
    bool more,
2811
    char const* data,
2812
    std::size_t size,
2813
    system::error_code& ec)
2814
12.2k
{
2815
    // see if we exited via exception
2816
    // on the last call to write_some
2817
12.2k
    if(! clean_)
2818
0
    {
2819
        // prevent UB
2820
0
        if(! ec_)
2821
0
        {
2822
0
            BOOST_JSON_FAIL(ec_, error::exception);
2823
0
        }
2824
0
    }
2825
12.2k
    if(ec_)
2826
0
    {
2827
        // error is sticky
2828
0
        ec = ec_;
2829
0
        return 0;
2830
0
    }
2831
12.2k
    clean_ = false;
2832
12.2k
    more_ = more;
2833
12.2k
    end_ = data + size;
2834
12.2k
    const char* p;
2835
12.2k
    if(BOOST_JSON_LIKELY(st_.empty()))
2836
12.2k
    {
2837
        // first time
2838
12.2k
        depth_ = opt_.max_depth;
2839
12.2k
        if(BOOST_JSON_UNLIKELY(
2840
12.2k
            ! h_.on_document_begin(ec_)))
2841
0
        {
2842
0
            ec = ec_;
2843
0
            return 0;
2844
0
        }
2845
12.2k
        p = parse_document(data, std::true_type());
2846
12.2k
    }
2847
0
    else
2848
0
    {
2849
0
        p = parse_document(data, std::false_type());
2850
0
    }
2851
2852
12.2k
    if(BOOST_JSON_LIKELY(p != sentinel()))
2853
1.94k
    {
2854
1.94k
        BOOST_ASSERT(! ec_);
2855
1.94k
        if(! done_)
2856
1.94k
        {
2857
1.94k
            done_ = true;
2858
1.94k
            h_.on_document_end(ec_);
2859
1.94k
        }
2860
1.94k
    }
2861
10.2k
    else
2862
10.2k
    {
2863
10.2k
        if(! ec_)
2864
3.43k
        {
2865
3.43k
            if(! more_)
2866
3.43k
            {
2867
3.43k
                BOOST_JSON_FAIL(ec_, error::incomplete);
2868
3.43k
            }
2869
0
            else if(! st_.empty())
2870
0
            {
2871
                // consume as much trailing whitespace in
2872
                // the JSON document as possible, but still
2873
                // consider the parse complete
2874
0
                state st;
2875
0
                st_.peek(st);
2876
0
                if( st == state::doc3 &&
2877
0
                    ! done_)
2878
0
                {
2879
0
                    done_ = true;
2880
0
                    h_.on_document_end(ec_);
2881
0
                }
2882
0
            }
2883
3.43k
        }
2884
10.2k
        p = end_;
2885
10.2k
    }
2886
0
    ec = ec_;
2887
12.2k
    clean_ = true;
2888
12.2k
    return p - data;
2889
12.2k
}
boost::json::basic_parser<boost::json::detail::into_handler<Object> >::write_some(bool, char const*, unsigned long, boost::system::error_code&)
Line
Count
Source
2814
6.93k
{
2815
    // see if we exited via exception
2816
    // on the last call to write_some
2817
6.93k
    if(! clean_)
2818
0
    {
2819
        // prevent UB
2820
0
        if(! ec_)
2821
0
        {
2822
0
            BOOST_JSON_FAIL(ec_, error::exception);
2823
0
        }
2824
0
    }
2825
6.93k
    if(ec_)
2826
0
    {
2827
        // error is sticky
2828
0
        ec = ec_;
2829
0
        return 0;
2830
0
    }
2831
6.93k
    clean_ = false;
2832
6.93k
    more_ = more;
2833
6.93k
    end_ = data + size;
2834
6.93k
    const char* p;
2835
6.93k
    if(BOOST_JSON_LIKELY(st_.empty()))
2836
6.93k
    {
2837
        // first time
2838
6.93k
        depth_ = opt_.max_depth;
2839
6.93k
        if(BOOST_JSON_UNLIKELY(
2840
6.93k
            ! h_.on_document_begin(ec_)))
2841
0
        {
2842
0
            ec = ec_;
2843
0
            return 0;
2844
0
        }
2845
6.93k
        p = parse_document(data, std::true_type());
2846
6.93k
    }
2847
0
    else
2848
0
    {
2849
0
        p = parse_document(data, std::false_type());
2850
0
    }
2851
2852
6.93k
    if(BOOST_JSON_LIKELY(p != sentinel()))
2853
69
    {
2854
69
        BOOST_ASSERT(! ec_);
2855
69
        if(! done_)
2856
69
        {
2857
69
            done_ = true;
2858
69
            h_.on_document_end(ec_);
2859
69
        }
2860
69
    }
2861
6.86k
    else
2862
6.86k
    {
2863
6.86k
        if(! ec_)
2864
1.87k
        {
2865
1.87k
            if(! more_)
2866
1.87k
            {
2867
1.87k
                BOOST_JSON_FAIL(ec_, error::incomplete);
2868
1.87k
            }
2869
0
            else if(! st_.empty())
2870
0
            {
2871
                // consume as much trailing whitespace in
2872
                // the JSON document as possible, but still
2873
                // consider the parse complete
2874
0
                state st;
2875
0
                st_.peek(st);
2876
0
                if( st == state::doc3 &&
2877
0
                    ! done_)
2878
0
                {
2879
0
                    done_ = true;
2880
0
                    h_.on_document_end(ec_);
2881
0
                }
2882
0
            }
2883
1.87k
        }
2884
6.86k
        p = end_;
2885
6.86k
    }
2886
0
    ec = ec_;
2887
6.93k
    clean_ = true;
2888
6.93k
    return p - data;
2889
6.93k
}
boost::json::basic_parser<null_parser::handler>::write_some(bool, char const*, unsigned long, boost::system::error_code&)
Line
Count
Source
2814
5.27k
{
2815
    // see if we exited via exception
2816
    // on the last call to write_some
2817
5.27k
    if(! clean_)
2818
0
    {
2819
        // prevent UB
2820
0
        if(! ec_)
2821
0
        {
2822
0
            BOOST_JSON_FAIL(ec_, error::exception);
2823
0
        }
2824
0
    }
2825
5.27k
    if(ec_)
2826
0
    {
2827
        // error is sticky
2828
0
        ec = ec_;
2829
0
        return 0;
2830
0
    }
2831
5.27k
    clean_ = false;
2832
5.27k
    more_ = more;
2833
5.27k
    end_ = data + size;
2834
5.27k
    const char* p;
2835
5.27k
    if(BOOST_JSON_LIKELY(st_.empty()))
2836
5.27k
    {
2837
        // first time
2838
5.27k
        depth_ = opt_.max_depth;
2839
5.27k
        if(BOOST_JSON_UNLIKELY(
2840
5.27k
            ! h_.on_document_begin(ec_)))
2841
0
        {
2842
0
            ec = ec_;
2843
0
            return 0;
2844
0
        }
2845
5.27k
        p = parse_document(data, std::true_type());
2846
5.27k
    }
2847
0
    else
2848
0
    {
2849
0
        p = parse_document(data, std::false_type());
2850
0
    }
2851
2852
5.27k
    if(BOOST_JSON_LIKELY(p != sentinel()))
2853
1.87k
    {
2854
1.87k
        BOOST_ASSERT(! ec_);
2855
1.87k
        if(! done_)
2856
1.87k
        {
2857
1.87k
            done_ = true;
2858
1.87k
            h_.on_document_end(ec_);
2859
1.87k
        }
2860
1.87k
    }
2861
3.39k
    else
2862
3.39k
    {
2863
3.39k
        if(! ec_)
2864
1.55k
        {
2865
1.55k
            if(! more_)
2866
1.55k
            {
2867
1.55k
                BOOST_JSON_FAIL(ec_, error::incomplete);
2868
1.55k
            }
2869
0
            else if(! st_.empty())
2870
0
            {
2871
                // consume as much trailing whitespace in
2872
                // the JSON document as possible, but still
2873
                // consider the parse complete
2874
0
                state st;
2875
0
                st_.peek(st);
2876
0
                if( st == state::doc3 &&
2877
0
                    ! done_)
2878
0
                {
2879
0
                    done_ = true;
2880
0
                    h_.on_document_end(ec_);
2881
0
                }
2882
0
            }
2883
1.55k
        }
2884
3.39k
        p = end_;
2885
3.39k
    }
2886
0
    ec = ec_;
2887
5.27k
    clean_ = true;
2888
5.27k
    return p - data;
2889
5.27k
}
2890
2891
template<class Handler>
2892
std::size_t
2893
basic_parser<Handler>::
2894
write_some(
2895
    bool more,
2896
    char const* data,
2897
    std::size_t size,
2898
    std::error_code& ec)
2899
{
2900
    system::error_code jec;
2901
    std::size_t const result = write_some(more, data, size, jec);
2902
    ec = jec;
2903
    return result;
2904
}
2905
2906
#endif
2907
2908
} // namespace json
2909
} // namespace boost
2910
2911
#ifdef _MSC_VER
2912
#pragma warning(pop)
2913
#endif
2914
2915
#endif