1c5f01b2fSopenharmony_ci//     __ _____ _____ _____
2c5f01b2fSopenharmony_ci//  __|  |   __|     |   | |  JSON for Modern C++ (supporting code)
3c5f01b2fSopenharmony_ci// |  |  |__   |  |  | | | |  version 3.11.2
4c5f01b2fSopenharmony_ci// |_____|_____|_____|_|___|  https://github.com/nlohmann/json
5c5f01b2fSopenharmony_ci//
6c5f01b2fSopenharmony_ci// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me>
7c5f01b2fSopenharmony_ci// SPDX-License-Identifier: MIT
8c5f01b2fSopenharmony_ci
9c5f01b2fSopenharmony_ci#include "doctest_compatibility.h"
10c5f01b2fSopenharmony_ci
11c5f01b2fSopenharmony_ci#define JSON_TESTS_PRIVATE
12c5f01b2fSopenharmony_ci#include <nlohmann/json.hpp>
13c5f01b2fSopenharmony_ciusing nlohmann::json;
14c5f01b2fSopenharmony_ci#ifdef JSON_TEST_NO_GLOBAL_UDLS
15c5f01b2fSopenharmony_ci    using namespace nlohmann::literals; // NOLINT(google-build-using-namespace)
16c5f01b2fSopenharmony_ci#endif
17c5f01b2fSopenharmony_ci
18c5f01b2fSopenharmony_ci#include <valarray>
19c5f01b2fSopenharmony_ci
20c5f01b2fSopenharmony_cinamespace
21c5f01b2fSopenharmony_ci{
22c5f01b2fSopenharmony_ciclass SaxEventLogger
23c5f01b2fSopenharmony_ci{
24c5f01b2fSopenharmony_ci  public:
25c5f01b2fSopenharmony_ci    bool null()
26c5f01b2fSopenharmony_ci    {
27c5f01b2fSopenharmony_ci        events.emplace_back("null()");
28c5f01b2fSopenharmony_ci        return true;
29c5f01b2fSopenharmony_ci    }
30c5f01b2fSopenharmony_ci
31c5f01b2fSopenharmony_ci    bool boolean(bool val)
32c5f01b2fSopenharmony_ci    {
33c5f01b2fSopenharmony_ci        events.emplace_back(val ? "boolean(true)" : "boolean(false)");
34c5f01b2fSopenharmony_ci        return true;
35c5f01b2fSopenharmony_ci    }
36c5f01b2fSopenharmony_ci
37c5f01b2fSopenharmony_ci    bool number_integer(json::number_integer_t val)
38c5f01b2fSopenharmony_ci    {
39c5f01b2fSopenharmony_ci        events.push_back("number_integer(" + std::to_string(val) + ")");
40c5f01b2fSopenharmony_ci        return true;
41c5f01b2fSopenharmony_ci    }
42c5f01b2fSopenharmony_ci
43c5f01b2fSopenharmony_ci    bool number_unsigned(json::number_unsigned_t val)
44c5f01b2fSopenharmony_ci    {
45c5f01b2fSopenharmony_ci        events.push_back("number_unsigned(" + std::to_string(val) + ")");
46c5f01b2fSopenharmony_ci        return true;
47c5f01b2fSopenharmony_ci    }
48c5f01b2fSopenharmony_ci
49c5f01b2fSopenharmony_ci    bool number_float(json::number_float_t /*unused*/, const std::string& s)
50c5f01b2fSopenharmony_ci    {
51c5f01b2fSopenharmony_ci        events.push_back("number_float(" + s + ")");
52c5f01b2fSopenharmony_ci        return true;
53c5f01b2fSopenharmony_ci    }
54c5f01b2fSopenharmony_ci
55c5f01b2fSopenharmony_ci    bool string(std::string& val)
56c5f01b2fSopenharmony_ci    {
57c5f01b2fSopenharmony_ci        events.push_back("string(" + val + ")");
58c5f01b2fSopenharmony_ci        return true;
59c5f01b2fSopenharmony_ci    }
60c5f01b2fSopenharmony_ci
61c5f01b2fSopenharmony_ci    bool binary(json::binary_t& val)
62c5f01b2fSopenharmony_ci    {
63c5f01b2fSopenharmony_ci        std::string binary_contents = "binary(";
64c5f01b2fSopenharmony_ci        std::string comma_space;
65c5f01b2fSopenharmony_ci        for (auto b : val)
66c5f01b2fSopenharmony_ci        {
67c5f01b2fSopenharmony_ci            binary_contents.append(comma_space);
68c5f01b2fSopenharmony_ci            binary_contents.append(std::to_string(static_cast<int>(b)));
69c5f01b2fSopenharmony_ci            comma_space = ", ";
70c5f01b2fSopenharmony_ci        }
71c5f01b2fSopenharmony_ci        binary_contents.append(")");
72c5f01b2fSopenharmony_ci        events.push_back(binary_contents);
73c5f01b2fSopenharmony_ci        return true;
74c5f01b2fSopenharmony_ci    }
75c5f01b2fSopenharmony_ci
76c5f01b2fSopenharmony_ci    bool start_object(std::size_t elements)
77c5f01b2fSopenharmony_ci    {
78c5f01b2fSopenharmony_ci        if (elements == static_cast<std::size_t>(-1))
79c5f01b2fSopenharmony_ci        {
80c5f01b2fSopenharmony_ci            events.emplace_back("start_object()");
81c5f01b2fSopenharmony_ci        }
82c5f01b2fSopenharmony_ci        else
83c5f01b2fSopenharmony_ci        {
84c5f01b2fSopenharmony_ci            events.push_back("start_object(" + std::to_string(elements) + ")");
85c5f01b2fSopenharmony_ci        }
86c5f01b2fSopenharmony_ci        return true;
87c5f01b2fSopenharmony_ci    }
88c5f01b2fSopenharmony_ci
89c5f01b2fSopenharmony_ci    bool key(std::string& val)
90c5f01b2fSopenharmony_ci    {
91c5f01b2fSopenharmony_ci        events.push_back("key(" + val + ")");
92c5f01b2fSopenharmony_ci        return true;
93c5f01b2fSopenharmony_ci    }
94c5f01b2fSopenharmony_ci
95c5f01b2fSopenharmony_ci    bool end_object()
96c5f01b2fSopenharmony_ci    {
97c5f01b2fSopenharmony_ci        events.emplace_back("end_object()");
98c5f01b2fSopenharmony_ci        return true;
99c5f01b2fSopenharmony_ci    }
100c5f01b2fSopenharmony_ci
101c5f01b2fSopenharmony_ci    bool start_array(std::size_t elements)
102c5f01b2fSopenharmony_ci    {
103c5f01b2fSopenharmony_ci        if (elements == static_cast<std::size_t>(-1))
104c5f01b2fSopenharmony_ci        {
105c5f01b2fSopenharmony_ci            events.emplace_back("start_array()");
106c5f01b2fSopenharmony_ci        }
107c5f01b2fSopenharmony_ci        else
108c5f01b2fSopenharmony_ci        {
109c5f01b2fSopenharmony_ci            events.push_back("start_array(" + std::to_string(elements) + ")");
110c5f01b2fSopenharmony_ci        }
111c5f01b2fSopenharmony_ci        return true;
112c5f01b2fSopenharmony_ci    }
113c5f01b2fSopenharmony_ci
114c5f01b2fSopenharmony_ci    bool end_array()
115c5f01b2fSopenharmony_ci    {
116c5f01b2fSopenharmony_ci        events.emplace_back("end_array()");
117c5f01b2fSopenharmony_ci        return true;
118c5f01b2fSopenharmony_ci    }
119c5f01b2fSopenharmony_ci
120c5f01b2fSopenharmony_ci    bool parse_error(std::size_t position, const std::string& /*unused*/, const json::exception& /*unused*/)
121c5f01b2fSopenharmony_ci    {
122c5f01b2fSopenharmony_ci        errored = true;
123c5f01b2fSopenharmony_ci        events.push_back("parse_error(" + std::to_string(position) + ")");
124c5f01b2fSopenharmony_ci        return false;
125c5f01b2fSopenharmony_ci    }
126c5f01b2fSopenharmony_ci
127c5f01b2fSopenharmony_ci    std::vector<std::string> events {};
128c5f01b2fSopenharmony_ci    bool errored = false;
129c5f01b2fSopenharmony_ci};
130c5f01b2fSopenharmony_ci
131c5f01b2fSopenharmony_ciclass SaxCountdown : public nlohmann::json::json_sax_t
132c5f01b2fSopenharmony_ci{
133c5f01b2fSopenharmony_ci  public:
134c5f01b2fSopenharmony_ci    explicit SaxCountdown(const int count) : events_left(count)
135c5f01b2fSopenharmony_ci    {}
136c5f01b2fSopenharmony_ci
137c5f01b2fSopenharmony_ci    bool null() override
138c5f01b2fSopenharmony_ci    {
139c5f01b2fSopenharmony_ci        return events_left-- > 0;
140c5f01b2fSopenharmony_ci    }
141c5f01b2fSopenharmony_ci
142c5f01b2fSopenharmony_ci    bool boolean(bool /*val*/) override
143c5f01b2fSopenharmony_ci    {
144c5f01b2fSopenharmony_ci        return events_left-- > 0;
145c5f01b2fSopenharmony_ci    }
146c5f01b2fSopenharmony_ci
147c5f01b2fSopenharmony_ci    bool number_integer(json::number_integer_t /*val*/) override
148c5f01b2fSopenharmony_ci    {
149c5f01b2fSopenharmony_ci        return events_left-- > 0;
150c5f01b2fSopenharmony_ci    }
151c5f01b2fSopenharmony_ci
152c5f01b2fSopenharmony_ci    bool number_unsigned(json::number_unsigned_t /*val*/) override
153c5f01b2fSopenharmony_ci    {
154c5f01b2fSopenharmony_ci        return events_left-- > 0;
155c5f01b2fSopenharmony_ci    }
156c5f01b2fSopenharmony_ci
157c5f01b2fSopenharmony_ci    bool number_float(json::number_float_t /*val*/, const std::string& /*s*/) override
158c5f01b2fSopenharmony_ci    {
159c5f01b2fSopenharmony_ci        return events_left-- > 0;
160c5f01b2fSopenharmony_ci    }
161c5f01b2fSopenharmony_ci
162c5f01b2fSopenharmony_ci    bool string(std::string& /*val*/) override
163c5f01b2fSopenharmony_ci    {
164c5f01b2fSopenharmony_ci        return events_left-- > 0;
165c5f01b2fSopenharmony_ci    }
166c5f01b2fSopenharmony_ci
167c5f01b2fSopenharmony_ci    bool binary(json::binary_t& /*val*/) override
168c5f01b2fSopenharmony_ci    {
169c5f01b2fSopenharmony_ci        return events_left-- > 0;
170c5f01b2fSopenharmony_ci    }
171c5f01b2fSopenharmony_ci
172c5f01b2fSopenharmony_ci    bool start_object(std::size_t /*elements*/) override
173c5f01b2fSopenharmony_ci    {
174c5f01b2fSopenharmony_ci        return events_left-- > 0;
175c5f01b2fSopenharmony_ci    }
176c5f01b2fSopenharmony_ci
177c5f01b2fSopenharmony_ci    bool key(std::string& /*val*/) override
178c5f01b2fSopenharmony_ci    {
179c5f01b2fSopenharmony_ci        return events_left-- > 0;
180c5f01b2fSopenharmony_ci    }
181c5f01b2fSopenharmony_ci
182c5f01b2fSopenharmony_ci    bool end_object() override
183c5f01b2fSopenharmony_ci    {
184c5f01b2fSopenharmony_ci        return events_left-- > 0;
185c5f01b2fSopenharmony_ci    }
186c5f01b2fSopenharmony_ci
187c5f01b2fSopenharmony_ci    bool start_array(std::size_t /*elements*/) override
188c5f01b2fSopenharmony_ci    {
189c5f01b2fSopenharmony_ci        return events_left-- > 0;
190c5f01b2fSopenharmony_ci    }
191c5f01b2fSopenharmony_ci
192c5f01b2fSopenharmony_ci    bool end_array() override
193c5f01b2fSopenharmony_ci    {
194c5f01b2fSopenharmony_ci        return events_left-- > 0;
195c5f01b2fSopenharmony_ci    }
196c5f01b2fSopenharmony_ci
197c5f01b2fSopenharmony_ci    bool parse_error(std::size_t /*position*/, const std::string& /*last_token*/, const json::exception& /*ex*/) override
198c5f01b2fSopenharmony_ci    {
199c5f01b2fSopenharmony_ci        return false;
200c5f01b2fSopenharmony_ci    }
201c5f01b2fSopenharmony_ci
202c5f01b2fSopenharmony_ci  private:
203c5f01b2fSopenharmony_ci    int events_left = 0;
204c5f01b2fSopenharmony_ci};
205c5f01b2fSopenharmony_ci
206c5f01b2fSopenharmony_cijson parser_helper(const std::string& s);
207c5f01b2fSopenharmony_cibool accept_helper(const std::string& s);
208c5f01b2fSopenharmony_civoid comments_helper(const std::string& s);
209c5f01b2fSopenharmony_ci
210c5f01b2fSopenharmony_cijson parser_helper(const std::string& s)
211c5f01b2fSopenharmony_ci{
212c5f01b2fSopenharmony_ci    json j;
213c5f01b2fSopenharmony_ci    json::parser(nlohmann::detail::input_adapter(s)).parse(true, j);
214c5f01b2fSopenharmony_ci
215c5f01b2fSopenharmony_ci    // if this line was reached, no exception occurred
216c5f01b2fSopenharmony_ci    // -> check if result is the same without exceptions
217c5f01b2fSopenharmony_ci    json j_nothrow;
218c5f01b2fSopenharmony_ci    CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j_nothrow));
219c5f01b2fSopenharmony_ci    CHECK(j_nothrow == j);
220c5f01b2fSopenharmony_ci
221c5f01b2fSopenharmony_ci    json j_sax;
222c5f01b2fSopenharmony_ci    nlohmann::detail::json_sax_dom_parser<json> sdp(j_sax);
223c5f01b2fSopenharmony_ci    json::sax_parse(s, &sdp);
224c5f01b2fSopenharmony_ci    CHECK(j_sax == j);
225c5f01b2fSopenharmony_ci
226c5f01b2fSopenharmony_ci    comments_helper(s);
227c5f01b2fSopenharmony_ci
228c5f01b2fSopenharmony_ci    return j;
229c5f01b2fSopenharmony_ci}
230c5f01b2fSopenharmony_ci
231c5f01b2fSopenharmony_cibool accept_helper(const std::string& s)
232c5f01b2fSopenharmony_ci{
233c5f01b2fSopenharmony_ci    CAPTURE(s)
234c5f01b2fSopenharmony_ci
235c5f01b2fSopenharmony_ci    // 1. parse s without exceptions
236c5f01b2fSopenharmony_ci    json j;
237c5f01b2fSopenharmony_ci    CHECK_NOTHROW(json::parser(nlohmann::detail::input_adapter(s), nullptr, false).parse(true, j));
238c5f01b2fSopenharmony_ci    const bool ok_noexcept = !j.is_discarded();
239c5f01b2fSopenharmony_ci
240c5f01b2fSopenharmony_ci    // 2. accept s
241c5f01b2fSopenharmony_ci    const bool ok_accept = json::parser(nlohmann::detail::input_adapter(s)).accept(true);
242c5f01b2fSopenharmony_ci
243c5f01b2fSopenharmony_ci    // 3. check if both approaches come to the same result
244c5f01b2fSopenharmony_ci    CHECK(ok_noexcept == ok_accept);
245c5f01b2fSopenharmony_ci
246c5f01b2fSopenharmony_ci    // 4. parse with SAX (compare with relaxed accept result)
247c5f01b2fSopenharmony_ci    SaxEventLogger el;
248c5f01b2fSopenharmony_ci    CHECK_NOTHROW(json::sax_parse(s, &el, json::input_format_t::json, false));
249c5f01b2fSopenharmony_ci    CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept(false) == !el.errored);
250c5f01b2fSopenharmony_ci
251c5f01b2fSopenharmony_ci    // 5. parse with simple callback
252c5f01b2fSopenharmony_ci    json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept
253c5f01b2fSopenharmony_ci    {
254c5f01b2fSopenharmony_ci        return true;
255c5f01b2fSopenharmony_ci    };
256c5f01b2fSopenharmony_ci    json j_cb = json::parse(s, cb, false);
257c5f01b2fSopenharmony_ci    const bool ok_noexcept_cb = !j_cb.is_discarded();
258c5f01b2fSopenharmony_ci
259c5f01b2fSopenharmony_ci    // 6. check if this approach came to the same result
260c5f01b2fSopenharmony_ci    CHECK(ok_noexcept == ok_noexcept_cb);
261c5f01b2fSopenharmony_ci
262c5f01b2fSopenharmony_ci    // 7. check if comments are properly ignored
263c5f01b2fSopenharmony_ci    if (ok_accept)
264c5f01b2fSopenharmony_ci    {
265c5f01b2fSopenharmony_ci        comments_helper(s);
266c5f01b2fSopenharmony_ci    }
267c5f01b2fSopenharmony_ci
268c5f01b2fSopenharmony_ci    // 8. return result
269c5f01b2fSopenharmony_ci    return ok_accept;
270c5f01b2fSopenharmony_ci}
271c5f01b2fSopenharmony_ci
272c5f01b2fSopenharmony_civoid comments_helper(const std::string& s)
273c5f01b2fSopenharmony_ci{
274c5f01b2fSopenharmony_ci    json _;
275c5f01b2fSopenharmony_ci
276c5f01b2fSopenharmony_ci    // parse/accept with default parser
277c5f01b2fSopenharmony_ci    CHECK_NOTHROW(_ = json::parse(s));
278c5f01b2fSopenharmony_ci    CHECK(json::accept(s));
279c5f01b2fSopenharmony_ci
280c5f01b2fSopenharmony_ci    // parse/accept while skipping comments
281c5f01b2fSopenharmony_ci    CHECK_NOTHROW(_ = json::parse(s, nullptr, false, true));
282c5f01b2fSopenharmony_ci    CHECK(json::accept(s, true));
283c5f01b2fSopenharmony_ci
284c5f01b2fSopenharmony_ci    std::vector<std::string> json_with_comments;
285c5f01b2fSopenharmony_ci
286c5f01b2fSopenharmony_ci    // start with a comment
287c5f01b2fSopenharmony_ci    json_with_comments.push_back(std::string("// this is a comment\n") + s);
288c5f01b2fSopenharmony_ci    json_with_comments.push_back(std::string("/* this is a comment */") + s);
289c5f01b2fSopenharmony_ci    // end with a comment
290c5f01b2fSopenharmony_ci    json_with_comments.push_back(s + "// this is a comment");
291c5f01b2fSopenharmony_ci    json_with_comments.push_back(s + "/* this is a comment */");
292c5f01b2fSopenharmony_ci
293c5f01b2fSopenharmony_ci    // check all strings
294c5f01b2fSopenharmony_ci    for (const auto& json_with_comment : json_with_comments)
295c5f01b2fSopenharmony_ci    {
296c5f01b2fSopenharmony_ci        CAPTURE(json_with_comment)
297c5f01b2fSopenharmony_ci        CHECK_THROWS_AS(_ = json::parse(json_with_comment), json::parse_error);
298c5f01b2fSopenharmony_ci        CHECK(!json::accept(json_with_comment));
299c5f01b2fSopenharmony_ci
300c5f01b2fSopenharmony_ci        CHECK_NOTHROW(_ = json::parse(json_with_comment, nullptr, true, true));
301c5f01b2fSopenharmony_ci        CHECK(json::accept(json_with_comment, true));
302c5f01b2fSopenharmony_ci    }
303c5f01b2fSopenharmony_ci}
304c5f01b2fSopenharmony_ci
305c5f01b2fSopenharmony_ci} // namespace
306c5f01b2fSopenharmony_ci
307c5f01b2fSopenharmony_ciTEST_CASE("parser class")
308c5f01b2fSopenharmony_ci{
309c5f01b2fSopenharmony_ci    SECTION("parse")
310c5f01b2fSopenharmony_ci    {
311c5f01b2fSopenharmony_ci        SECTION("null")
312c5f01b2fSopenharmony_ci        {
313c5f01b2fSopenharmony_ci            CHECK(parser_helper("null") == json(nullptr));
314c5f01b2fSopenharmony_ci        }
315c5f01b2fSopenharmony_ci
316c5f01b2fSopenharmony_ci        SECTION("true")
317c5f01b2fSopenharmony_ci        {
318c5f01b2fSopenharmony_ci            CHECK(parser_helper("true") == json(true));
319c5f01b2fSopenharmony_ci        }
320c5f01b2fSopenharmony_ci
321c5f01b2fSopenharmony_ci        SECTION("false")
322c5f01b2fSopenharmony_ci        {
323c5f01b2fSopenharmony_ci            CHECK(parser_helper("false") == json(false));
324c5f01b2fSopenharmony_ci        }
325c5f01b2fSopenharmony_ci
326c5f01b2fSopenharmony_ci        SECTION("array")
327c5f01b2fSopenharmony_ci        {
328c5f01b2fSopenharmony_ci            SECTION("empty array")
329c5f01b2fSopenharmony_ci            {
330c5f01b2fSopenharmony_ci                CHECK(parser_helper("[]") == json(json::value_t::array));
331c5f01b2fSopenharmony_ci                CHECK(parser_helper("[ ]") == json(json::value_t::array));
332c5f01b2fSopenharmony_ci            }
333c5f01b2fSopenharmony_ci
334c5f01b2fSopenharmony_ci            SECTION("nonempty array")
335c5f01b2fSopenharmony_ci            {
336c5f01b2fSopenharmony_ci                CHECK(parser_helper("[true, false, null]") == json({true, false, nullptr}));
337c5f01b2fSopenharmony_ci            }
338c5f01b2fSopenharmony_ci        }
339c5f01b2fSopenharmony_ci
340c5f01b2fSopenharmony_ci        SECTION("object")
341c5f01b2fSopenharmony_ci        {
342c5f01b2fSopenharmony_ci            SECTION("empty object")
343c5f01b2fSopenharmony_ci            {
344c5f01b2fSopenharmony_ci                CHECK(parser_helper("{}") == json(json::value_t::object));
345c5f01b2fSopenharmony_ci                CHECK(parser_helper("{ }") == json(json::value_t::object));
346c5f01b2fSopenharmony_ci            }
347c5f01b2fSopenharmony_ci
348c5f01b2fSopenharmony_ci            SECTION("nonempty object")
349c5f01b2fSopenharmony_ci            {
350c5f01b2fSopenharmony_ci                CHECK(parser_helper("{\"\": true, \"one\": 1, \"two\": null}") == json({{"", true}, {"one", 1}, {"two", nullptr}}));
351c5f01b2fSopenharmony_ci            }
352c5f01b2fSopenharmony_ci        }
353c5f01b2fSopenharmony_ci
354c5f01b2fSopenharmony_ci        SECTION("string")
355c5f01b2fSopenharmony_ci        {
356c5f01b2fSopenharmony_ci            // empty string
357c5f01b2fSopenharmony_ci            CHECK(parser_helper("\"\"") == json(json::value_t::string));
358c5f01b2fSopenharmony_ci
359c5f01b2fSopenharmony_ci            SECTION("errors")
360c5f01b2fSopenharmony_ci            {
361c5f01b2fSopenharmony_ci                // error: tab in string
362c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\t\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"<U+0009>'", json::parse_error&);
363c5f01b2fSopenharmony_ci                // error: newline in string
364c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\n\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"<U+000A>'", json::parse_error&);
365c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\r\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"<U+000D>'", json::parse_error&);
366c5f01b2fSopenharmony_ci                // error: backspace in string
367c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"<U+0008>'", json::parse_error&);
368c5f01b2fSopenharmony_ci                // improve code coverage
369c5f01b2fSopenharmony_ci                CHECK_THROWS_AS(parser_helper("\uFF01"), json::parse_error&);
370c5f01b2fSopenharmony_ci                CHECK_THROWS_AS(parser_helper("[-4:1,]"), json::parse_error&);
371c5f01b2fSopenharmony_ci                // unescaped control characters
372c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x00\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'", json::parse_error&); // NOLINT(bugprone-string-literal-with-embedded-nul)
373c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x01\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0001 (SOH) must be escaped to \\u0001; last read: '\"<U+0001>'", json::parse_error&);
374c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x02\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0002 (STX) must be escaped to \\u0002; last read: '\"<U+0002>'", json::parse_error&);
375c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x03\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0003 (ETX) must be escaped to \\u0003; last read: '\"<U+0003>'", json::parse_error&);
376c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x04\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0004 (EOT) must be escaped to \\u0004; last read: '\"<U+0004>'", json::parse_error&);
377c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x05\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0005 (ENQ) must be escaped to \\u0005; last read: '\"<U+0005>'", json::parse_error&);
378c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x06\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0006 (ACK) must be escaped to \\u0006; last read: '\"<U+0006>'", json::parse_error&);
379c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x07\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0007 (BEL) must be escaped to \\u0007; last read: '\"<U+0007>'", json::parse_error&);
380c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x08\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0008 (BS) must be escaped to \\u0008 or \\b; last read: '\"<U+0008>'", json::parse_error&);
381c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x09\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0009 (HT) must be escaped to \\u0009 or \\t; last read: '\"<U+0009>'", json::parse_error&);
382c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x0a\""), "[json.exception.parse_error.101] parse error at line 2, column 0: syntax error while parsing value - invalid string: control character U+000A (LF) must be escaped to \\u000A or \\n; last read: '\"<U+000A>'", json::parse_error&);
383c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x0b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000B (VT) must be escaped to \\u000B; last read: '\"<U+000B>'", json::parse_error&);
384c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x0c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000C (FF) must be escaped to \\u000C or \\f; last read: '\"<U+000C>'", json::parse_error&);
385c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x0d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000D (CR) must be escaped to \\u000D or \\r; last read: '\"<U+000D>'", json::parse_error&);
386c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x0e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000E (SO) must be escaped to \\u000E; last read: '\"<U+000E>'", json::parse_error&);
387c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x0f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+000F (SI) must be escaped to \\u000F; last read: '\"<U+000F>'", json::parse_error&);
388c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x10\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0010 (DLE) must be escaped to \\u0010; last read: '\"<U+0010>'", json::parse_error&);
389c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x11\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0011 (DC1) must be escaped to \\u0011; last read: '\"<U+0011>'", json::parse_error&);
390c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x12\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0012 (DC2) must be escaped to \\u0012; last read: '\"<U+0012>'", json::parse_error&);
391c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x13\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0013 (DC3) must be escaped to \\u0013; last read: '\"<U+0013>'", json::parse_error&);
392c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x14\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0014 (DC4) must be escaped to \\u0014; last read: '\"<U+0014>'", json::parse_error&);
393c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x15\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0015 (NAK) must be escaped to \\u0015; last read: '\"<U+0015>'", json::parse_error&);
394c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x16\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0016 (SYN) must be escaped to \\u0016; last read: '\"<U+0016>'", json::parse_error&);
395c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x17\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0017 (ETB) must be escaped to \\u0017; last read: '\"<U+0017>'", json::parse_error&);
396c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x18\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0018 (CAN) must be escaped to \\u0018; last read: '\"<U+0018>'", json::parse_error&);
397c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x19\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0019 (EM) must be escaped to \\u0019; last read: '\"<U+0019>'", json::parse_error&);
398c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x1a\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001A (SUB) must be escaped to \\u001A; last read: '\"<U+001A>'", json::parse_error&);
399c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x1b\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001B (ESC) must be escaped to \\u001B; last read: '\"<U+001B>'", json::parse_error&);
400c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x1c\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001C (FS) must be escaped to \\u001C; last read: '\"<U+001C>'", json::parse_error&);
401c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x1d\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001D (GS) must be escaped to \\u001D; last read: '\"<U+001D>'", json::parse_error&);
402c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x1e\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001E (RS) must be escaped to \\u001E; last read: '\"<U+001E>'", json::parse_error&);
403c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("\"\x1f\""), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+001F (US) must be escaped to \\u001F; last read: '\"<U+001F>'", json::parse_error&);
404c5f01b2fSopenharmony_ci
405c5f01b2fSopenharmony_ci                SECTION("additional test for null byte")
406c5f01b2fSopenharmony_ci                {
407c5f01b2fSopenharmony_ci                    // The test above for the null byte is wrong, because passing
408c5f01b2fSopenharmony_ci                    // a string to the parser only reads int until it encounters
409c5f01b2fSopenharmony_ci                    // a null byte. This test inserts the null byte later on and
410c5f01b2fSopenharmony_ci                    // uses an iterator range.
411c5f01b2fSopenharmony_ci                    std::string s = "\"1\"";
412c5f01b2fSopenharmony_ci                    s[1] = '\0';
413c5f01b2fSopenharmony_ci                    json _;
414c5f01b2fSopenharmony_ci                    CHECK_THROWS_WITH_AS(_ = json::parse(s.begin(), s.end()), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: control character U+0000 (NUL) must be escaped to \\u0000; last read: '\"<U+0000>'", json::parse_error&);
415c5f01b2fSopenharmony_ci                }
416c5f01b2fSopenharmony_ci            }
417c5f01b2fSopenharmony_ci
418c5f01b2fSopenharmony_ci            SECTION("escaped")
419c5f01b2fSopenharmony_ci            {
420c5f01b2fSopenharmony_ci                // quotation mark "\""
421c5f01b2fSopenharmony_ci                auto r1 = R"("\"")"_json;
422c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\\"\"") == r1);
423c5f01b2fSopenharmony_ci                // reverse solidus "\\"
424c5f01b2fSopenharmony_ci                auto r2 = R"("\\")"_json;
425c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\\\\"") == r2);
426c5f01b2fSopenharmony_ci                // solidus
427c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\/\"") == R"("/")"_json);
428c5f01b2fSopenharmony_ci                // backspace
429c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\b\"") == json("\b"));
430c5f01b2fSopenharmony_ci                // formfeed
431c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\f\"") == json("\f"));
432c5f01b2fSopenharmony_ci                // newline
433c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\n\"") == json("\n"));
434c5f01b2fSopenharmony_ci                // carriage return
435c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\r\"") == json("\r"));
436c5f01b2fSopenharmony_ci                // horizontal tab
437c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\t\"") == json("\t"));
438c5f01b2fSopenharmony_ci
439c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u0001\"").get<json::string_t>() == "\x01");
440c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u000a\"").get<json::string_t>() == "\n");
441c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u00b0\"").get<json::string_t>() == "°");
442c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u0c00\"").get<json::string_t>() == "ఀ");
443c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\ud000\"").get<json::string_t>() == "퀀");
444c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u000E\"").get<json::string_t>() == "\x0E");
445c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u00F0\"").get<json::string_t>() == "ð");
446c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u0100\"").get<json::string_t>() == "Ā");
447c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u2000\"").get<json::string_t>() == " ");
448c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\uFFFF\"").get<json::string_t>() == "￿");
449c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\u20AC\"").get<json::string_t>() == "€");
450c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"€\"").get<json::string_t>() == "€");
451c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"�\"").get<json::string_t>() == "�");
452c5f01b2fSopenharmony_ci
453c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\ud80c\\udc60\"").get<json::string_t>() == "\xf0\x93\x81\xa0");
454c5f01b2fSopenharmony_ci                CHECK(parser_helper("\"\\ud83c\\udf1e\"").get<json::string_t>() == "�");
455c5f01b2fSopenharmony_ci            }
456c5f01b2fSopenharmony_ci        }
457c5f01b2fSopenharmony_ci
458c5f01b2fSopenharmony_ci        SECTION("number")
459c5f01b2fSopenharmony_ci        {
460c5f01b2fSopenharmony_ci            SECTION("integers")
461c5f01b2fSopenharmony_ci            {
462c5f01b2fSopenharmony_ci                SECTION("without exponent")
463c5f01b2fSopenharmony_ci                {
464c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-128") == json(-128));
465c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0") == json(-0));
466c5f01b2fSopenharmony_ci                    CHECK(parser_helper("0") == json(0));
467c5f01b2fSopenharmony_ci                    CHECK(parser_helper("128") == json(128));
468c5f01b2fSopenharmony_ci                }
469c5f01b2fSopenharmony_ci
470c5f01b2fSopenharmony_ci                SECTION("with exponent")
471c5f01b2fSopenharmony_ci                {
472c5f01b2fSopenharmony_ci                    CHECK(parser_helper("0e1") == json(0e1));
473c5f01b2fSopenharmony_ci                    CHECK(parser_helper("0E1") == json(0e1));
474c5f01b2fSopenharmony_ci
475c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E-4") == json(10000e-4));
476c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E-3") == json(10000e-3));
477c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E-2") == json(10000e-2));
478c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E-1") == json(10000e-1));
479c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E0") == json(10000e0));
480c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E1") == json(10000e1));
481c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E2") == json(10000e2));
482c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E3") == json(10000e3));
483c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000E4") == json(10000e4));
484c5f01b2fSopenharmony_ci
485c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e-4") == json(10000e-4));
486c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e-3") == json(10000e-3));
487c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e-2") == json(10000e-2));
488c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e-1") == json(10000e-1));
489c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e0") == json(10000e0));
490c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e1") == json(10000e1));
491c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e2") == json(10000e2));
492c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e3") == json(10000e3));
493c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10000e4") == json(10000e4));
494c5f01b2fSopenharmony_ci
495c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0e1") == json(-0e1));
496c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0E1") == json(-0e1));
497c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0E123") == json(-0e123));
498c5f01b2fSopenharmony_ci
499c5f01b2fSopenharmony_ci                    // numbers after exponent
500c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E0") == json(10e0));
501c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E1") == json(10e1));
502c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E2") == json(10e2));
503c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E3") == json(10e3));
504c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E4") == json(10e4));
505c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E5") == json(10e5));
506c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E6") == json(10e6));
507c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E7") == json(10e7));
508c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E8") == json(10e8));
509c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E9") == json(10e9));
510c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+0") == json(10e0));
511c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+1") == json(10e1));
512c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+2") == json(10e2));
513c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+3") == json(10e3));
514c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+4") == json(10e4));
515c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+5") == json(10e5));
516c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+6") == json(10e6));
517c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+7") == json(10e7));
518c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+8") == json(10e8));
519c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E+9") == json(10e9));
520c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-1") == json(10e-1));
521c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-2") == json(10e-2));
522c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-3") == json(10e-3));
523c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-4") == json(10e-4));
524c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-5") == json(10e-5));
525c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-6") == json(10e-6));
526c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-7") == json(10e-7));
527c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-8") == json(10e-8));
528c5f01b2fSopenharmony_ci                    CHECK(parser_helper("10E-9") == json(10e-9));
529c5f01b2fSopenharmony_ci                }
530c5f01b2fSopenharmony_ci
531c5f01b2fSopenharmony_ci                SECTION("edge cases")
532c5f01b2fSopenharmony_ci                {
533c5f01b2fSopenharmony_ci                    // From RFC8259, Section 6:
534c5f01b2fSopenharmony_ci                    // Note that when such software is used, numbers that are
535c5f01b2fSopenharmony_ci                    // integers and are in the range [-(2**53)+1, (2**53)-1]
536c5f01b2fSopenharmony_ci                    // are interoperable in the sense that implementations will
537c5f01b2fSopenharmony_ci                    // agree exactly on their numeric values.
538c5f01b2fSopenharmony_ci
539c5f01b2fSopenharmony_ci                    // -(2**53)+1
540c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-9007199254740991").get<int64_t>() == -9007199254740991);
541c5f01b2fSopenharmony_ci                    // (2**53)-1
542c5f01b2fSopenharmony_ci                    CHECK(parser_helper("9007199254740991").get<int64_t>() == 9007199254740991);
543c5f01b2fSopenharmony_ci                }
544c5f01b2fSopenharmony_ci
545c5f01b2fSopenharmony_ci                SECTION("over the edge cases")  // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
546c5f01b2fSopenharmony_ci                {
547c5f01b2fSopenharmony_ci                    // While RFC8259, Section 6 specifies a preference for support
548c5f01b2fSopenharmony_ci                    // for ranges in range of IEEE 754-2008 binary64 (double precision)
549c5f01b2fSopenharmony_ci                    // this does not accommodate 64 bit integers without loss of accuracy.
550c5f01b2fSopenharmony_ci                    // As 64 bit integers are now widely used in software, it is desirable
551c5f01b2fSopenharmony_ci                    // to expand support to to the full 64 bit (signed and unsigned) range
552c5f01b2fSopenharmony_ci                    // i.e. -(2**63) -> (2**64)-1.
553c5f01b2fSopenharmony_ci
554c5f01b2fSopenharmony_ci                    // -(2**63)    ** Note: compilers see negative literals as negated positive numbers (hence the -1))
555c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-9223372036854775808").get<int64_t>() == -9223372036854775807 - 1);
556c5f01b2fSopenharmony_ci                    // (2**63)-1
557c5f01b2fSopenharmony_ci                    CHECK(parser_helper("9223372036854775807").get<int64_t>() == 9223372036854775807);
558c5f01b2fSopenharmony_ci                    // (2**64)-1
559c5f01b2fSopenharmony_ci                    CHECK(parser_helper("18446744073709551615").get<uint64_t>() == 18446744073709551615u);
560c5f01b2fSopenharmony_ci                }
561c5f01b2fSopenharmony_ci            }
562c5f01b2fSopenharmony_ci
563c5f01b2fSopenharmony_ci            SECTION("floating-point")
564c5f01b2fSopenharmony_ci            {
565c5f01b2fSopenharmony_ci                SECTION("without exponent")
566c5f01b2fSopenharmony_ci                {
567c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-128.5") == json(-128.5));
568c5f01b2fSopenharmony_ci                    CHECK(parser_helper("0.999") == json(0.999));
569c5f01b2fSopenharmony_ci                    CHECK(parser_helper("128.5") == json(128.5));
570c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0.0") == json(-0.0));
571c5f01b2fSopenharmony_ci                }
572c5f01b2fSopenharmony_ci
573c5f01b2fSopenharmony_ci                SECTION("with exponent")
574c5f01b2fSopenharmony_ci                {
575c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-128.5E3") == json(-128.5E3));
576c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-128.5E-3") == json(-128.5E-3));
577c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0.0e1") == json(-0.0e1));
578c5f01b2fSopenharmony_ci                    CHECK(parser_helper("-0.0E1") == json(-0.0e1));
579c5f01b2fSopenharmony_ci                }
580c5f01b2fSopenharmony_ci            }
581c5f01b2fSopenharmony_ci
582c5f01b2fSopenharmony_ci            SECTION("overflow")
583c5f01b2fSopenharmony_ci            {
584c5f01b2fSopenharmony_ci                // overflows during parsing yield an exception
585c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("1.18973e+4932").empty(), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'", json::out_of_range&);
586c5f01b2fSopenharmony_ci            }
587c5f01b2fSopenharmony_ci
588c5f01b2fSopenharmony_ci            SECTION("invalid numbers")
589c5f01b2fSopenharmony_ci            {
590c5f01b2fSopenharmony_ci                // numbers must not begin with "+"
591c5f01b2fSopenharmony_ci                CHECK_THROWS_AS(parser_helper("+1"), json::parse_error&);
592c5f01b2fSopenharmony_ci                CHECK_THROWS_AS(parser_helper("+0"), json::parse_error&);
593c5f01b2fSopenharmony_ci
594c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("01"),
595c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected number literal; expected end of input", json::parse_error&);
596c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-01"),
597c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - unexpected number literal; expected end of input", json::parse_error&);
598c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("--1"),
599c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'", json::parse_error&);
600c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("1."),
601c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.'", json::parse_error&);
602c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("1E"),
603c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E'", json::parse_error&);
604c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("1E-"),
605c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '1E-'", json::parse_error&);
606c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("1.E1"),
607c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '1.E'", json::parse_error&);
608c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-1E"),
609c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-1E'", json::parse_error&);
610c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0E#"),
611c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '-0E#'", json::parse_error&);
612c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0E-#"),
613c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0E-#'", json::parse_error&);
614c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0#"),
615c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: '-0#'; expected end of input", json::parse_error&);
616c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0.0:"),
617c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - unexpected ':'; expected end of input", json::parse_error&);
618c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0.0Z"),
619c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: '-0.0Z'; expected end of input", json::parse_error&);
620c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0E123:"),
621c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - unexpected ':'; expected end of input", json::parse_error&);
622c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0e0-:"),
623c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'; expected end of input", json::parse_error&);
624c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0e-:"),
625c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid number; expected digit after exponent sign; last read: '-0e-:'", json::parse_error&);
626c5f01b2fSopenharmony_ci                CHECK_THROWS_WITH_AS(parser_helper("-0f"),
627c5f01b2fSopenharmony_ci                                     "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: '-0f'; expected end of input", json::parse_error&);
628c5f01b2fSopenharmony_ci            }
629c5f01b2fSopenharmony_ci        }
630c5f01b2fSopenharmony_ci    }
631c5f01b2fSopenharmony_ci
632c5f01b2fSopenharmony_ci    SECTION("accept")
633c5f01b2fSopenharmony_ci    {
634c5f01b2fSopenharmony_ci        SECTION("null")
635c5f01b2fSopenharmony_ci        {
636c5f01b2fSopenharmony_ci            CHECK(accept_helper("null"));
637c5f01b2fSopenharmony_ci        }
638c5f01b2fSopenharmony_ci
639c5f01b2fSopenharmony_ci        SECTION("true")
640c5f01b2fSopenharmony_ci        {
641c5f01b2fSopenharmony_ci            CHECK(accept_helper("true"));
642c5f01b2fSopenharmony_ci        }
643c5f01b2fSopenharmony_ci
644c5f01b2fSopenharmony_ci        SECTION("false")
645c5f01b2fSopenharmony_ci        {
646c5f01b2fSopenharmony_ci            CHECK(accept_helper("false"));
647c5f01b2fSopenharmony_ci        }
648c5f01b2fSopenharmony_ci
649c5f01b2fSopenharmony_ci        SECTION("array")
650c5f01b2fSopenharmony_ci        {
651c5f01b2fSopenharmony_ci            SECTION("empty array")
652c5f01b2fSopenharmony_ci            {
653c5f01b2fSopenharmony_ci                CHECK(accept_helper("[]"));
654c5f01b2fSopenharmony_ci                CHECK(accept_helper("[ ]"));
655c5f01b2fSopenharmony_ci            }
656c5f01b2fSopenharmony_ci
657c5f01b2fSopenharmony_ci            SECTION("nonempty array")
658c5f01b2fSopenharmony_ci            {
659c5f01b2fSopenharmony_ci                CHECK(accept_helper("[true, false, null]"));
660c5f01b2fSopenharmony_ci            }
661c5f01b2fSopenharmony_ci        }
662c5f01b2fSopenharmony_ci
663c5f01b2fSopenharmony_ci        SECTION("object")
664c5f01b2fSopenharmony_ci        {
665c5f01b2fSopenharmony_ci            SECTION("empty object")
666c5f01b2fSopenharmony_ci            {
667c5f01b2fSopenharmony_ci                CHECK(accept_helper("{}"));
668c5f01b2fSopenharmony_ci                CHECK(accept_helper("{ }"));
669c5f01b2fSopenharmony_ci            }
670c5f01b2fSopenharmony_ci
671c5f01b2fSopenharmony_ci            SECTION("nonempty object")
672c5f01b2fSopenharmony_ci            {
673c5f01b2fSopenharmony_ci                CHECK(accept_helper("{\"\": true, \"one\": 1, \"two\": null}"));
674c5f01b2fSopenharmony_ci            }
675c5f01b2fSopenharmony_ci        }
676c5f01b2fSopenharmony_ci
677c5f01b2fSopenharmony_ci        SECTION("string")
678c5f01b2fSopenharmony_ci        {
679c5f01b2fSopenharmony_ci            // empty string
680c5f01b2fSopenharmony_ci            CHECK(accept_helper("\"\""));
681c5f01b2fSopenharmony_ci
682c5f01b2fSopenharmony_ci            SECTION("errors")
683c5f01b2fSopenharmony_ci            {
684c5f01b2fSopenharmony_ci                // error: tab in string
685c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\t\"") == false);
686c5f01b2fSopenharmony_ci                // error: newline in string
687c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\n\"") == false);
688c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\r\"") == false);
689c5f01b2fSopenharmony_ci                // error: backspace in string
690c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\b\"") == false);
691c5f01b2fSopenharmony_ci                // improve code coverage
692c5f01b2fSopenharmony_ci                CHECK(accept_helper("\uFF01") == false);
693c5f01b2fSopenharmony_ci                CHECK(accept_helper("[-4:1,]") == false);
694c5f01b2fSopenharmony_ci                // unescaped control characters
695c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x00\"") == false); // NOLINT(bugprone-string-literal-with-embedded-nul)
696c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x01\"") == false);
697c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x02\"") == false);
698c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x03\"") == false);
699c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x04\"") == false);
700c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x05\"") == false);
701c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x06\"") == false);
702c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x07\"") == false);
703c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x08\"") == false);
704c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x09\"") == false);
705c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x0a\"") == false);
706c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x0b\"") == false);
707c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x0c\"") == false);
708c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x0d\"") == false);
709c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x0e\"") == false);
710c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x0f\"") == false);
711c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x10\"") == false);
712c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x11\"") == false);
713c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x12\"") == false);
714c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x13\"") == false);
715c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x14\"") == false);
716c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x15\"") == false);
717c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x16\"") == false);
718c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x17\"") == false);
719c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x18\"") == false);
720c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x19\"") == false);
721c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x1a\"") == false);
722c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x1b\"") == false);
723c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x1c\"") == false);
724c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x1d\"") == false);
725c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x1e\"") == false);
726c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\x1f\"") == false);
727c5f01b2fSopenharmony_ci            }
728c5f01b2fSopenharmony_ci
729c5f01b2fSopenharmony_ci            SECTION("escaped")
730c5f01b2fSopenharmony_ci            {
731c5f01b2fSopenharmony_ci                // quotation mark "\""
732c5f01b2fSopenharmony_ci                auto r1 = R"("\"")"_json;
733c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\\"\""));
734c5f01b2fSopenharmony_ci                // reverse solidus "\\"
735c5f01b2fSopenharmony_ci                auto r2 = R"("\\")"_json;
736c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\\\\""));
737c5f01b2fSopenharmony_ci                // solidus
738c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\/\""));
739c5f01b2fSopenharmony_ci                // backspace
740c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\b\""));
741c5f01b2fSopenharmony_ci                // formfeed
742c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\f\""));
743c5f01b2fSopenharmony_ci                // newline
744c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\n\""));
745c5f01b2fSopenharmony_ci                // carriage return
746c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\r\""));
747c5f01b2fSopenharmony_ci                // horizontal tab
748c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\t\""));
749c5f01b2fSopenharmony_ci
750c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u0001\""));
751c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u000a\""));
752c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u00b0\""));
753c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u0c00\""));
754c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\ud000\""));
755c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u000E\""));
756c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u00F0\""));
757c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u0100\""));
758c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u2000\""));
759c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\uFFFF\""));
760c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\u20AC\""));
761c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"€\""));
762c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"�\""));
763c5f01b2fSopenharmony_ci
764c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\ud80c\\udc60\""));
765c5f01b2fSopenharmony_ci                CHECK(accept_helper("\"\\ud83c\\udf1e\""));
766c5f01b2fSopenharmony_ci            }
767c5f01b2fSopenharmony_ci        }
768c5f01b2fSopenharmony_ci
769c5f01b2fSopenharmony_ci        SECTION("number")
770c5f01b2fSopenharmony_ci        {
771c5f01b2fSopenharmony_ci            SECTION("integers")
772c5f01b2fSopenharmony_ci            {
773c5f01b2fSopenharmony_ci                SECTION("without exponent")
774c5f01b2fSopenharmony_ci                {
775c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-128"));
776c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0"));
777c5f01b2fSopenharmony_ci                    CHECK(accept_helper("0"));
778c5f01b2fSopenharmony_ci                    CHECK(accept_helper("128"));
779c5f01b2fSopenharmony_ci                }
780c5f01b2fSopenharmony_ci
781c5f01b2fSopenharmony_ci                SECTION("with exponent")
782c5f01b2fSopenharmony_ci                {
783c5f01b2fSopenharmony_ci                    CHECK(accept_helper("0e1"));
784c5f01b2fSopenharmony_ci                    CHECK(accept_helper("0E1"));
785c5f01b2fSopenharmony_ci
786c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E-4"));
787c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E-3"));
788c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E-2"));
789c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E-1"));
790c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E0"));
791c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E1"));
792c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E2"));
793c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E3"));
794c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000E4"));
795c5f01b2fSopenharmony_ci
796c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e-4"));
797c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e-3"));
798c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e-2"));
799c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e-1"));
800c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e0"));
801c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e1"));
802c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e2"));
803c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e3"));
804c5f01b2fSopenharmony_ci                    CHECK(accept_helper("10000e4"));
805c5f01b2fSopenharmony_ci
806c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0e1"));
807c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0E1"));
808c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0E123"));
809c5f01b2fSopenharmony_ci                }
810c5f01b2fSopenharmony_ci
811c5f01b2fSopenharmony_ci                SECTION("edge cases")
812c5f01b2fSopenharmony_ci                {
813c5f01b2fSopenharmony_ci                    // From RFC8259, Section 6:
814c5f01b2fSopenharmony_ci                    // Note that when such software is used, numbers that are
815c5f01b2fSopenharmony_ci                    // integers and are in the range [-(2**53)+1, (2**53)-1]
816c5f01b2fSopenharmony_ci                    // are interoperable in the sense that implementations will
817c5f01b2fSopenharmony_ci                    // agree exactly on their numeric values.
818c5f01b2fSopenharmony_ci
819c5f01b2fSopenharmony_ci                    // -(2**53)+1
820c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-9007199254740991"));
821c5f01b2fSopenharmony_ci                    // (2**53)-1
822c5f01b2fSopenharmony_ci                    CHECK(accept_helper("9007199254740991"));
823c5f01b2fSopenharmony_ci                }
824c5f01b2fSopenharmony_ci
825c5f01b2fSopenharmony_ci                SECTION("over the edge cases")  // issue #178 - Integer conversion to unsigned (incorrect handling of 64 bit integers)
826c5f01b2fSopenharmony_ci                {
827c5f01b2fSopenharmony_ci                    // While RFC8259, Section 6 specifies a preference for support
828c5f01b2fSopenharmony_ci                    // for ranges in range of IEEE 754-2008 binary64 (double precision)
829c5f01b2fSopenharmony_ci                    // this does not accommodate 64 bit integers without loss of accuracy.
830c5f01b2fSopenharmony_ci                    // As 64 bit integers are now widely used in software, it is desirable
831c5f01b2fSopenharmony_ci                    // to expand support to to the full 64 bit (signed and unsigned) range
832c5f01b2fSopenharmony_ci                    // i.e. -(2**63) -> (2**64)-1.
833c5f01b2fSopenharmony_ci
834c5f01b2fSopenharmony_ci                    // -(2**63)    ** Note: compilers see negative literals as negated positive numbers (hence the -1))
835c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-9223372036854775808"));
836c5f01b2fSopenharmony_ci                    // (2**63)-1
837c5f01b2fSopenharmony_ci                    CHECK(accept_helper("9223372036854775807"));
838c5f01b2fSopenharmony_ci                    // (2**64)-1
839c5f01b2fSopenharmony_ci                    CHECK(accept_helper("18446744073709551615"));
840c5f01b2fSopenharmony_ci                }
841c5f01b2fSopenharmony_ci            }
842c5f01b2fSopenharmony_ci
843c5f01b2fSopenharmony_ci            SECTION("floating-point")
844c5f01b2fSopenharmony_ci            {
845c5f01b2fSopenharmony_ci                SECTION("without exponent")
846c5f01b2fSopenharmony_ci                {
847c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-128.5"));
848c5f01b2fSopenharmony_ci                    CHECK(accept_helper("0.999"));
849c5f01b2fSopenharmony_ci                    CHECK(accept_helper("128.5"));
850c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0.0"));
851c5f01b2fSopenharmony_ci                }
852c5f01b2fSopenharmony_ci
853c5f01b2fSopenharmony_ci                SECTION("with exponent")
854c5f01b2fSopenharmony_ci                {
855c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-128.5E3"));
856c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-128.5E-3"));
857c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0.0e1"));
858c5f01b2fSopenharmony_ci                    CHECK(accept_helper("-0.0E1"));
859c5f01b2fSopenharmony_ci                }
860c5f01b2fSopenharmony_ci            }
861c5f01b2fSopenharmony_ci
862c5f01b2fSopenharmony_ci            SECTION("overflow")
863c5f01b2fSopenharmony_ci            {
864c5f01b2fSopenharmony_ci                // overflows during parsing
865c5f01b2fSopenharmony_ci                CHECK(!accept_helper("1.18973e+4932"));
866c5f01b2fSopenharmony_ci            }
867c5f01b2fSopenharmony_ci
868c5f01b2fSopenharmony_ci            SECTION("invalid numbers")
869c5f01b2fSopenharmony_ci            {
870c5f01b2fSopenharmony_ci                CHECK(accept_helper("01") == false);
871c5f01b2fSopenharmony_ci                CHECK(accept_helper("--1") == false);
872c5f01b2fSopenharmony_ci                CHECK(accept_helper("1.") == false);
873c5f01b2fSopenharmony_ci                CHECK(accept_helper("1E") == false);
874c5f01b2fSopenharmony_ci                CHECK(accept_helper("1E-") == false);
875c5f01b2fSopenharmony_ci                CHECK(accept_helper("1.E1") == false);
876c5f01b2fSopenharmony_ci                CHECK(accept_helper("-1E") == false);
877c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0E#") == false);
878c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0E-#") == false);
879c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0#") == false);
880c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0.0:") == false);
881c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0.0Z") == false);
882c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0E123:") == false);
883c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0e0-:") == false);
884c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0e-:") == false);
885c5f01b2fSopenharmony_ci                CHECK(accept_helper("-0f") == false);
886c5f01b2fSopenharmony_ci
887c5f01b2fSopenharmony_ci                // numbers must not begin with "+"
888c5f01b2fSopenharmony_ci                CHECK(accept_helper("+1") == false);
889c5f01b2fSopenharmony_ci                CHECK(accept_helper("+0") == false);
890c5f01b2fSopenharmony_ci            }
891c5f01b2fSopenharmony_ci        }
892c5f01b2fSopenharmony_ci    }
893c5f01b2fSopenharmony_ci
894c5f01b2fSopenharmony_ci    SECTION("parse errors")
895c5f01b2fSopenharmony_ci    {
896c5f01b2fSopenharmony_ci        // unexpected end of number
897c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("0."),
898c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.'", json::parse_error&);
899c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("-"),
900c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-'", json::parse_error&);
901c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("--"),
902c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '--'", json::parse_error&);
903c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("-0."),
904c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid number; expected digit after '.'; last read: '-0.'", json::parse_error&);
905c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("-."),
906c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-.'", json::parse_error&);
907c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("-:"),
908c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid number; expected digit after '-'; last read: '-:'", json::parse_error&);
909c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("0.:"),
910c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected digit after '.'; last read: '0.:'", json::parse_error&);
911c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("e."),
912c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - invalid literal; last read: 'e'", json::parse_error&);
913c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("1e."),
914c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e.'", json::parse_error&);
915c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("1e/"),
916c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e/'", json::parse_error&);
917c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("1e:"),
918c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1e:'", json::parse_error&);
919c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("1E."),
920c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E.'", json::parse_error&);
921c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("1E/"),
922c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E/'", json::parse_error&);
923c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("1E:"),
924c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid number; expected '+', '-', or digit after exponent; last read: '1E:'", json::parse_error&);
925c5f01b2fSopenharmony_ci
926c5f01b2fSopenharmony_ci        // unexpected end of null
927c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("n"),
928c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'n'", json::parse_error&);
929c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("nu"),
930c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'nu'", json::parse_error&);
931c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("nul"),
932c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nul'", json::parse_error&);
933c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("nulk"),
934c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulk'", json::parse_error&);
935c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("nulm"),
936c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'nulm'", json::parse_error&);
937c5f01b2fSopenharmony_ci
938c5f01b2fSopenharmony_ci        // unexpected end of true
939c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("t"),
940c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 't'", json::parse_error&);
941c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("tr"),
942c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'tr'", json::parse_error&);
943c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("tru"),
944c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'tru'", json::parse_error&);
945c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("trud"),
946c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'trud'", json::parse_error&);
947c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("truf"),
948c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'truf'", json::parse_error&);
949c5f01b2fSopenharmony_ci
950c5f01b2fSopenharmony_ci        // unexpected end of false
951c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("f"),
952c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid literal; last read: 'f'", json::parse_error&);
953c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("fa"),
954c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid literal; last read: 'fa'", json::parse_error&);
955c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("fal"),
956c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid literal; last read: 'fal'", json::parse_error&);
957c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("fals"),
958c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'fals'", json::parse_error&);
959c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("falsd"),
960c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsd'", json::parse_error&);
961c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("falsf"),
962c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid literal; last read: 'falsf'", json::parse_error&);
963c5f01b2fSopenharmony_ci
964c5f01b2fSopenharmony_ci        // missing/unexpected end of array
965c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("["),
966c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
967c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("[1"),
968c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&);
969c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("[1,"),
970c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
971c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("[1,]"),
972c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal", json::parse_error&);
973c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("]"),
974c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected ']'; expected '[', '{', or a literal", json::parse_error&);
975c5f01b2fSopenharmony_ci
976c5f01b2fSopenharmony_ci        // missing/unexpected end of object
977c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("{"),
978c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected end of input; expected string literal", json::parse_error&);
979c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("{\"foo\""),
980c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing object separator - unexpected end of input; expected ':'", json::parse_error&);
981c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("{\"foo\":"),
982c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&);
983c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("{\"foo\":}"),
984c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal", json::parse_error&);
985c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("{\"foo\":1,}"),
986c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 10: syntax error while parsing object key - unexpected '}'; expected string literal", json::parse_error&);
987c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("}"),
988c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 1: syntax error while parsing value - unexpected '}'; expected '[', '{', or a literal", json::parse_error&);
989c5f01b2fSopenharmony_ci
990c5f01b2fSopenharmony_ci        // missing/unexpected end of string
991c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\""),
992c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid string: missing closing quote; last read: '\"'", json::parse_error&);
993c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\\""),
994c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: missing closing quote; last read: '\"\\\"'", json::parse_error&);
995c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u\""),
996c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u\"'", json::parse_error&);
997c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u0\""),
998c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0\"'", json::parse_error&);
999c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u01\""),
1000c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01\"'", json::parse_error&);
1001c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u012\""),
1002c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012\"'", json::parse_error&);
1003c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u"),
1004c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u'", json::parse_error&);
1005c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u0"),
1006c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u0'", json::parse_error&);
1007c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u01"),
1008c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u01'", json::parse_error&);
1009c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("\"\\u012"),
1010c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '\"\\u012'", json::parse_error&);
1011c5f01b2fSopenharmony_ci
1012c5f01b2fSopenharmony_ci        // invalid escapes
1013c5f01b2fSopenharmony_ci        for (int c = 1; c < 128; ++c)
1014c5f01b2fSopenharmony_ci        {
1015c5f01b2fSopenharmony_ci            auto s = std::string("\"\\") + std::string(1, static_cast<char>(c)) + "\"";
1016c5f01b2fSopenharmony_ci
1017c5f01b2fSopenharmony_ci            switch (c)
1018c5f01b2fSopenharmony_ci            {
1019c5f01b2fSopenharmony_ci                // valid escapes
1020c5f01b2fSopenharmony_ci                case ('"'):
1021c5f01b2fSopenharmony_ci                case ('\\'):
1022c5f01b2fSopenharmony_ci                case ('/'):
1023c5f01b2fSopenharmony_ci                case ('b'):
1024c5f01b2fSopenharmony_ci                case ('f'):
1025c5f01b2fSopenharmony_ci                case ('n'):
1026c5f01b2fSopenharmony_ci                case ('r'):
1027c5f01b2fSopenharmony_ci                case ('t'):
1028c5f01b2fSopenharmony_ci                {
1029c5f01b2fSopenharmony_ci                    CHECK_NOTHROW(parser_helper(s));
1030c5f01b2fSopenharmony_ci                    break;
1031c5f01b2fSopenharmony_ci                }
1032c5f01b2fSopenharmony_ci
1033c5f01b2fSopenharmony_ci                // \u must be followed with four numbers, so we skip it here
1034c5f01b2fSopenharmony_ci                case ('u'):
1035c5f01b2fSopenharmony_ci                {
1036c5f01b2fSopenharmony_ci                    break;
1037c5f01b2fSopenharmony_ci                }
1038c5f01b2fSopenharmony_ci
1039c5f01b2fSopenharmony_ci                // any other combination of backslash and character is invalid
1040c5f01b2fSopenharmony_ci                default:
1041c5f01b2fSopenharmony_ci                {
1042c5f01b2fSopenharmony_ci                    CHECK_THROWS_AS(parser_helper(s), json::parse_error&);
1043c5f01b2fSopenharmony_ci                    // only check error message if c is not a control character
1044c5f01b2fSopenharmony_ci                    if (c > 0x1f)
1045c5f01b2fSopenharmony_ci                    {
1046c5f01b2fSopenharmony_ci                        CHECK_THROWS_WITH_STD_STR(parser_helper(s),
1047c5f01b2fSopenharmony_ci                                                  "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid string: forbidden character after backslash; last read: '\"\\" + std::string(1, static_cast<char>(c)) + "'");
1048c5f01b2fSopenharmony_ci                    }
1049c5f01b2fSopenharmony_ci                    break;
1050c5f01b2fSopenharmony_ci                }
1051c5f01b2fSopenharmony_ci            }
1052c5f01b2fSopenharmony_ci        }
1053c5f01b2fSopenharmony_ci
1054c5f01b2fSopenharmony_ci        // invalid \uxxxx escapes
1055c5f01b2fSopenharmony_ci        {
1056c5f01b2fSopenharmony_ci            // check whether character is a valid hex character
1057c5f01b2fSopenharmony_ci            const auto valid = [](int c)
1058c5f01b2fSopenharmony_ci            {
1059c5f01b2fSopenharmony_ci                switch (c)
1060c5f01b2fSopenharmony_ci                {
1061c5f01b2fSopenharmony_ci                    case ('0'):
1062c5f01b2fSopenharmony_ci                    case ('1'):
1063c5f01b2fSopenharmony_ci                    case ('2'):
1064c5f01b2fSopenharmony_ci                    case ('3'):
1065c5f01b2fSopenharmony_ci                    case ('4'):
1066c5f01b2fSopenharmony_ci                    case ('5'):
1067c5f01b2fSopenharmony_ci                    case ('6'):
1068c5f01b2fSopenharmony_ci                    case ('7'):
1069c5f01b2fSopenharmony_ci                    case ('8'):
1070c5f01b2fSopenharmony_ci                    case ('9'):
1071c5f01b2fSopenharmony_ci                    case ('a'):
1072c5f01b2fSopenharmony_ci                    case ('b'):
1073c5f01b2fSopenharmony_ci                    case ('c'):
1074c5f01b2fSopenharmony_ci                    case ('d'):
1075c5f01b2fSopenharmony_ci                    case ('e'):
1076c5f01b2fSopenharmony_ci                    case ('f'):
1077c5f01b2fSopenharmony_ci                    case ('A'):
1078c5f01b2fSopenharmony_ci                    case ('B'):
1079c5f01b2fSopenharmony_ci                    case ('C'):
1080c5f01b2fSopenharmony_ci                    case ('D'):
1081c5f01b2fSopenharmony_ci                    case ('E'):
1082c5f01b2fSopenharmony_ci                    case ('F'):
1083c5f01b2fSopenharmony_ci                    {
1084c5f01b2fSopenharmony_ci                        return true;
1085c5f01b2fSopenharmony_ci                    }
1086c5f01b2fSopenharmony_ci
1087c5f01b2fSopenharmony_ci                    default:
1088c5f01b2fSopenharmony_ci                    {
1089c5f01b2fSopenharmony_ci                        return false;
1090c5f01b2fSopenharmony_ci                    }
1091c5f01b2fSopenharmony_ci                }
1092c5f01b2fSopenharmony_ci            };
1093c5f01b2fSopenharmony_ci
1094c5f01b2fSopenharmony_ci            for (int c = 1; c < 128; ++c)
1095c5f01b2fSopenharmony_ci            {
1096c5f01b2fSopenharmony_ci                std::string s = "\"\\u";
1097c5f01b2fSopenharmony_ci
1098c5f01b2fSopenharmony_ci                // create a string with the iterated character at each position
1099c5f01b2fSopenharmony_ci                auto s1 = s + "000" + std::string(1, static_cast<char>(c)) + "\"";
1100c5f01b2fSopenharmony_ci                auto s2 = s + "00" + std::string(1, static_cast<char>(c)) + "0\"";
1101c5f01b2fSopenharmony_ci                auto s3 = s + "0" + std::string(1, static_cast<char>(c)) + "00\"";
1102c5f01b2fSopenharmony_ci                auto s4 = s + std::string(1, static_cast<char>(c)) + "000\"";
1103c5f01b2fSopenharmony_ci
1104c5f01b2fSopenharmony_ci                if (valid(c))
1105c5f01b2fSopenharmony_ci                {
1106c5f01b2fSopenharmony_ci                    CAPTURE(s1)
1107c5f01b2fSopenharmony_ci                    CHECK_NOTHROW(parser_helper(s1));
1108c5f01b2fSopenharmony_ci                    CAPTURE(s2)
1109c5f01b2fSopenharmony_ci                    CHECK_NOTHROW(parser_helper(s2));
1110c5f01b2fSopenharmony_ci                    CAPTURE(s3)
1111c5f01b2fSopenharmony_ci                    CHECK_NOTHROW(parser_helper(s3));
1112c5f01b2fSopenharmony_ci                    CAPTURE(s4)
1113c5f01b2fSopenharmony_ci                    CHECK_NOTHROW(parser_helper(s4));
1114c5f01b2fSopenharmony_ci                }
1115c5f01b2fSopenharmony_ci                else
1116c5f01b2fSopenharmony_ci                {
1117c5f01b2fSopenharmony_ci                    CAPTURE(s1)
1118c5f01b2fSopenharmony_ci                    CHECK_THROWS_AS(parser_helper(s1), json::parse_error&);
1119c5f01b2fSopenharmony_ci                    // only check error message if c is not a control character
1120c5f01b2fSopenharmony_ci                    if (c > 0x1f)
1121c5f01b2fSopenharmony_ci                    {
1122c5f01b2fSopenharmony_ci                        CHECK_THROWS_WITH_STD_STR(parser_helper(s1),
1123c5f01b2fSopenharmony_ci                                                  "[json.exception.parse_error.101] parse error at line 1, column 7: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s1.substr(0, 7) + "'");
1124c5f01b2fSopenharmony_ci                    }
1125c5f01b2fSopenharmony_ci
1126c5f01b2fSopenharmony_ci                    CAPTURE(s2)
1127c5f01b2fSopenharmony_ci                    CHECK_THROWS_AS(parser_helper(s2), json::parse_error&);
1128c5f01b2fSopenharmony_ci                    // only check error message if c is not a control character
1129c5f01b2fSopenharmony_ci                    if (c > 0x1f)
1130c5f01b2fSopenharmony_ci                    {
1131c5f01b2fSopenharmony_ci                        CHECK_THROWS_WITH_STD_STR(parser_helper(s2),
1132c5f01b2fSopenharmony_ci                                                  "[json.exception.parse_error.101] parse error at line 1, column 6: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s2.substr(0, 6) + "'");
1133c5f01b2fSopenharmony_ci                    }
1134c5f01b2fSopenharmony_ci
1135c5f01b2fSopenharmony_ci                    CAPTURE(s3)
1136c5f01b2fSopenharmony_ci                    CHECK_THROWS_AS(parser_helper(s3), json::parse_error&);
1137c5f01b2fSopenharmony_ci                    // only check error message if c is not a control character
1138c5f01b2fSopenharmony_ci                    if (c > 0x1f)
1139c5f01b2fSopenharmony_ci                    {
1140c5f01b2fSopenharmony_ci                        CHECK_THROWS_WITH_STD_STR(parser_helper(s3),
1141c5f01b2fSopenharmony_ci                                                  "[json.exception.parse_error.101] parse error at line 1, column 5: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s3.substr(0, 5) + "'");
1142c5f01b2fSopenharmony_ci                    }
1143c5f01b2fSopenharmony_ci
1144c5f01b2fSopenharmony_ci                    CAPTURE(s4)
1145c5f01b2fSopenharmony_ci                    CHECK_THROWS_AS(parser_helper(s4), json::parse_error&);
1146c5f01b2fSopenharmony_ci                    // only check error message if c is not a control character
1147c5f01b2fSopenharmony_ci                    if (c > 0x1f)
1148c5f01b2fSopenharmony_ci                    {
1149c5f01b2fSopenharmony_ci                        CHECK_THROWS_WITH_STD_STR(parser_helper(s4),
1150c5f01b2fSopenharmony_ci                                                  "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: '\\u' must be followed by 4 hex digits; last read: '" + s4.substr(0, 4) + "'");
1151c5f01b2fSopenharmony_ci                    }
1152c5f01b2fSopenharmony_ci                }
1153c5f01b2fSopenharmony_ci            }
1154c5f01b2fSopenharmony_ci        }
1155c5f01b2fSopenharmony_ci
1156c5f01b2fSopenharmony_ci        json _;
1157c5f01b2fSopenharmony_ci
1158c5f01b2fSopenharmony_ci        // missing part of a surrogate pair
1159c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\""), "[json.exception.parse_error.101] parse error at line 1, column 8: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\"'", json::parse_error&);
1160c5f01b2fSopenharmony_ci        // invalid surrogate pair
1161c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\\uD80C\""),
1162c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uD80C'", json::parse_error&);
1163c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\\u0000\""),
1164c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\u0000'", json::parse_error&);
1165c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(_ = json::parse("\"\\uD80C\\uFFFF\""),
1166c5f01b2fSopenharmony_ci                             "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing value - invalid string: surrogate U+D800..U+DBFF must be followed by U+DC00..U+DFFF; last read: '\"\\uD80C\\uFFFF'", json::parse_error&);
1167c5f01b2fSopenharmony_ci    }
1168c5f01b2fSopenharmony_ci
1169c5f01b2fSopenharmony_ci    SECTION("parse errors (accept)")
1170c5f01b2fSopenharmony_ci    {
1171c5f01b2fSopenharmony_ci        // unexpected end of number
1172c5f01b2fSopenharmony_ci        CHECK(accept_helper("0.") == false);
1173c5f01b2fSopenharmony_ci        CHECK(accept_helper("-") == false);
1174c5f01b2fSopenharmony_ci        CHECK(accept_helper("--") == false);
1175c5f01b2fSopenharmony_ci        CHECK(accept_helper("-0.") == false);
1176c5f01b2fSopenharmony_ci        CHECK(accept_helper("-.") == false);
1177c5f01b2fSopenharmony_ci        CHECK(accept_helper("-:") == false);
1178c5f01b2fSopenharmony_ci        CHECK(accept_helper("0.:") == false);
1179c5f01b2fSopenharmony_ci        CHECK(accept_helper("e.") == false);
1180c5f01b2fSopenharmony_ci        CHECK(accept_helper("1e.") == false);
1181c5f01b2fSopenharmony_ci        CHECK(accept_helper("1e/") == false);
1182c5f01b2fSopenharmony_ci        CHECK(accept_helper("1e:") == false);
1183c5f01b2fSopenharmony_ci        CHECK(accept_helper("1E.") == false);
1184c5f01b2fSopenharmony_ci        CHECK(accept_helper("1E/") == false);
1185c5f01b2fSopenharmony_ci        CHECK(accept_helper("1E:") == false);
1186c5f01b2fSopenharmony_ci
1187c5f01b2fSopenharmony_ci        // unexpected end of null
1188c5f01b2fSopenharmony_ci        CHECK(accept_helper("n") == false);
1189c5f01b2fSopenharmony_ci        CHECK(accept_helper("nu") == false);
1190c5f01b2fSopenharmony_ci        CHECK(accept_helper("nul") == false);
1191c5f01b2fSopenharmony_ci
1192c5f01b2fSopenharmony_ci        // unexpected end of true
1193c5f01b2fSopenharmony_ci        CHECK(accept_helper("t") == false);
1194c5f01b2fSopenharmony_ci        CHECK(accept_helper("tr") == false);
1195c5f01b2fSopenharmony_ci        CHECK(accept_helper("tru") == false);
1196c5f01b2fSopenharmony_ci
1197c5f01b2fSopenharmony_ci        // unexpected end of false
1198c5f01b2fSopenharmony_ci        CHECK(accept_helper("f") == false);
1199c5f01b2fSopenharmony_ci        CHECK(accept_helper("fa") == false);
1200c5f01b2fSopenharmony_ci        CHECK(accept_helper("fal") == false);
1201c5f01b2fSopenharmony_ci        CHECK(accept_helper("fals") == false);
1202c5f01b2fSopenharmony_ci
1203c5f01b2fSopenharmony_ci        // missing/unexpected end of array
1204c5f01b2fSopenharmony_ci        CHECK(accept_helper("[") == false);
1205c5f01b2fSopenharmony_ci        CHECK(accept_helper("[1") == false);
1206c5f01b2fSopenharmony_ci        CHECK(accept_helper("[1,") == false);
1207c5f01b2fSopenharmony_ci        CHECK(accept_helper("[1,]") == false);
1208c5f01b2fSopenharmony_ci        CHECK(accept_helper("]") == false);
1209c5f01b2fSopenharmony_ci
1210c5f01b2fSopenharmony_ci        // missing/unexpected end of object
1211c5f01b2fSopenharmony_ci        CHECK(accept_helper("{") == false);
1212c5f01b2fSopenharmony_ci        CHECK(accept_helper("{\"foo\"") == false);
1213c5f01b2fSopenharmony_ci        CHECK(accept_helper("{\"foo\":") == false);
1214c5f01b2fSopenharmony_ci        CHECK(accept_helper("{\"foo\":}") == false);
1215c5f01b2fSopenharmony_ci        CHECK(accept_helper("{\"foo\":1,}") == false);
1216c5f01b2fSopenharmony_ci        CHECK(accept_helper("}") == false);
1217c5f01b2fSopenharmony_ci
1218c5f01b2fSopenharmony_ci        // missing/unexpected end of string
1219c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"") == false);
1220c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\\"") == false);
1221c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u\"") == false);
1222c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u0\"") == false);
1223c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u01\"") == false);
1224c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u012\"") == false);
1225c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u") == false);
1226c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u0") == false);
1227c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u01") == false);
1228c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\u012") == false);
1229c5f01b2fSopenharmony_ci
1230c5f01b2fSopenharmony_ci        // unget of newline
1231c5f01b2fSopenharmony_ci        CHECK(parser_helper("\n123\n") == 123);
1232c5f01b2fSopenharmony_ci
1233c5f01b2fSopenharmony_ci        // invalid escapes
1234c5f01b2fSopenharmony_ci        for (int c = 1; c < 128; ++c)
1235c5f01b2fSopenharmony_ci        {
1236c5f01b2fSopenharmony_ci            auto s = std::string("\"\\") + std::string(1, static_cast<char>(c)) + "\"";
1237c5f01b2fSopenharmony_ci
1238c5f01b2fSopenharmony_ci            switch (c)
1239c5f01b2fSopenharmony_ci            {
1240c5f01b2fSopenharmony_ci                // valid escapes
1241c5f01b2fSopenharmony_ci                case ('"'):
1242c5f01b2fSopenharmony_ci                case ('\\'):
1243c5f01b2fSopenharmony_ci                case ('/'):
1244c5f01b2fSopenharmony_ci                case ('b'):
1245c5f01b2fSopenharmony_ci                case ('f'):
1246c5f01b2fSopenharmony_ci                case ('n'):
1247c5f01b2fSopenharmony_ci                case ('r'):
1248c5f01b2fSopenharmony_ci                case ('t'):
1249c5f01b2fSopenharmony_ci                {
1250c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept());
1251c5f01b2fSopenharmony_ci                    break;
1252c5f01b2fSopenharmony_ci                }
1253c5f01b2fSopenharmony_ci
1254c5f01b2fSopenharmony_ci                // \u must be followed with four numbers, so we skip it here
1255c5f01b2fSopenharmony_ci                case ('u'):
1256c5f01b2fSopenharmony_ci                {
1257c5f01b2fSopenharmony_ci                    break;
1258c5f01b2fSopenharmony_ci                }
1259c5f01b2fSopenharmony_ci
1260c5f01b2fSopenharmony_ci                // any other combination of backslash and character is invalid
1261c5f01b2fSopenharmony_ci                default:
1262c5f01b2fSopenharmony_ci                {
1263c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s)).accept() == false);
1264c5f01b2fSopenharmony_ci                    break;
1265c5f01b2fSopenharmony_ci                }
1266c5f01b2fSopenharmony_ci            }
1267c5f01b2fSopenharmony_ci        }
1268c5f01b2fSopenharmony_ci
1269c5f01b2fSopenharmony_ci        // invalid \uxxxx escapes
1270c5f01b2fSopenharmony_ci        {
1271c5f01b2fSopenharmony_ci            // check whether character is a valid hex character
1272c5f01b2fSopenharmony_ci            const auto valid = [](int c)
1273c5f01b2fSopenharmony_ci            {
1274c5f01b2fSopenharmony_ci                switch (c)
1275c5f01b2fSopenharmony_ci                {
1276c5f01b2fSopenharmony_ci                    case ('0'):
1277c5f01b2fSopenharmony_ci                    case ('1'):
1278c5f01b2fSopenharmony_ci                    case ('2'):
1279c5f01b2fSopenharmony_ci                    case ('3'):
1280c5f01b2fSopenharmony_ci                    case ('4'):
1281c5f01b2fSopenharmony_ci                    case ('5'):
1282c5f01b2fSopenharmony_ci                    case ('6'):
1283c5f01b2fSopenharmony_ci                    case ('7'):
1284c5f01b2fSopenharmony_ci                    case ('8'):
1285c5f01b2fSopenharmony_ci                    case ('9'):
1286c5f01b2fSopenharmony_ci                    case ('a'):
1287c5f01b2fSopenharmony_ci                    case ('b'):
1288c5f01b2fSopenharmony_ci                    case ('c'):
1289c5f01b2fSopenharmony_ci                    case ('d'):
1290c5f01b2fSopenharmony_ci                    case ('e'):
1291c5f01b2fSopenharmony_ci                    case ('f'):
1292c5f01b2fSopenharmony_ci                    case ('A'):
1293c5f01b2fSopenharmony_ci                    case ('B'):
1294c5f01b2fSopenharmony_ci                    case ('C'):
1295c5f01b2fSopenharmony_ci                    case ('D'):
1296c5f01b2fSopenharmony_ci                    case ('E'):
1297c5f01b2fSopenharmony_ci                    case ('F'):
1298c5f01b2fSopenharmony_ci                    {
1299c5f01b2fSopenharmony_ci                        return true;
1300c5f01b2fSopenharmony_ci                    }
1301c5f01b2fSopenharmony_ci
1302c5f01b2fSopenharmony_ci                    default:
1303c5f01b2fSopenharmony_ci                    {
1304c5f01b2fSopenharmony_ci                        return false;
1305c5f01b2fSopenharmony_ci                    }
1306c5f01b2fSopenharmony_ci                }
1307c5f01b2fSopenharmony_ci            };
1308c5f01b2fSopenharmony_ci
1309c5f01b2fSopenharmony_ci            for (int c = 1; c < 128; ++c)
1310c5f01b2fSopenharmony_ci            {
1311c5f01b2fSopenharmony_ci                std::string s = "\"\\u";
1312c5f01b2fSopenharmony_ci
1313c5f01b2fSopenharmony_ci                // create a string with the iterated character at each position
1314c5f01b2fSopenharmony_ci                const auto s1 = s + "000" + std::string(1, static_cast<char>(c)) + "\"";
1315c5f01b2fSopenharmony_ci                const auto s2 = s + "00" + std::string(1, static_cast<char>(c)) + "0\"";
1316c5f01b2fSopenharmony_ci                const auto s3 = s + "0" + std::string(1, static_cast<char>(c)) + "00\"";
1317c5f01b2fSopenharmony_ci                const auto s4 = s + std::string(1, static_cast<char>(c)) + "000\"";
1318c5f01b2fSopenharmony_ci
1319c5f01b2fSopenharmony_ci                if (valid(c))
1320c5f01b2fSopenharmony_ci                {
1321c5f01b2fSopenharmony_ci                    CAPTURE(s1)
1322c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s1)).accept());
1323c5f01b2fSopenharmony_ci                    CAPTURE(s2)
1324c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s2)).accept());
1325c5f01b2fSopenharmony_ci                    CAPTURE(s3)
1326c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s3)).accept());
1327c5f01b2fSopenharmony_ci                    CAPTURE(s4)
1328c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s4)).accept());
1329c5f01b2fSopenharmony_ci                }
1330c5f01b2fSopenharmony_ci                else
1331c5f01b2fSopenharmony_ci                {
1332c5f01b2fSopenharmony_ci                    CAPTURE(s1)
1333c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s1)).accept() == false);
1334c5f01b2fSopenharmony_ci
1335c5f01b2fSopenharmony_ci                    CAPTURE(s2)
1336c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s2)).accept() == false);
1337c5f01b2fSopenharmony_ci
1338c5f01b2fSopenharmony_ci                    CAPTURE(s3)
1339c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s3)).accept() == false);
1340c5f01b2fSopenharmony_ci
1341c5f01b2fSopenharmony_ci                    CAPTURE(s4)
1342c5f01b2fSopenharmony_ci                    CHECK(json::parser(nlohmann::detail::input_adapter(s4)).accept() == false);
1343c5f01b2fSopenharmony_ci                }
1344c5f01b2fSopenharmony_ci            }
1345c5f01b2fSopenharmony_ci        }
1346c5f01b2fSopenharmony_ci
1347c5f01b2fSopenharmony_ci        // missing part of a surrogate pair
1348c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\uD80C\"") == false);
1349c5f01b2fSopenharmony_ci        // invalid surrogate pair
1350c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\uD80C\\uD80C\"") == false);
1351c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\uD80C\\u0000\"") == false);
1352c5f01b2fSopenharmony_ci        CHECK(accept_helper("\"\\uD80C\\uFFFF\"") == false);
1353c5f01b2fSopenharmony_ci    }
1354c5f01b2fSopenharmony_ci
1355c5f01b2fSopenharmony_ci    SECTION("tests found by mutate++")
1356c5f01b2fSopenharmony_ci    {
1357c5f01b2fSopenharmony_ci        // test case to make sure no comma precedes the first key
1358c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("{,\"key\": false}"), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing object key - unexpected ','; expected string literal", json::parse_error&);
1359c5f01b2fSopenharmony_ci        // test case to make sure an object is properly closed
1360c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(parser_helper("[{\"key\": false true]"), "[json.exception.parse_error.101] parse error at line 1, column 19: syntax error while parsing object - unexpected true literal; expected '}'", json::parse_error&);
1361c5f01b2fSopenharmony_ci
1362c5f01b2fSopenharmony_ci        // test case to make sure the callback is properly evaluated after reading a key
1363c5f01b2fSopenharmony_ci        {
1364c5f01b2fSopenharmony_ci            json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t event, json& /*unused*/) noexcept
1365c5f01b2fSopenharmony_ci            {
1366c5f01b2fSopenharmony_ci                return event != json::parse_event_t::key;
1367c5f01b2fSopenharmony_ci            };
1368c5f01b2fSopenharmony_ci
1369c5f01b2fSopenharmony_ci            json x = json::parse("{\"key\": false}", cb);
1370c5f01b2fSopenharmony_ci            CHECK(x == json::object());
1371c5f01b2fSopenharmony_ci        }
1372c5f01b2fSopenharmony_ci    }
1373c5f01b2fSopenharmony_ci
1374c5f01b2fSopenharmony_ci    SECTION("callback function")
1375c5f01b2fSopenharmony_ci    {
1376c5f01b2fSopenharmony_ci        const auto* s_object = R"(
1377c5f01b2fSopenharmony_ci            {
1378c5f01b2fSopenharmony_ci                "foo": 2,
1379c5f01b2fSopenharmony_ci                "bar": {
1380c5f01b2fSopenharmony_ci                    "baz": 1
1381c5f01b2fSopenharmony_ci                }
1382c5f01b2fSopenharmony_ci            }
1383c5f01b2fSopenharmony_ci        )";
1384c5f01b2fSopenharmony_ci
1385c5f01b2fSopenharmony_ci        const auto* s_array = R"(
1386c5f01b2fSopenharmony_ci            [1,2,[3,4,5],4,5]
1387c5f01b2fSopenharmony_ci        )";
1388c5f01b2fSopenharmony_ci
1389c5f01b2fSopenharmony_ci        const auto* structured_array = R"(
1390c5f01b2fSopenharmony_ci            [
1391c5f01b2fSopenharmony_ci                1,
1392c5f01b2fSopenharmony_ci                {
1393c5f01b2fSopenharmony_ci                     "foo": "bar"
1394c5f01b2fSopenharmony_ci                },
1395c5f01b2fSopenharmony_ci                {
1396c5f01b2fSopenharmony_ci                     "qux": "baz"
1397c5f01b2fSopenharmony_ci                }
1398c5f01b2fSopenharmony_ci            ]
1399c5f01b2fSopenharmony_ci        )";
1400c5f01b2fSopenharmony_ci
1401c5f01b2fSopenharmony_ci        SECTION("filter nothing")
1402c5f01b2fSopenharmony_ci        {
1403c5f01b2fSopenharmony_ci            json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
1404c5f01b2fSopenharmony_ci            {
1405c5f01b2fSopenharmony_ci                return true;
1406c5f01b2fSopenharmony_ci            });
1407c5f01b2fSopenharmony_ci
1408c5f01b2fSopenharmony_ci            CHECK (j_object == json({{"foo", 2}, {"bar", {{"baz", 1}}}}));
1409c5f01b2fSopenharmony_ci
1410c5f01b2fSopenharmony_ci            json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
1411c5f01b2fSopenharmony_ci            {
1412c5f01b2fSopenharmony_ci                return true;
1413c5f01b2fSopenharmony_ci            });
1414c5f01b2fSopenharmony_ci
1415c5f01b2fSopenharmony_ci            CHECK (j_array == json({1, 2, {3, 4, 5}, 4, 5}));
1416c5f01b2fSopenharmony_ci        }
1417c5f01b2fSopenharmony_ci
1418c5f01b2fSopenharmony_ci        SECTION("filter everything")
1419c5f01b2fSopenharmony_ci        {
1420c5f01b2fSopenharmony_ci            json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
1421c5f01b2fSopenharmony_ci            {
1422c5f01b2fSopenharmony_ci                return false;
1423c5f01b2fSopenharmony_ci            });
1424c5f01b2fSopenharmony_ci
1425c5f01b2fSopenharmony_ci            // the top-level object will be discarded, leaving a null
1426c5f01b2fSopenharmony_ci            CHECK (j_object.is_null());
1427c5f01b2fSopenharmony_ci
1428c5f01b2fSopenharmony_ci            json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t /*unused*/, const json& /*unused*/) noexcept
1429c5f01b2fSopenharmony_ci            {
1430c5f01b2fSopenharmony_ci                return false;
1431c5f01b2fSopenharmony_ci            });
1432c5f01b2fSopenharmony_ci
1433c5f01b2fSopenharmony_ci            // the top-level array will be discarded, leaving a null
1434c5f01b2fSopenharmony_ci            CHECK (j_array.is_null());
1435c5f01b2fSopenharmony_ci        }
1436c5f01b2fSopenharmony_ci
1437c5f01b2fSopenharmony_ci        SECTION("filter specific element")
1438c5f01b2fSopenharmony_ci        {
1439c5f01b2fSopenharmony_ci            json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t event, const json & j) noexcept
1440c5f01b2fSopenharmony_ci            {
1441c5f01b2fSopenharmony_ci                // filter all number(2) elements
1442c5f01b2fSopenharmony_ci                return event != json::parse_event_t::value || j != json(2);
1443c5f01b2fSopenharmony_ci            });
1444c5f01b2fSopenharmony_ci
1445c5f01b2fSopenharmony_ci            CHECK (j_object == json({{"bar", {{"baz", 1}}}}));
1446c5f01b2fSopenharmony_ci
1447c5f01b2fSopenharmony_ci            json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t event, const json & j) noexcept
1448c5f01b2fSopenharmony_ci            {
1449c5f01b2fSopenharmony_ci                return event != json::parse_event_t::value || j != json(2);
1450c5f01b2fSopenharmony_ci            });
1451c5f01b2fSopenharmony_ci
1452c5f01b2fSopenharmony_ci            CHECK (j_array == json({1, {3, 4, 5}, 4, 5}));
1453c5f01b2fSopenharmony_ci        }
1454c5f01b2fSopenharmony_ci
1455c5f01b2fSopenharmony_ci        SECTION("filter object in array")
1456c5f01b2fSopenharmony_ci        {
1457c5f01b2fSopenharmony_ci            json j_filtered1 = json::parse(structured_array, [](int /*unused*/, json::parse_event_t e, const json & parsed)
1458c5f01b2fSopenharmony_ci            {
1459c5f01b2fSopenharmony_ci                return !(e == json::parse_event_t::object_end && parsed.contains("foo"));
1460c5f01b2fSopenharmony_ci            });
1461c5f01b2fSopenharmony_ci
1462c5f01b2fSopenharmony_ci            // the specified object will be discarded, and removed.
1463c5f01b2fSopenharmony_ci            CHECK (j_filtered1.size() == 2);
1464c5f01b2fSopenharmony_ci            CHECK (j_filtered1 == json({1, {{"qux", "baz"}}}));
1465c5f01b2fSopenharmony_ci
1466c5f01b2fSopenharmony_ci            json j_filtered2 = json::parse(structured_array, [](int /*unused*/, json::parse_event_t e, const json& /*parsed*/) noexcept
1467c5f01b2fSopenharmony_ci            {
1468c5f01b2fSopenharmony_ci                return e != json::parse_event_t::object_end;
1469c5f01b2fSopenharmony_ci            });
1470c5f01b2fSopenharmony_ci
1471c5f01b2fSopenharmony_ci            // removed all objects in array.
1472c5f01b2fSopenharmony_ci            CHECK (j_filtered2.size() == 1);
1473c5f01b2fSopenharmony_ci            CHECK (j_filtered2 == json({1}));
1474c5f01b2fSopenharmony_ci        }
1475c5f01b2fSopenharmony_ci
1476c5f01b2fSopenharmony_ci        SECTION("filter specific events")
1477c5f01b2fSopenharmony_ci        {
1478c5f01b2fSopenharmony_ci            SECTION("first closing event")
1479c5f01b2fSopenharmony_ci            {
1480c5f01b2fSopenharmony_ci                {
1481c5f01b2fSopenharmony_ci                    json j_object = json::parse(s_object, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
1482c5f01b2fSopenharmony_ci                    {
1483c5f01b2fSopenharmony_ci                        static bool first = true;
1484c5f01b2fSopenharmony_ci                        if (e == json::parse_event_t::object_end && first)
1485c5f01b2fSopenharmony_ci                        {
1486c5f01b2fSopenharmony_ci                            first = false;
1487c5f01b2fSopenharmony_ci                            return false;
1488c5f01b2fSopenharmony_ci                        }
1489c5f01b2fSopenharmony_ci
1490c5f01b2fSopenharmony_ci                        return true;
1491c5f01b2fSopenharmony_ci                    });
1492c5f01b2fSopenharmony_ci
1493c5f01b2fSopenharmony_ci                    // the first completed object will be discarded
1494c5f01b2fSopenharmony_ci                    CHECK (j_object == json({{"foo", 2}}));
1495c5f01b2fSopenharmony_ci                }
1496c5f01b2fSopenharmony_ci
1497c5f01b2fSopenharmony_ci                {
1498c5f01b2fSopenharmony_ci                    json j_array = json::parse(s_array, [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
1499c5f01b2fSopenharmony_ci                    {
1500c5f01b2fSopenharmony_ci                        static bool first = true;
1501c5f01b2fSopenharmony_ci                        if (e == json::parse_event_t::array_end && first)
1502c5f01b2fSopenharmony_ci                        {
1503c5f01b2fSopenharmony_ci                            first = false;
1504c5f01b2fSopenharmony_ci                            return false;
1505c5f01b2fSopenharmony_ci                        }
1506c5f01b2fSopenharmony_ci
1507c5f01b2fSopenharmony_ci                        return true;
1508c5f01b2fSopenharmony_ci                    });
1509c5f01b2fSopenharmony_ci
1510c5f01b2fSopenharmony_ci                    // the first completed array will be discarded
1511c5f01b2fSopenharmony_ci                    CHECK (j_array == json({1, 2, 4, 5}));
1512c5f01b2fSopenharmony_ci                }
1513c5f01b2fSopenharmony_ci            }
1514c5f01b2fSopenharmony_ci        }
1515c5f01b2fSopenharmony_ci
1516c5f01b2fSopenharmony_ci        SECTION("special cases")
1517c5f01b2fSopenharmony_ci        {
1518c5f01b2fSopenharmony_ci            // the following test cases cover the situation in which an empty
1519c5f01b2fSopenharmony_ci            // object and array is discarded only after the closing character
1520c5f01b2fSopenharmony_ci            // has been read
1521c5f01b2fSopenharmony_ci
1522c5f01b2fSopenharmony_ci            json j_empty_object = json::parse("{}", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
1523c5f01b2fSopenharmony_ci            {
1524c5f01b2fSopenharmony_ci                return e != json::parse_event_t::object_end;
1525c5f01b2fSopenharmony_ci            });
1526c5f01b2fSopenharmony_ci            CHECK(j_empty_object == json());
1527c5f01b2fSopenharmony_ci
1528c5f01b2fSopenharmony_ci            json j_empty_array = json::parse("[]", [](int /*unused*/, json::parse_event_t e, const json& /*unused*/) noexcept
1529c5f01b2fSopenharmony_ci            {
1530c5f01b2fSopenharmony_ci                return e != json::parse_event_t::array_end;
1531c5f01b2fSopenharmony_ci            });
1532c5f01b2fSopenharmony_ci            CHECK(j_empty_array == json());
1533c5f01b2fSopenharmony_ci        }
1534c5f01b2fSopenharmony_ci    }
1535c5f01b2fSopenharmony_ci
1536c5f01b2fSopenharmony_ci    SECTION("constructing from contiguous containers")
1537c5f01b2fSopenharmony_ci    {
1538c5f01b2fSopenharmony_ci        SECTION("from std::vector")
1539c5f01b2fSopenharmony_ci        {
1540c5f01b2fSopenharmony_ci            std::vector<uint8_t> v = {'t', 'r', 'u', 'e'};
1541c5f01b2fSopenharmony_ci            json j;
1542c5f01b2fSopenharmony_ci            json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
1543c5f01b2fSopenharmony_ci            CHECK(j == json(true));
1544c5f01b2fSopenharmony_ci        }
1545c5f01b2fSopenharmony_ci
1546c5f01b2fSopenharmony_ci        SECTION("from std::array")
1547c5f01b2fSopenharmony_ci        {
1548c5f01b2fSopenharmony_ci            std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} };
1549c5f01b2fSopenharmony_ci            json j;
1550c5f01b2fSopenharmony_ci            json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
1551c5f01b2fSopenharmony_ci            CHECK(j == json(true));
1552c5f01b2fSopenharmony_ci        }
1553c5f01b2fSopenharmony_ci
1554c5f01b2fSopenharmony_ci        SECTION("from array")
1555c5f01b2fSopenharmony_ci        {
1556c5f01b2fSopenharmony_ci            uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays)
1557c5f01b2fSopenharmony_ci            json j;
1558c5f01b2fSopenharmony_ci            json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
1559c5f01b2fSopenharmony_ci            CHECK(j == json(true));
1560c5f01b2fSopenharmony_ci        }
1561c5f01b2fSopenharmony_ci
1562c5f01b2fSopenharmony_ci        SECTION("from char literal")
1563c5f01b2fSopenharmony_ci        {
1564c5f01b2fSopenharmony_ci            CHECK(parser_helper("true") == json(true));
1565c5f01b2fSopenharmony_ci        }
1566c5f01b2fSopenharmony_ci
1567c5f01b2fSopenharmony_ci        SECTION("from std::string")
1568c5f01b2fSopenharmony_ci        {
1569c5f01b2fSopenharmony_ci            std::string v = {'t', 'r', 'u', 'e'};
1570c5f01b2fSopenharmony_ci            json j;
1571c5f01b2fSopenharmony_ci            json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
1572c5f01b2fSopenharmony_ci            CHECK(j == json(true));
1573c5f01b2fSopenharmony_ci        }
1574c5f01b2fSopenharmony_ci
1575c5f01b2fSopenharmony_ci        SECTION("from std::initializer_list")
1576c5f01b2fSopenharmony_ci        {
1577c5f01b2fSopenharmony_ci            std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'};
1578c5f01b2fSopenharmony_ci            json j;
1579c5f01b2fSopenharmony_ci            json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
1580c5f01b2fSopenharmony_ci            CHECK(j == json(true));
1581c5f01b2fSopenharmony_ci        }
1582c5f01b2fSopenharmony_ci
1583c5f01b2fSopenharmony_ci        SECTION("from std::valarray")
1584c5f01b2fSopenharmony_ci        {
1585c5f01b2fSopenharmony_ci            std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'};
1586c5f01b2fSopenharmony_ci            json j;
1587c5f01b2fSopenharmony_ci            json::parser(nlohmann::detail::input_adapter(std::begin(v), std::end(v))).parse(true, j);
1588c5f01b2fSopenharmony_ci            CHECK(j == json(true));
1589c5f01b2fSopenharmony_ci        }
1590c5f01b2fSopenharmony_ci    }
1591c5f01b2fSopenharmony_ci
1592c5f01b2fSopenharmony_ci    SECTION("improve test coverage")
1593c5f01b2fSopenharmony_ci    {
1594c5f01b2fSopenharmony_ci        SECTION("parser with callback")
1595c5f01b2fSopenharmony_ci        {
1596c5f01b2fSopenharmony_ci            json::parser_callback_t cb = [](int /*unused*/, json::parse_event_t /*unused*/, json& /*unused*/) noexcept
1597c5f01b2fSopenharmony_ci            {
1598c5f01b2fSopenharmony_ci                return true;
1599c5f01b2fSopenharmony_ci            };
1600c5f01b2fSopenharmony_ci
1601c5f01b2fSopenharmony_ci            CHECK(json::parse("{\"foo\": true:", cb, false).is_discarded());
1602c5f01b2fSopenharmony_ci
1603c5f01b2fSopenharmony_ci            json _;
1604c5f01b2fSopenharmony_ci            CHECK_THROWS_WITH_AS(_ = json::parse("{\"foo\": true:", cb), "[json.exception.parse_error.101] parse error at line 1, column 13: syntax error while parsing object - unexpected ':'; expected '}'", json::parse_error&);
1605c5f01b2fSopenharmony_ci
1606c5f01b2fSopenharmony_ci            CHECK_THROWS_WITH_AS(_ = json::parse("1.18973e+4932", cb), "[json.exception.out_of_range.406] number overflow parsing '1.18973e+4932'", json::out_of_range&);
1607c5f01b2fSopenharmony_ci        }
1608c5f01b2fSopenharmony_ci
1609c5f01b2fSopenharmony_ci        SECTION("SAX parser")
1610c5f01b2fSopenharmony_ci        {
1611c5f01b2fSopenharmony_ci            SECTION("} without value")
1612c5f01b2fSopenharmony_ci            {
1613c5f01b2fSopenharmony_ci                SaxCountdown s(1);
1614c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("{}", &s) == false);
1615c5f01b2fSopenharmony_ci            }
1616c5f01b2fSopenharmony_ci
1617c5f01b2fSopenharmony_ci            SECTION("} with value")
1618c5f01b2fSopenharmony_ci            {
1619c5f01b2fSopenharmony_ci                SaxCountdown s(3);
1620c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("{\"k1\": true}", &s) == false);
1621c5f01b2fSopenharmony_ci            }
1622c5f01b2fSopenharmony_ci
1623c5f01b2fSopenharmony_ci            SECTION("second key")
1624c5f01b2fSopenharmony_ci            {
1625c5f01b2fSopenharmony_ci                SaxCountdown s(3);
1626c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("{\"k1\": true, \"k2\": false}", &s) == false);
1627c5f01b2fSopenharmony_ci            }
1628c5f01b2fSopenharmony_ci
1629c5f01b2fSopenharmony_ci            SECTION("] without value")
1630c5f01b2fSopenharmony_ci            {
1631c5f01b2fSopenharmony_ci                SaxCountdown s(1);
1632c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("[]", &s) == false);
1633c5f01b2fSopenharmony_ci            }
1634c5f01b2fSopenharmony_ci
1635c5f01b2fSopenharmony_ci            SECTION("] with value")
1636c5f01b2fSopenharmony_ci            {
1637c5f01b2fSopenharmony_ci                SaxCountdown s(2);
1638c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("[1]", &s) == false);
1639c5f01b2fSopenharmony_ci            }
1640c5f01b2fSopenharmony_ci
1641c5f01b2fSopenharmony_ci            SECTION("float")
1642c5f01b2fSopenharmony_ci            {
1643c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1644c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("3.14", &s) == false);
1645c5f01b2fSopenharmony_ci            }
1646c5f01b2fSopenharmony_ci
1647c5f01b2fSopenharmony_ci            SECTION("false")
1648c5f01b2fSopenharmony_ci            {
1649c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1650c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("false", &s) == false);
1651c5f01b2fSopenharmony_ci            }
1652c5f01b2fSopenharmony_ci
1653c5f01b2fSopenharmony_ci            SECTION("null")
1654c5f01b2fSopenharmony_ci            {
1655c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1656c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("null", &s) == false);
1657c5f01b2fSopenharmony_ci            }
1658c5f01b2fSopenharmony_ci
1659c5f01b2fSopenharmony_ci            SECTION("true")
1660c5f01b2fSopenharmony_ci            {
1661c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1662c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("true", &s) == false);
1663c5f01b2fSopenharmony_ci            }
1664c5f01b2fSopenharmony_ci
1665c5f01b2fSopenharmony_ci            SECTION("unsigned")
1666c5f01b2fSopenharmony_ci            {
1667c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1668c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("12", &s) == false);
1669c5f01b2fSopenharmony_ci            }
1670c5f01b2fSopenharmony_ci
1671c5f01b2fSopenharmony_ci            SECTION("integer")
1672c5f01b2fSopenharmony_ci            {
1673c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1674c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("-12", &s) == false);
1675c5f01b2fSopenharmony_ci            }
1676c5f01b2fSopenharmony_ci
1677c5f01b2fSopenharmony_ci            SECTION("string")
1678c5f01b2fSopenharmony_ci            {
1679c5f01b2fSopenharmony_ci                SaxCountdown s(0);
1680c5f01b2fSopenharmony_ci                CHECK(json::sax_parse("\"foo\"", &s) == false);
1681c5f01b2fSopenharmony_ci            }
1682c5f01b2fSopenharmony_ci        }
1683c5f01b2fSopenharmony_ci    }
1684c5f01b2fSopenharmony_ci
1685c5f01b2fSopenharmony_ci    SECTION("error messages for comments")
1686c5f01b2fSopenharmony_ci    {
1687c5f01b2fSopenharmony_ci        json _;
1688c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(_ = json::parse("/a", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid comment; expecting '/' or '*' after '/'; last read: '/a'", json::parse_error);
1689c5f01b2fSopenharmony_ci        CHECK_THROWS_WITH_AS(_ = json::parse("/*", nullptr, true, true), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid comment; missing closing '*/'; last read: '/*<U+0000>'", json::parse_error);
1690c5f01b2fSopenharmony_ci    }
1691c5f01b2fSopenharmony_ci}
1692