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