1  
//
1  
//
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
2  
// Copyright (c) 2019 Vinnie Falco (vinnie.falco@gmail.com)
3  
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
3  
// Copyright (c) 2020 Krystian Stasiowski (sdkrystian@gmail.com)
4  
//
4  
//
5  
// Distributed under the Boost Software License, Version 1.0. (See accompanying
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)
6  
// file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
7  
//
7  
//
8  
// Official repository: https://github.com/boostorg/json
8  
// Official repository: https://github.com/boostorg/json
9  
//
9  
//
10  

10  

11  
#ifndef BOOST_JSON_BASIC_PARSER_IMPL_HPP
11  
#ifndef BOOST_JSON_BASIC_PARSER_IMPL_HPP
12  
#define BOOST_JSON_BASIC_PARSER_IMPL_HPP
12  
#define BOOST_JSON_BASIC_PARSER_IMPL_HPP
13  

13  

14  
#include <boost/json/detail/config.hpp>
14  
#include <boost/json/detail/config.hpp>
15  
#include <boost/json/detail/literals.hpp>
15  
#include <boost/json/detail/literals.hpp>
16  
#include <boost/json/basic_parser.hpp>
16  
#include <boost/json/basic_parser.hpp>
17  
#include <boost/json/error.hpp>
17  
#include <boost/json/error.hpp>
18  
#include <boost/json/detail/buffer.hpp>
18  
#include <boost/json/detail/buffer.hpp>
19  
#include <boost/json/detail/charconv/from_chars.hpp>
19  
#include <boost/json/detail/charconv/from_chars.hpp>
20  
#include <boost/json/detail/sse2.hpp>
20  
#include <boost/json/detail/sse2.hpp>
21  
#include <boost/mp11/algorithm.hpp>
21  
#include <boost/mp11/algorithm.hpp>
22  
#include <boost/mp11/integral.hpp>
22  
#include <boost/mp11/integral.hpp>
23  
#include <cmath>
23  
#include <cmath>
24  
#include <limits>
24  
#include <limits>
25  
#include <cstring>
25  
#include <cstring>
26  

26  

27  
#ifdef _MSC_VER
27  
#ifdef _MSC_VER
28  
#pragma warning(push)
28  
#pragma warning(push)
29  
#pragma warning(disable: 4702) // unreachable code
29  
#pragma warning(disable: 4702) // unreachable code
30  
#pragma warning(disable: 4127) // conditional expression is constant
30  
#pragma warning(disable: 4127) // conditional expression is constant
31  
#endif
31  
#endif
32  

32  

33  
/*  This file must be manually included to get the
33  
/*  This file must be manually included to get the
34  
    function template definitions for basic_parser.
34  
    function template definitions for basic_parser.
35  
*/
35  
*/
36  

36  

37  
/*  Reference:
37  
/*  Reference:
38  

38  

39  
    https://www.json.org/
39  
    https://www.json.org/
40  

40  

41  
    RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
41  
    RFC 7159: The JavaScript Object Notation (JSON) Data Interchange Format
42  
    https://tools.ietf.org/html/rfc7159
42  
    https://tools.ietf.org/html/rfc7159
43  

43  

44  
    https://ampl.com/netlib/fp/dtoa.c
44  
    https://ampl.com/netlib/fp/dtoa.c
45  
*/
45  
*/
46  

46  

47  
#ifndef BOOST_JSON_DOCS
47  
#ifndef BOOST_JSON_DOCS
48  

48  

49  
namespace boost {
49  
namespace boost {
50  
namespace json {
50  
namespace json {
51  
namespace detail {
51  
namespace detail {
52  

52  

53  
inline
53  
inline
54  
double
54  
double
55  
pow10(int exp) noexcept
55  
pow10(int exp) noexcept
56  
{
56  
{
57  
    static double const tab[618] = {
57  
    static double const tab[618] = {
58  
                        1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
58  
                        1e-308, 1e-307, 1e-306, 1e-305, 1e-304, 1e-303, 1e-302, 1e-301,
59  

59  

60  
        1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
60  
        1e-300, 1e-299, 1e-298, 1e-297, 1e-296, 1e-295, 1e-294, 1e-293, 1e-292, 1e-291,
61  
        1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
61  
        1e-290, 1e-289, 1e-288, 1e-287, 1e-286, 1e-285, 1e-284, 1e-283, 1e-282, 1e-281,
62  
        1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
62  
        1e-280, 1e-279, 1e-278, 1e-277, 1e-276, 1e-275, 1e-274, 1e-273, 1e-272, 1e-271,
63  
        1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
63  
        1e-270, 1e-269, 1e-268, 1e-267, 1e-266, 1e-265, 1e-264, 1e-263, 1e-262, 1e-261,
64  
        1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
64  
        1e-260, 1e-259, 1e-258, 1e-257, 1e-256, 1e-255, 1e-254, 1e-253, 1e-252, 1e-251,
65  
        1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
65  
        1e-250, 1e-249, 1e-248, 1e-247, 1e-246, 1e-245, 1e-244, 1e-243, 1e-242, 1e-241,
66  
        1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
66  
        1e-240, 1e-239, 1e-238, 1e-237, 1e-236, 1e-235, 1e-234, 1e-233, 1e-232, 1e-231,
67  
        1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
67  
        1e-230, 1e-229, 1e-228, 1e-227, 1e-226, 1e-225, 1e-224, 1e-223, 1e-222, 1e-221,
68  
        1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
68  
        1e-220, 1e-219, 1e-218, 1e-217, 1e-216, 1e-215, 1e-214, 1e-213, 1e-212, 1e-211,
69  
        1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
69  
        1e-210, 1e-209, 1e-208, 1e-207, 1e-206, 1e-205, 1e-204, 1e-203, 1e-202, 1e-201,
70  

70  

71  
        1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
71  
        1e-200, 1e-199, 1e-198, 1e-197, 1e-196, 1e-195, 1e-194, 1e-193, 1e-192, 1e-191,
72  
        1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
72  
        1e-190, 1e-189, 1e-188, 1e-187, 1e-186, 1e-185, 1e-184, 1e-183, 1e-182, 1e-181,
73  
        1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
73  
        1e-180, 1e-179, 1e-178, 1e-177, 1e-176, 1e-175, 1e-174, 1e-173, 1e-172, 1e-171,
74  
        1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
74  
        1e-170, 1e-169, 1e-168, 1e-167, 1e-166, 1e-165, 1e-164, 1e-163, 1e-162, 1e-161,
75  
        1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
75  
        1e-160, 1e-159, 1e-158, 1e-157, 1e-156, 1e-155, 1e-154, 1e-153, 1e-152, 1e-151,
76  
        1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
76  
        1e-150, 1e-149, 1e-148, 1e-147, 1e-146, 1e-145, 1e-144, 1e-143, 1e-142, 1e-141,
77  
        1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
77  
        1e-140, 1e-139, 1e-138, 1e-137, 1e-136, 1e-135, 1e-134, 1e-133, 1e-132, 1e-131,
78  
        1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
78  
        1e-130, 1e-129, 1e-128, 1e-127, 1e-126, 1e-125, 1e-124, 1e-123, 1e-122, 1e-121,
79  
        1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
79  
        1e-120, 1e-119, 1e-118, 1e-117, 1e-116, 1e-115, 1e-114, 1e-113, 1e-112, 1e-111,
80  
        1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
80  
        1e-110, 1e-109, 1e-108, 1e-107, 1e-106, 1e-105, 1e-104, 1e-103, 1e-102, 1e-101,
81  

81  

82  
        1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
82  
        1e-100, 1e-099, 1e-098, 1e-097, 1e-096, 1e-095, 1e-094, 1e-093, 1e-092, 1e-091,
83  
        1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
83  
        1e-090, 1e-089, 1e-088, 1e-087, 1e-086, 1e-085, 1e-084, 1e-083, 1e-082, 1e-081,
84  
        1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
84  
        1e-080, 1e-079, 1e-078, 1e-077, 1e-076, 1e-075, 1e-074, 1e-073, 1e-072, 1e-071,
85  
        1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
85  
        1e-070, 1e-069, 1e-068, 1e-067, 1e-066, 1e-065, 1e-064, 1e-063, 1e-062, 1e-061,
86  
        1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
86  
        1e-060, 1e-059, 1e-058, 1e-057, 1e-056, 1e-055, 1e-054, 1e-053, 1e-052, 1e-051,
87  
        1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
87  
        1e-050, 1e-049, 1e-048, 1e-047, 1e-046, 1e-045, 1e-044, 1e-043, 1e-042, 1e-041,
88  
        1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
88  
        1e-040, 1e-039, 1e-038, 1e-037, 1e-036, 1e-035, 1e-034, 1e-033, 1e-032, 1e-031,
89  
        1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
89  
        1e-030, 1e-029, 1e-028, 1e-027, 1e-026, 1e-025, 1e-024, 1e-023, 1e-022, 1e-021,
90  
        1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
90  
        1e-020, 1e-019, 1e-018, 1e-017, 1e-016, 1e-015, 1e-014, 1e-013, 1e-012, 1e-011,
91  
        1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
91  
        1e-010, 1e-009, 1e-008, 1e-007, 1e-006, 1e-005, 1e-004, 1e-003, 1e-002, 1e-001,
92  

92  

93  
        1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
93  
        1e+000, 1e+001, 1e+002, 1e+003, 1e+004, 1e+005, 1e+006, 1e+007, 1e+008, 1e+009,
94  
        1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
94  
        1e+010, 1e+011, 1e+012, 1e+013, 1e+014, 1e+015, 1e+016, 1e+017, 1e+018, 1e+019,
95  
        1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
95  
        1e+020, 1e+021, 1e+022, 1e+023, 1e+024, 1e+025, 1e+026, 1e+027, 1e+028, 1e+029,
96  
        1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
96  
        1e+030, 1e+031, 1e+032, 1e+033, 1e+034, 1e+035, 1e+036, 1e+037, 1e+038, 1e+039,
97  
        1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
97  
        1e+040, 1e+041, 1e+042, 1e+043, 1e+044, 1e+045, 1e+046, 1e+047, 1e+048, 1e+049,
98  
        1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
98  
        1e+050, 1e+051, 1e+052, 1e+053, 1e+054, 1e+055, 1e+056, 1e+057, 1e+058, 1e+059,
99  
        1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
99  
        1e+060, 1e+061, 1e+062, 1e+063, 1e+064, 1e+065, 1e+066, 1e+067, 1e+068, 1e+069,
100  
        1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
100  
        1e+070, 1e+071, 1e+072, 1e+073, 1e+074, 1e+075, 1e+076, 1e+077, 1e+078, 1e+079,
101  
        1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
101  
        1e+080, 1e+081, 1e+082, 1e+083, 1e+084, 1e+085, 1e+086, 1e+087, 1e+088, 1e+089,
102  
        1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
102  
        1e+090, 1e+091, 1e+092, 1e+093, 1e+094, 1e+095, 1e+096, 1e+097, 1e+098, 1e+099,
103  

103  

104  
        1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
104  
        1e+100, 1e+101, 1e+102, 1e+103, 1e+104, 1e+105, 1e+106, 1e+107, 1e+108, 1e+109,
105  
        1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
105  
        1e+110, 1e+111, 1e+112, 1e+113, 1e+114, 1e+115, 1e+116, 1e+117, 1e+118, 1e+119,
106  
        1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
106  
        1e+120, 1e+121, 1e+122, 1e+123, 1e+124, 1e+125, 1e+126, 1e+127, 1e+128, 1e+129,
107  
        1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
107  
        1e+130, 1e+131, 1e+132, 1e+133, 1e+134, 1e+135, 1e+136, 1e+137, 1e+138, 1e+139,
108  
        1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
108  
        1e+140, 1e+141, 1e+142, 1e+143, 1e+144, 1e+145, 1e+146, 1e+147, 1e+148, 1e+149,
109  
        1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
109  
        1e+150, 1e+151, 1e+152, 1e+153, 1e+154, 1e+155, 1e+156, 1e+157, 1e+158, 1e+159,
110  
        1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
110  
        1e+160, 1e+161, 1e+162, 1e+163, 1e+164, 1e+165, 1e+166, 1e+167, 1e+168, 1e+169,
111  
        1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
111  
        1e+170, 1e+171, 1e+172, 1e+173, 1e+174, 1e+175, 1e+176, 1e+177, 1e+178, 1e+179,
112  
        1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
112  
        1e+180, 1e+181, 1e+182, 1e+183, 1e+184, 1e+185, 1e+186, 1e+187, 1e+188, 1e+189,
113  
        1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
113  
        1e+190, 1e+191, 1e+192, 1e+193, 1e+194, 1e+195, 1e+196, 1e+197, 1e+198, 1e+199,
114  

114  

115  
        1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
115  
        1e+200, 1e+201, 1e+202, 1e+203, 1e+204, 1e+205, 1e+206, 1e+207, 1e+208, 1e+209,
116  
        1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
116  
        1e+210, 1e+211, 1e+212, 1e+213, 1e+214, 1e+215, 1e+216, 1e+217, 1e+218, 1e+219,
117  
        1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
117  
        1e+220, 1e+221, 1e+222, 1e+223, 1e+224, 1e+225, 1e+226, 1e+227, 1e+228, 1e+229,
118  
        1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
118  
        1e+230, 1e+231, 1e+232, 1e+233, 1e+234, 1e+235, 1e+236, 1e+237, 1e+238, 1e+239,
119  
        1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
119  
        1e+240, 1e+241, 1e+242, 1e+243, 1e+244, 1e+245, 1e+246, 1e+247, 1e+248, 1e+249,
120  
        1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
120  
        1e+250, 1e+251, 1e+252, 1e+253, 1e+254, 1e+255, 1e+256, 1e+257, 1e+258, 1e+259,
121  
        1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
121  
        1e+260, 1e+261, 1e+262, 1e+263, 1e+264, 1e+265, 1e+266, 1e+267, 1e+268, 1e+269,
122  
        1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
122  
        1e+270, 1e+271, 1e+272, 1e+273, 1e+274, 1e+275, 1e+276, 1e+277, 1e+278, 1e+279,
123  
        1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
123  
        1e+280, 1e+281, 1e+282, 1e+283, 1e+284, 1e+285, 1e+286, 1e+287, 1e+288, 1e+289,
124  
        1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
124  
        1e+290, 1e+291, 1e+292, 1e+293, 1e+294, 1e+295, 1e+296, 1e+297, 1e+298, 1e+299,
125  

125  

126  
        1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
126  
        1e+300, 1e+301, 1e+302, 1e+303, 1e+304, 1e+305, 1e+306, 1e+307, 1e+308 };
127  

127  

128  
    if( exp > 308 )
128  
    if( exp > 308 )
129  
    {
129  
    {
130  
        return std::numeric_limits<double>::infinity();
130  
        return std::numeric_limits<double>::infinity();
131  
    }
131  
    }
132  
    else if( exp < -308 )
132  
    else if( exp < -308 )
133  
    {
133  
    {
134  
        // due to the way pow10 is used by dec_to_float,
134  
        // due to the way pow10 is used by dec_to_float,
135  
        // we can afford to return 0.0 here
135  
        // we can afford to return 0.0 here
136  
        return 0.0;
136  
        return 0.0;
137  
    }
137  
    }
138  
    else
138  
    else
139  
    {
139  
    {
140  
        exp += 308;
140  
        exp += 308;
141  
        BOOST_ASSERT(exp >= 0 && exp < 618);
141  
        BOOST_ASSERT(exp >= 0 && exp < 618);
142  
        return tab[exp];
142  
        return tab[exp];
143  
    }
143  
    }
144  
}
144  
}
145  

145  

146  
inline
146  
inline
147  
double
147  
double
148  
dec_to_float(
148  
dec_to_float(
149  
    std::uint64_t m,
149  
    std::uint64_t m,
150  
    std::int32_t e,
150  
    std::int32_t e,
151  
    bool neg) noexcept
151  
    bool neg) noexcept
152  
{
152  
{
153  
    // convert to double explicitly to silence warnings
153  
    // convert to double explicitly to silence warnings
154  
    double x = static_cast<double>(m);
154  
    double x = static_cast<double>(m);
155  
    if(neg)
155  
    if(neg)
156  
        x = -x;
156  
        x = -x;
157  

157  

158  
    if(e < -305)
158  
    if(e < -305)
159  
    {
159  
    {
160  
        x *= 1e-305 ;
160  
        x *= 1e-305 ;
161  
        e += 305;
161  
        e += 305;
162  
    }
162  
    }
163  

163  

164  
    if(e >= -22 && e < 0)
164  
    if(e >= -22 && e < 0)
165  
        return x / pow10(-e);
165  
        return x / pow10(-e);
166  

166  

167  
    return x * pow10(e);
167  
    return x * pow10(e);
168  
}
168  
}
169  

169  

170  
inline
170  
inline
171  
bool
171  
bool
172  
is_control(char c) noexcept
172  
is_control(char c) noexcept
173  
{
173  
{
174  
    return static_cast<unsigned char>(c) < 32;
174  
    return static_cast<unsigned char>(c) < 32;
175  
}
175  
}
176  

176  

177  
inline
177  
inline
178  
int
178  
int
179  
hex_digit(unsigned char c) noexcept
179  
hex_digit(unsigned char c) noexcept
180  
{
180  
{
181  
    // by Peter Dimov
181  
    // by Peter Dimov
182  
    if( c >= '0' && c <= '9' )
182  
    if( c >= '0' && c <= '9' )
183  
        return c - '0';
183  
        return c - '0';
184  
    c &= ~0x20;
184  
    c &= ~0x20;
185  
    if( c >= 'A' && c <= 'F' )
185  
    if( c >= 'A' && c <= 'F' )
186  
        return 10 + c - 'A';
186  
        return 10 + c - 'A';
187  
    return -1;
187  
    return -1;
188  
}
188  
}
189  

189  

190  
} // detail
190  
} // detail
191  

191  

192  
//----------------------------------------------------------
192  
//----------------------------------------------------------
193  

193  

194  
template< class Handler >
194  
template< class Handler >
195  
template< bool StackEmpty_, char First_ >
195  
template< bool StackEmpty_, char First_ >
196  
struct basic_parser<Handler>::
196  
struct basic_parser<Handler>::
197  
parse_number_helper
197  
parse_number_helper
198  
{
198  
{
199  
    basic_parser* parser;
199  
    basic_parser* parser;
200  
    char const* p;
200  
    char const* p;
201  

201  

202  
    template< std::size_t N >
202  
    template< std::size_t N >
203  
    char const*
203  
    char const*
204  
    operator()( mp11::mp_size_t<N> ) const
204  
    operator()( mp11::mp_size_t<N> ) const
205  
    {
205  
    {
206  
        return parser->parse_number(
206  
        return parser->parse_number(
207  
            p,
207  
            p,
208  
            std::integral_constant<bool, StackEmpty_>(),
208  
            std::integral_constant<bool, StackEmpty_>(),
209  
            std::integral_constant<char, First_>(),
209  
            std::integral_constant<char, First_>(),
210  
            std::integral_constant<
210  
            std::integral_constant<
211  
                number_precision, static_cast<number_precision>(N)>() );
211  
                number_precision, static_cast<number_precision>(N)>() );
212  
    }
212  
    }
213  
};
213  
};
214  

214  

215  
//----------------------------------------------------------
215  
//----------------------------------------------------------
216  

216  

217  
template<class Handler>
217  
template<class Handler>
218  
void
218  
void
219  
basic_parser<Handler>::
219  
basic_parser<Handler>::
220  
reserve()
220  
reserve()
221  
{
221  
{
222  
    if(BOOST_JSON_LIKELY(
222  
    if(BOOST_JSON_LIKELY(
223  
        ! st_.empty()))
223  
        ! st_.empty()))
224  
        return;
224  
        return;
225  
    // Reserve the largest stack we need,
225  
    // Reserve the largest stack we need,
226  
    // to avoid reallocation during suspend.
226  
    // to avoid reallocation during suspend.
227  
    st_.reserve(
227  
    st_.reserve(
228  
        sizeof(state) + // document parsing state
228  
        sizeof(state) + // document parsing state
229  
        (sizeof(state) +
229  
        (sizeof(state) +
230  
            sizeof(std::size_t)) * depth() + // array and object state + size
230  
            sizeof(std::size_t)) * depth() + // array and object state + size
231  
        sizeof(state) + // value parsing state
231  
        sizeof(state) + // value parsing state
232  
        sizeof(std::size_t) + // string size
232  
        sizeof(std::size_t) + // string size
233  
        sizeof(state)); // comment state
233  
        sizeof(state)); // comment state
234  
}
234  
}
235  

235  

236  
//----------------------------------------------------------
236  
//----------------------------------------------------------
237  
//
237  
//
238  
// The sentinel value is returned by parse functions
238  
// The sentinel value is returned by parse functions
239  
// to indicate that the parser failed, or suspended.
239  
// to indicate that the parser failed, or suspended.
240  
// this is used as it is distinct from all valid values
240  
// this is used as it is distinct from all valid values
241  
// for data in write
241  
// for data in write
242  

242  

243  
template<class Handler>
243  
template<class Handler>
244  
const char*
244  
const char*
245  
basic_parser<Handler>::
245  
basic_parser<Handler>::
246  
sentinel()
246  
sentinel()
247  
{
247  
{
248  
    // the "+1" ensures that the returned pointer is unique even if
248  
    // the "+1" ensures that the returned pointer is unique even if
249  
    // the given input buffer borders on this object
249  
    // the given input buffer borders on this object
250  
    return reinterpret_cast<
250  
    return reinterpret_cast<
251  
        const char*>(this) + 1;
251  
        const char*>(this) + 1;
252  
}
252  
}
253  

253  

254  
template<class Handler>
254  
template<class Handler>
255  
bool
255  
bool
256  
basic_parser<Handler>::
256  
basic_parser<Handler>::
257  
incomplete(
257  
incomplete(
258  
    const detail::const_stream_wrapper& cs)
258  
    const detail::const_stream_wrapper& cs)
259  
{
259  
{
260  
    return cs.begin() == sentinel();
260  
    return cs.begin() == sentinel();
261  
}
261  
}
262  

262  

263  
//----------------------------------------------------------
263  
//----------------------------------------------------------
264  
//
264  
//
265  
// These functions are declared with the BOOST_NOINLINE
265  
// These functions are declared with the BOOST_NOINLINE
266  
// attribute to avoid polluting the parsers hot-path.
266  
// attribute to avoid polluting the parsers hot-path.
267  
// They return the canary value to indicate suspension
267  
// They return the canary value to indicate suspension
268  
// or failure.
268  
// or failure.
269  

269  

270  
template<class Handler>
270  
template<class Handler>
271  
const char*
271  
const char*
272  
basic_parser<Handler>::
272  
basic_parser<Handler>::
273  
suspend_or_fail(state st)
273  
suspend_or_fail(state st)
274  
{
274  
{
275  
    if(BOOST_JSON_LIKELY(
275  
    if(BOOST_JSON_LIKELY(
276  
        ! ec_ && more_))
276  
        ! ec_ && more_))
277  
    {
277  
    {
278  
        // suspend
278  
        // suspend
279  
        reserve();
279  
        reserve();
280  
        st_.push_unchecked(st);
280  
        st_.push_unchecked(st);
281  
    }
281  
    }
282  
    return sentinel();
282  
    return sentinel();
283  
}
283  
}
284  

284  

285  
template<class Handler>
285  
template<class Handler>
286  
const char*
286  
const char*
287  
basic_parser<Handler>::
287  
basic_parser<Handler>::
288  
suspend_or_fail(
288  
suspend_or_fail(
289  
    state st,
289  
    state st,
290  
    std::size_t n)
290  
    std::size_t n)
291  
{
291  
{
292  
    if(BOOST_JSON_LIKELY(
292  
    if(BOOST_JSON_LIKELY(
293  
        ! ec_ && more_))
293  
        ! ec_ && more_))
294  
    {
294  
    {
295  
        // suspend
295  
        // suspend
296  
        reserve();
296  
        reserve();
297  
        st_.push_unchecked(n);
297  
        st_.push_unchecked(n);
298  
        st_.push_unchecked(st);
298  
        st_.push_unchecked(st);
299  
    }
299  
    }
300  
    return sentinel();
300  
    return sentinel();
301  
}
301  
}
302  

302  

303  

303  

304  
template<class Handler>
304  
template<class Handler>
305  
const char*
305  
const char*
306  
basic_parser<Handler>::
306  
basic_parser<Handler>::
307  
fail(const char* p) noexcept
307  
fail(const char* p) noexcept
308  
{
308  
{
309  
    BOOST_ASSERT( p != sentinel() );
309  
    BOOST_ASSERT( p != sentinel() );
310  
    end_ = p;
310  
    end_ = p;
311  
    return sentinel();
311  
    return sentinel();
312  
}
312  
}
313  

313  

314  
template<class Handler>
314  
template<class Handler>
315  
const char*
315  
const char*
316  
basic_parser<Handler>::
316  
basic_parser<Handler>::
317  
fail(
317  
fail(
318  
    const char* p,
318  
    const char* p,
319  
    error ev,
319  
    error ev,
320  
    source_location const* loc) noexcept
320  
    source_location const* loc) noexcept
321  
{
321  
{
322  
    BOOST_ASSERT( p != sentinel() );
322  
    BOOST_ASSERT( p != sentinel() );
323  
    end_ = p;
323  
    end_ = p;
324  
    ec_.assign(ev, loc);
324  
    ec_.assign(ev, loc);
325  
    return sentinel();
325  
    return sentinel();
326  
}
326  
}
327  

327  

328  
template<class Handler>
328  
template<class Handler>
329  
const char*
329  
const char*
330  
basic_parser<Handler>::
330  
basic_parser<Handler>::
331  
maybe_suspend(
331  
maybe_suspend(
332  
    const char* p,
332  
    const char* p,
333  
    state st)
333  
    state st)
334  
{
334  
{
335  
    if( p != sentinel() )
335  
    if( p != sentinel() )
336  
        end_ = p;
336  
        end_ = p;
337  
    if(BOOST_JSON_LIKELY(more_))
337  
    if(BOOST_JSON_LIKELY(more_))
338  
    {
338  
    {
339  
        // suspend
339  
        // suspend
340  
        reserve();
340  
        reserve();
341  
        st_.push_unchecked(st);
341  
        st_.push_unchecked(st);
342  
    }
342  
    }
343  
    return sentinel();
343  
    return sentinel();
344  
}
344  
}
345  

345  

346  
template<class Handler>
346  
template<class Handler>
347  
const char*
347  
const char*
348  
basic_parser<Handler>::
348  
basic_parser<Handler>::
349  
maybe_suspend(
349  
maybe_suspend(
350  
    const char* p,
350  
    const char* p,
351  
    state st,
351  
    state st,
352  
    std::size_t n)
352  
    std::size_t n)
353  
{
353  
{
354  
    BOOST_ASSERT( p != sentinel() );
354  
    BOOST_ASSERT( p != sentinel() );
355  
    end_ = p;
355  
    end_ = p;
356  
    if(BOOST_JSON_LIKELY(more_))
356  
    if(BOOST_JSON_LIKELY(more_))
357  
    {
357  
    {
358  
        // suspend
358  
        // suspend
359  
        reserve();
359  
        reserve();
360  
        st_.push_unchecked(n);
360  
        st_.push_unchecked(n);
361  
        st_.push_unchecked(st);
361  
        st_.push_unchecked(st);
362  
    }
362  
    }
363  
    return sentinel();
363  
    return sentinel();
364  
}
364  
}
365  

365  

366  
template<class Handler>
366  
template<class Handler>
367  
const char*
367  
const char*
368  
basic_parser<Handler>::
368  
basic_parser<Handler>::
369  
maybe_suspend(
369  
maybe_suspend(
370  
    const char* p,
370  
    const char* p,
371  
    state st,
371  
    state st,
372  
    const number& num)
372  
    const number& num)
373  
{
373  
{
374  
    BOOST_ASSERT( p != sentinel() );
374  
    BOOST_ASSERT( p != sentinel() );
375  
    end_ = p;
375  
    end_ = p;
376  
    if(BOOST_JSON_LIKELY(more_))
376  
    if(BOOST_JSON_LIKELY(more_))
377  
    {
377  
    {
378  
        // suspend
378  
        // suspend
379  
        num_ = num;
379  
        num_ = num;
380  
        reserve();
380  
        reserve();
381  
        st_.push_unchecked(st);;
381  
        st_.push_unchecked(st);;
382  
    }
382  
    }
383  
    return sentinel();
383  
    return sentinel();
384  
}
384  
}
385  

385  

386  
template<class Handler>
386  
template<class Handler>
387  
const char*
387  
const char*
388  
basic_parser<Handler>::
388  
basic_parser<Handler>::
389  
suspend(
389  
suspend(
390  
    const char* p,
390  
    const char* p,
391  
    state st)
391  
    state st)
392  
{
392  
{
393  
    BOOST_ASSERT( p != sentinel() );
393  
    BOOST_ASSERT( p != sentinel() );
394  
    end_ = p;
394  
    end_ = p;
395  
    // suspend
395  
    // suspend
396  
    reserve();
396  
    reserve();
397  
    st_.push_unchecked(st);
397  
    st_.push_unchecked(st);
398  
    return sentinel();
398  
    return sentinel();
399  
}
399  
}
400  

400  

401  
template<class Handler>
401  
template<class Handler>
402  
const char*
402  
const char*
403  
basic_parser<Handler>::
403  
basic_parser<Handler>::
404  
suspend(
404  
suspend(
405  
    const char* p,
405  
    const char* p,
406  
    state st,
406  
    state st,
407  
    const number& num)
407  
    const number& num)
408  
{
408  
{
409  
    BOOST_ASSERT( p != sentinel() );
409  
    BOOST_ASSERT( p != sentinel() );
410  
    end_ = p;
410  
    end_ = p;
411  
    // suspend
411  
    // suspend
412  
    num_ = num;
412  
    num_ = num;
413  
    reserve();
413  
    reserve();
414  
    st_.push_unchecked(st);
414  
    st_.push_unchecked(st);
415  
    return sentinel();
415  
    return sentinel();
416  
}
416  
}
417  

417  

418  
template<class Handler>
418  
template<class Handler>
419  
template<
419  
template<
420  
    bool StackEmpty_/*,
420  
    bool StackEmpty_/*,
421  
    bool Terminal_*/>
421  
    bool Terminal_*/>
422  
const char*
422  
const char*
423  
basic_parser<Handler>::
423  
basic_parser<Handler>::
424  
parse_comment(const char* p,
424  
parse_comment(const char* p,
425  
    std::integral_constant<bool, StackEmpty_> stack_empty,
425  
    std::integral_constant<bool, StackEmpty_> stack_empty,
426  
    /*std::integral_constant<bool, Terminal_>*/ bool terminal)
426  
    /*std::integral_constant<bool, Terminal_>*/ bool terminal)
427  
{
427  
{
428  
    detail::const_stream_wrapper cs(p, end_);
428  
    detail::const_stream_wrapper cs(p, end_);
429  
    const char* start = cs.begin();
429  
    const char* start = cs.begin();
430  
    std::size_t remain;
430  
    std::size_t remain;
431  
    if(! stack_empty && ! st_.empty())
431  
    if(! stack_empty && ! st_.empty())
432  
    {
432  
    {
433  
        state st;
433  
        state st;
434  
        st_.pop(st);
434  
        st_.pop(st);
435  
        switch(st)
435  
        switch(st)
436  
        {
436  
        {
437  
            default: BOOST_JSON_UNREACHABLE();
437  
            default: BOOST_JSON_UNREACHABLE();
438  
            case state::com1: goto do_com1;
438  
            case state::com1: goto do_com1;
439  
            case state::com2: goto do_com2;
439  
            case state::com2: goto do_com2;
440  
            case state::com3: goto do_com3;
440  
            case state::com3: goto do_com3;
441  
            case state::com4: goto do_com4;
441  
            case state::com4: goto do_com4;
442  
        }
442  
        }
443  
    }
443  
    }
444  
    BOOST_ASSERT(*cs == '/');
444  
    BOOST_ASSERT(*cs == '/');
445  
    ++cs;
445  
    ++cs;
446  
do_com1:
446  
do_com1:
447  
    if(BOOST_JSON_UNLIKELY(! cs))
447  
    if(BOOST_JSON_UNLIKELY(! cs))
448  
        return maybe_suspend(cs.begin(), state::com1);
448  
        return maybe_suspend(cs.begin(), state::com1);
449  
    switch(*cs)
449  
    switch(*cs)
450  
    {
450  
    {
451  
    default:
451  
    default:
452  
        {
452  
        {
453  
            BOOST_STATIC_CONSTEXPR source_location loc
453  
            BOOST_STATIC_CONSTEXPR source_location loc
454  
                = BOOST_CURRENT_LOCATION;
454  
                = BOOST_CURRENT_LOCATION;
455  
            return fail(cs.begin(), error::syntax, &loc);
455  
            return fail(cs.begin(), error::syntax, &loc);
456  
        }
456  
        }
457  
    case '/':
457  
    case '/':
458  
        ++cs;
458  
        ++cs;
459  
do_com2:
459  
do_com2:
460  
        // KRYSTIAN TODO: this is a mess, we have to fix this
460  
        // KRYSTIAN TODO: this is a mess, we have to fix this
461  
        remain = cs.remain();
461  
        remain = cs.remain();
462  
        cs = remain ? static_cast<const char*>(
462  
        cs = remain ? static_cast<const char*>(
463  
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
463  
            std::memchr(cs.begin(), '\n', remain)) : sentinel();
464  
        if(! cs.begin())
464  
        if(! cs.begin())
465  
            cs = sentinel();
465  
            cs = sentinel();
466  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
466  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
467  
        {
467  
        {
468  
            // if the doc does not terminate
468  
            // if the doc does not terminate
469  
            // with a newline, treat it as the
469  
            // with a newline, treat it as the
470  
            // end of the comment
470  
            // end of the comment
471  
            if(terminal && ! more_)
471  
            if(terminal && ! more_)
472  
            {
472  
            {
473  
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
473  
                if(BOOST_JSON_UNLIKELY(! h_.on_comment(
474  
                    {start, cs.remain(start)}, ec_)))
474  
                    {start, cs.remain(start)}, ec_)))
475  
                    return fail(cs.end());
475  
                    return fail(cs.end());
476  
                return cs.end();
476  
                return cs.end();
477  
            }
477  
            }
478  
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
478  
            if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
479  
                {start, cs.remain(start)}, ec_)))
479  
                {start, cs.remain(start)}, ec_)))
480  
                return fail(cs.end());
480  
                return fail(cs.end());
481  
            if(terminal)
481  
            if(terminal)
482  
                return suspend(cs.end(), state::com2);
482  
                return suspend(cs.end(), state::com2);
483  
            return maybe_suspend(cs.end(), state::com2);
483  
            return maybe_suspend(cs.end(), state::com2);
484  
        }
484  
        }
485  
        break;
485  
        break;
486  
    case '*':
486  
    case '*':
487  
        do
487  
        do
488  
        {
488  
        {
489  
            ++cs;
489  
            ++cs;
490  
do_com3:
490  
do_com3:
491  
            // KRYSTIAN TODO: this is a mess, we have to fix this
491  
            // KRYSTIAN TODO: this is a mess, we have to fix this
492  
            remain = cs.remain();
492  
            remain = cs.remain();
493  
            cs = remain ? static_cast<const char*>(
493  
            cs = remain ? static_cast<const char*>(
494  
                std::memchr(cs.begin(), '*', remain)) : sentinel();
494  
                std::memchr(cs.begin(), '*', remain)) : sentinel();
495  
            if(! cs.begin())
495  
            if(! cs.begin())
496  
                cs = sentinel();
496  
                cs = sentinel();
497  
            // stopped inside a c comment
497  
            // stopped inside a c comment
498  
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
498  
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
499  
            {
499  
            {
500  
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
500  
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
501  
                    {start, cs.remain(start)}, ec_)))
501  
                    {start, cs.remain(start)}, ec_)))
502  
                    return fail(cs.end());
502  
                    return fail(cs.end());
503  
                return maybe_suspend(cs.end(), state::com3);
503  
                return maybe_suspend(cs.end(), state::com3);
504  
            }
504  
            }
505  
            // found a asterisk, check if the next char is a slash
505  
            // found a asterisk, check if the next char is a slash
506  
            ++cs;
506  
            ++cs;
507  
do_com4:
507  
do_com4:
508  
            if(BOOST_JSON_UNLIKELY(! cs))
508  
            if(BOOST_JSON_UNLIKELY(! cs))
509  
            {
509  
            {
510  
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
510  
                if(BOOST_JSON_UNLIKELY(! h_.on_comment_part(
511  
                    {start, cs.used(start)}, ec_)))
511  
                    {start, cs.used(start)}, ec_)))
512  
                    return fail(cs.begin());
512  
                    return fail(cs.begin());
513  
                return maybe_suspend(cs.begin(), state::com4);
513  
                return maybe_suspend(cs.begin(), state::com4);
514  
            }
514  
            }
515  
        }
515  
        }
516  
        while(*cs != '/');
516  
        while(*cs != '/');
517  
    }
517  
    }
518  
    ++cs;
518  
    ++cs;
519  
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
519  
    if(BOOST_JSON_UNLIKELY(! h_.on_comment(
520  
        {start, cs.used(start)}, ec_)))
520  
        {start, cs.used(start)}, ec_)))
521  
        return fail(cs.begin());
521  
        return fail(cs.begin());
522  
    return cs.begin();
522  
    return cs.begin();
523  
}
523  
}
524  

524  

525  
template<class Handler>
525  
template<class Handler>
526  
template<bool StackEmpty_>
526  
template<bool StackEmpty_>
527  
const char*
527  
const char*
528  
basic_parser<Handler>::
528  
basic_parser<Handler>::
529  
parse_document(const char* p,
529  
parse_document(const char* p,
530  
    std::integral_constant<bool, StackEmpty_> stack_empty)
530  
    std::integral_constant<bool, StackEmpty_> stack_empty)
531  
{
531  
{
532  
    detail::const_stream_wrapper cs(p, end_);
532  
    detail::const_stream_wrapper cs(p, end_);
533  
    if(! stack_empty && ! st_.empty())
533  
    if(! stack_empty && ! st_.empty())
534  
    {
534  
    {
535  
        state st;
535  
        state st;
536  
        st_.peek(st);
536  
        st_.peek(st);
537  
        switch(st)
537  
        switch(st)
538  
        {
538  
        {
539  
        default: goto do_doc2;
539  
        default: goto do_doc2;
540  
        case state::doc1:
540  
        case state::doc1:
541  
                 st_.pop(st);
541  
                 st_.pop(st);
542  
                 goto do_doc1;
542  
                 goto do_doc1;
543  
        case state::doc3:
543  
        case state::doc3:
544  
                 st_.pop(st);
544  
                 st_.pop(st);
545  
                 goto do_doc3;
545  
                 goto do_doc3;
546  
        case state::com1: case state::com2:
546  
        case state::com1: case state::com2:
547  
        case state::com3: case state::com4:
547  
        case state::com3: case state::com4:
548  
                 goto do_doc4;
548  
                 goto do_doc4;
549  
        }
549  
        }
550  
    }
550  
    }
551  
do_doc1:
551  
do_doc1:
552  
    cs = detail::count_whitespace(cs.begin(), cs.end());
552  
    cs = detail::count_whitespace(cs.begin(), cs.end());
553  
    if(BOOST_JSON_UNLIKELY(! cs))
553  
    if(BOOST_JSON_UNLIKELY(! cs))
554  
        return maybe_suspend(cs.begin(), state::doc1);
554  
        return maybe_suspend(cs.begin(), state::doc1);
555  
do_doc2:
555  
do_doc2:
556  
    switch(+opt_.allow_comments |
556  
    switch(+opt_.allow_comments |
557  
        (opt_.allow_trailing_commas << 1) |
557  
        (opt_.allow_trailing_commas << 1) |
558  
        (opt_.allow_invalid_utf8 << 2))
558  
        (opt_.allow_invalid_utf8 << 2))
559  
    {
559  
    {
560  
    // no extensions
560  
    // no extensions
561  
    default:
561  
    default:
562  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
562  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
563  
        break;
563  
        break;
564  
    // comments
564  
    // comments
565  
    case 1:
565  
    case 1:
566  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
566  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::false_type(), opt_.allow_invalid_utf16);
567  
        break;
567  
        break;
568  
    // trailing
568  
    // trailing
569  
    case 2:
569  
    case 2:
570  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
570  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
571  
        break;
571  
        break;
572  
    // comments & trailing
572  
    // comments & trailing
573  
    case 3:
573  
    case 3:
574  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
574  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::false_type(), opt_.allow_invalid_utf16);
575  
        break;
575  
        break;
576  
    // skip validation
576  
    // skip validation
577  
    case 4:
577  
    case 4:
578  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
578  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
579  
        break;
579  
        break;
580  
    // comments & skip validation
580  
    // comments & skip validation
581  
    case 5:
581  
    case 5:
582  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
582  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::false_type(), std::true_type(), opt_.allow_invalid_utf16);
583  
        break;
583  
        break;
584  
    // trailing & skip validation
584  
    // trailing & skip validation
585  
    case 6:
585  
    case 6:
586  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
586  
        cs = parse_value(cs.begin(), stack_empty, std::false_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
587  
        break;
587  
        break;
588  
    // comments & trailing & skip validation
588  
    // comments & trailing & skip validation
589  
    case 7:
589  
    case 7:
590  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
590  
        cs = parse_value(cs.begin(), stack_empty, std::true_type(), std::true_type(), std::true_type(), opt_.allow_invalid_utf16);
591  
        break;
591  
        break;
592  
    }
592  
    }
593  
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
593  
    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
594  
        // the appropriate state has already been pushed into stack
594  
        // the appropriate state has already been pushed into stack
595  
        return sentinel();
595  
        return sentinel();
596  
do_doc3:
596  
do_doc3:
597  
    cs = detail::count_whitespace(cs.begin(), cs.end());
597  
    cs = detail::count_whitespace(cs.begin(), cs.end());
598  
    if(BOOST_JSON_UNLIKELY(! cs))
598  
    if(BOOST_JSON_UNLIKELY(! cs))
599  
    {
599  
    {
600  
        if(more_)
600  
        if(more_)
601  
            return suspend(cs.begin(), state::doc3);
601  
            return suspend(cs.begin(), state::doc3);
602  
    }
602  
    }
603  
    else if(opt_.allow_comments && *cs == '/')
603  
    else if(opt_.allow_comments && *cs == '/')
604  
    {
604  
    {
605  
do_doc4:
605  
do_doc4:
606  
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
606  
        cs = parse_comment(cs.begin(), stack_empty, std::true_type());
607  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
607  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
608  
            return sentinel();
608  
            return sentinel();
609  
        goto do_doc3;
609  
        goto do_doc3;
610  
    }
610  
    }
611  
    return cs.begin();
611  
    return cs.begin();
612  
}
612  
}
613  

613  

614  
template<class Handler>
614  
template<class Handler>
615  
template<
615  
template<
616  
    bool StackEmpty_,
616  
    bool StackEmpty_,
617  
    bool AllowComments_/*,
617  
    bool AllowComments_/*,
618  
    bool AllowTrailing_,
618  
    bool AllowTrailing_,
619  
    bool AllowBadUTF8_*/>
619  
    bool AllowBadUTF8_*/>
620  
const char*
620  
const char*
621  
basic_parser<Handler>::
621  
basic_parser<Handler>::
622  
parse_value(const char* p,
622  
parse_value(const char* p,
623  
    std::integral_constant<bool, StackEmpty_> stack_empty,
623  
    std::integral_constant<bool, StackEmpty_> stack_empty,
624  
    std::integral_constant<bool, AllowComments_> allow_comments,
624  
    std::integral_constant<bool, AllowComments_> allow_comments,
625  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
625  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
626  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
626  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
627  
    bool allow_bad_utf16)
627  
    bool allow_bad_utf16)
628  
{
628  
{
629  
    if(stack_empty || st_.empty())
629  
    if(stack_empty || st_.empty())
630  
    {
630  
    {
631  
loop:
631  
loop:
632  
        switch(*p)
632  
        switch(*p)
633  
        {
633  
        {
634  
        case '0':
634  
        case '0':
635  
            return mp11::mp_with_index<3>(
635  
            return mp11::mp_with_index<3>(
636  
                static_cast<unsigned char>(opt_.numbers),
636  
                static_cast<unsigned char>(opt_.numbers),
637  
                parse_number_helper<true, '0'>{ this, p });
637  
                parse_number_helper<true, '0'>{ this, p });
638  
        case '-':
638  
        case '-':
639  
            return mp11::mp_with_index<3>(
639  
            return mp11::mp_with_index<3>(
640  
                static_cast<unsigned char>(opt_.numbers),
640  
                static_cast<unsigned char>(opt_.numbers),
641  
                parse_number_helper<true, '-'>{ this, p });
641  
                parse_number_helper<true, '-'>{ this, p });
642  
        case '1': case '2': case '3':
642  
        case '1': case '2': case '3':
643  
        case '4': case '5': case '6':
643  
        case '4': case '5': case '6':
644  
        case '7': case '8': case '9':
644  
        case '7': case '8': case '9':
645  
            return mp11::mp_with_index<3>(
645  
            return mp11::mp_with_index<3>(
646  
                static_cast<unsigned char>(opt_.numbers),
646  
                static_cast<unsigned char>(opt_.numbers),
647  
                parse_number_helper<true, '+'>{ this, p });
647  
                parse_number_helper<true, '+'>{ this, p });
648  
        case 'n':
648  
        case 'n':
649  
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
649  
            return parse_literal( p, detail::literals_c<detail::literals::null>() );
650  
        case 't':
650  
        case 't':
651  
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
651  
            return parse_literal( p, detail::literals_c<detail::literals::true_>() );
652  
        case 'f':
652  
        case 'f':
653  
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
653  
            return parse_literal( p, detail::literals_c<detail::literals::false_>() );
654  
        case 'I':
654  
        case 'I':
655  
            if( !opt_.allow_infinity_and_nan )
655  
            if( !opt_.allow_infinity_and_nan )
656  
            {
656  
            {
657  
                BOOST_STATIC_CONSTEXPR source_location loc
657  
                BOOST_STATIC_CONSTEXPR source_location loc
658  
                    = BOOST_CURRENT_LOCATION;
658  
                    = BOOST_CURRENT_LOCATION;
659  
                return fail(p, error::syntax, &loc);
659  
                return fail(p, error::syntax, &loc);
660  
            }
660  
            }
661  
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
661  
            return parse_literal( p, detail::literals_c<detail::literals::infinity>() );
662  
        case 'N':
662  
        case 'N':
663  
            if( !opt_.allow_infinity_and_nan )
663  
            if( !opt_.allow_infinity_and_nan )
664  
            {
664  
            {
665  
                BOOST_STATIC_CONSTEXPR source_location loc
665  
                BOOST_STATIC_CONSTEXPR source_location loc
666  
                    = BOOST_CURRENT_LOCATION;
666  
                    = BOOST_CURRENT_LOCATION;
667  
                return fail(p, error::syntax, &loc);
667  
                return fail(p, error::syntax, &loc);
668  
            }
668  
            }
669  
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
669  
            return parse_literal(p, detail::literals_c<detail::literals::nan>() );
670  
        case '"':
670  
        case '"':
671  
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
671  
            return parse_string(p, std::true_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
672  
        case '[':
672  
        case '[':
673  
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
673  
            return parse_array(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
674  
        case '{':
674  
        case '{':
675  
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
675  
            return parse_object(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
676  
        case '/':
676  
        case '/':
677  
            if(! allow_comments)
677  
            if(! allow_comments)
678  
            {
678  
            {
679  
                BOOST_STATIC_CONSTEXPR source_location loc
679  
                BOOST_STATIC_CONSTEXPR source_location loc
680  
                    = BOOST_CURRENT_LOCATION;
680  
                    = BOOST_CURRENT_LOCATION;
681  
                return fail(p, error::syntax, &loc);
681  
                return fail(p, error::syntax, &loc);
682  
            }
682  
            }
683  
            p = parse_comment(p, stack_empty, std::false_type());
683  
            p = parse_comment(p, stack_empty, std::false_type());
684  
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
684  
            // KRYSTIAN NOTE: incomplete takes const_stream, we either
685  
            // can add an overload, change the existing one to take a pointer,
685  
            // can add an overload, change the existing one to take a pointer,
686  
            // or just leave it as is
686  
            // or just leave it as is
687  
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
687  
            if(BOOST_JSON_UNLIKELY(p == sentinel()))
688  
                return maybe_suspend(p, state::val2);
688  
                return maybe_suspend(p, state::val2);
689  
            BOOST_FALLTHROUGH;
689  
            BOOST_FALLTHROUGH;
690  
        case ' ':
690  
        case ' ':
691  
        case '\t':
691  
        case '\t':
692  
        case '\n':
692  
        case '\n':
693  
        case '\r':
693  
        case '\r':
694  
            p = detail::count_whitespace(p, end_);
694  
            p = detail::count_whitespace(p, end_);
695  
            if(BOOST_JSON_UNLIKELY(p == end_))
695  
            if(BOOST_JSON_UNLIKELY(p == end_))
696  
                return maybe_suspend(p, state::val1);
696  
                return maybe_suspend(p, state::val1);
697  
            goto loop;
697  
            goto loop;
698  
        default:
698  
        default:
699  
            {
699  
            {
700  
                BOOST_STATIC_CONSTEXPR source_location loc
700  
                BOOST_STATIC_CONSTEXPR source_location loc
701  
                    = BOOST_CURRENT_LOCATION;
701  
                    = BOOST_CURRENT_LOCATION;
702  
                return fail(p, error::syntax, &loc);
702  
                return fail(p, error::syntax, &loc);
703  
            }
703  
            }
704  
        }
704  
        }
705  
    }
705  
    }
706  
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
706  
    return resume_value(p, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
707  
}
707  
}
708  

708  

709  
template<class Handler>
709  
template<class Handler>
710  
template<
710  
template<
711  
    bool AllowComments_/*,
711  
    bool AllowComments_/*,
712  
    bool AllowTrailing_,
712  
    bool AllowTrailing_,
713  
    bool AllowBadUTF8_*/>
713  
    bool AllowBadUTF8_*/>
714  
const char*
714  
const char*
715  
basic_parser<Handler>::
715  
basic_parser<Handler>::
716  
resume_value(const char* p,
716  
resume_value(const char* p,
717  
    std::integral_constant<bool, AllowComments_> allow_comments,
717  
    std::integral_constant<bool, AllowComments_> allow_comments,
718  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
718  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
719  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
719  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
720  
    bool allow_bad_utf16)
720  
    bool allow_bad_utf16)
721  
{
721  
{
722  
    state st;
722  
    state st;
723  
    st_.peek(st);
723  
    st_.peek(st);
724  
    switch(st)
724  
    switch(st)
725  
    {
725  
    {
726  
    default: BOOST_JSON_UNREACHABLE();
726  
    default: BOOST_JSON_UNREACHABLE();
727  
    case state::lit1:
727  
    case state::lit1:
728  
        return parse_literal(p,  detail::literals_c<detail::literals::resume>() );
728  
        return parse_literal(p,  detail::literals_c<detail::literals::resume>() );
729  

729  

730  
    case state::str1: case state::str2:
730  
    case state::str1: case state::str2:
731  
    case state::str8:
731  
    case state::str8:
732  
        return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
732  
        return parse_string(p, std::false_type(), std::false_type(), allow_bad_utf8, allow_bad_utf16);
733  

733  

734  
    case state::arr1: case state::arr2:
734  
    case state::arr1: case state::arr2:
735  
    case state::arr3: case state::arr4:
735  
    case state::arr3: case state::arr4:
736  
    case state::arr5: case state::arr6:
736  
    case state::arr5: case state::arr6:
737  
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
737  
        return parse_array(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
738  

738  

739  
    case state::obj1: case state::obj2:
739  
    case state::obj1: case state::obj2:
740  
    case state::obj3: case state::obj4:
740  
    case state::obj3: case state::obj4:
741  
    case state::obj5: case state::obj6:
741  
    case state::obj5: case state::obj6:
742  
    case state::obj7: case state::obj8:
742  
    case state::obj7: case state::obj8:
743  
    case state::obj9: case state::obj10:
743  
    case state::obj9: case state::obj10:
744  
    case state::obj11:
744  
    case state::obj11:
745  
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
745  
        return parse_object(p, std::false_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
746  

746  

747  
    case state::num1: case state::num2:
747  
    case state::num1: case state::num2:
748  
    case state::num3: case state::num4:
748  
    case state::num3: case state::num4:
749  
    case state::num5: case state::num6:
749  
    case state::num5: case state::num6:
750  
    case state::num7: case state::num8:
750  
    case state::num7: case state::num8:
751  
    case state::exp1: case state::exp2:
751  
    case state::exp1: case state::exp2:
752  
    case state::exp3:
752  
    case state::exp3:
753  
        return mp11::mp_with_index<3>(
753  
        return mp11::mp_with_index<3>(
754  
            static_cast<unsigned char>(opt_.numbers),
754  
            static_cast<unsigned char>(opt_.numbers),
755  
            parse_number_helper<false, 0>{ this, p });
755  
            parse_number_helper<false, 0>{ this, p });
756  

756  

757  
    // KRYSTIAN NOTE: these are special cases
757  
    // KRYSTIAN NOTE: these are special cases
758  
    case state::val1:
758  
    case state::val1:
759  
    {
759  
    {
760  
        st_.pop(st);
760  
        st_.pop(st);
761  
        BOOST_ASSERT(st_.empty());
761  
        BOOST_ASSERT(st_.empty());
762  
        p = detail::count_whitespace(p, end_);
762  
        p = detail::count_whitespace(p, end_);
763  
        if(BOOST_JSON_UNLIKELY(p == end_))
763  
        if(BOOST_JSON_UNLIKELY(p == end_))
764  
            return maybe_suspend(p, state::val1);
764  
            return maybe_suspend(p, state::val1);
765  
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
765  
        return parse_value(p, std::true_type(), allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
766  
    }
766  
    }
767  

767  

768  
    case state::val2:
768  
    case state::val2:
769  
    {
769  
    {
770  
        st_.pop(st);
770  
        st_.pop(st);
771  
        p = parse_comment(p, std::false_type(), std::false_type());
771  
        p = parse_comment(p, std::false_type(), std::false_type());
772  
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
772  
        if(BOOST_JSON_UNLIKELY(p == sentinel()))
773  
            return maybe_suspend(p, state::val2);
773  
            return maybe_suspend(p, state::val2);
774  
        if(BOOST_JSON_UNLIKELY( p == end_ ))
774  
        if(BOOST_JSON_UNLIKELY( p == end_ ))
775  
            return maybe_suspend(p, state::val3);
775  
            return maybe_suspend(p, state::val3);
776  
        BOOST_ASSERT(st_.empty());
776  
        BOOST_ASSERT(st_.empty());
777  
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
777  
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
778  
    }
778  
    }
779  

779  

780  
    case state::val3:
780  
    case state::val3:
781  
    {
781  
    {
782  
        st_.pop(st);
782  
        st_.pop(st);
783  
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
783  
        return parse_value(p, std::true_type(), std::true_type(), allow_trailing, allow_bad_utf8, allow_bad_utf16);
784  
    }
784  
    }
785  
    }
785  
    }
786  
}
786  
}
787  

787  

788  
template<class Handler>
788  
template<class Handler>
789  
template<class Literal>
789  
template<class Literal>
790  
const char*
790  
const char*
791  
basic_parser<Handler>::
791  
basic_parser<Handler>::
792  
parse_literal(const char* p, Literal)
792  
parse_literal(const char* p, Literal)
793  
{
793  
{
794  
    using L = detail::literals;
794  
    using L = detail::literals;
795  

795  

796  
    std::size_t cur_lit;
796  
    std::size_t cur_lit;
797  
    std::size_t offset;
797  
    std::size_t offset;
798  

798  

799  
    detail::const_stream_wrapper cs(p, end_);
799  
    detail::const_stream_wrapper cs(p, end_);
800  
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
800  
    BOOST_IF_CONSTEXPR( Literal::value != L::resume )
801  
    {
801  
    {
802  
        constexpr std::size_t index = literal_index(Literal::value);
802  
        constexpr std::size_t index = literal_index(Literal::value);
803  
        constexpr char const* literal = detail::literal_strings[index];
803  
        constexpr char const* literal = detail::literal_strings[index];
804  
        constexpr std::size_t sz = detail::literal_sizes[index];
804  
        constexpr std::size_t sz = detail::literal_sizes[index];
805  

805  

806  
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
806  
        if(BOOST_JSON_LIKELY( cs.remain() >= sz ))
807  
        {
807  
        {
808  
            int const cmp = std::memcmp(cs.begin(), literal, sz);
808  
            int const cmp = std::memcmp(cs.begin(), literal, sz);
809  
            if( cmp != 0 )
809  
            if( cmp != 0 )
810  
            {
810  
            {
811  
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
811  
                BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
812  
                return fail(cs.begin(), error::syntax, &loc);
812  
                return fail(cs.begin(), error::syntax, &loc);
813  
            }
813  
            }
814  

814  

815  
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
815  
            BOOST_IF_CONSTEXPR( Literal::value == L::null )
816  
            {
816  
            {
817  
                if(BOOST_JSON_UNLIKELY(
817  
                if(BOOST_JSON_UNLIKELY(
818  
                    ! h_.on_null(ec_)))
818  
                    ! h_.on_null(ec_)))
819  
                    return fail(cs.begin());
819  
                    return fail(cs.begin());
820  
            }
820  
            }
821  
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
821  
            else BOOST_IF_CONSTEXPR( Literal::value == L::true_ )
822  
            {
822  
            {
823  
                if(BOOST_JSON_UNLIKELY(
823  
                if(BOOST_JSON_UNLIKELY(
824  
                    ! h_.on_bool(true, ec_)))
824  
                    ! h_.on_bool(true, ec_)))
825  
                    return fail(cs.begin());
825  
                    return fail(cs.begin());
826  
            }
826  
            }
827  
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
827  
            else BOOST_IF_CONSTEXPR( Literal::value == L::false_ )
828  
            {
828  
            {
829  
                if(BOOST_JSON_UNLIKELY(
829  
                if(BOOST_JSON_UNLIKELY(
830  
                    ! h_.on_bool(false, ec_)))
830  
                    ! h_.on_bool(false, ec_)))
831  
                    return fail(cs.begin());
831  
                    return fail(cs.begin());
832  
            }
832  
            }
833  
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
833  
            else BOOST_IF_CONSTEXPR( Literal::value == L::infinity )
834  
            {
834  
            {
835  
                if(BOOST_JSON_UNLIKELY(
835  
                if(BOOST_JSON_UNLIKELY(
836  
                    ! h_.on_double(
836  
                    ! h_.on_double(
837  
                        std::numeric_limits<double>::infinity(),
837  
                        std::numeric_limits<double>::infinity(),
838  
                        string_view(literal, sz),
838  
                        string_view(literal, sz),
839  
                        ec_)))
839  
                        ec_)))
840  
                    return fail(cs.begin());
840  
                    return fail(cs.begin());
841  
            }
841  
            }
842  
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
842  
            else BOOST_IF_CONSTEXPR( Literal::value == L::neg_infinity )
843  
            {
843  
            {
844  
                if(BOOST_JSON_UNLIKELY(
844  
                if(BOOST_JSON_UNLIKELY(
845  
                    ! h_.on_double(
845  
                    ! h_.on_double(
846  
                        -std::numeric_limits<double>::infinity(),
846  
                        -std::numeric_limits<double>::infinity(),
847  
                        string_view(literal, sz),
847  
                        string_view(literal, sz),
848  
                        ec_)))
848  
                        ec_)))
849  
                    return fail(cs.begin());
849  
                    return fail(cs.begin());
850  
            }
850  
            }
851  
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
851  
            else BOOST_IF_CONSTEXPR( Literal::value == L::nan )
852  
            {
852  
            {
853  
                if(BOOST_JSON_UNLIKELY(
853  
                if(BOOST_JSON_UNLIKELY(
854  
                    ! h_.on_double(
854  
                    ! h_.on_double(
855  
                        std::numeric_limits<double>::quiet_NaN(),
855  
                        std::numeric_limits<double>::quiet_NaN(),
856  
                        string_view(literal, sz),
856  
                        string_view(literal, sz),
857  
                        ec_)))
857  
                        ec_)))
858  
                    return fail(cs.begin());
858  
                    return fail(cs.begin());
859  
            }
859  
            }
860  
            else
860  
            else
861  
            {
861  
            {
862  
                BOOST_JSON_UNREACHABLE();
862  
                BOOST_JSON_UNREACHABLE();
863  
            }
863  
            }
864  

864  

865  
            cs += sz;
865  
            cs += sz;
866  
            return cs.begin();
866  
            return cs.begin();
867  
        }
867  
        }
868  

868  

869  
        offset = 0;
869  
        offset = 0;
870  
        cur_lit = index;
870  
        cur_lit = index;
871  
    }
871  
    }
872  
    else
872  
    else
873  
    {
873  
    {
874  
        state st;
874  
        state st;
875  
        st_.pop(st);
875  
        st_.pop(st);
876  
        BOOST_ASSERT( st == state::lit1 );
876  
        BOOST_ASSERT( st == state::lit1 );
877  

877  

878  
        cur_lit = cur_lit_;
878  
        cur_lit = cur_lit_;
879  
        offset = lit_offset_;
879  
        offset = lit_offset_;
880  
    }
880  
    }
881  

881  

882  
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
882  
    std::size_t const lit_size = detail::literal_sizes[cur_lit];
883  
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
883  
    std::size_t const size = (std::min)( lit_size - offset, cs.remain() );
884  
    int cmp = 0;
884  
    int cmp = 0;
885  
    if(BOOST_JSON_LIKELY( cs.begin() ))
885  
    if(BOOST_JSON_LIKELY( cs.begin() ))
886  
        cmp = std::memcmp(
886  
        cmp = std::memcmp(
887  
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
887  
            cs.begin(), detail::literal_strings[cur_lit] + offset, size );
888  
    if( cmp != 0 )
888  
    if( cmp != 0 )
889  
    {
889  
    {
890  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
890  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
891  
        return fail(cs.begin(), error::syntax, &loc);
891  
        return fail(cs.begin(), error::syntax, &loc);
892  
    }
892  
    }
893  

893  

894  
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
894  
    if(BOOST_JSON_UNLIKELY( offset + size < lit_size ))
895  
    {
895  
    {
896  
        BOOST_ASSERT( cur_lit < 256 );
896  
        BOOST_ASSERT( cur_lit < 256 );
897  
        cur_lit_ = static_cast<unsigned char>( cur_lit );
897  
        cur_lit_ = static_cast<unsigned char>( cur_lit );
898  
        BOOST_ASSERT( offset + size < 256 );
898  
        BOOST_ASSERT( offset + size < 256 );
899  
        lit_offset_ = static_cast<unsigned char>( offset + size );
899  
        lit_offset_ = static_cast<unsigned char>( offset + size );
900  
        return maybe_suspend(cs.begin() + size, state::lit1);
900  
        return maybe_suspend(cs.begin() + size, state::lit1);
901  
    }
901  
    }
902  

902  

903  
    switch( static_cast<L>(cur_lit) )
903  
    switch( static_cast<L>(cur_lit) )
904  
    {
904  
    {
905  
    case L::null:
905  
    case L::null:
906  
        if(BOOST_JSON_UNLIKELY(
906  
        if(BOOST_JSON_UNLIKELY(
907  
            ! h_.on_null(ec_)))
907  
            ! h_.on_null(ec_)))
908  
            return fail(cs.begin());
908  
            return fail(cs.begin());
909  
        break;
909  
        break;
910  
    case L::true_:
910  
    case L::true_:
911  
        if(BOOST_JSON_UNLIKELY(
911  
        if(BOOST_JSON_UNLIKELY(
912  
            ! h_.on_bool(true, ec_)))
912  
            ! h_.on_bool(true, ec_)))
913  
            return fail(cs.begin());
913  
            return fail(cs.begin());
914  
        break;
914  
        break;
915  
    case L::false_:
915  
    case L::false_:
916  
        if(BOOST_JSON_UNLIKELY(
916  
        if(BOOST_JSON_UNLIKELY(
917  
            ! h_.on_bool(false, ec_)))
917  
            ! h_.on_bool(false, ec_)))
918  
            return fail(cs.begin());
918  
            return fail(cs.begin());
919  
        break;
919  
        break;
920  
    case L::infinity:
920  
    case L::infinity:
921  
        if(BOOST_JSON_UNLIKELY(
921  
        if(BOOST_JSON_UNLIKELY(
922  
            ! h_.on_double(
922  
            ! h_.on_double(
923  
                std::numeric_limits<double>::infinity(),
923  
                std::numeric_limits<double>::infinity(),
924  
                string_view(
924  
                string_view(
925  
                    detail::literal_strings[ literal_index(L::infinity) ],
925  
                    detail::literal_strings[ literal_index(L::infinity) ],
926  
                    detail::literal_sizes[ literal_index(L::infinity) ]),
926  
                    detail::literal_sizes[ literal_index(L::infinity) ]),
927  
                ec_)))
927  
                ec_)))
928  
            return fail(cs.begin());
928  
            return fail(cs.begin());
929  
        break;
929  
        break;
930  
    case L::neg_infinity:
930  
    case L::neg_infinity:
931  
        if(BOOST_JSON_UNLIKELY(
931  
        if(BOOST_JSON_UNLIKELY(
932  
            ! h_.on_double(
932  
            ! h_.on_double(
933  
                -std::numeric_limits<double>::infinity(),
933  
                -std::numeric_limits<double>::infinity(),
934  
                string_view(
934  
                string_view(
935  
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
935  
                    detail::literal_strings[ literal_index(L::neg_infinity) ],
936  
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
936  
                    detail::literal_sizes[ literal_index(L::neg_infinity) ]),
937  
                ec_)))
937  
                ec_)))
938  
            return fail(cs.begin());
938  
            return fail(cs.begin());
939  
        break;
939  
        break;
940  
    case L::nan:
940  
    case L::nan:
941  
        if(BOOST_JSON_UNLIKELY(
941  
        if(BOOST_JSON_UNLIKELY(
942  
            ! h_.on_double(
942  
            ! h_.on_double(
943  
                std::numeric_limits<double>::quiet_NaN(),
943  
                std::numeric_limits<double>::quiet_NaN(),
944  
                string_view(
944  
                string_view(
945  
                    detail::literal_strings[ literal_index(L::nan) ],
945  
                    detail::literal_strings[ literal_index(L::nan) ],
946  
                    detail::literal_sizes[ literal_index(L::nan) ]),
946  
                    detail::literal_sizes[ literal_index(L::nan) ]),
947  
                ec_)))
947  
                ec_)))
948  
            return fail(cs.begin());
948  
            return fail(cs.begin());
949  
        break;
949  
        break;
950  
    default: BOOST_JSON_UNREACHABLE();
950  
    default: BOOST_JSON_UNREACHABLE();
951  
    }
951  
    }
952  

952  

953  
    cs += size;
953  
    cs += size;
954  
    return cs.begin();
954  
    return cs.begin();
955  
}
955  
}
956  

956  

957  
//----------------------------------------------------------
957  
//----------------------------------------------------------
958  

958  

959  
template<class Handler>
959  
template<class Handler>
960  
template<bool StackEmpty_, bool IsKey_>
960  
template<bool StackEmpty_, bool IsKey_>
961  
const char*
961  
const char*
962  
basic_parser<Handler>::
962  
basic_parser<Handler>::
963  
parse_string(const char* p,
963  
parse_string(const char* p,
964  
    std::integral_constant<bool, StackEmpty_> stack_empty,
964  
    std::integral_constant<bool, StackEmpty_> stack_empty,
965  
    std::integral_constant<bool, IsKey_> is_key,
965  
    std::integral_constant<bool, IsKey_> is_key,
966  
    bool allow_bad_utf8,
966  
    bool allow_bad_utf8,
967  
    bool allow_bad_utf16)
967  
    bool allow_bad_utf16)
968  
{
968  
{
969  
    detail::const_stream_wrapper cs(p, end_);
969  
    detail::const_stream_wrapper cs(p, end_);
970  
    std::size_t total;
970  
    std::size_t total;
971  
    char const* start;
971  
    char const* start;
972  
    std::size_t size;
972  
    std::size_t size;
973  
    if(! stack_empty && ! st_.empty())
973  
    if(! stack_empty && ! st_.empty())
974  
    {
974  
    {
975  
        state st;
975  
        state st;
976  
        st_.pop(st);
976  
        st_.pop(st);
977  
        st_.pop(total);
977  
        st_.pop(total);
978  
        switch(st)
978  
        switch(st)
979  
        {
979  
        {
980  
        default: BOOST_JSON_UNREACHABLE();
980  
        default: BOOST_JSON_UNREACHABLE();
981  
        case state::str2: goto do_str2;
981  
        case state::str2: goto do_str2;
982  
        case state::str8: goto do_str8;
982  
        case state::str8: goto do_str8;
983  
        case state::str1: break;
983  
        case state::str1: break;
984  
        }
984  
        }
985  
    }
985  
    }
986  
    else
986  
    else
987  
    {
987  
    {
988  
        BOOST_ASSERT(*cs == '\x22'); // '"'
988  
        BOOST_ASSERT(*cs == '\x22'); // '"'
989  
        ++cs;
989  
        ++cs;
990  
        total = 0;
990  
        total = 0;
991  
    }
991  
    }
992  

992  

993  
do_str1:
993  
do_str1:
994  
    start = cs.begin();
994  
    start = cs.begin();
995  
    cs = allow_bad_utf8?
995  
    cs = allow_bad_utf8?
996  
        detail::count_valid<true>(cs.begin(), cs.end()):
996  
        detail::count_valid<true>(cs.begin(), cs.end()):
997  
        detail::count_valid<false>(cs.begin(), cs.end());
997  
        detail::count_valid<false>(cs.begin(), cs.end());
998  
    size = cs.used(start);
998  
    size = cs.used(start);
999  
    if(is_key)
999  
    if(is_key)
1000  
    {
1000  
    {
1001  
        BOOST_ASSERT(total <= Handler::max_key_size);
1001  
        BOOST_ASSERT(total <= Handler::max_key_size);
1002  
        if(BOOST_JSON_UNLIKELY(size >
1002  
        if(BOOST_JSON_UNLIKELY(size >
1003  
            Handler::max_key_size - total))
1003  
            Handler::max_key_size - total))
1004  
        {
1004  
        {
1005  
            BOOST_STATIC_CONSTEXPR source_location loc
1005  
            BOOST_STATIC_CONSTEXPR source_location loc
1006  
                = BOOST_CURRENT_LOCATION;
1006  
                = BOOST_CURRENT_LOCATION;
1007  
            return fail(cs.begin(), error::key_too_large, &loc);
1007  
            return fail(cs.begin(), error::key_too_large, &loc);
1008  
        }
1008  
        }
1009  
    }
1009  
    }
1010  
    else
1010  
    else
1011  
    {
1011  
    {
1012  
        BOOST_ASSERT(total <= Handler::max_string_size);
1012  
        BOOST_ASSERT(total <= Handler::max_string_size);
1013  
        if(BOOST_JSON_UNLIKELY(size >
1013  
        if(BOOST_JSON_UNLIKELY(size >
1014  
            Handler::max_string_size - total))
1014  
            Handler::max_string_size - total))
1015  
        {
1015  
        {
1016  
            BOOST_STATIC_CONSTEXPR source_location loc
1016  
            BOOST_STATIC_CONSTEXPR source_location loc
1017  
                = BOOST_CURRENT_LOCATION;
1017  
                = BOOST_CURRENT_LOCATION;
1018  
            return fail(cs.begin(), error::string_too_large, &loc);
1018  
            return fail(cs.begin(), error::string_too_large, &loc);
1019  
        }
1019  
        }
1020  
    }
1020  
    }
1021  
    total += size;
1021  
    total += size;
1022  
    if(BOOST_JSON_UNLIKELY(! cs))
1022  
    if(BOOST_JSON_UNLIKELY(! cs))
1023  
    {
1023  
    {
1024  
        // call handler if the string isn't empty
1024  
        // call handler if the string isn't empty
1025  
        if(BOOST_JSON_LIKELY(size))
1025  
        if(BOOST_JSON_LIKELY(size))
1026  
        {
1026  
        {
1027  
            {
1027  
            {
1028  
                bool r = is_key?
1028  
                bool r = is_key?
1029  
                    h_.on_key_part( {start, size}, total, ec_ ):
1029  
                    h_.on_key_part( {start, size}, total, ec_ ):
1030  
                    h_.on_string_part( {start, size}, total, ec_ );
1030  
                    h_.on_string_part( {start, size}, total, ec_ );
1031  

1031  

1032  
                if(BOOST_JSON_UNLIKELY(!r))
1032  
                if(BOOST_JSON_UNLIKELY(!r))
1033  
                {
1033  
                {
1034  
                    return fail(cs.begin());
1034  
                    return fail(cs.begin());
1035  
                }
1035  
                }
1036  
            }
1036  
            }
1037  
        }
1037  
        }
1038  
        return maybe_suspend(cs.begin(), state::str1, total);
1038  
        return maybe_suspend(cs.begin(), state::str1, total);
1039  
    }
1039  
    }
1040  
    // at this point all valid characters have been skipped, so any remaining
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
1041  
    // if there are any more characters, they are either escaped, or incomplete
1042  
    // utf8, or invalid utf8
1042  
    // utf8, or invalid utf8
1043  
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1043  
    if(BOOST_JSON_UNLIKELY(*cs != '\x22')) // '"'
1044  
    {
1044  
    {
1045  
        // sequence is invalid or incomplete
1045  
        // sequence is invalid or incomplete
1046  
        if((*cs & 0x80) && !allow_bad_utf8)
1046  
        if((*cs & 0x80) && !allow_bad_utf8)
1047  
        {
1047  
        {
1048  
            seq_.save(cs.begin(), cs.remain());
1048  
            seq_.save(cs.begin(), cs.remain());
1049  
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1049  
            if(BOOST_JSON_UNLIKELY(seq_.complete()))
1050  
            {
1050  
            {
1051  
                BOOST_STATIC_CONSTEXPR source_location loc
1051  
                BOOST_STATIC_CONSTEXPR source_location loc
1052  
                    = BOOST_CURRENT_LOCATION;
1052  
                    = BOOST_CURRENT_LOCATION;
1053  
                return fail(cs.begin(), error::syntax, &loc);
1053  
                return fail(cs.begin(), error::syntax, &loc);
1054  
            }
1054  
            }
1055  
            if(BOOST_JSON_LIKELY(size))
1055  
            if(BOOST_JSON_LIKELY(size))
1056  
            {
1056  
            {
1057  
                bool const r = is_key?
1057  
                bool const r = is_key?
1058  
                    h_.on_key_part( {start, size}, total, ec_ ):
1058  
                    h_.on_key_part( {start, size}, total, ec_ ):
1059  
                    h_.on_string_part( {start, size}, total, ec_ );
1059  
                    h_.on_string_part( {start, size}, total, ec_ );
1060  
                if(BOOST_JSON_UNLIKELY( !r ))
1060  
                if(BOOST_JSON_UNLIKELY( !r ))
1061  
                    return fail( cs.begin() );
1061  
                    return fail( cs.begin() );
1062  
            }
1062  
            }
1063  
            return maybe_suspend(cs.end(), state::str8, total);
1063  
            return maybe_suspend(cs.end(), state::str8, total);
1064  
        }
1064  
        }
1065  
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1065  
        else if(BOOST_JSON_LIKELY(*cs == '\\'))
1066  
        {
1066  
        {
1067  
            // flush unescaped run from input
1067  
            // flush unescaped run from input
1068  
            if(BOOST_JSON_LIKELY(size))
1068  
            if(BOOST_JSON_LIKELY(size))
1069  
            {
1069  
            {
1070  
                bool const r = is_key?
1070  
                bool const r = is_key?
1071  
                    h_.on_key_part( {start, size}, total, ec_ ):
1071  
                    h_.on_key_part( {start, size}, total, ec_ ):
1072  
                    h_.on_string_part( {start, size}, total, ec_ );
1072  
                    h_.on_string_part( {start, size}, total, ec_ );
1073  
                if(BOOST_JSON_UNLIKELY( !r ))
1073  
                if(BOOST_JSON_UNLIKELY( !r ))
1074  
                    return fail( cs.begin() );
1074  
                    return fail( cs.begin() );
1075  
            }
1075  
            }
1076  
do_str2:
1076  
do_str2:
1077  
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1077  
            cs = parse_escaped(cs.begin(), total, stack_empty, is_key, allow_bad_utf16);
1078  
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1078  
            if(BOOST_JSON_UNLIKELY( incomplete(cs) ))
1079  
                return suspend_or_fail(state::str2, total);
1079  
                return suspend_or_fail(state::str2, total);
1080  

1080  

1081  
            goto do_str1;
1081  
            goto do_str1;
1082  
        }
1082  
        }
1083  
        // illegal control
1083  
        // illegal control
1084  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1084  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1085  
        return fail(cs.begin(), error::syntax, &loc);
1085  
        return fail(cs.begin(), error::syntax, &loc);
1086  
    }
1086  
    }
1087  

1087  

1088  
    {
1088  
    {
1089  
        bool r = is_key?
1089  
        bool r = is_key?
1090  
            h_.on_key( {start, size}, total, ec_ ):
1090  
            h_.on_key( {start, size}, total, ec_ ):
1091  
            h_.on_string( {start, size}, total, ec_ );
1091  
            h_.on_string( {start, size}, total, ec_ );
1092  

1092  

1093  
        if(BOOST_JSON_UNLIKELY(!r))
1093  
        if(BOOST_JSON_UNLIKELY(!r))
1094  
        {
1094  
        {
1095  
            return fail(cs.begin());
1095  
            return fail(cs.begin());
1096  
        }
1096  
        }
1097  
    }
1097  
    }
1098  

1098  

1099  
    ++cs;
1099  
    ++cs;
1100  
    return cs.begin();
1100  
    return cs.begin();
1101  

1101  

1102  
do_str8:
1102  
do_str8:
1103  
    uint8_t needed = seq_.needed();
1103  
    uint8_t needed = seq_.needed();
1104  
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1104  
    if(BOOST_JSON_UNLIKELY( !seq_.append(cs.begin(), cs.remain()) ))
1105  
        return maybe_suspend(cs.end(), state::str8, total);
1105  
        return maybe_suspend(cs.end(), state::str8, total);
1106  
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1106  
    if(BOOST_JSON_UNLIKELY( !seq_.valid() ))
1107  
    {
1107  
    {
1108  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1108  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1109  
        return fail(cs.begin(), error::syntax, &loc);
1109  
        return fail(cs.begin(), error::syntax, &loc);
1110  
    }
1110  
    }
1111  
    {
1111  
    {
1112  
        bool const r = is_key?
1112  
        bool const r = is_key?
1113  
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1113  
            h_.on_key_part( {seq_.data(), seq_.length()}, total, ec_ ):
1114  
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1114  
            h_.on_string_part( {seq_.data(), seq_.length()}, total, ec_ );
1115  
        if(BOOST_JSON_UNLIKELY( !r ))
1115  
        if(BOOST_JSON_UNLIKELY( !r ))
1116  
            return fail( cs.begin() );
1116  
            return fail( cs.begin() );
1117  
    }
1117  
    }
1118  
    cs += needed;
1118  
    cs += needed;
1119  
    goto do_str1;
1119  
    goto do_str1;
1120  
}
1120  
}
1121  

1121  

1122  
template<class Handler>
1122  
template<class Handler>
1123  
template<bool StackEmpty_>
1123  
template<bool StackEmpty_>
1124  
const char*
1124  
const char*
1125  
basic_parser<Handler>::
1125  
basic_parser<Handler>::
1126  
parse_escaped(
1126  
parse_escaped(
1127  
    const char* p,
1127  
    const char* p,
1128  
    std::size_t& total,
1128  
    std::size_t& total,
1129  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1129  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1130  
    bool is_key,
1130  
    bool is_key,
1131  
    bool allow_bad_utf16)
1131  
    bool allow_bad_utf16)
1132  
{
1132  
{
1133  
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1133  
    constexpr unsigned urc = 0xFFFD; // Unicode replacement character
1134  
    auto const ev_too_large = is_key?
1134  
    auto const ev_too_large = is_key?
1135  
        error::key_too_large : error::string_too_large;
1135  
        error::key_too_large : error::string_too_large;
1136  
    auto const max_size = is_key?
1136  
    auto const max_size = is_key?
1137  
        Handler::max_key_size : Handler::max_string_size;
1137  
        Handler::max_key_size : Handler::max_string_size;
1138  
    int digit;
1138  
    int digit;
1139  

1139  

1140  
    //---------------------------------------------------------------
1140  
    //---------------------------------------------------------------
1141  
    //
1141  
    //
1142  
    // To handle escapes, a local temporary buffer accumulates
1142  
    // To handle escapes, a local temporary buffer accumulates
1143  
    // the unescaped result. The algorithm attempts to fill the
1143  
    // the unescaped result. The algorithm attempts to fill the
1144  
    // buffer to capacity before invoking the handler.
1144  
    // buffer to capacity before invoking the handler.
1145  
    // In some cases the temporary buffer needs to be flushed
1145  
    // In some cases the temporary buffer needs to be flushed
1146  
    // before it is full:
1146  
    // before it is full:
1147  
    // * When the closing double quote is seen
1147  
    // * When the closing double quote is seen
1148  
    // * When there in no more input (and more is expected later)
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
1149  
    // A goal of the algorithm is to call the handler as few times
1150  
    // as possible. Thus, when the first escape is encountered,
1150  
    // as possible. Thus, when the first escape is encountered,
1151  
    // the algorithm attempts to fill the temporary buffer first.
1151  
    // the algorithm attempts to fill the temporary buffer first.
1152  
    //
1152  
    //
1153  
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1153  
    detail::buffer<BOOST_JSON_STACK_BUFFER_SIZE> temp;
1154  

1154  

1155  
    // Unescaped JSON is never larger than its escaped version.
1155  
    // Unescaped JSON is never larger than its escaped version.
1156  
    // To efficiently process only what will fit in the temporary buffer,
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
1157  
    // the size of the input stream is temporarily "clipped" to the size
1158  
    // of the temporary buffer.
1158  
    // of the temporary buffer.
1159  
    // handle escaped character
1159  
    // handle escaped character
1160  
    detail::clipped_const_stream cs(p, end_);
1160  
    detail::clipped_const_stream cs(p, end_);
1161  
    cs.clip(temp.max_size());
1161  
    cs.clip(temp.max_size());
1162  

1162  

1163  
    if(! stack_empty && ! st_.empty())
1163  
    if(! stack_empty && ! st_.empty())
1164  
    {
1164  
    {
1165  
        state st;
1165  
        state st;
1166  
        st_.pop(st);
1166  
        st_.pop(st);
1167  
        switch(st)
1167  
        switch(st)
1168  
        {
1168  
        {
1169  
        default: BOOST_JSON_UNREACHABLE();
1169  
        default: BOOST_JSON_UNREACHABLE();
1170  
        case state::str3: goto do_str3;
1170  
        case state::str3: goto do_str3;
1171  
        case state::str4: goto do_str4;
1171  
        case state::str4: goto do_str4;
1172  
        case state::str5: goto do_str5;
1172  
        case state::str5: goto do_str5;
1173  
        case state::str6: goto do_str6;
1173  
        case state::str6: goto do_str6;
1174  
        case state::str7: goto do_str7;
1174  
        case state::str7: goto do_str7;
1175  
        case state::sur1: goto do_sur1;
1175  
        case state::sur1: goto do_sur1;
1176  
        case state::sur2: goto do_sur2;
1176  
        case state::sur2: goto do_sur2;
1177  
        case state::sur3: goto do_sur3;
1177  
        case state::sur3: goto do_sur3;
1178  
        case state::sur4: goto do_sur4;
1178  
        case state::sur4: goto do_sur4;
1179  
        case state::sur5: goto do_sur5;
1179  
        case state::sur5: goto do_sur5;
1180  
        case state::sur6: goto do_sur6;
1180  
        case state::sur6: goto do_sur6;
1181  
        }
1181  
        }
1182  
    }
1182  
    }
1183  

1183  

1184  
    while(true)
1184  
    while(true)
1185  
    {
1185  
    {
1186  
        BOOST_ASSERT( temp.capacity() );
1186  
        BOOST_ASSERT( temp.capacity() );
1187  
        BOOST_ASSERT(*cs == '\\');
1187  
        BOOST_ASSERT(*cs == '\\');
1188  
        ++cs;
1188  
        ++cs;
1189  
do_str3:
1189  
do_str3:
1190  
        if(BOOST_JSON_UNLIKELY(! cs))
1190  
        if(BOOST_JSON_UNLIKELY(! cs))
1191  
        {
1191  
        {
1192  
            if(BOOST_JSON_LIKELY(! temp.empty()))
1192  
            if(BOOST_JSON_LIKELY(! temp.empty()))
1193  
            {
1193  
            {
1194  
                BOOST_ASSERT(total <= max_size);
1194  
                BOOST_ASSERT(total <= max_size);
1195  
                if(BOOST_JSON_UNLIKELY(
1195  
                if(BOOST_JSON_UNLIKELY(
1196  
                    temp.size() > max_size - total))
1196  
                    temp.size() > max_size - total))
1197  
                {
1197  
                {
1198  
                    BOOST_STATIC_CONSTEXPR source_location loc
1198  
                    BOOST_STATIC_CONSTEXPR source_location loc
1199  
                        = BOOST_CURRENT_LOCATION;
1199  
                        = BOOST_CURRENT_LOCATION;
1200  
                    return fail(cs.begin(), ev_too_large, &loc);
1200  
                    return fail(cs.begin(), ev_too_large, &loc);
1201  
                }
1201  
                }
1202  
                total += temp.size();
1202  
                total += temp.size();
1203  
                {
1203  
                {
1204  
                    bool r = is_key
1204  
                    bool r = is_key
1205  
                        ? h_.on_key_part(temp.get(), total, ec_)
1205  
                        ? h_.on_key_part(temp.get(), total, ec_)
1206  
                        : h_.on_string_part(temp.get(), total, ec_);
1206  
                        : h_.on_string_part(temp.get(), total, ec_);
1207  

1207  

1208  
                    if(BOOST_JSON_UNLIKELY(!r))
1208  
                    if(BOOST_JSON_UNLIKELY(!r))
1209  
                    {
1209  
                    {
1210  
                        return fail(cs.begin());
1210  
                        return fail(cs.begin());
1211  
                    }
1211  
                    }
1212  
                }
1212  
                }
1213  
                temp.clear();
1213  
                temp.clear();
1214  
            }
1214  
            }
1215  
            cs.clip(temp.max_size());
1215  
            cs.clip(temp.max_size());
1216  
            if(BOOST_JSON_UNLIKELY(! cs))
1216  
            if(BOOST_JSON_UNLIKELY(! cs))
1217  
                return maybe_suspend(cs.begin(), state::str3);
1217  
                return maybe_suspend(cs.begin(), state::str3);
1218  
        }
1218  
        }
1219  
        switch(*cs)
1219  
        switch(*cs)
1220  
        {
1220  
        {
1221  
        default:
1221  
        default:
1222  
            {
1222  
            {
1223  
                BOOST_STATIC_CONSTEXPR source_location loc
1223  
                BOOST_STATIC_CONSTEXPR source_location loc
1224  
                    = BOOST_CURRENT_LOCATION;
1224  
                    = BOOST_CURRENT_LOCATION;
1225  
                return fail(cs.begin(), error::syntax, &loc);
1225  
                return fail(cs.begin(), error::syntax, &loc);
1226  
            }
1226  
            }
1227  
        case '\x22': // '"'
1227  
        case '\x22': // '"'
1228  
            temp.push_back('\x22');
1228  
            temp.push_back('\x22');
1229  
            ++cs;
1229  
            ++cs;
1230  
            break;
1230  
            break;
1231  
        case '\\':
1231  
        case '\\':
1232  
            temp.push_back('\\');
1232  
            temp.push_back('\\');
1233  
            ++cs;
1233  
            ++cs;
1234  
            break;
1234  
            break;
1235  
        case '/':
1235  
        case '/':
1236  
            temp.push_back('/');
1236  
            temp.push_back('/');
1237  
            ++cs;
1237  
            ++cs;
1238  
            break;
1238  
            break;
1239  
        case 'b':
1239  
        case 'b':
1240  
            temp.push_back('\x08');
1240  
            temp.push_back('\x08');
1241  
            ++cs;
1241  
            ++cs;
1242  
            break;
1242  
            break;
1243  
        case 'f':
1243  
        case 'f':
1244  
            temp.push_back('\x0c');
1244  
            temp.push_back('\x0c');
1245  
            ++cs;
1245  
            ++cs;
1246  
            break;
1246  
            break;
1247  
        case 'n':
1247  
        case 'n':
1248  
            temp.push_back('\x0a');
1248  
            temp.push_back('\x0a');
1249  
            ++cs;
1249  
            ++cs;
1250  
            break;
1250  
            break;
1251  
        case 'r':
1251  
        case 'r':
1252  
            temp.push_back('\x0d');
1252  
            temp.push_back('\x0d');
1253  
            ++cs;
1253  
            ++cs;
1254  
            break;
1254  
            break;
1255  
        case 't':
1255  
        case 't':
1256  
            temp.push_back('\x09');
1256  
            temp.push_back('\x09');
1257  
            ++cs;
1257  
            ++cs;
1258  
            break;
1258  
            break;
1259  
        case 'u':
1259  
        case 'u':
1260  
            // utf16 escape
1260  
            // utf16 escape
1261  
            //
1261  
            //
1262  
            // fast path only when the buffer
1262  
            // fast path only when the buffer
1263  
            // is large enough for 2 surrogates
1263  
            // is large enough for 2 surrogates
1264  
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1264  
            if(BOOST_JSON_LIKELY(cs.remain() > 10))
1265  
            {
1265  
            {
1266  
                // KRYSTIAN TODO: this could be done
1266  
                // KRYSTIAN TODO: this could be done
1267  
                // with fewer instructions
1267  
                // with fewer instructions
1268  
                digit = detail::load_little_endian<4>(
1268  
                digit = detail::load_little_endian<4>(
1269  
                    cs.begin() + 1);
1269  
                    cs.begin() + 1);
1270  
                int d4 = detail::hex_digit(static_cast<
1270  
                int d4 = detail::hex_digit(static_cast<
1271  
                    unsigned char>(digit >> 24));
1271  
                    unsigned char>(digit >> 24));
1272  
                int d3 = detail::hex_digit(static_cast<
1272  
                int d3 = detail::hex_digit(static_cast<
1273  
                    unsigned char>(digit >> 16));
1273  
                    unsigned char>(digit >> 16));
1274  
                int d2 = detail::hex_digit(static_cast<
1274  
                int d2 = detail::hex_digit(static_cast<
1275  
                    unsigned char>(digit >> 8));
1275  
                    unsigned char>(digit >> 8));
1276  
                int d1 = detail::hex_digit(static_cast<
1276  
                int d1 = detail::hex_digit(static_cast<
1277  
                    unsigned char>(digit));
1277  
                    unsigned char>(digit));
1278  
                if(BOOST_JSON_UNLIKELY(
1278  
                if(BOOST_JSON_UNLIKELY(
1279  
                    (d1 | d2 | d3 | d4) == -1))
1279  
                    (d1 | d2 | d3 | d4) == -1))
1280  
                {
1280  
                {
1281  
                    if(d1 != -1)
1281  
                    if(d1 != -1)
1282  
                        ++cs;
1282  
                        ++cs;
1283  
                    if(d2 != -1)
1283  
                    if(d2 != -1)
1284  
                        ++cs;
1284  
                        ++cs;
1285  
                    if(d3 != -1)
1285  
                    if(d3 != -1)
1286  
                        ++cs;
1286  
                        ++cs;
1287  
                    BOOST_STATIC_CONSTEXPR source_location loc
1287  
                    BOOST_STATIC_CONSTEXPR source_location loc
1288  
                        = BOOST_CURRENT_LOCATION;
1288  
                        = BOOST_CURRENT_LOCATION;
1289  
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1289  
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1290  
                }
1290  
                }
1291  
                // 32 bit unicode scalar value
1291  
                // 32 bit unicode scalar value
1292  
                unsigned u1 =
1292  
                unsigned u1 =
1293  
                    (d1 << 12) + (d2 << 8) +
1293  
                    (d1 << 12) + (d2 << 8) +
1294  
                    (d3 << 4) + d4;
1294  
                    (d3 << 4) + d4;
1295  
                // valid unicode scalar values are
1295  
                // valid unicode scalar values are
1296  
                // [0, D7FF] and [E000, 10FFFF]
1296  
                // [0, D7FF] and [E000, 10FFFF]
1297  
                // values within this range are valid utf-8
1297  
                // values within this range are valid utf-8
1298  
                // code points and invalid leading surrogates.
1298  
                // code points and invalid leading surrogates.
1299  
                if(BOOST_JSON_LIKELY(
1299  
                if(BOOST_JSON_LIKELY(
1300  
                    u1 < 0xd800 || u1 > 0xdfff))
1300  
                    u1 < 0xd800 || u1 > 0xdfff))
1301  
                {
1301  
                {
1302  
                    cs += 5;
1302  
                    cs += 5;
1303  
                    temp.append_utf8(u1);
1303  
                    temp.append_utf8(u1);
1304  
                    break;
1304  
                    break;
1305  
                }
1305  
                }
1306  
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1306  
                if(BOOST_JSON_UNLIKELY(u1 > 0xdbff))
1307  
                {
1307  
                {
1308  
                    // If it's an illegal leading surrogate and
1308  
                    // If it's an illegal leading surrogate and
1309  
                    // the parser does not allow it, return an error.
1309  
                    // the parser does not allow it, return an error.
1310  
                    if(!allow_bad_utf16)
1310  
                    if(!allow_bad_utf16)
1311  
                    {
1311  
                    {
1312  
                        BOOST_STATIC_CONSTEXPR source_location loc
1312  
                        BOOST_STATIC_CONSTEXPR source_location loc
1313  
                            = BOOST_CURRENT_LOCATION;
1313  
                            = BOOST_CURRENT_LOCATION;
1314  
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1314  
                        return fail(cs.begin(), error::illegal_leading_surrogate,
1315  
                            &loc);
1315  
                            &loc);
1316  
                    }
1316  
                    }
1317  
                    // Otherwise, append the Unicode replacement character
1317  
                    // Otherwise, append the Unicode replacement character
1318  
                    else
1318  
                    else
1319  
                    {
1319  
                    {
1320  
                        cs += 5;
1320  
                        cs += 5;
1321  
                        temp.append_utf8(urc);
1321  
                        temp.append_utf8(urc);
1322  
                        break;
1322  
                        break;
1323  
                    }
1323  
                    }
1324  
                }
1324  
                }
1325  
                cs += 5;
1325  
                cs += 5;
1326  
                // KRYSTIAN TODO: this can be a two byte load
1326  
                // KRYSTIAN TODO: this can be a two byte load
1327  
                // and a single comparison. We lose error information,
1327  
                // and a single comparison. We lose error information,
1328  
                // but it's faster.
1328  
                // but it's faster.
1329  
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1329  
                if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1330  
                {
1330  
                {
1331  
                    // If the next character is not a backslash and
1331  
                    // If the next character is not a backslash and
1332  
                    // the parser does not allow it, return a syntax error.
1332  
                    // the parser does not allow it, return a syntax error.
1333  
                    if(!allow_bad_utf16)
1333  
                    if(!allow_bad_utf16)
1334  
                    {
1334  
                    {
1335  
                        BOOST_STATIC_CONSTEXPR source_location loc
1335  
                        BOOST_STATIC_CONSTEXPR source_location loc
1336  
                            = BOOST_CURRENT_LOCATION;
1336  
                            = BOOST_CURRENT_LOCATION;
1337  
                        return fail(cs.begin(), error::syntax, &loc);
1337  
                        return fail(cs.begin(), error::syntax, &loc);
1338  
                    }
1338  
                    }
1339  
                    // Otherwise, append the Unicode replacement character since
1339  
                    // Otherwise, append the Unicode replacement character since
1340  
                    // the first code point is a valid leading surrogate
1340  
                    // the first code point is a valid leading surrogate
1341  
                    else
1341  
                    else
1342  
                    {
1342  
                    {
1343  
                        temp.append_utf8(urc);
1343  
                        temp.append_utf8(urc);
1344  
                        break;
1344  
                        break;
1345  
                    }
1345  
                    }
1346  
                }
1346  
                }
1347  
                ++cs;
1347  
                ++cs;
1348  
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1348  
                if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1349  
                {
1349  
                {
1350  
                    if (!allow_bad_utf16)
1350  
                    if (!allow_bad_utf16)
1351  
                    {
1351  
                    {
1352  
                        BOOST_STATIC_CONSTEXPR source_location loc
1352  
                        BOOST_STATIC_CONSTEXPR source_location loc
1353  
                            = BOOST_CURRENT_LOCATION;
1353  
                            = BOOST_CURRENT_LOCATION;
1354  
                        return fail(cs.begin(), error::syntax, &loc);
1354  
                        return fail(cs.begin(), error::syntax, &loc);
1355  
                    }
1355  
                    }
1356  
                    // Otherwise, append the Unicode replacement character since
1356  
                    // Otherwise, append the Unicode replacement character since
1357  
                    // the first code point is a valid leading surrogate
1357  
                    // the first code point is a valid leading surrogate
1358  
                    else
1358  
                    else
1359  
                    {
1359  
                    {
1360  
                        temp.append_utf8(urc);
1360  
                        temp.append_utf8(urc);
1361  
                        goto do_str3;
1361  
                        goto do_str3;
1362  
                    }
1362  
                    }
1363  
                }
1363  
                }
1364  
                ++cs;
1364  
                ++cs;
1365  
                digit = detail::load_little_endian<4>(cs.begin());
1365  
                digit = detail::load_little_endian<4>(cs.begin());
1366  
                d4 = detail::hex_digit(static_cast<
1366  
                d4 = detail::hex_digit(static_cast<
1367  
                    unsigned char>(digit >> 24));
1367  
                    unsigned char>(digit >> 24));
1368  
                d3 = detail::hex_digit(static_cast<
1368  
                d3 = detail::hex_digit(static_cast<
1369  
                    unsigned char>(digit >> 16));
1369  
                    unsigned char>(digit >> 16));
1370  
                d2 = detail::hex_digit(static_cast<
1370  
                d2 = detail::hex_digit(static_cast<
1371  
                    unsigned char>(digit >> 8));
1371  
                    unsigned char>(digit >> 8));
1372  
                d1 = detail::hex_digit(static_cast<
1372  
                d1 = detail::hex_digit(static_cast<
1373  
                    unsigned char>(digit));
1373  
                    unsigned char>(digit));
1374  
                if(BOOST_JSON_UNLIKELY(
1374  
                if(BOOST_JSON_UNLIKELY(
1375  
                    (d1 | d2 | d3 | d4) == -1))
1375  
                    (d1 | d2 | d3 | d4) == -1))
1376  
                {
1376  
                {
1377  
                    if(d1 != -1)
1377  
                    if(d1 != -1)
1378  
                        ++cs;
1378  
                        ++cs;
1379  
                    if(d2 != -1)
1379  
                    if(d2 != -1)
1380  
                        ++cs;
1380  
                        ++cs;
1381  
                    if(d3 != -1)
1381  
                    if(d3 != -1)
1382  
                        ++cs;
1382  
                        ++cs;
1383  
                    BOOST_STATIC_CONSTEXPR source_location loc
1383  
                    BOOST_STATIC_CONSTEXPR source_location loc
1384  
                        = BOOST_CURRENT_LOCATION;
1384  
                        = BOOST_CURRENT_LOCATION;
1385  
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1385  
                    return fail(cs.begin(), error::expected_hex_digit, &loc);
1386  
                }
1386  
                }
1387  
                unsigned u2 =
1387  
                unsigned u2 =
1388  
                    (d1 << 12) + (d2 << 8) +
1388  
                    (d1 << 12) + (d2 << 8) +
1389  
                    (d3 << 4) + d4;
1389  
                    (d3 << 4) + d4;
1390  
                // Check if the second code point is a valid trailing surrogate.
1390  
                // Check if the second code point is a valid trailing surrogate.
1391  
                // Valid trailing surrogates are [DC00, DFFF]
1391  
                // Valid trailing surrogates are [DC00, DFFF]
1392  
                if(BOOST_JSON_UNLIKELY(
1392  
                if(BOOST_JSON_UNLIKELY(
1393  
                    u2 < 0xdc00 || u2 > 0xdfff))
1393  
                    u2 < 0xdc00 || u2 > 0xdfff))
1394  
                {
1394  
                {
1395  
                    // If not valid and the parser does not allow it, return an error.
1395  
                    // If not valid and the parser does not allow it, return an error.
1396  
                    if(!allow_bad_utf16)
1396  
                    if(!allow_bad_utf16)
1397  
                    {
1397  
                    {
1398  
                        BOOST_STATIC_CONSTEXPR source_location loc
1398  
                        BOOST_STATIC_CONSTEXPR source_location loc
1399  
                            = BOOST_CURRENT_LOCATION;
1399  
                            = BOOST_CURRENT_LOCATION;
1400  
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1400  
                        return fail(cs.begin(), error::illegal_trailing_surrogate,
1401  
                            &loc);
1401  
                            &loc);
1402  
                    }
1402  
                    }
1403  
                    // Append the replacement character for the
1403  
                    // Append the replacement character for the
1404  
                    // first leading surrogate.
1404  
                    // first leading surrogate.
1405  
                    cs += 4;
1405  
                    cs += 4;
1406  
                    temp.append_utf8(urc);
1406  
                    temp.append_utf8(urc);
1407  
                    // Check if the second code point is a
1407  
                    // Check if the second code point is a
1408  
                    // valid unicode scalar value (invalid leading
1408  
                    // valid unicode scalar value (invalid leading
1409  
                    // or trailing surrogate)
1409  
                    // or trailing surrogate)
1410  
                    if (u2 < 0xd800 || u2 > 0xdbff)
1410  
                    if (u2 < 0xd800 || u2 > 0xdbff)
1411  
                    {
1411  
                    {
1412  
                        temp.append_utf8(u2);
1412  
                        temp.append_utf8(u2);
1413  
                        break;
1413  
                        break;
1414  
                    }
1414  
                    }
1415  
                    // If it is a valid leading surrogate
1415  
                    // If it is a valid leading surrogate
1416  
                    else
1416  
                    else
1417  
                    {
1417  
                    {
1418  
                        u1_ = u2;
1418  
                        u1_ = u2;
1419  
                        goto do_sur1;
1419  
                        goto do_sur1;
1420  
                    }
1420  
                    }
1421  
                }
1421  
                }
1422  
                cs += 4;
1422  
                cs += 4;
1423  
                // Calculate the Unicode code point from the surrogate pair and
1423  
                // Calculate the Unicode code point from the surrogate pair and
1424  
                // append the UTF-8 representation.
1424  
                // append the UTF-8 representation.
1425  
                unsigned cp =
1425  
                unsigned cp =
1426  
                    ((u1 - 0xd800) << 10) +
1426  
                    ((u1 - 0xd800) << 10) +
1427  
                    ((u2 - 0xdc00)) +
1427  
                    ((u2 - 0xdc00)) +
1428  
                        0x10000;
1428  
                        0x10000;
1429  
                // utf-16 surrogate pair
1429  
                // utf-16 surrogate pair
1430  
                temp.append_utf8(cp);
1430  
                temp.append_utf8(cp);
1431  
                break;
1431  
                break;
1432  
            }
1432  
            }
1433  
            // flush
1433  
            // flush
1434  
            if(BOOST_JSON_LIKELY(! temp.empty()))
1434  
            if(BOOST_JSON_LIKELY(! temp.empty()))
1435  
            {
1435  
            {
1436  
                BOOST_ASSERT(total <= max_size);
1436  
                BOOST_ASSERT(total <= max_size);
1437  
                if(BOOST_JSON_UNLIKELY(
1437  
                if(BOOST_JSON_UNLIKELY(
1438  
                    temp.size() > max_size - total))
1438  
                    temp.size() > max_size - total))
1439  
                {
1439  
                {
1440  
                    BOOST_STATIC_CONSTEXPR source_location loc
1440  
                    BOOST_STATIC_CONSTEXPR source_location loc
1441  
                        = BOOST_CURRENT_LOCATION;
1441  
                        = BOOST_CURRENT_LOCATION;
1442  
                    return fail(cs.begin(), ev_too_large, &loc);
1442  
                    return fail(cs.begin(), ev_too_large, &loc);
1443  
                }
1443  
                }
1444  
                total += temp.size();
1444  
                total += temp.size();
1445  
                {
1445  
                {
1446  
                    bool r = is_key
1446  
                    bool r = is_key
1447  
                        ? h_.on_key_part(temp.get(), total, ec_)
1447  
                        ? h_.on_key_part(temp.get(), total, ec_)
1448  
                        : h_.on_string_part(temp.get(), total, ec_);
1448  
                        : h_.on_string_part(temp.get(), total, ec_);
1449  

1449  

1450  
                    if(BOOST_JSON_UNLIKELY(!r))
1450  
                    if(BOOST_JSON_UNLIKELY(!r))
1451  
                    {
1451  
                    {
1452  
                        return fail(cs.begin());
1452  
                        return fail(cs.begin());
1453  
                    }
1453  
                    }
1454  
                }
1454  
                }
1455  
                temp.clear();
1455  
                temp.clear();
1456  
                cs.clip(temp.max_size());
1456  
                cs.clip(temp.max_size());
1457  
            }
1457  
            }
1458  
            ++cs;
1458  
            ++cs;
1459  
            // utf-16 escape
1459  
            // utf-16 escape
1460  
    do_str4:
1460  
    do_str4:
1461  
            if(BOOST_JSON_UNLIKELY(! cs))
1461  
            if(BOOST_JSON_UNLIKELY(! cs))
1462  
                return maybe_suspend(cs.begin(), state::str4);
1462  
                return maybe_suspend(cs.begin(), state::str4);
1463  
            digit = detail::hex_digit(*cs);
1463  
            digit = detail::hex_digit(*cs);
1464  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1464  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1465  
            {
1465  
            {
1466  
                BOOST_STATIC_CONSTEXPR source_location loc
1466  
                BOOST_STATIC_CONSTEXPR source_location loc
1467  
                    = BOOST_CURRENT_LOCATION;
1467  
                    = BOOST_CURRENT_LOCATION;
1468  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1468  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1469  
            }
1469  
            }
1470  
            ++cs;
1470  
            ++cs;
1471  
            u1_ = digit << 12;
1471  
            u1_ = digit << 12;
1472  
    do_str5:
1472  
    do_str5:
1473  
            if(BOOST_JSON_UNLIKELY(! cs))
1473  
            if(BOOST_JSON_UNLIKELY(! cs))
1474  
                return maybe_suspend(cs.begin(), state::str5);
1474  
                return maybe_suspend(cs.begin(), state::str5);
1475  
            digit = detail::hex_digit(*cs);
1475  
            digit = detail::hex_digit(*cs);
1476  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1476  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1477  
            {
1477  
            {
1478  
                BOOST_STATIC_CONSTEXPR source_location loc
1478  
                BOOST_STATIC_CONSTEXPR source_location loc
1479  
                    = BOOST_CURRENT_LOCATION;
1479  
                    = BOOST_CURRENT_LOCATION;
1480  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1480  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1481  
            }
1481  
            }
1482  
            ++cs;
1482  
            ++cs;
1483  
            u1_ += digit << 8;
1483  
            u1_ += digit << 8;
1484  
    do_str6:
1484  
    do_str6:
1485  
            if(BOOST_JSON_UNLIKELY(! cs))
1485  
            if(BOOST_JSON_UNLIKELY(! cs))
1486  
                return maybe_suspend(cs.begin(), state::str6);
1486  
                return maybe_suspend(cs.begin(), state::str6);
1487  
            digit = detail::hex_digit(*cs);
1487  
            digit = detail::hex_digit(*cs);
1488  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1488  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1489  
            {
1489  
            {
1490  
                BOOST_STATIC_CONSTEXPR source_location loc
1490  
                BOOST_STATIC_CONSTEXPR source_location loc
1491  
                    = BOOST_CURRENT_LOCATION;
1491  
                    = BOOST_CURRENT_LOCATION;
1492  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1492  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1493  
            }
1493  
            }
1494  
            ++cs;
1494  
            ++cs;
1495  
            u1_ += digit << 4;
1495  
            u1_ += digit << 4;
1496  
    do_str7:
1496  
    do_str7:
1497  
            if(BOOST_JSON_UNLIKELY(! cs))
1497  
            if(BOOST_JSON_UNLIKELY(! cs))
1498  
                return maybe_suspend(cs.begin(), state::str7);
1498  
                return maybe_suspend(cs.begin(), state::str7);
1499  
            digit = detail::hex_digit(*cs);
1499  
            digit = detail::hex_digit(*cs);
1500  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1500  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1501  
            {
1501  
            {
1502  
                BOOST_STATIC_CONSTEXPR source_location loc
1502  
                BOOST_STATIC_CONSTEXPR source_location loc
1503  
                    = BOOST_CURRENT_LOCATION;
1503  
                    = BOOST_CURRENT_LOCATION;
1504  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1504  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1505  
            }
1505  
            }
1506  
            ++cs;
1506  
            ++cs;
1507  
            u1_ += digit;
1507  
            u1_ += digit;
1508  
            if(BOOST_JSON_LIKELY(
1508  
            if(BOOST_JSON_LIKELY(
1509  
                u1_ < 0xd800 || u1_ > 0xdfff))
1509  
                u1_ < 0xd800 || u1_ > 0xdfff))
1510  
            {
1510  
            {
1511  
                BOOST_ASSERT(temp.empty());
1511  
                BOOST_ASSERT(temp.empty());
1512  
                // utf-8 codepoint
1512  
                // utf-8 codepoint
1513  
                temp.append_utf8(u1_);
1513  
                temp.append_utf8(u1_);
1514  
                break;
1514  
                break;
1515  
            }
1515  
            }
1516  
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1516  
            if(BOOST_JSON_UNLIKELY(u1_ > 0xdbff))
1517  
            {
1517  
            {
1518  
                // If it's an illegal leading surrogate and
1518  
                // If it's an illegal leading surrogate and
1519  
                // the parser does not allow it, return an error.
1519  
                // the parser does not allow it, return an error.
1520  
                if(!allow_bad_utf16)
1520  
                if(!allow_bad_utf16)
1521  
                {
1521  
                {
1522  
                    BOOST_STATIC_CONSTEXPR source_location loc
1522  
                    BOOST_STATIC_CONSTEXPR source_location loc
1523  
                        = BOOST_CURRENT_LOCATION;
1523  
                        = BOOST_CURRENT_LOCATION;
1524  
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1524  
                    return fail(cs.begin(), error::illegal_leading_surrogate, &loc);
1525  
                }
1525  
                }
1526  
                // Otherwise, append the Unicode replacement character
1526  
                // Otherwise, append the Unicode replacement character
1527  
                else
1527  
                else
1528  
                {
1528  
                {
1529  
                    BOOST_ASSERT(temp.empty());
1529  
                    BOOST_ASSERT(temp.empty());
1530  
                    temp.append_utf8(urc);
1530  
                    temp.append_utf8(urc);
1531  
                    break;
1531  
                    break;
1532  
                }
1532  
                }
1533  
            }
1533  
            }
1534  
    do_sur1:
1534  
    do_sur1:
1535  
            if(BOOST_JSON_UNLIKELY(! cs))
1535  
            if(BOOST_JSON_UNLIKELY(! cs))
1536  
                return maybe_suspend(cs.begin(), state::sur1);
1536  
                return maybe_suspend(cs.begin(), state::sur1);
1537  
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1537  
            if(BOOST_JSON_UNLIKELY(*cs != '\\'))
1538  
            {
1538  
            {
1539  
                // If the next character is not a backslash and
1539  
                // If the next character is not a backslash and
1540  
                // the parser does not allow it, return a syntax error.
1540  
                // the parser does not allow it, return a syntax error.
1541  
                if(!allow_bad_utf16)
1541  
                if(!allow_bad_utf16)
1542  
                {
1542  
                {
1543  
                    BOOST_STATIC_CONSTEXPR source_location loc
1543  
                    BOOST_STATIC_CONSTEXPR source_location loc
1544  
                        = BOOST_CURRENT_LOCATION;
1544  
                        = BOOST_CURRENT_LOCATION;
1545  
                    return fail(cs.begin(), error::syntax, &loc);
1545  
                    return fail(cs.begin(), error::syntax, &loc);
1546  
                }
1546  
                }
1547  
                // Otherwise, append the Unicode replacement character since
1547  
                // Otherwise, append the Unicode replacement character since
1548  
                // the first code point is a valid leading surrogate
1548  
                // the first code point is a valid leading surrogate
1549  
                else
1549  
                else
1550  
                {
1550  
                {
1551  
                    temp.append_utf8(urc);
1551  
                    temp.append_utf8(urc);
1552  
                    break;
1552  
                    break;
1553  
                }
1553  
                }
1554  
            }
1554  
            }
1555  
            ++cs;
1555  
            ++cs;
1556  
    do_sur2:
1556  
    do_sur2:
1557  
            if(BOOST_JSON_UNLIKELY(! cs))
1557  
            if(BOOST_JSON_UNLIKELY(! cs))
1558  
                return maybe_suspend(cs.begin(), state::sur2);
1558  
                return maybe_suspend(cs.begin(), state::sur2);
1559  
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1559  
            if(BOOST_JSON_UNLIKELY(*cs != 'u'))
1560  
            {
1560  
            {
1561  
                if (!allow_bad_utf16)
1561  
                if (!allow_bad_utf16)
1562  
                {
1562  
                {
1563  
                    BOOST_STATIC_CONSTEXPR source_location loc
1563  
                    BOOST_STATIC_CONSTEXPR source_location loc
1564  
                        = BOOST_CURRENT_LOCATION;
1564  
                        = BOOST_CURRENT_LOCATION;
1565  
                    return fail(cs.begin(), error::syntax, &loc);
1565  
                    return fail(cs.begin(), error::syntax, &loc);
1566  
                }
1566  
                }
1567  
                // Otherwise, append the Unicode replacement character since
1567  
                // Otherwise, append the Unicode replacement character since
1568  
                // the first code point is a valid leading surrogate
1568  
                // the first code point is a valid leading surrogate
1569  
                else
1569  
                else
1570  
                {
1570  
                {
1571  
                    temp.append_utf8(urc);
1571  
                    temp.append_utf8(urc);
1572  
                    goto do_str3;
1572  
                    goto do_str3;
1573  
                }
1573  
                }
1574  
            }
1574  
            }
1575  
            ++cs;
1575  
            ++cs;
1576  
    do_sur3:
1576  
    do_sur3:
1577  
            if(BOOST_JSON_UNLIKELY(! cs))
1577  
            if(BOOST_JSON_UNLIKELY(! cs))
1578  
                return maybe_suspend(cs.begin(), state::sur3);
1578  
                return maybe_suspend(cs.begin(), state::sur3);
1579  
            digit = detail::hex_digit(*cs);
1579  
            digit = detail::hex_digit(*cs);
1580  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1580  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1581  
            {
1581  
            {
1582  
                BOOST_STATIC_CONSTEXPR source_location loc
1582  
                BOOST_STATIC_CONSTEXPR source_location loc
1583  
                    = BOOST_CURRENT_LOCATION;
1583  
                    = BOOST_CURRENT_LOCATION;
1584  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1584  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1585  
            }
1585  
            }
1586  
            ++cs;
1586  
            ++cs;
1587  
            u2_ = digit << 12;
1587  
            u2_ = digit << 12;
1588  
    do_sur4:
1588  
    do_sur4:
1589  
            if(BOOST_JSON_UNLIKELY(! cs))
1589  
            if(BOOST_JSON_UNLIKELY(! cs))
1590  
                return maybe_suspend(cs.begin(), state::sur4);
1590  
                return maybe_suspend(cs.begin(), state::sur4);
1591  
            digit = detail::hex_digit(*cs);
1591  
            digit = detail::hex_digit(*cs);
1592  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1592  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1593  
            {
1593  
            {
1594  
                BOOST_STATIC_CONSTEXPR source_location loc
1594  
                BOOST_STATIC_CONSTEXPR source_location loc
1595  
                    = BOOST_CURRENT_LOCATION;
1595  
                    = BOOST_CURRENT_LOCATION;
1596  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1596  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1597  
            }
1597  
            }
1598  
            ++cs;
1598  
            ++cs;
1599  
            u2_ += digit << 8;
1599  
            u2_ += digit << 8;
1600  
    do_sur5:
1600  
    do_sur5:
1601  
            if(BOOST_JSON_UNLIKELY(! cs))
1601  
            if(BOOST_JSON_UNLIKELY(! cs))
1602  
                return maybe_suspend(cs.begin(), state::sur5);
1602  
                return maybe_suspend(cs.begin(), state::sur5);
1603  
            digit = detail::hex_digit(*cs);
1603  
            digit = detail::hex_digit(*cs);
1604  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1604  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1605  
            {
1605  
            {
1606  
                BOOST_STATIC_CONSTEXPR source_location loc
1606  
                BOOST_STATIC_CONSTEXPR source_location loc
1607  
                    = BOOST_CURRENT_LOCATION;
1607  
                    = BOOST_CURRENT_LOCATION;
1608  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1608  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1609  
            }
1609  
            }
1610  
            ++cs;
1610  
            ++cs;
1611  
            u2_ += digit << 4;
1611  
            u2_ += digit << 4;
1612  
    do_sur6:
1612  
    do_sur6:
1613  
            if(BOOST_JSON_UNLIKELY(! cs))
1613  
            if(BOOST_JSON_UNLIKELY(! cs))
1614  
                return maybe_suspend(cs.begin(), state::sur6);
1614  
                return maybe_suspend(cs.begin(), state::sur6);
1615  
            digit = detail::hex_digit(*cs);
1615  
            digit = detail::hex_digit(*cs);
1616  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1616  
            if(BOOST_JSON_UNLIKELY(digit == -1))
1617  
            {
1617  
            {
1618  
                BOOST_STATIC_CONSTEXPR source_location loc
1618  
                BOOST_STATIC_CONSTEXPR source_location loc
1619  
                    = BOOST_CURRENT_LOCATION;
1619  
                    = BOOST_CURRENT_LOCATION;
1620  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1620  
                return fail(cs.begin(), error::expected_hex_digit, &loc);
1621  
            }
1621  
            }
1622  
            ++cs;
1622  
            ++cs;
1623  
            u2_ += digit;
1623  
            u2_ += digit;
1624  
            // Check if the second code point is a valid trailing surrogate.
1624  
            // Check if the second code point is a valid trailing surrogate.
1625  
            // Valid trailing surrogates are [DC00, DFFF]
1625  
            // Valid trailing surrogates are [DC00, DFFF]
1626  
            if(BOOST_JSON_UNLIKELY(
1626  
            if(BOOST_JSON_UNLIKELY(
1627  
                u2_ < 0xdc00 || u2_ > 0xdfff))
1627  
                u2_ < 0xdc00 || u2_ > 0xdfff))
1628  
            {
1628  
            {
1629  
                // If not valid and the parser does not allow it, return an error.
1629  
                // If not valid and the parser does not allow it, return an error.
1630  
                if(!allow_bad_utf16)
1630  
                if(!allow_bad_utf16)
1631  
                {
1631  
                {
1632  
                    BOOST_STATIC_CONSTEXPR source_location loc
1632  
                    BOOST_STATIC_CONSTEXPR source_location loc
1633  
                        = BOOST_CURRENT_LOCATION;
1633  
                        = BOOST_CURRENT_LOCATION;
1634  
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1634  
                    return fail(cs.begin(), error::illegal_trailing_surrogate, &loc);
1635  
                }
1635  
                }
1636  
                // Append the replacement character for the
1636  
                // Append the replacement character for the
1637  
                // first leading surrogate.
1637  
                // first leading surrogate.
1638  
                temp.append_utf8(urc);
1638  
                temp.append_utf8(urc);
1639  
                // Check if the second code point is a
1639  
                // Check if the second code point is a
1640  
                // valid unicode scalar value (invalid leading
1640  
                // valid unicode scalar value (invalid leading
1641  
                // or trailing surrogate)
1641  
                // or trailing surrogate)
1642  
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1642  
                if (u2_ < 0xd800 || u2_ > 0xdbff)
1643  
                {
1643  
                {
1644  
                    temp.append_utf8(u2_);
1644  
                    temp.append_utf8(u2_);
1645  
                    break;
1645  
                    break;
1646  
                }
1646  
                }
1647  
                // If it is a valid leading surrogate
1647  
                // If it is a valid leading surrogate
1648  
                else
1648  
                else
1649  
                {
1649  
                {
1650  
                    u1_ = u2_;
1650  
                    u1_ = u2_;
1651  
                    goto do_sur1;
1651  
                    goto do_sur1;
1652  
                }
1652  
                }
1653  
            }
1653  
            }
1654  
            // Calculate the Unicode code point from the surrogate pair and
1654  
            // Calculate the Unicode code point from the surrogate pair and
1655  
            // append the UTF-8 representation.
1655  
            // append the UTF-8 representation.
1656  
            unsigned cp =
1656  
            unsigned cp =
1657  
                ((u1_ - 0xd800) << 10) +
1657  
                ((u1_ - 0xd800) << 10) +
1658  
                ((u2_ - 0xdc00)) +
1658  
                ((u2_ - 0xdc00)) +
1659  
                    0x10000;
1659  
                    0x10000;
1660  
            // utf-16 surrogate pair
1660  
            // utf-16 surrogate pair
1661  
            temp.append_utf8(cp);
1661  
            temp.append_utf8(cp);
1662  
        }
1662  
        }
1663  

1663  

1664  
        // flush
1664  
        // flush
1665  
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1665  
        if(BOOST_JSON_UNLIKELY( !cs ) || *cs != '\\')
1666  
            break;
1666  
            break;
1667  
    }
1667  
    }
1668  

1668  

1669  
    if(BOOST_JSON_LIKELY( temp.size() ))
1669  
    if(BOOST_JSON_LIKELY( temp.size() ))
1670  
    {
1670  
    {
1671  
        BOOST_ASSERT(total <= max_size);
1671  
        BOOST_ASSERT(total <= max_size);
1672  
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1672  
        if(BOOST_JSON_UNLIKELY( temp.size() > max_size - total ))
1673  
        {
1673  
        {
1674  
            BOOST_STATIC_CONSTEXPR source_location loc
1674  
            BOOST_STATIC_CONSTEXPR source_location loc
1675  
                = BOOST_CURRENT_LOCATION;
1675  
                = BOOST_CURRENT_LOCATION;
1676  
            return fail(cs.begin(), ev_too_large, &loc);
1676  
            return fail(cs.begin(), ev_too_large, &loc);
1677  
        }
1677  
        }
1678  

1678  

1679  
        total += temp.size();
1679  
        total += temp.size();
1680  
        bool const r = is_key
1680  
        bool const r = is_key
1681  
            ? h_.on_key_part(temp.get(), total, ec_)
1681  
            ? h_.on_key_part(temp.get(), total, ec_)
1682  
            : h_.on_string_part(temp.get(), total, ec_);
1682  
            : h_.on_string_part(temp.get(), total, ec_);
1683  
        if(BOOST_JSON_UNLIKELY( !r ))
1683  
        if(BOOST_JSON_UNLIKELY( !r ))
1684  
            return fail( cs.begin() );
1684  
            return fail( cs.begin() );
1685  
    }
1685  
    }
1686  

1686  

1687  
    return cs.begin();
1687  
    return cs.begin();
1688  
}
1688  
}
1689  

1689  

1690  
//----------------------------------------------------------
1690  
//----------------------------------------------------------
1691  

1691  

1692  
template<class Handler>
1692  
template<class Handler>
1693  
template<
1693  
template<
1694  
    bool StackEmpty_,
1694  
    bool StackEmpty_,
1695  
    bool AllowComments_/*,
1695  
    bool AllowComments_/*,
1696  
    bool AllowTrailing_,
1696  
    bool AllowTrailing_,
1697  
    bool AllowBadUTF8_*/>
1697  
    bool AllowBadUTF8_*/>
1698  
const char*
1698  
const char*
1699  
basic_parser<Handler>::
1699  
basic_parser<Handler>::
1700  
parse_object(const char* p,
1700  
parse_object(const char* p,
1701  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1701  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1702  
    std::integral_constant<bool, AllowComments_> allow_comments,
1702  
    std::integral_constant<bool, AllowComments_> allow_comments,
1703  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1703  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1704  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1704  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1705  
    bool allow_bad_utf16)
1705  
    bool allow_bad_utf16)
1706  
{
1706  
{
1707  
    detail::const_stream_wrapper cs(p, end_);
1707  
    detail::const_stream_wrapper cs(p, end_);
1708  
    std::size_t size;
1708  
    std::size_t size;
1709  
    if(! stack_empty && ! st_.empty())
1709  
    if(! stack_empty && ! st_.empty())
1710  
    {
1710  
    {
1711  
        // resume
1711  
        // resume
1712  
        state st;
1712  
        state st;
1713  
        st_.pop(st);
1713  
        st_.pop(st);
1714  
        st_.pop(size);
1714  
        st_.pop(size);
1715  
        switch(st)
1715  
        switch(st)
1716  
        {
1716  
        {
1717  
        default: BOOST_JSON_UNREACHABLE();
1717  
        default: BOOST_JSON_UNREACHABLE();
1718  
        case state::obj1: goto do_obj1;
1718  
        case state::obj1: goto do_obj1;
1719  
        case state::obj2: goto do_obj2;
1719  
        case state::obj2: goto do_obj2;
1720  
        case state::obj3: goto do_obj3;
1720  
        case state::obj3: goto do_obj3;
1721  
        case state::obj4: goto do_obj4;
1721  
        case state::obj4: goto do_obj4;
1722  
        case state::obj5: goto do_obj5;
1722  
        case state::obj5: goto do_obj5;
1723  
        case state::obj6: goto do_obj6;
1723  
        case state::obj6: goto do_obj6;
1724  
        case state::obj7: goto do_obj7;
1724  
        case state::obj7: goto do_obj7;
1725  
        case state::obj8: goto do_obj8;
1725  
        case state::obj8: goto do_obj8;
1726  
        case state::obj9: goto do_obj9;
1726  
        case state::obj9: goto do_obj9;
1727  
        case state::obj10: goto do_obj10;
1727  
        case state::obj10: goto do_obj10;
1728  
        case state::obj11: goto do_obj11;
1728  
        case state::obj11: goto do_obj11;
1729  
        }
1729  
        }
1730  
    }
1730  
    }
1731  
    BOOST_ASSERT(*cs == '{');
1731  
    BOOST_ASSERT(*cs == '{');
1732  
    size = 0;
1732  
    size = 0;
1733  
    if(BOOST_JSON_UNLIKELY(! depth_))
1733  
    if(BOOST_JSON_UNLIKELY(! depth_))
1734  
    {
1734  
    {
1735  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1735  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1736  
        return fail(cs.begin(), error::too_deep, &loc);
1736  
        return fail(cs.begin(), error::too_deep, &loc);
1737  
    }
1737  
    }
1738  
    --depth_;
1738  
    --depth_;
1739  
    if(BOOST_JSON_UNLIKELY(
1739  
    if(BOOST_JSON_UNLIKELY(
1740  
        ! h_.on_object_begin(ec_)))
1740  
        ! h_.on_object_begin(ec_)))
1741  
        return fail(cs.begin());
1741  
        return fail(cs.begin());
1742  
    ++cs;
1742  
    ++cs;
1743  
    // object:
1743  
    // object:
1744  
    //     '{' *ws '}'
1744  
    //     '{' *ws '}'
1745  
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1745  
    //     '{' *ws string *ws ':' *ws value *ws *[ ',' *ws string *ws ':' *ws value *ws ] '}'
1746  
do_obj1:
1746  
do_obj1:
1747  
    cs = detail::count_whitespace(cs.begin(), cs.end());
1747  
    cs = detail::count_whitespace(cs.begin(), cs.end());
1748  
    if(BOOST_JSON_UNLIKELY(! cs))
1748  
    if(BOOST_JSON_UNLIKELY(! cs))
1749  
        return maybe_suspend(cs.begin(), state::obj1, size);
1749  
        return maybe_suspend(cs.begin(), state::obj1, size);
1750  
    if(BOOST_JSON_LIKELY(*cs != '}'))
1750  
    if(BOOST_JSON_LIKELY(*cs != '}'))
1751  
    {
1751  
    {
1752  
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1752  
        if(BOOST_JSON_UNLIKELY(*cs != '\x22'))
1753  
        {
1753  
        {
1754  
            if(allow_comments && *cs == '/')
1754  
            if(allow_comments && *cs == '/')
1755  
            {
1755  
            {
1756  
do_obj2:
1756  
do_obj2:
1757  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1757  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1758  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1758  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1759  
                    return suspend_or_fail(state::obj2, size);
1759  
                    return suspend_or_fail(state::obj2, size);
1760  
                goto do_obj1;
1760  
                goto do_obj1;
1761  
            }
1761  
            }
1762  
            BOOST_STATIC_CONSTEXPR source_location loc
1762  
            BOOST_STATIC_CONSTEXPR source_location loc
1763  
                = BOOST_CURRENT_LOCATION;
1763  
                = BOOST_CURRENT_LOCATION;
1764  
            return fail(cs.begin(), error::syntax, &loc);
1764  
            return fail(cs.begin(), error::syntax, &loc);
1765  
        }
1765  
        }
1766  
loop:
1766  
loop:
1767  
        if(BOOST_JSON_UNLIKELY(++size >
1767  
        if(BOOST_JSON_UNLIKELY(++size >
1768  
            Handler::max_object_size))
1768  
            Handler::max_object_size))
1769  
        {
1769  
        {
1770  
            BOOST_STATIC_CONSTEXPR source_location loc
1770  
            BOOST_STATIC_CONSTEXPR source_location loc
1771  
                = BOOST_CURRENT_LOCATION;
1771  
                = BOOST_CURRENT_LOCATION;
1772  
            return fail(cs.begin(), error::object_too_large, &loc);
1772  
            return fail(cs.begin(), error::object_too_large, &loc);
1773  
        }
1773  
        }
1774  
do_obj3:
1774  
do_obj3:
1775  
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1775  
        cs = parse_string(cs.begin(), stack_empty, std::true_type(), allow_bad_utf8, allow_bad_utf16);
1776  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1776  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1777  
            return suspend_or_fail(state::obj3, size);
1777  
            return suspend_or_fail(state::obj3, size);
1778  
do_obj4:
1778  
do_obj4:
1779  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1779  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1780  
        if(BOOST_JSON_UNLIKELY(! cs))
1780  
        if(BOOST_JSON_UNLIKELY(! cs))
1781  
            return maybe_suspend(cs.begin(), state::obj4, size);
1781  
            return maybe_suspend(cs.begin(), state::obj4, size);
1782  
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1782  
        if(BOOST_JSON_UNLIKELY(*cs != ':'))
1783  
        {
1783  
        {
1784  
            if(allow_comments && *cs == '/')
1784  
            if(allow_comments && *cs == '/')
1785  
            {
1785  
            {
1786  
do_obj5:
1786  
do_obj5:
1787  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1787  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1788  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1788  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1789  
                    return suspend_or_fail(state::obj5, size);
1789  
                    return suspend_or_fail(state::obj5, size);
1790  
                goto do_obj4;
1790  
                goto do_obj4;
1791  
            }
1791  
            }
1792  
            BOOST_STATIC_CONSTEXPR source_location loc
1792  
            BOOST_STATIC_CONSTEXPR source_location loc
1793  
                = BOOST_CURRENT_LOCATION;
1793  
                = BOOST_CURRENT_LOCATION;
1794  
            return fail(cs.begin(), error::syntax, &loc);
1794  
            return fail(cs.begin(), error::syntax, &loc);
1795  
        }
1795  
        }
1796  
        ++cs;
1796  
        ++cs;
1797  
do_obj6:
1797  
do_obj6:
1798  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1798  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1799  
        if(BOOST_JSON_UNLIKELY(! cs))
1799  
        if(BOOST_JSON_UNLIKELY(! cs))
1800  
            return maybe_suspend(cs.begin(), state::obj6, size);
1800  
            return maybe_suspend(cs.begin(), state::obj6, size);
1801  
do_obj7:
1801  
do_obj7:
1802  
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1802  
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1803  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1803  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1804  
            return suspend_or_fail(state::obj7, size);
1804  
            return suspend_or_fail(state::obj7, size);
1805  
do_obj8:
1805  
do_obj8:
1806  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1806  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1807  
        if(BOOST_JSON_UNLIKELY(! cs))
1807  
        if(BOOST_JSON_UNLIKELY(! cs))
1808  
            return maybe_suspend(cs.begin(), state::obj8, size);
1808  
            return maybe_suspend(cs.begin(), state::obj8, size);
1809  
        if(BOOST_JSON_LIKELY(*cs == ','))
1809  
        if(BOOST_JSON_LIKELY(*cs == ','))
1810  
        {
1810  
        {
1811  
            ++cs;
1811  
            ++cs;
1812  
do_obj9:
1812  
do_obj9:
1813  
            cs = detail::count_whitespace(cs.begin(), cs.end());
1813  
            cs = detail::count_whitespace(cs.begin(), cs.end());
1814  
            if(BOOST_JSON_UNLIKELY(! cs))
1814  
            if(BOOST_JSON_UNLIKELY(! cs))
1815  
                return maybe_suspend(cs.begin(), state::obj9, size);
1815  
                return maybe_suspend(cs.begin(), state::obj9, size);
1816  

1816  

1817  
            // loop for next element
1817  
            // loop for next element
1818  
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1818  
            if(BOOST_JSON_LIKELY(*cs == '\x22'))
1819  
                goto loop;
1819  
                goto loop;
1820  
            if(! allow_trailing || *cs != '}')
1820  
            if(! allow_trailing || *cs != '}')
1821  
            {
1821  
            {
1822  
                if(allow_comments && *cs == '/')
1822  
                if(allow_comments && *cs == '/')
1823  
                {
1823  
                {
1824  
do_obj10:
1824  
do_obj10:
1825  
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1825  
                    cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1826  
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1826  
                    if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1827  
                        return suspend_or_fail(state::obj10, size);
1827  
                        return suspend_or_fail(state::obj10, size);
1828  
                    goto do_obj9;
1828  
                    goto do_obj9;
1829  
                }
1829  
                }
1830  
                BOOST_STATIC_CONSTEXPR source_location loc
1830  
                BOOST_STATIC_CONSTEXPR source_location loc
1831  
                    = BOOST_CURRENT_LOCATION;
1831  
                    = BOOST_CURRENT_LOCATION;
1832  
                return fail(cs.begin(), error::syntax, &loc);
1832  
                return fail(cs.begin(), error::syntax, &loc);
1833  
            }
1833  
            }
1834  
        }
1834  
        }
1835  
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1835  
        else if(BOOST_JSON_UNLIKELY(*cs != '}'))
1836  
        {
1836  
        {
1837  
            if(allow_comments && *cs == '/')
1837  
            if(allow_comments && *cs == '/')
1838  
            {
1838  
            {
1839  
do_obj11:
1839  
do_obj11:
1840  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1840  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1841  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1841  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1842  
                    return suspend_or_fail(state::obj11, size);
1842  
                    return suspend_or_fail(state::obj11, size);
1843  
                goto do_obj8;
1843  
                goto do_obj8;
1844  
            }
1844  
            }
1845  
            BOOST_STATIC_CONSTEXPR source_location loc
1845  
            BOOST_STATIC_CONSTEXPR source_location loc
1846  
                = BOOST_CURRENT_LOCATION;
1846  
                = BOOST_CURRENT_LOCATION;
1847  
            return fail(cs.begin(), error::syntax, &loc);
1847  
            return fail(cs.begin(), error::syntax, &loc);
1848  
        }
1848  
        }
1849  
        // got closing brace, fall through
1849  
        // got closing brace, fall through
1850  
    }
1850  
    }
1851  
    if(BOOST_JSON_UNLIKELY(
1851  
    if(BOOST_JSON_UNLIKELY(
1852  
        ! h_.on_object_end(size, ec_)))
1852  
        ! h_.on_object_end(size, ec_)))
1853  
        return fail(cs.begin());
1853  
        return fail(cs.begin());
1854  
    ++depth_;
1854  
    ++depth_;
1855  
    ++cs;
1855  
    ++cs;
1856  
    return cs.begin();
1856  
    return cs.begin();
1857  
}
1857  
}
1858  

1858  

1859  
//----------------------------------------------------------
1859  
//----------------------------------------------------------
1860  

1860  

1861  
template<class Handler>
1861  
template<class Handler>
1862  
template<
1862  
template<
1863  
    bool StackEmpty_,
1863  
    bool StackEmpty_,
1864  
    bool AllowComments_/*,
1864  
    bool AllowComments_/*,
1865  
    bool AllowTrailing_,
1865  
    bool AllowTrailing_,
1866  
    bool AllowBadUTF8_*/>
1866  
    bool AllowBadUTF8_*/>
1867  
const char*
1867  
const char*
1868  
basic_parser<Handler>::
1868  
basic_parser<Handler>::
1869  
parse_array(const char* p,
1869  
parse_array(const char* p,
1870  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1870  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1871  
    std::integral_constant<bool, AllowComments_> allow_comments,
1871  
    std::integral_constant<bool, AllowComments_> allow_comments,
1872  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1872  
    /*std::integral_constant<bool, AllowTrailing_>*/ bool allow_trailing,
1873  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1873  
    /*std::integral_constant<bool, AllowBadUTF8_>*/ bool allow_bad_utf8,
1874  
    bool allow_bad_utf16)
1874  
    bool allow_bad_utf16)
1875  
{
1875  
{
1876  
    detail::const_stream_wrapper cs(p, end_);
1876  
    detail::const_stream_wrapper cs(p, end_);
1877  
    std::size_t size;
1877  
    std::size_t size;
1878  
    if(! stack_empty && ! st_.empty())
1878  
    if(! stack_empty && ! st_.empty())
1879  
    {
1879  
    {
1880  
        // resume
1880  
        // resume
1881  
        state st;
1881  
        state st;
1882  
        st_.pop(st);
1882  
        st_.pop(st);
1883  
        st_.pop(size);
1883  
        st_.pop(size);
1884  
        switch(st)
1884  
        switch(st)
1885  
        {
1885  
        {
1886  
        default: BOOST_JSON_UNREACHABLE();
1886  
        default: BOOST_JSON_UNREACHABLE();
1887  
        case state::arr1: goto do_arr1;
1887  
        case state::arr1: goto do_arr1;
1888  
        case state::arr2: goto do_arr2;
1888  
        case state::arr2: goto do_arr2;
1889  
        case state::arr3: goto do_arr3;
1889  
        case state::arr3: goto do_arr3;
1890  
        case state::arr4: goto do_arr4;
1890  
        case state::arr4: goto do_arr4;
1891  
        case state::arr5: goto do_arr5;
1891  
        case state::arr5: goto do_arr5;
1892  
        case state::arr6: goto do_arr6;
1892  
        case state::arr6: goto do_arr6;
1893  
        }
1893  
        }
1894  
    }
1894  
    }
1895  
    BOOST_ASSERT(*cs == '[');
1895  
    BOOST_ASSERT(*cs == '[');
1896  
    size = 0;
1896  
    size = 0;
1897  
    if(BOOST_JSON_UNLIKELY(! depth_))
1897  
    if(BOOST_JSON_UNLIKELY(! depth_))
1898  
    {
1898  
    {
1899  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1899  
        BOOST_STATIC_CONSTEXPR source_location loc = BOOST_CURRENT_LOCATION;
1900  
        return fail(cs.begin(), error::too_deep, &loc);
1900  
        return fail(cs.begin(), error::too_deep, &loc);
1901  
    }
1901  
    }
1902  
    --depth_;
1902  
    --depth_;
1903  
    if(BOOST_JSON_UNLIKELY(
1903  
    if(BOOST_JSON_UNLIKELY(
1904  
        ! h_.on_array_begin(ec_)))
1904  
        ! h_.on_array_begin(ec_)))
1905  
        return fail(cs.begin());
1905  
        return fail(cs.begin());
1906  
    ++cs;
1906  
    ++cs;
1907  
    // array:
1907  
    // array:
1908  
    //     '[' *ws ']'
1908  
    //     '[' *ws ']'
1909  
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1909  
    //     '[' *ws value *ws *[ ',' *ws value *ws ] ']'
1910  
do_arr1:
1910  
do_arr1:
1911  
    cs = detail::count_whitespace(cs.begin(), cs.end());
1911  
    cs = detail::count_whitespace(cs.begin(), cs.end());
1912  
    if(BOOST_JSON_UNLIKELY(! cs))
1912  
    if(BOOST_JSON_UNLIKELY(! cs))
1913  
        return maybe_suspend(cs.begin(), state::arr1, size);
1913  
        return maybe_suspend(cs.begin(), state::arr1, size);
1914  
    if(BOOST_JSON_LIKELY(*cs != ']'))
1914  
    if(BOOST_JSON_LIKELY(*cs != ']'))
1915  
    {
1915  
    {
1916  
loop:
1916  
loop:
1917  
        if(allow_comments && *cs == '/')
1917  
        if(allow_comments && *cs == '/')
1918  
        {
1918  
        {
1919  
do_arr2:
1919  
do_arr2:
1920  
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1920  
            cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1921  
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1921  
            if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1922  
                return suspend_or_fail(state::arr2, size);
1922  
                return suspend_or_fail(state::arr2, size);
1923  
            goto do_arr1;
1923  
            goto do_arr1;
1924  
        }
1924  
        }
1925  
        if(BOOST_JSON_UNLIKELY(++size >
1925  
        if(BOOST_JSON_UNLIKELY(++size >
1926  
            Handler::max_array_size))
1926  
            Handler::max_array_size))
1927  
        {
1927  
        {
1928  
            BOOST_STATIC_CONSTEXPR source_location loc
1928  
            BOOST_STATIC_CONSTEXPR source_location loc
1929  
                = BOOST_CURRENT_LOCATION;
1929  
                = BOOST_CURRENT_LOCATION;
1930  
            return fail(cs.begin(), error::array_too_large, &loc);
1930  
            return fail(cs.begin(), error::array_too_large, &loc);
1931  
        }
1931  
        }
1932  
do_arr3:
1932  
do_arr3:
1933  
        // array is not empty, value required
1933  
        // array is not empty, value required
1934  
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1934  
        cs = parse_value(cs.begin(), stack_empty, allow_comments, allow_trailing, allow_bad_utf8, allow_bad_utf16);
1935  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1935  
        if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1936  
            return suspend_or_fail(state::arr3, size);
1936  
            return suspend_or_fail(state::arr3, size);
1937  
do_arr4:
1937  
do_arr4:
1938  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1938  
        cs = detail::count_whitespace(cs.begin(), cs.end());
1939  
        if(BOOST_JSON_UNLIKELY(! cs))
1939  
        if(BOOST_JSON_UNLIKELY(! cs))
1940  
            return maybe_suspend(cs.begin(), state::arr4, size);
1940  
            return maybe_suspend(cs.begin(), state::arr4, size);
1941  
        if(BOOST_JSON_LIKELY(*cs == ','))
1941  
        if(BOOST_JSON_LIKELY(*cs == ','))
1942  
        {
1942  
        {
1943  
            ++cs;
1943  
            ++cs;
1944  
do_arr5:
1944  
do_arr5:
1945  
            cs = detail::count_whitespace(cs.begin(), cs.end());
1945  
            cs = detail::count_whitespace(cs.begin(), cs.end());
1946  
            if(BOOST_JSON_UNLIKELY(! cs))
1946  
            if(BOOST_JSON_UNLIKELY(! cs))
1947  
                return maybe_suspend(cs.begin(), state::arr5, size);
1947  
                return maybe_suspend(cs.begin(), state::arr5, size);
1948  
            // loop for next element
1948  
            // loop for next element
1949  
            if(! allow_trailing || *cs != ']')
1949  
            if(! allow_trailing || *cs != ']')
1950  
                goto loop;
1950  
                goto loop;
1951  
        }
1951  
        }
1952  
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1952  
        else if(BOOST_JSON_UNLIKELY(*cs != ']'))
1953  
        {
1953  
        {
1954  
            if(allow_comments && *cs == '/')
1954  
            if(allow_comments && *cs == '/')
1955  
            {
1955  
            {
1956  
do_arr6:
1956  
do_arr6:
1957  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1957  
                cs = parse_comment(cs.begin(), stack_empty, std::false_type());
1958  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1958  
                if(BOOST_JSON_UNLIKELY(incomplete(cs)))
1959  
                    return suspend_or_fail(state::arr6, size);
1959  
                    return suspend_or_fail(state::arr6, size);
1960  
                goto do_arr4;
1960  
                goto do_arr4;
1961  
            }
1961  
            }
1962  
            BOOST_STATIC_CONSTEXPR source_location loc
1962  
            BOOST_STATIC_CONSTEXPR source_location loc
1963  
                = BOOST_CURRENT_LOCATION;
1963  
                = BOOST_CURRENT_LOCATION;
1964  
            return fail(cs.begin(), error::syntax, &loc);
1964  
            return fail(cs.begin(), error::syntax, &loc);
1965  
        }
1965  
        }
1966  
        // got closing bracket; fall through
1966  
        // got closing bracket; fall through
1967  
    }
1967  
    }
1968  
    if(BOOST_JSON_UNLIKELY(
1968  
    if(BOOST_JSON_UNLIKELY(
1969  
        ! h_.on_array_end(size, ec_)))
1969  
        ! h_.on_array_end(size, ec_)))
1970  
        return fail(cs.begin());
1970  
        return fail(cs.begin());
1971  
    ++depth_;
1971  
    ++depth_;
1972  
    ++cs;
1972  
    ++cs;
1973  
    return cs.begin();
1973  
    return cs.begin();
1974  
}
1974  
}
1975  

1975  

1976  
//----------------------------------------------------------
1976  
//----------------------------------------------------------
1977  

1977  

1978  
template<class Handler>
1978  
template<class Handler>
1979  
template<bool StackEmpty_, char First_, number_precision Numbers_>
1979  
template<bool StackEmpty_, char First_, number_precision Numbers_>
1980  
const char*
1980  
const char*
1981  
basic_parser<Handler>::
1981  
basic_parser<Handler>::
1982  
parse_number(const char* p,
1982  
parse_number(const char* p,
1983  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1983  
    std::integral_constant<bool, StackEmpty_> stack_empty,
1984  
    std::integral_constant<char, First_> first,
1984  
    std::integral_constant<char, First_> first,
1985  
    std::integral_constant<number_precision, Numbers_> mode)
1985  
    std::integral_constant<number_precision, Numbers_> mode)
1986  
{
1986  
{
1987  
    constexpr bool precise_parsing = mode == number_precision::precise;
1987  
    constexpr bool precise_parsing = mode == number_precision::precise;
1988  
    constexpr bool no_parsing = mode == number_precision::none;
1988  
    constexpr bool no_parsing = mode == number_precision::none;
1989  

1989  

1990  
    // only one of these will be true if we are not resuming
1990  
    // only one of these will be true if we are not resuming
1991  
    // if negative then !zero_first && !nonzero_first
1991  
    // if negative then !zero_first && !nonzero_first
1992  
    // if zero_first then !nonzero_first && !negative
1992  
    // if zero_first then !nonzero_first && !negative
1993  
    // if nonzero_first then !zero_first && !negative
1993  
    // if nonzero_first then !zero_first && !negative
1994  
    bool const negative = first == '-';
1994  
    bool const negative = first == '-';
1995  
    bool const zero_first = first == '0';
1995  
    bool const zero_first = first == '0';
1996  
    bool const nonzero_first = first == '+';
1996  
    bool const nonzero_first = first == '+';
1997  
    detail::const_stream_wrapper cs(p, end_);
1997  
    detail::const_stream_wrapper cs(p, end_);
1998  
    number num;
1998  
    number num;
1999  
    const char* begin = cs.begin();
1999  
    const char* begin = cs.begin();
2000  
    if(stack_empty || st_.empty())
2000  
    if(stack_empty || st_.empty())
2001  
    {
2001  
    {
2002  
        num.bias = 0;
2002  
        num.bias = 0;
2003  
        num.exp = 0;
2003  
        num.exp = 0;
2004  
        num.frac = false;
2004  
        num.frac = false;
2005  
        num_buf_.clear();
2005  
        num_buf_.clear();
2006  

2006  

2007  
        //----------------------------------
2007  
        //----------------------------------
2008  
        //
2008  
        //
2009  
        // '-'
2009  
        // '-'
2010  
        // leading minus sign
2010  
        // leading minus sign
2011  
        //
2011  
        //
2012  
        BOOST_ASSERT(cs);
2012  
        BOOST_ASSERT(cs);
2013  
        if(negative)
2013  
        if(negative)
2014  
            ++cs;
2014  
            ++cs;
2015  

2015  

2016  
        num.neg = negative;
2016  
        num.neg = negative;
2017  
        num.frac = false;
2017  
        num.frac = false;
2018  
        num.exp = 0;
2018  
        num.exp = 0;
2019  
        num.bias = 0;
2019  
        num.bias = 0;
2020  

2020  

2021  
        // fast path
2021  
        // fast path
2022  
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2022  
        if( cs.remain() >= 16 + 1 + 16 ) // digits . digits
2023  
        {
2023  
        {
2024  
            int n1;
2024  
            int n1;
2025  

2025  

2026  
            if( nonzero_first ||
2026  
            if( nonzero_first ||
2027  
                (negative && *cs != '0') )
2027  
                (negative && *cs != '0') )
2028  
            {
2028  
            {
2029  
                n1 = detail::count_digits( cs.begin() );
2029  
                n1 = detail::count_digits( cs.begin() );
2030  
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2030  
                BOOST_ASSERT(n1 >= 0 && n1 <= 16);
2031  

2031  

2032  
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2032  
                if( negative && n1 == 0 && opt_.allow_infinity_and_nan )
2033  
                {
2033  
                {
2034  
                    return parse_literal(
2034  
                    return parse_literal(
2035  
                        p - 1,
2035  
                        p - 1,
2036  
                        detail::literals_c<detail::literals::neg_infinity>());
2036  
                        detail::literals_c<detail::literals::neg_infinity>());
2037  
                }
2037  
                }
2038  

2038  

2039  
                if( ! nonzero_first && n1 == 0 )
2039  
                if( ! nonzero_first && n1 == 0 )
2040  
                {
2040  
                {
2041  
                    // digit required
2041  
                    // digit required
2042  
                    BOOST_STATIC_CONSTEXPR source_location loc
2042  
                    BOOST_STATIC_CONSTEXPR source_location loc
2043  
                        = BOOST_CURRENT_LOCATION;
2043  
                        = BOOST_CURRENT_LOCATION;
2044  
                    return fail(cs.begin(), error::syntax, &loc);
2044  
                    return fail(cs.begin(), error::syntax, &loc);
2045  
                }
2045  
                }
2046  

2046  

2047  
                BOOST_IF_CONSTEXPR( !no_parsing )
2047  
                BOOST_IF_CONSTEXPR( !no_parsing )
2048  
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2048  
                    num.mant = detail::parse_unsigned( 0, cs.begin(), n1 );
2049  
                else
2049  
                else
2050  
                    num.mant = 0;
2050  
                    num.mant = 0;
2051  

2051  

2052  
                cs += n1;
2052  
                cs += n1;
2053  

2053  

2054  
                // integer or floating-point with
2054  
                // integer or floating-point with
2055  
                // >= 16 leading digits
2055  
                // >= 16 leading digits
2056  
                if( n1 == 16 )
2056  
                if( n1 == 16 )
2057  
                {
2057  
                {
2058  
                    goto do_num2;
2058  
                    goto do_num2;
2059  
                }
2059  
                }
2060  
            }
2060  
            }
2061  
            else
2061  
            else
2062  
            {
2062  
            {
2063  
                // 0. floating-point or 0e integer
2063  
                // 0. floating-point or 0e integer
2064  
                num.mant = 0;
2064  
                num.mant = 0;
2065  
                n1 = 0;
2065  
                n1 = 0;
2066  
                ++cs;
2066  
                ++cs;
2067  
            }
2067  
            }
2068  

2068  

2069  
            {
2069  
            {
2070  
                const char c = *cs;
2070  
                const char c = *cs;
2071  
                if(c != '.')
2071  
                if(c != '.')
2072  
                {
2072  
                {
2073  
                    if((c | 32) == 'e')
2073  
                    if((c | 32) == 'e')
2074  
                    {
2074  
                    {
2075  
                        ++cs;
2075  
                        ++cs;
2076  
                        goto do_exp1;
2076  
                        goto do_exp1;
2077  
                    }
2077  
                    }
2078  
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2078  
                    BOOST_IF_CONSTEXPR( negative && !no_parsing )
2079  
                        num.mant = ~num.mant + 1;
2079  
                        num.mant = ~num.mant + 1;
2080  
                    goto finish_signed;
2080  
                    goto finish_signed;
2081  
                }
2081  
                }
2082  
            }
2082  
            }
2083  

2083  

2084  
            // floating-point number
2084  
            // floating-point number
2085  

2085  

2086  
            ++cs;
2086  
            ++cs;
2087  

2087  

2088  
            int n2 = detail::count_digits( cs.begin() );
2088  
            int n2 = detail::count_digits( cs.begin() );
2089  
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2089  
            BOOST_ASSERT(n2 >= 0 && n2 <= 16);
2090  

2090  

2091  
            if( n2 == 0 )
2091  
            if( n2 == 0 )
2092  
            {
2092  
            {
2093  
                // digit required
2093  
                // digit required
2094  
                BOOST_STATIC_CONSTEXPR source_location loc
2094  
                BOOST_STATIC_CONSTEXPR source_location loc
2095  
                    = BOOST_CURRENT_LOCATION;
2095  
                    = BOOST_CURRENT_LOCATION;
2096  
                return fail(cs.begin(), error::syntax, &loc);
2096  
                return fail(cs.begin(), error::syntax, &loc);
2097  
            }
2097  
            }
2098  

2098  

2099  
            // floating-point mantissa overflow
2099  
            // floating-point mantissa overflow
2100  
            if( n1 + n2 >= 19 )
2100  
            if( n1 + n2 >= 19 )
2101  
            {
2101  
            {
2102  
                goto do_num7;
2102  
                goto do_num7;
2103  
            }
2103  
            }
2104  

2104  

2105  
            BOOST_IF_CONSTEXPR( !no_parsing )
2105  
            BOOST_IF_CONSTEXPR( !no_parsing )
2106  
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2106  
                num.mant = detail::parse_unsigned( num.mant, cs.begin(), n2 );
2107  

2107  

2108  
            BOOST_ASSERT(num.bias == 0);
2108  
            BOOST_ASSERT(num.bias == 0);
2109  

2109  

2110  
            num.bias -= n2;
2110  
            num.bias -= n2;
2111  

2111  

2112  
            cs += n2;
2112  
            cs += n2;
2113  

2113  

2114  
            char ch = *cs;
2114  
            char ch = *cs;
2115  

2115  

2116  
            if( (ch | 32) == 'e' )
2116  
            if( (ch | 32) == 'e' )
2117  
            {
2117  
            {
2118  
                ++cs;
2118  
                ++cs;
2119  
                goto do_exp1;
2119  
                goto do_exp1;
2120  
            }
2120  
            }
2121  
            else if( ch >= '0' && ch <= '9' )
2121  
            else if( ch >= '0' && ch <= '9' )
2122  
            {
2122  
            {
2123  
                goto do_num8;
2123  
                goto do_num8;
2124  
            }
2124  
            }
2125  

2125  

2126  
            goto finish_dub;
2126  
            goto finish_dub;
2127  
        }
2127  
        }
2128  
    }
2128  
    }
2129  
    else
2129  
    else
2130  
    {
2130  
    {
2131  
        num = num_;
2131  
        num = num_;
2132  
        state st;
2132  
        state st;
2133  
        st_.pop(st);
2133  
        st_.pop(st);
2134  
        switch(st)
2134  
        switch(st)
2135  
        {
2135  
        {
2136  
        default: BOOST_JSON_UNREACHABLE();
2136  
        default: BOOST_JSON_UNREACHABLE();
2137  
        case state::num1: goto do_num1;
2137  
        case state::num1: goto do_num1;
2138  
        case state::num2: goto do_num2;
2138  
        case state::num2: goto do_num2;
2139  
        case state::num3: goto do_num3;
2139  
        case state::num3: goto do_num3;
2140  
        case state::num4: goto do_num4;
2140  
        case state::num4: goto do_num4;
2141  
        case state::num5: goto do_num5;
2141  
        case state::num5: goto do_num5;
2142  
        case state::num6: goto do_num6;
2142  
        case state::num6: goto do_num6;
2143  
        case state::num7: goto do_num7;
2143  
        case state::num7: goto do_num7;
2144  
        case state::num8: goto do_num8;
2144  
        case state::num8: goto do_num8;
2145  
        case state::exp1: goto do_exp1;
2145  
        case state::exp1: goto do_exp1;
2146  
        case state::exp2: goto do_exp2;
2146  
        case state::exp2: goto do_exp2;
2147  
        case state::exp3: goto do_exp3;
2147  
        case state::exp3: goto do_exp3;
2148  
        }
2148  
        }
2149  
    }
2149  
    }
2150  

2150  

2151  
    //----------------------------------
2151  
    //----------------------------------
2152  
    //
2152  
    //
2153  
    // DIGIT
2153  
    // DIGIT
2154  
    // first digit
2154  
    // first digit
2155  
    //
2155  
    //
2156  
do_num1:
2156  
do_num1:
2157  
    if(zero_first || nonzero_first ||
2157  
    if(zero_first || nonzero_first ||
2158  
        BOOST_JSON_LIKELY(cs))
2158  
        BOOST_JSON_LIKELY(cs))
2159  
    {
2159  
    {
2160  
        char const c = *cs;
2160  
        char const c = *cs;
2161  
        if(zero_first)
2161  
        if(zero_first)
2162  
        {
2162  
        {
2163  
            ++cs;
2163  
            ++cs;
2164  
            num.mant = 0;
2164  
            num.mant = 0;
2165  
            goto do_num6;
2165  
            goto do_num6;
2166  
        }
2166  
        }
2167  
        else if(nonzero_first || BOOST_JSON_LIKELY(
2167  
        else if(nonzero_first || BOOST_JSON_LIKELY(
2168  
            c >= '1' && c <= '9'))
2168  
            c >= '1' && c <= '9'))
2169  
        {
2169  
        {
2170  
            ++cs;
2170  
            ++cs;
2171  
            num.mant = c - '0';
2171  
            num.mant = c - '0';
2172  
        }
2172  
        }
2173  
        else if(BOOST_JSON_UNLIKELY(
2173  
        else if(BOOST_JSON_UNLIKELY(
2174  
            c == '0'))
2174  
            c == '0'))
2175  
        {
2175  
        {
2176  
            ++cs;
2176  
            ++cs;
2177  
            num.mant = 0;
2177  
            num.mant = 0;
2178  
            goto do_num6;
2178  
            goto do_num6;
2179  
        }
2179  
        }
2180  
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2180  
        else if( (negative || num.neg) && opt_.allow_infinity_and_nan )
2181  
        {
2181  
        {
2182  
            st_.push(state::lit1);
2182  
            st_.push(state::lit1);
2183  
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2183  
            cur_lit_ = literal_index(detail::literals::neg_infinity);
2184  
            lit_offset_ = 1;
2184  
            lit_offset_ = 1;
2185  
            return parse_literal(
2185  
            return parse_literal(
2186  
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2186  
                cs.begin(), detail::literals_c<detail::literals::resume>() );
2187  
        }
2187  
        }
2188  
        else
2188  
        else
2189  
        {
2189  
        {
2190  
            BOOST_STATIC_CONSTEXPR source_location loc
2190  
            BOOST_STATIC_CONSTEXPR source_location loc
2191  
                = BOOST_CURRENT_LOCATION;
2191  
                = BOOST_CURRENT_LOCATION;
2192  
            return fail(cs.begin(), error::syntax, &loc);
2192  
            return fail(cs.begin(), error::syntax, &loc);
2193  
        }
2193  
        }
2194  
    }
2194  
    }
2195  
    else
2195  
    else
2196  
    {
2196  
    {
2197  
        if(BOOST_JSON_UNLIKELY(
2197  
        if(BOOST_JSON_UNLIKELY(
2198  
            ! h_.on_number_part(
2198  
            ! h_.on_number_part(
2199  
                {begin, cs.used(begin)}, ec_)))
2199  
                {begin, cs.used(begin)}, ec_)))
2200  
            return fail(cs.begin());
2200  
            return fail(cs.begin());
2201  

2201  

2202  
        BOOST_IF_CONSTEXPR( precise_parsing )
2202  
        BOOST_IF_CONSTEXPR( precise_parsing )
2203  
            num_buf_.append( begin, cs.used(begin) );
2203  
            num_buf_.append( begin, cs.used(begin) );
2204  
        return maybe_suspend(
2204  
        return maybe_suspend(
2205  
            cs.begin(), state::num1, num);
2205  
            cs.begin(), state::num1, num);
2206  
    }
2206  
    }
2207  

2207  

2208  
    //----------------------------------
2208  
    //----------------------------------
2209  
    //
2209  
    //
2210  
    // 1*DIGIT
2210  
    // 1*DIGIT
2211  
    // significant digits left of decimal
2211  
    // significant digits left of decimal
2212  
    //
2212  
    //
2213  
do_num2:
2213  
do_num2:
2214  
    if(negative || (!stack_empty && num.neg))
2214  
    if(negative || (!stack_empty && num.neg))
2215  
    {
2215  
    {
2216  
        for(;;)
2216  
        for(;;)
2217  
        {
2217  
        {
2218  
            if(BOOST_JSON_UNLIKELY(! cs))
2218  
            if(BOOST_JSON_UNLIKELY(! cs))
2219  
            {
2219  
            {
2220  
                if(BOOST_JSON_UNLIKELY(more_))
2220  
                if(BOOST_JSON_UNLIKELY(more_))
2221  
                {
2221  
                {
2222  
                    if(BOOST_JSON_UNLIKELY(
2222  
                    if(BOOST_JSON_UNLIKELY(
2223  
                        ! h_.on_number_part(
2223  
                        ! h_.on_number_part(
2224  
                            {begin, cs.used(begin)}, ec_)))
2224  
                            {begin, cs.used(begin)}, ec_)))
2225  
                        return fail(cs.begin());
2225  
                        return fail(cs.begin());
2226  

2226  

2227  
                    BOOST_IF_CONSTEXPR( precise_parsing )
2227  
                    BOOST_IF_CONSTEXPR( precise_parsing )
2228  
                        num_buf_.append( begin, cs.used(begin) );
2228  
                        num_buf_.append( begin, cs.used(begin) );
2229  
                    return suspend(cs.begin(), state::num2, num);
2229  
                    return suspend(cs.begin(), state::num2, num);
2230  
                }
2230  
                }
2231  
                goto finish_int;
2231  
                goto finish_int;
2232  
            }
2232  
            }
2233  
            char const c = *cs;
2233  
            char const c = *cs;
2234  
            if(BOOST_JSON_LIKELY(
2234  
            if(BOOST_JSON_LIKELY(
2235  
                c >= '0' && c <= '9'))
2235  
                c >= '0' && c <= '9'))
2236  
            {
2236  
            {
2237  
                ++cs;
2237  
                ++cs;
2238  
                //              9223372036854775808 INT64_MIN
2238  
                //              9223372036854775808 INT64_MIN
2239  
                if( num.mant  > 922337203685477580 || (
2239  
                if( num.mant  > 922337203685477580 || (
2240  
                    num.mant == 922337203685477580 && c > '8'))
2240  
                    num.mant == 922337203685477580 && c > '8'))
2241  
                    break;
2241  
                    break;
2242  
                BOOST_IF_CONSTEXPR( !no_parsing )
2242  
                BOOST_IF_CONSTEXPR( !no_parsing )
2243  
                    num.mant = 10 * num.mant + ( c - '0' );
2243  
                    num.mant = 10 * num.mant + ( c - '0' );
2244  
                continue;
2244  
                continue;
2245  
            }
2245  
            }
2246  
            goto do_num6; // [.eE]
2246  
            goto do_num6; // [.eE]
2247  
        }
2247  
        }
2248  
    }
2248  
    }
2249  
    else
2249  
    else
2250  
    {
2250  
    {
2251  
        for(;;)
2251  
        for(;;)
2252  
        {
2252  
        {
2253  
            if(BOOST_JSON_UNLIKELY(! cs))
2253  
            if(BOOST_JSON_UNLIKELY(! cs))
2254  
            {
2254  
            {
2255  
                if(BOOST_JSON_UNLIKELY(more_))
2255  
                if(BOOST_JSON_UNLIKELY(more_))
2256  
                {
2256  
                {
2257  
                    if(BOOST_JSON_UNLIKELY(
2257  
                    if(BOOST_JSON_UNLIKELY(
2258  
                        ! h_.on_number_part(
2258  
                        ! h_.on_number_part(
2259  
                            {begin, cs.used(begin)}, ec_)))
2259  
                            {begin, cs.used(begin)}, ec_)))
2260  
                        return fail(cs.begin());
2260  
                        return fail(cs.begin());
2261  

2261  

2262  
                    BOOST_IF_CONSTEXPR( precise_parsing )
2262  
                    BOOST_IF_CONSTEXPR( precise_parsing )
2263  
                        num_buf_.append( begin, cs.used(begin) );
2263  
                        num_buf_.append( begin, cs.used(begin) );
2264  
                    return suspend(cs.begin(), state::num2, num);
2264  
                    return suspend(cs.begin(), state::num2, num);
2265  
                }
2265  
                }
2266  
                goto finish_int;
2266  
                goto finish_int;
2267  
            }
2267  
            }
2268  
            char const c = *cs;
2268  
            char const c = *cs;
2269  
            if(BOOST_JSON_LIKELY(
2269  
            if(BOOST_JSON_LIKELY(
2270  
                c >= '0' && c <= '9'))
2270  
                c >= '0' && c <= '9'))
2271  
            {
2271  
            {
2272  
                ++cs;
2272  
                ++cs;
2273  
                //              18446744073709551615 UINT64_MAX
2273  
                //              18446744073709551615 UINT64_MAX
2274  
                if( num.mant  > 1844674407370955161 || (
2274  
                if( num.mant  > 1844674407370955161 || (
2275  
                    num.mant == 1844674407370955161 && c > '5'))
2275  
                    num.mant == 1844674407370955161 && c > '5'))
2276  
                    break;
2276  
                    break;
2277  
                BOOST_IF_CONSTEXPR( !no_parsing )
2277  
                BOOST_IF_CONSTEXPR( !no_parsing )
2278  
                    num.mant = 10 * num.mant + ( c - '0' );
2278  
                    num.mant = 10 * num.mant + ( c - '0' );
2279  
            }
2279  
            }
2280  
            else
2280  
            else
2281  
            {
2281  
            {
2282  
                goto do_num6; // [.eE]
2282  
                goto do_num6; // [.eE]
2283  
            }
2283  
            }
2284  
        }
2284  
        }
2285  
    }
2285  
    }
2286  
    ++num.bias;
2286  
    ++num.bias;
2287  

2287  

2288  
    //----------------------------------
2288  
    //----------------------------------
2289  
    //
2289  
    //
2290  
    // 1*DIGIT
2290  
    // 1*DIGIT
2291  
    // non-significant digits left of decimal
2291  
    // non-significant digits left of decimal
2292  
    //
2292  
    //
2293  
do_num3:
2293  
do_num3:
2294  
    for(;;)
2294  
    for(;;)
2295  
    {
2295  
    {
2296  
        if(BOOST_JSON_UNLIKELY(! cs))
2296  
        if(BOOST_JSON_UNLIKELY(! cs))
2297  
        {
2297  
        {
2298  
            if(BOOST_JSON_UNLIKELY(more_))
2298  
            if(BOOST_JSON_UNLIKELY(more_))
2299  
            {
2299  
            {
2300  
                if(BOOST_JSON_UNLIKELY(
2300  
                if(BOOST_JSON_UNLIKELY(
2301  
                    ! h_.on_number_part(
2301  
                    ! h_.on_number_part(
2302  
                        {begin, cs.used(begin)}, ec_)))
2302  
                        {begin, cs.used(begin)}, ec_)))
2303  
                    return fail(cs.begin());
2303  
                    return fail(cs.begin());
2304  

2304  

2305  
                BOOST_IF_CONSTEXPR( precise_parsing )
2305  
                BOOST_IF_CONSTEXPR( precise_parsing )
2306  
                    num_buf_.append( begin, cs.used(begin) );
2306  
                    num_buf_.append( begin, cs.used(begin) );
2307  
                return suspend(cs.begin(), state::num3, num);
2307  
                return suspend(cs.begin(), state::num3, num);
2308  
            }
2308  
            }
2309  
            goto finish_dub;
2309  
            goto finish_dub;
2310  
        }
2310  
        }
2311  
        char const c = *cs;
2311  
        char const c = *cs;
2312  
        if(BOOST_JSON_UNLIKELY(
2312  
        if(BOOST_JSON_UNLIKELY(
2313  
            c >= '0' && c <= '9'))
2313  
            c >= '0' && c <= '9'))
2314  
        {
2314  
        {
2315  
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2315  
            if(BOOST_JSON_UNLIKELY( num.bias + 1 == INT_MAX ))
2316  
            {
2316  
            {
2317  
                BOOST_STATIC_CONSTEXPR source_location loc
2317  
                BOOST_STATIC_CONSTEXPR source_location loc
2318  
                    = BOOST_CURRENT_LOCATION;
2318  
                    = BOOST_CURRENT_LOCATION;
2319  
                return fail(cs.begin(), error::exponent_overflow, &loc);
2319  
                return fail(cs.begin(), error::exponent_overflow, &loc);
2320  
            }
2320  
            }
2321  
            ++cs;
2321  
            ++cs;
2322  
            ++num.bias;
2322  
            ++num.bias;
2323  
        }
2323  
        }
2324  
        else if(BOOST_JSON_LIKELY(
2324  
        else if(BOOST_JSON_LIKELY(
2325  
            c == '.'))
2325  
            c == '.'))
2326  
        {
2326  
        {
2327  
            ++cs;
2327  
            ++cs;
2328  
            break;
2328  
            break;
2329  
        }
2329  
        }
2330  
        else if((c | 32) == 'e')
2330  
        else if((c | 32) == 'e')
2331  
        {
2331  
        {
2332  
            ++cs;
2332  
            ++cs;
2333  
            goto do_exp1;
2333  
            goto do_exp1;
2334  
        }
2334  
        }
2335  
        else
2335  
        else
2336  
        {
2336  
        {
2337  
            goto finish_dub;
2337  
            goto finish_dub;
2338  
        }
2338  
        }
2339  
    }
2339  
    }
2340  

2340  

2341  
    //----------------------------------
2341  
    //----------------------------------
2342  
    //
2342  
    //
2343  
    // DIGIT
2343  
    // DIGIT
2344  
    // first non-significant digit
2344  
    // first non-significant digit
2345  
    // to the right of decimal
2345  
    // to the right of decimal
2346  
    //
2346  
    //
2347  
do_num4:
2347  
do_num4:
2348  
    {
2348  
    {
2349  
        if(BOOST_JSON_UNLIKELY(! cs))
2349  
        if(BOOST_JSON_UNLIKELY(! cs))
2350  
        {
2350  
        {
2351  
            if(BOOST_JSON_UNLIKELY(
2351  
            if(BOOST_JSON_UNLIKELY(
2352  
                ! h_.on_number_part(
2352  
                ! h_.on_number_part(
2353  
                    {begin, cs.used(begin)}, ec_)))
2353  
                    {begin, cs.used(begin)}, ec_)))
2354  
                return fail(cs.begin());
2354  
                return fail(cs.begin());
2355  

2355  

2356  
            BOOST_IF_CONSTEXPR( precise_parsing )
2356  
            BOOST_IF_CONSTEXPR( precise_parsing )
2357  
                num_buf_.append( begin, cs.used(begin) );
2357  
                num_buf_.append( begin, cs.used(begin) );
2358  
            return maybe_suspend(
2358  
            return maybe_suspend(
2359  
                cs.begin(), state::num4, num);
2359  
                cs.begin(), state::num4, num);
2360  
        }
2360  
        }
2361  
        char const c = *cs;
2361  
        char const c = *cs;
2362  
        if(BOOST_JSON_LIKELY(
2362  
        if(BOOST_JSON_LIKELY(
2363  
            //static_cast<unsigned char>(c - '0') < 10))
2363  
            //static_cast<unsigned char>(c - '0') < 10))
2364  
            c >= '0' && c <= '9'))
2364  
            c >= '0' && c <= '9'))
2365  
        {
2365  
        {
2366  
            ++cs;
2366  
            ++cs;
2367  
        }
2367  
        }
2368  
        else
2368  
        else
2369  
        {
2369  
        {
2370  
            // digit required
2370  
            // digit required
2371  
            BOOST_STATIC_CONSTEXPR source_location loc
2371  
            BOOST_STATIC_CONSTEXPR source_location loc
2372  
                = BOOST_CURRENT_LOCATION;
2372  
                = BOOST_CURRENT_LOCATION;
2373  
            return fail(cs.begin(), error::syntax, &loc);
2373  
            return fail(cs.begin(), error::syntax, &loc);
2374  
        }
2374  
        }
2375  
    }
2375  
    }
2376  

2376  

2377  
    //----------------------------------
2377  
    //----------------------------------
2378  
    //
2378  
    //
2379  
    // 1*DIGIT
2379  
    // 1*DIGIT
2380  
    // non-significant digits
2380  
    // non-significant digits
2381  
    // to the right of decimal
2381  
    // to the right of decimal
2382  
    //
2382  
    //
2383  
do_num5:
2383  
do_num5:
2384  
    for(;;)
2384  
    for(;;)
2385  
    {
2385  
    {
2386  
        if(BOOST_JSON_UNLIKELY(! cs))
2386  
        if(BOOST_JSON_UNLIKELY(! cs))
2387  
        {
2387  
        {
2388  
            if(BOOST_JSON_UNLIKELY(more_))
2388  
            if(BOOST_JSON_UNLIKELY(more_))
2389  
            {
2389  
            {
2390  
                if(BOOST_JSON_UNLIKELY(
2390  
                if(BOOST_JSON_UNLIKELY(
2391  
                    ! h_.on_number_part(
2391  
                    ! h_.on_number_part(
2392  
                        {begin, cs.used(begin)}, ec_)))
2392  
                        {begin, cs.used(begin)}, ec_)))
2393  
                    return fail(cs.begin());
2393  
                    return fail(cs.begin());
2394  

2394  

2395  
                BOOST_IF_CONSTEXPR( precise_parsing )
2395  
                BOOST_IF_CONSTEXPR( precise_parsing )
2396  
                    num_buf_.append( begin, cs.used(begin) );
2396  
                    num_buf_.append( begin, cs.used(begin) );
2397  
                return suspend(cs.begin(), state::num5, num);
2397  
                return suspend(cs.begin(), state::num5, num);
2398  
            }
2398  
            }
2399  
            goto finish_dub;
2399  
            goto finish_dub;
2400  
        }
2400  
        }
2401  
        char const c = *cs;
2401  
        char const c = *cs;
2402  
        if(BOOST_JSON_LIKELY(
2402  
        if(BOOST_JSON_LIKELY(
2403  
            c >= '0' && c <= '9'))
2403  
            c >= '0' && c <= '9'))
2404  
        {
2404  
        {
2405  
            ++cs;
2405  
            ++cs;
2406  
        }
2406  
        }
2407  
        else if((c | 32) == 'e')
2407  
        else if((c | 32) == 'e')
2408  
        {
2408  
        {
2409  
            ++cs;
2409  
            ++cs;
2410  
            goto do_exp1;
2410  
            goto do_exp1;
2411  
        }
2411  
        }
2412  
        else
2412  
        else
2413  
        {
2413  
        {
2414  
            goto finish_dub;
2414  
            goto finish_dub;
2415  
        }
2415  
        }
2416  
    }
2416  
    }
2417  

2417  

2418  
    //----------------------------------
2418  
    //----------------------------------
2419  
    //
2419  
    //
2420  
    // [.eE]
2420  
    // [.eE]
2421  
    //
2421  
    //
2422  
do_num6:
2422  
do_num6:
2423  
    {
2423  
    {
2424  
        if(BOOST_JSON_UNLIKELY(! cs))
2424  
        if(BOOST_JSON_UNLIKELY(! cs))
2425  
        {
2425  
        {
2426  
            if(BOOST_JSON_UNLIKELY(more_))
2426  
            if(BOOST_JSON_UNLIKELY(more_))
2427  
            {
2427  
            {
2428  
                if(BOOST_JSON_UNLIKELY(
2428  
                if(BOOST_JSON_UNLIKELY(
2429  
                    ! h_.on_number_part(
2429  
                    ! h_.on_number_part(
2430  
                        {begin, cs.used(begin)}, ec_)))
2430  
                        {begin, cs.used(begin)}, ec_)))
2431  
                    return fail(cs.begin());
2431  
                    return fail(cs.begin());
2432  

2432  

2433  
                BOOST_IF_CONSTEXPR( precise_parsing )
2433  
                BOOST_IF_CONSTEXPR( precise_parsing )
2434  
                    num_buf_.append( begin, cs.used(begin) );
2434  
                    num_buf_.append( begin, cs.used(begin) );
2435  
                return suspend(cs.begin(), state::num6, num);
2435  
                return suspend(cs.begin(), state::num6, num);
2436  
            }
2436  
            }
2437  
            goto finish_int;
2437  
            goto finish_int;
2438  
        }
2438  
        }
2439  
        char const c = *cs;
2439  
        char const c = *cs;
2440  
        if(BOOST_JSON_LIKELY(
2440  
        if(BOOST_JSON_LIKELY(
2441  
            c == '.'))
2441  
            c == '.'))
2442  
        {
2442  
        {
2443  
            ++cs;
2443  
            ++cs;
2444  
        }
2444  
        }
2445  
        else if((c | 32) == 'e')
2445  
        else if((c | 32) == 'e')
2446  
        {
2446  
        {
2447  
            ++cs;
2447  
            ++cs;
2448  
            goto do_exp1;
2448  
            goto do_exp1;
2449  
        }
2449  
        }
2450  
        else
2450  
        else
2451  
        {
2451  
        {
2452  
            goto finish_int;
2452  
            goto finish_int;
2453  
        }
2453  
        }
2454  
    }
2454  
    }
2455  

2455  

2456  
    //----------------------------------
2456  
    //----------------------------------
2457  
    //
2457  
    //
2458  
    // DIGIT
2458  
    // DIGIT
2459  
    // first significant digit
2459  
    // first significant digit
2460  
    // to the right of decimal
2460  
    // to the right of decimal
2461  
    //
2461  
    //
2462  
do_num7:
2462  
do_num7:
2463  
    {
2463  
    {
2464  
        if(BOOST_JSON_UNLIKELY(! cs))
2464  
        if(BOOST_JSON_UNLIKELY(! cs))
2465  
        {
2465  
        {
2466  
            if(BOOST_JSON_UNLIKELY(more_))
2466  
            if(BOOST_JSON_UNLIKELY(more_))
2467  
            {
2467  
            {
2468  
                if(BOOST_JSON_UNLIKELY(
2468  
                if(BOOST_JSON_UNLIKELY(
2469  
                    ! h_.on_number_part(
2469  
                    ! h_.on_number_part(
2470  
                        {begin, cs.used(begin)}, ec_)))
2470  
                        {begin, cs.used(begin)}, ec_)))
2471  
                    return fail(cs.begin());
2471  
                    return fail(cs.begin());
2472  

2472  

2473  
                BOOST_IF_CONSTEXPR( precise_parsing )
2473  
                BOOST_IF_CONSTEXPR( precise_parsing )
2474  
                    num_buf_.append( begin, cs.used(begin) );
2474  
                    num_buf_.append( begin, cs.used(begin) );
2475  
                return suspend(cs.begin(), state::num7, num);
2475  
                return suspend(cs.begin(), state::num7, num);
2476  
            }
2476  
            }
2477  
            // digit required
2477  
            // digit required
2478  
            BOOST_STATIC_CONSTEXPR source_location loc
2478  
            BOOST_STATIC_CONSTEXPR source_location loc
2479  
                = BOOST_CURRENT_LOCATION;
2479  
                = BOOST_CURRENT_LOCATION;
2480  
            return fail(cs.begin(), error::syntax, &loc);
2480  
            return fail(cs.begin(), error::syntax, &loc);
2481  
        }
2481  
        }
2482  
        char const c = *cs;
2482  
        char const c = *cs;
2483  
        if(BOOST_JSON_UNLIKELY(
2483  
        if(BOOST_JSON_UNLIKELY(
2484  
            c < '0' || c > '9'))
2484  
            c < '0' || c > '9'))
2485  
        {
2485  
        {
2486  
            // digit required
2486  
            // digit required
2487  
            BOOST_STATIC_CONSTEXPR source_location loc
2487  
            BOOST_STATIC_CONSTEXPR source_location loc
2488  
                = BOOST_CURRENT_LOCATION;
2488  
                = BOOST_CURRENT_LOCATION;
2489  
            return fail(cs.begin(), error::syntax, &loc);
2489  
            return fail(cs.begin(), error::syntax, &loc);
2490  
        }
2490  
        }
2491  
    }
2491  
    }
2492  

2492  

2493  
    //----------------------------------
2493  
    //----------------------------------
2494  
    //
2494  
    //
2495  
    // 1*DIGIT
2495  
    // 1*DIGIT
2496  
    // significant digits
2496  
    // significant digits
2497  
    // to the right of decimal
2497  
    // to the right of decimal
2498  
    //
2498  
    //
2499  
do_num8:
2499  
do_num8:
2500  
    for(;;)
2500  
    for(;;)
2501  
    {
2501  
    {
2502  
        if(BOOST_JSON_UNLIKELY(! cs))
2502  
        if(BOOST_JSON_UNLIKELY(! cs))
2503  
        {
2503  
        {
2504  
            if(BOOST_JSON_UNLIKELY(more_))
2504  
            if(BOOST_JSON_UNLIKELY(more_))
2505  
            {
2505  
            {
2506  
                if(BOOST_JSON_UNLIKELY(
2506  
                if(BOOST_JSON_UNLIKELY(
2507  
                    ! h_.on_number_part(
2507  
                    ! h_.on_number_part(
2508  
                        {begin, cs.used(begin)}, ec_)))
2508  
                        {begin, cs.used(begin)}, ec_)))
2509  
                    return fail(cs.begin());
2509  
                    return fail(cs.begin());
2510  

2510  

2511  
                BOOST_IF_CONSTEXPR( precise_parsing )
2511  
                BOOST_IF_CONSTEXPR( precise_parsing )
2512  
                    num_buf_.append( begin, cs.used(begin) );
2512  
                    num_buf_.append( begin, cs.used(begin) );
2513  
                return suspend(cs.begin(), state::num8, num);
2513  
                return suspend(cs.begin(), state::num8, num);
2514  
            }
2514  
            }
2515  
            goto finish_dub;
2515  
            goto finish_dub;
2516  
        }
2516  
        }
2517  
        char const c = *cs;
2517  
        char const c = *cs;
2518  
        if(BOOST_JSON_LIKELY(
2518  
        if(BOOST_JSON_LIKELY(
2519  
            c >= '0' && c <= '9'))
2519  
            c >= '0' && c <= '9'))
2520  
        {
2520  
        {
2521  
            ++cs;
2521  
            ++cs;
2522  
            if(!no_parsing && BOOST_JSON_LIKELY(
2522  
            if(!no_parsing && BOOST_JSON_LIKELY(
2523  
                num.mant <= 9007199254740991)) // 2^53-1
2523  
                num.mant <= 9007199254740991)) // 2^53-1
2524  
            {
2524  
            {
2525  
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2525  
                if(BOOST_JSON_UNLIKELY( num.bias - 1 == INT_MIN ))
2526  
                {
2526  
                {
2527  
                    BOOST_STATIC_CONSTEXPR source_location loc
2527  
                    BOOST_STATIC_CONSTEXPR source_location loc
2528  
                        = BOOST_CURRENT_LOCATION;
2528  
                        = BOOST_CURRENT_LOCATION;
2529  
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2529  
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2530  
                }
2530  
                }
2531  
                --num.bias;
2531  
                --num.bias;
2532  
                num.mant = 10 * num.mant + ( c - '0' );
2532  
                num.mant = 10 * num.mant + ( c - '0' );
2533  
            }
2533  
            }
2534  
            else
2534  
            else
2535  
            {
2535  
            {
2536  
                goto do_num5;
2536  
                goto do_num5;
2537  
            }
2537  
            }
2538  
        }
2538  
        }
2539  
        else if((c | 32) == 'e')
2539  
        else if((c | 32) == 'e')
2540  
        {
2540  
        {
2541  
            ++cs;
2541  
            ++cs;
2542  
            goto do_exp1;
2542  
            goto do_exp1;
2543  
        }
2543  
        }
2544  
        else
2544  
        else
2545  
        {
2545  
        {
2546  
            goto finish_dub;
2546  
            goto finish_dub;
2547  
        }
2547  
        }
2548  
    }
2548  
    }
2549  

2549  

2550  
    //----------------------------------
2550  
    //----------------------------------
2551  
    //
2551  
    //
2552  
    // *[+-]
2552  
    // *[+-]
2553  
    //
2553  
    //
2554  
do_exp1:
2554  
do_exp1:
2555  
    if(BOOST_JSON_UNLIKELY(! cs))
2555  
    if(BOOST_JSON_UNLIKELY(! cs))
2556  
    {
2556  
    {
2557  
        if(BOOST_JSON_UNLIKELY(
2557  
        if(BOOST_JSON_UNLIKELY(
2558  
            ! h_.on_number_part(
2558  
            ! h_.on_number_part(
2559  
                {begin, cs.used(begin)}, ec_)))
2559  
                {begin, cs.used(begin)}, ec_)))
2560  
            return fail(cs.begin());
2560  
            return fail(cs.begin());
2561  

2561  

2562  
        BOOST_IF_CONSTEXPR( precise_parsing )
2562  
        BOOST_IF_CONSTEXPR( precise_parsing )
2563  
            num_buf_.append( begin, cs.used(begin) );
2563  
            num_buf_.append( begin, cs.used(begin) );
2564  
        return maybe_suspend(
2564  
        return maybe_suspend(
2565  
            cs.begin(), state::exp1, num);
2565  
            cs.begin(), state::exp1, num);
2566  
    }
2566  
    }
2567  
    if(*cs == '+')
2567  
    if(*cs == '+')
2568  
    {
2568  
    {
2569  
        ++cs;
2569  
        ++cs;
2570  
    }
2570  
    }
2571  
    else if(*cs == '-')
2571  
    else if(*cs == '-')
2572  
    {
2572  
    {
2573  
        ++cs;
2573  
        ++cs;
2574  
        num.frac = true;
2574  
        num.frac = true;
2575  
    }
2575  
    }
2576  

2576  

2577  
    //----------------------------------
2577  
    //----------------------------------
2578  
    //
2578  
    //
2579  
    // DIGIT
2579  
    // DIGIT
2580  
    // first digit of the exponent
2580  
    // first digit of the exponent
2581  
    //
2581  
    //
2582  
do_exp2:
2582  
do_exp2:
2583  
    {
2583  
    {
2584  
        if(BOOST_JSON_UNLIKELY(! cs))
2584  
        if(BOOST_JSON_UNLIKELY(! cs))
2585  
        {
2585  
        {
2586  
            if(BOOST_JSON_UNLIKELY(more_))
2586  
            if(BOOST_JSON_UNLIKELY(more_))
2587  
            {
2587  
            {
2588  
                if(BOOST_JSON_UNLIKELY(
2588  
                if(BOOST_JSON_UNLIKELY(
2589  
                    ! h_.on_number_part(
2589  
                    ! h_.on_number_part(
2590  
                        {begin, cs.used(begin)}, ec_)))
2590  
                        {begin, cs.used(begin)}, ec_)))
2591  
                    return fail(cs.begin());
2591  
                    return fail(cs.begin());
2592  

2592  

2593  
                BOOST_IF_CONSTEXPR( precise_parsing )
2593  
                BOOST_IF_CONSTEXPR( precise_parsing )
2594  
                    num_buf_.append( begin, cs.used(begin) );
2594  
                    num_buf_.append( begin, cs.used(begin) );
2595  
                return suspend(cs.begin(), state::exp2, num);
2595  
                return suspend(cs.begin(), state::exp2, num);
2596  
            }
2596  
            }
2597  
            // digit required
2597  
            // digit required
2598  
            BOOST_STATIC_CONSTEXPR source_location loc
2598  
            BOOST_STATIC_CONSTEXPR source_location loc
2599  
                = BOOST_CURRENT_LOCATION;
2599  
                = BOOST_CURRENT_LOCATION;
2600  
            return fail(cs.begin(), error::syntax, &loc);
2600  
            return fail(cs.begin(), error::syntax, &loc);
2601  
        }
2601  
        }
2602  
        char const c = *cs;
2602  
        char const c = *cs;
2603  
        if(BOOST_JSON_UNLIKELY(
2603  
        if(BOOST_JSON_UNLIKELY(
2604  
            c < '0' || c > '9'))
2604  
            c < '0' || c > '9'))
2605  
        {
2605  
        {
2606  
            // digit required
2606  
            // digit required
2607  
            BOOST_STATIC_CONSTEXPR source_location loc
2607  
            BOOST_STATIC_CONSTEXPR source_location loc
2608  
                = BOOST_CURRENT_LOCATION;
2608  
                = BOOST_CURRENT_LOCATION;
2609  
            return fail(cs.begin(), error::syntax, &loc);
2609  
            return fail(cs.begin(), error::syntax, &loc);
2610  
        }
2610  
        }
2611  
        ++cs;
2611  
        ++cs;
2612  
        num.exp = c - '0';
2612  
        num.exp = c - '0';
2613  
    }
2613  
    }
2614  

2614  

2615  
    //----------------------------------
2615  
    //----------------------------------
2616  
    //
2616  
    //
2617  
    // 1*DIGIT
2617  
    // 1*DIGIT
2618  
    // subsequent digits in the exponent
2618  
    // subsequent digits in the exponent
2619  
    //
2619  
    //
2620  
do_exp3:
2620  
do_exp3:
2621  
    for(;;)
2621  
    for(;;)
2622  
    {
2622  
    {
2623  
        if(BOOST_JSON_UNLIKELY(! cs))
2623  
        if(BOOST_JSON_UNLIKELY(! cs))
2624  
        {
2624  
        {
2625  
            if(BOOST_JSON_UNLIKELY(more_))
2625  
            if(BOOST_JSON_UNLIKELY(more_))
2626  
            {
2626  
            {
2627  
                if(BOOST_JSON_UNLIKELY(
2627  
                if(BOOST_JSON_UNLIKELY(
2628  
                    ! h_.on_number_part(
2628  
                    ! h_.on_number_part(
2629  
                        {begin, cs.used(begin)}, ec_)))
2629  
                        {begin, cs.used(begin)}, ec_)))
2630  
                    return fail(cs.begin());
2630  
                    return fail(cs.begin());
2631  

2631  

2632  
                BOOST_IF_CONSTEXPR( precise_parsing )
2632  
                BOOST_IF_CONSTEXPR( precise_parsing )
2633  
                    num_buf_.append( begin, cs.used(begin) );
2633  
                    num_buf_.append( begin, cs.used(begin) );
2634  
                return suspend(cs.begin(), state::exp3, num);
2634  
                return suspend(cs.begin(), state::exp3, num);
2635  
            }
2635  
            }
2636  
        }
2636  
        }
2637  
        else
2637  
        else
2638  
        {
2638  
        {
2639  
            char const c = *cs;
2639  
            char const c = *cs;
2640  
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2640  
            if(BOOST_JSON_LIKELY( c >= '0' && c <= '9' ))
2641  
            {
2641  
            {
2642  
                if(BOOST_JSON_UNLIKELY(
2642  
                if(BOOST_JSON_UNLIKELY(
2643  
                //              2147483647 INT_MAX
2643  
                //              2147483647 INT_MAX
2644  
                    num.exp  >  214748364 ||
2644  
                    num.exp  >  214748364 ||
2645  
                    (num.exp == 214748364 && c > '7')
2645  
                    (num.exp == 214748364 && c > '7')
2646  
                ))
2646  
                ))
2647  
                    num.exp = INT_MAX;
2647  
                    num.exp = INT_MAX;
2648  
                else BOOST_IF_CONSTEXPR( !no_parsing )
2648  
                else BOOST_IF_CONSTEXPR( !no_parsing )
2649  
                    num.exp = 10 * num.exp + ( c - '0' );
2649  
                    num.exp = 10 * num.exp + ( c - '0' );
2650  

2650  

2651  
                ++cs;
2651  
                ++cs;
2652  
                continue;
2652  
                continue;
2653  
            }
2653  
            }
2654  
        }
2654  
        }
2655  
        BOOST_ASSERT(num.exp >= 0);
2655  
        BOOST_ASSERT(num.exp >= 0);
2656  
        if ( num.frac )
2656  
        if ( num.frac )
2657  
        {
2657  
        {
2658  
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2658  
            if(BOOST_JSON_UNLIKELY( num.bias < (INT_MIN + num.exp) ))
2659  
            {
2659  
            {
2660  
                // if exponent overflowed, bias is a very large negative
2660  
                // if exponent overflowed, bias is a very large negative
2661  
                // number, and mantissa isn't zero, then we cannot parse the
2661  
                // number, and mantissa isn't zero, then we cannot parse the
2662  
                // number correctly
2662  
                // number correctly
2663  
                if(BOOST_JSON_UNLIKELY(
2663  
                if(BOOST_JSON_UNLIKELY(
2664  
                    (num.exp == INT_MAX) &&
2664  
                    (num.exp == INT_MAX) &&
2665  
                    (num.bias < 0) &&
2665  
                    (num.bias < 0) &&
2666  
                    (num.exp + num.bias < 308) &&
2666  
                    (num.exp + num.bias < 308) &&
2667  
                    num.mant ))
2667  
                    num.mant ))
2668  
                {
2668  
                {
2669  
                    BOOST_STATIC_CONSTEXPR source_location loc
2669  
                    BOOST_STATIC_CONSTEXPR source_location loc
2670  
                        = BOOST_CURRENT_LOCATION;
2670  
                        = BOOST_CURRENT_LOCATION;
2671  
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2671  
                    return fail(cs.begin(), error::exponent_overflow, &loc);
2672  
                }
2672  
                }
2673  

2673  

2674  
                num.bias = 0;
2674  
                num.bias = 0;
2675  
                num.exp = INT_MAX;
2675  
                num.exp = INT_MAX;
2676  
            }
2676  
            }
2677  
        }
2677  
        }
2678  
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2678  
        else if (BOOST_JSON_UNLIKELY( num.bias > (INT_MAX - num.exp) ))
2679  
        {
2679  
        {
2680  
            // if exponent overflowed, bias is a very large positive number,
2680  
            // if exponent overflowed, bias is a very large positive number,
2681  
            // and mantissa isn't zero, then we cannot parse the
2681  
            // and mantissa isn't zero, then we cannot parse the
2682  
            // number correctly
2682  
            // number correctly
2683  
            if(BOOST_JSON_UNLIKELY(
2683  
            if(BOOST_JSON_UNLIKELY(
2684  
                (num.exp == INT_MAX) &&
2684  
                (num.exp == INT_MAX) &&
2685  
                (num.bias > 0) &&
2685  
                (num.bias > 0) &&
2686  
                (num.exp - num.bias < 308) &&
2686  
                (num.exp - num.bias < 308) &&
2687  
                num.mant ))
2687  
                num.mant ))
2688  
            {
2688  
            {
2689  
                BOOST_STATIC_CONSTEXPR source_location loc
2689  
                BOOST_STATIC_CONSTEXPR source_location loc
2690  
                    = BOOST_CURRENT_LOCATION;
2690  
                    = BOOST_CURRENT_LOCATION;
2691  
                return fail(cs.begin(), error::exponent_overflow, &loc);
2691  
                return fail(cs.begin(), error::exponent_overflow, &loc);
2692  
            }
2692  
            }
2693  

2693  

2694  
            num.bias = 0;
2694  
            num.bias = 0;
2695  
            num.exp = INT_MAX;
2695  
            num.exp = INT_MAX;
2696  
        }
2696  
        }
2697  
        goto finish_dub;
2697  
        goto finish_dub;
2698  
    }
2698  
    }
2699  

2699  

2700  
finish_int:
2700  
finish_int:
2701  
    if(negative || (!stack_empty && num.neg))
2701  
    if(negative || (!stack_empty && num.neg))
2702  
    {
2702  
    {
2703  
        if(BOOST_JSON_UNLIKELY(
2703  
        if(BOOST_JSON_UNLIKELY(
2704  
            ! h_.on_int64(static_cast<
2704  
            ! h_.on_int64(static_cast<
2705  
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2705  
                int64_t>(~num.mant + 1), {begin, cs.used(begin)}, ec_)))
2706  
            return fail(cs.begin());
2706  
            return fail(cs.begin());
2707  
        return cs.begin();
2707  
        return cs.begin();
2708  
    }
2708  
    }
2709  
    if(num.mant <= INT64_MAX)
2709  
    if(num.mant <= INT64_MAX)
2710  
    {
2710  
    {
2711  
finish_signed:
2711  
finish_signed:
2712  
        if(BOOST_JSON_UNLIKELY(
2712  
        if(BOOST_JSON_UNLIKELY(
2713  
            ! h_.on_int64(static_cast<
2713  
            ! h_.on_int64(static_cast<
2714  
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2714  
                int64_t>(num.mant), {begin, cs.used(begin)}, ec_)))
2715  
            return fail(cs.begin());
2715  
            return fail(cs.begin());
2716  
        return cs.begin();
2716  
        return cs.begin();
2717  
    }
2717  
    }
2718  
    if(BOOST_JSON_UNLIKELY(
2718  
    if(BOOST_JSON_UNLIKELY(
2719  
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2719  
        ! h_.on_uint64(num.mant, {begin, cs.used(begin)}, ec_)))
2720  
        return fail(cs.begin());
2720  
        return fail(cs.begin());
2721  
    return cs.begin();
2721  
    return cs.begin();
2722  
finish_dub:
2722  
finish_dub:
2723  
    double d;
2723  
    double d;
2724  
    std::size_t const size = cs.used(begin);
2724  
    std::size_t const size = cs.used(begin);
2725  
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2725  
    BOOST_ASSERT( !num_buf_.size() || precise_parsing );
2726  
    BOOST_IF_CONSTEXPR( precise_parsing )
2726  
    BOOST_IF_CONSTEXPR( precise_parsing )
2727  
    {
2727  
    {
2728  
        char const* data = begin;
2728  
        char const* data = begin;
2729  
        std::size_t full_size = size;
2729  
        std::size_t full_size = size;
2730  
         // if we previously suspended or if the current input ends with the
2730  
         // if we previously suspended or if the current input ends with the
2731  
         // number, we need to copy the current part of the number to the
2731  
         // number, we need to copy the current part of the number to the
2732  
         // temporary buffer
2732  
         // temporary buffer
2733  
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2733  
        if(BOOST_JSON_UNLIKELY( num_buf_.size() ))
2734  
        {
2734  
        {
2735  
            data = num_buf_.append( begin, size );
2735  
            data = num_buf_.append( begin, size );
2736  
            full_size = num_buf_.size();
2736  
            full_size = num_buf_.size();
2737  
        }
2737  
        }
2738  
        auto const err = detail::charconv::from_chars(
2738  
        auto const err = detail::charconv::from_chars(
2739  
            data, data + full_size, d );
2739  
            data, data + full_size, d );
2740  
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2740  
        BOOST_ASSERT( err.ec != std::errc::invalid_argument );
2741  
        BOOST_ASSERT( err.ptr == data + full_size );
2741  
        BOOST_ASSERT( err.ptr == data + full_size );
2742  
        (void)err;
2742  
        (void)err;
2743  
    }
2743  
    }
2744  
    else BOOST_IF_CONSTEXPR( no_parsing )
2744  
    else BOOST_IF_CONSTEXPR( no_parsing )
2745  
        d = 0;
2745  
        d = 0;
2746  
    else
2746  
    else
2747  
        d = detail::dec_to_float(
2747  
        d = detail::dec_to_float(
2748  
            num.mant,
2748  
            num.mant,
2749  
            num.bias + (num.frac ?
2749  
            num.bias + (num.frac ?
2750  
                -num.exp : num.exp),
2750  
                -num.exp : num.exp),
2751  
            num.neg);
2751  
            num.neg);
2752  
    if(BOOST_JSON_UNLIKELY(
2752  
    if(BOOST_JSON_UNLIKELY(
2753  
        ! h_.on_double(d, {begin, size}, ec_)))
2753  
        ! h_.on_double(d, {begin, size}, ec_)))
2754  
        return fail(cs.begin());
2754  
        return fail(cs.begin());
2755  
    return cs.begin();
2755  
    return cs.begin();
2756  
}
2756  
}
2757  

2757  

2758  
//----------------------------------------------------------
2758  
//----------------------------------------------------------
2759  

2759  

2760  
template<class Handler>
2760  
template<class Handler>
2761  
template<class... Args>
2761  
template<class... Args>
2762  
basic_parser<Handler>::
2762  
basic_parser<Handler>::
2763  
basic_parser(
2763  
basic_parser(
2764  
    parse_options const& opt,
2764  
    parse_options const& opt,
2765  
    Args&&... args)
2765  
    Args&&... args)
2766  
    : h_(std::forward<Args>(args)...)
2766  
    : h_(std::forward<Args>(args)...)
2767  
    , opt_(opt)
2767  
    , opt_(opt)
2768  
{
2768  
{
2769  
}
2769  
}
2770  

2770  

2771  
//----------------------------------------------------------
2771  
//----------------------------------------------------------
2772  

2772  

2773  
template<class Handler>
2773  
template<class Handler>
2774  
void
2774  
void
2775  
basic_parser<Handler>::
2775  
basic_parser<Handler>::
2776  
reset() noexcept
2776  
reset() noexcept
2777  
{
2777  
{
2778  
    ec_ = {};
2778  
    ec_ = {};
2779  
    st_.clear();
2779  
    st_.clear();
2780  
    more_ = true;
2780  
    more_ = true;
2781  
    done_ = false;
2781  
    done_ = false;
2782  
    clean_ = true;
2782  
    clean_ = true;
2783  
    num_buf_.clear();
2783  
    num_buf_.clear();
2784  
}
2784  
}
2785  

2785  

2786  
template<class Handler>
2786  
template<class Handler>
2787  
void
2787  
void
2788  
basic_parser<Handler>::
2788  
basic_parser<Handler>::
2789  
fail(system::error_code ec) noexcept
2789  
fail(system::error_code ec) noexcept
2790  
{
2790  
{
2791  
    if(! ec)
2791  
    if(! ec)
2792  
    {
2792  
    {
2793  
        // assign an arbitrary
2793  
        // assign an arbitrary
2794  
        // error code to prevent UB
2794  
        // error code to prevent UB
2795  
        BOOST_JSON_FAIL(ec_, error::incomplete);
2795  
        BOOST_JSON_FAIL(ec_, error::incomplete);
2796  
    }
2796  
    }
2797  
    else
2797  
    else
2798  
    {
2798  
    {
2799  
        ec_ = ec;
2799  
        ec_ = ec;
2800  
    }
2800  
    }
2801  
    done_ = false;
2801  
    done_ = false;
2802  
}
2802  
}
2803  

2803  

2804  
//----------------------------------------------------------
2804  
//----------------------------------------------------------
2805  

2805  

2806  
template<class Handler>
2806  
template<class Handler>
2807  
std::size_t
2807  
std::size_t
2808  
basic_parser<Handler>::
2808  
basic_parser<Handler>::
2809  
write_some(
2809  
write_some(
2810  
    bool more,
2810  
    bool more,
2811  
    char const* data,
2811  
    char const* data,
2812  
    std::size_t size,
2812  
    std::size_t size,
2813  
    system::error_code& ec)
2813  
    system::error_code& ec)
2814  
{
2814  
{
2815  
    // see if we exited via exception
2815  
    // see if we exited via exception
2816  
    // on the last call to write_some
2816  
    // on the last call to write_some
2817  
    if(! clean_)
2817  
    if(! clean_)
2818  
    {
2818  
    {
2819  
        // prevent UB
2819  
        // prevent UB
2820  
        if(! ec_)
2820  
        if(! ec_)
2821  
        {
2821  
        {
2822  
            BOOST_JSON_FAIL(ec_, error::exception);
2822  
            BOOST_JSON_FAIL(ec_, error::exception);
2823  
        }
2823  
        }
2824  
    }
2824  
    }
2825  
    if(ec_)
2825  
    if(ec_)
2826  
    {
2826  
    {
2827  
        // error is sticky
2827  
        // error is sticky
2828  
        ec = ec_;
2828  
        ec = ec_;
2829  
        return 0;
2829  
        return 0;
2830  
    }
2830  
    }
2831  
    clean_ = false;
2831  
    clean_ = false;
2832  
    more_ = more;
2832  
    more_ = more;
2833  
    end_ = data + size;
2833  
    end_ = data + size;
2834  
    const char* p;
2834  
    const char* p;
2835  
    if(BOOST_JSON_LIKELY(st_.empty()))
2835  
    if(BOOST_JSON_LIKELY(st_.empty()))
2836  
    {
2836  
    {
2837  
        // first time
2837  
        // first time
2838  
        depth_ = opt_.max_depth;
2838  
        depth_ = opt_.max_depth;
2839  
        if(BOOST_JSON_UNLIKELY(
2839  
        if(BOOST_JSON_UNLIKELY(
2840  
            ! h_.on_document_begin(ec_)))
2840  
            ! h_.on_document_begin(ec_)))
2841  
        {
2841  
        {
2842  
            ec = ec_;
2842  
            ec = ec_;
2843  
            return 0;
2843  
            return 0;
2844  
        }
2844  
        }
2845  
        p = parse_document(data, std::true_type());
2845  
        p = parse_document(data, std::true_type());
2846  
    }
2846  
    }
2847  
    else
2847  
    else
2848  
    {
2848  
    {
2849  
        p = parse_document(data, std::false_type());
2849  
        p = parse_document(data, std::false_type());
2850  
    }
2850  
    }
2851  

2851  

2852  
    if(BOOST_JSON_LIKELY(p != sentinel()))
2852  
    if(BOOST_JSON_LIKELY(p != sentinel()))
2853  
    {
2853  
    {
2854  
        BOOST_ASSERT(! ec_);
2854  
        BOOST_ASSERT(! ec_);
2855  
        if(! done_)
2855  
        if(! done_)
2856  
        {
2856  
        {
2857  
            done_ = true;
2857  
            done_ = true;
2858  
            h_.on_document_end(ec_);
2858  
            h_.on_document_end(ec_);
2859  
        }
2859  
        }
2860  
    }
2860  
    }
2861  
    else
2861  
    else
2862  
    {
2862  
    {
2863  
        if(! ec_)
2863  
        if(! ec_)
2864  
        {
2864  
        {
2865  
            if(! more_)
2865  
            if(! more_)
2866  
            {
2866  
            {
2867  
                BOOST_JSON_FAIL(ec_, error::incomplete);
2867  
                BOOST_JSON_FAIL(ec_, error::incomplete);
2868  
            }
2868  
            }
2869  
            else if(! st_.empty())
2869  
            else if(! st_.empty())
2870  
            {
2870  
            {
2871  
                // consume as much trailing whitespace in
2871  
                // consume as much trailing whitespace in
2872  
                // the JSON document as possible, but still
2872  
                // the JSON document as possible, but still
2873  
                // consider the parse complete
2873  
                // consider the parse complete
2874  
                state st;
2874  
                state st;
2875  
                st_.peek(st);
2875  
                st_.peek(st);
2876  
                if( st == state::doc3 &&
2876  
                if( st == state::doc3 &&
2877  
                    ! done_)
2877  
                    ! done_)
2878  
                {
2878  
                {
2879  
                    done_ = true;
2879  
                    done_ = true;
2880  
                    h_.on_document_end(ec_);
2880  
                    h_.on_document_end(ec_);
2881  
                }
2881  
                }
2882  
            }
2882  
            }
2883  
        }
2883  
        }
2884  
        p = end_;
2884  
        p = end_;
2885  
    }
2885  
    }
2886  
    ec = ec_;
2886  
    ec = ec_;
2887  
    clean_ = true;
2887  
    clean_ = true;
2888  
    return p - data;
2888  
    return p - data;
2889  
}
2889  
}
2890  

2890  

2891  
template<class Handler>
2891  
template<class Handler>
2892  
std::size_t
2892  
std::size_t
2893  
basic_parser<Handler>::
2893  
basic_parser<Handler>::
2894  
write_some(
2894  
write_some(
2895  
    bool more,
2895  
    bool more,
2896  
    char const* data,
2896  
    char const* data,
2897  
    std::size_t size,
2897  
    std::size_t size,
2898  
    std::error_code& ec)
2898  
    std::error_code& ec)
2899  
{
2899  
{
2900  
    system::error_code jec;
2900  
    system::error_code jec;
2901  
    std::size_t const result = write_some(more, data, size, jec);
2901  
    std::size_t const result = write_some(more, data, size, jec);
2902  
    ec = jec;
2902  
    ec = jec;
2903  
    return result;
2903  
    return result;
2904  
}
2904  
}
2905  

2905  

2906  
#endif
2906  
#endif
2907  

2907  

2908  
} // namespace json
2908  
} // namespace json
2909  
} // namespace boost
2909  
} // namespace boost
2910  

2910  

2911  
#ifdef _MSC_VER
2911  
#ifdef _MSC_VER
2912  
#pragma warning(pop)
2912  
#pragma warning(pop)
2913  
#endif
2913  
#endif
2914  

2914  

2915  
#endif
2915  
#endif