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