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