1// __ _____ _____ _____ 2// __| | __| | | | JSON for Modern C++ (supporting code) 3// | | |__ | | | | | | version 3.11.2 4// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5// 6// Copyright (c) 2013-2022 Niels Lohmann <http://nlohmann.me>. 7// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 8// SPDX-License-Identifier: MIT 9 10#include "doctest_compatibility.h" 11 12#include <nlohmann/json.hpp> 13using nlohmann::json; 14#ifdef JSON_TEST_NO_GLOBAL_UDLS 15 using namespace nlohmann::literals; // NOLINT(google-build-using-namespace) 16#endif 17 18#include <iostream> 19#include <iterator> 20#include <sstream> 21#include <valarray> 22 23namespace 24{ 25struct SaxEventLogger : public nlohmann::json_sax<json> 26{ 27 bool null() override 28 { 29 events.emplace_back("null()"); 30 return true; 31 } 32 33 bool boolean(bool val) override 34 { 35 events.emplace_back(val ? "boolean(true)" : "boolean(false)"); 36 return true; 37 } 38 39 bool number_integer(json::number_integer_t val) override 40 { 41 events.push_back("number_integer(" + std::to_string(val) + ")"); 42 return true; 43 } 44 45 bool number_unsigned(json::number_unsigned_t val) override 46 { 47 events.push_back("number_unsigned(" + std::to_string(val) + ")"); 48 return true; 49 } 50 51 bool number_float(json::number_float_t /*val*/, const std::string& s) override 52 { 53 events.push_back("number_float(" + s + ")"); 54 return true; 55 } 56 57 bool string(std::string& val) override 58 { 59 events.push_back("string(" + val + ")"); 60 return true; 61 } 62 63 bool binary(json::binary_t& val) override 64 { 65 std::string binary_contents = "binary("; 66 std::string comma_space; 67 for (auto b : val) 68 { 69 binary_contents.append(comma_space); 70 binary_contents.append(std::to_string(static_cast<int>(b))); 71 comma_space = ", "; 72 } 73 binary_contents.append(")"); 74 events.push_back(binary_contents); 75 return true; 76 } 77 78 bool start_object(std::size_t elements) override 79 { 80 if (elements == static_cast<std::size_t>(-1)) 81 { 82 events.emplace_back("start_object()"); 83 } 84 else 85 { 86 events.push_back("start_object(" + std::to_string(elements) + ")"); 87 } 88 return true; 89 } 90 91 bool key(std::string& val) override 92 { 93 events.push_back("key(" + val + ")"); 94 return true; 95 } 96 97 bool end_object() override 98 { 99 events.emplace_back("end_object()"); 100 return true; 101 } 102 103 bool start_array(std::size_t elements) override 104 { 105 if (elements == static_cast<std::size_t>(-1)) 106 { 107 events.emplace_back("start_array()"); 108 } 109 else 110 { 111 events.push_back("start_array(" + std::to_string(elements) + ")"); 112 } 113 return true; 114 } 115 116 bool end_array() override 117 { 118 events.emplace_back("end_array()"); 119 return true; 120 } 121 122 bool parse_error(std::size_t position, const std::string& /*last_token*/, const json::exception& /*ex*/) override 123 { 124 events.push_back("parse_error(" + std::to_string(position) + ")"); 125 return false; 126 } 127 128 std::vector<std::string> events {}; 129}; 130 131struct SaxEventLoggerExitAfterStartObject : public SaxEventLogger 132{ 133 bool start_object(std::size_t elements) override 134 { 135 if (elements == static_cast<std::size_t>(-1)) 136 { 137 events.emplace_back("start_object()"); 138 } 139 else 140 { 141 events.push_back("start_object(" + std::to_string(elements) + ")"); 142 } 143 return false; 144 } 145}; 146 147struct SaxEventLoggerExitAfterKey : public SaxEventLogger 148{ 149 bool key(std::string& val) override 150 { 151 events.push_back("key(" + val + ")"); 152 return false; 153 } 154}; 155 156struct SaxEventLoggerExitAfterStartArray : public SaxEventLogger 157{ 158 bool start_array(std::size_t elements) override 159 { 160 if (elements == static_cast<std::size_t>(-1)) 161 { 162 events.emplace_back("start_array()"); 163 } 164 else 165 { 166 events.push_back("start_array(" + std::to_string(elements) + ")"); 167 } 168 return false; 169 } 170}; 171 172template <typename T> 173class proxy_iterator 174{ 175 public: 176 using iterator = typename T::iterator; 177 using value_type = typename std::iterator_traits<iterator>::value_type; 178 using reference = typename std::iterator_traits<iterator>::reference; 179 using pointer = typename std::iterator_traits<iterator>::pointer; 180 using difference_type = 181 typename std::iterator_traits<iterator>::difference_type; 182 using iterator_category = std::input_iterator_tag; 183 184 proxy_iterator() = default; 185 explicit proxy_iterator(iterator& it) : m_it(std::addressof(it)) {} 186 187 proxy_iterator& operator++() 188 { 189 ++*m_it; 190 return *this; 191 } 192 193 proxy_iterator& operator--() 194 { 195 --*m_it; 196 return *this; 197 } 198 199 bool operator==(const proxy_iterator& rhs) const 200 { 201 return (m_it && rhs.m_it) ? (*m_it == *rhs.m_it) : (m_it == rhs.m_it); 202 } 203 204 bool operator!=(const proxy_iterator& rhs) const 205 { 206 return !(*this == rhs); 207 } 208 209 reference operator*() const 210 { 211 return **m_it; 212 } 213 214 private: 215 iterator* m_it = nullptr; 216}; 217} // namespace 218 219TEST_CASE("deserialization") 220{ 221 SECTION("successful deserialization") 222 { 223 SECTION("stream") 224 { 225 std::stringstream ss1; 226 std::stringstream ss2; 227 std::stringstream ss3; 228 ss1 << R"(["foo",1,2,3,false,{"one":1}])"; 229 ss2 << R"(["foo",1,2,3,false,{"one":1}])"; 230 ss3 << R"(["foo",1,2,3,false,{"one":1}])"; 231 json j = json::parse(ss1); 232 CHECK(json::accept(ss2)); 233 CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); 234 235 SaxEventLogger l; 236 CHECK(json::sax_parse(ss3, &l)); 237 CHECK(l.events.size() == 11); 238 CHECK(l.events == std::vector<std::string>( 239 { 240 "start_array()", "string(foo)", "number_unsigned(1)", 241 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)", 242 "start_object()", "key(one)", "number_unsigned(1)", 243 "end_object()", "end_array()" 244 })); 245 } 246 247 SECTION("string literal") 248 { 249 const auto* s = R"(["foo",1,2,3,false,{"one":1}])"; 250 json j = json::parse(s); 251 CHECK(json::accept(s)); 252 CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); 253 254 SaxEventLogger l; 255 CHECK(json::sax_parse(s, &l)); 256 CHECK(l.events.size() == 11); 257 CHECK(l.events == std::vector<std::string>( 258 { 259 "start_array()", "string(foo)", "number_unsigned(1)", 260 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)", 261 "start_object()", "key(one)", "number_unsigned(1)", 262 "end_object()", "end_array()" 263 })); 264 } 265 266 SECTION("string_t") 267 { 268 json::string_t s = R"(["foo",1,2,3,false,{"one":1}])"; 269 json j = json::parse(s); 270 CHECK(json::accept(s)); 271 CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); 272 273 SaxEventLogger l; 274 CHECK(json::sax_parse(s, &l)); 275 CHECK(l.events.size() == 11); 276 CHECK(l.events == std::vector<std::string>( 277 { 278 "start_array()", "string(foo)", "number_unsigned(1)", 279 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)", 280 "start_object()", "key(one)", "number_unsigned(1)", 281 "end_object()", "end_array()" 282 })); 283 } 284 285 SECTION("operator<<") 286 { 287 std::stringstream ss; 288 ss << R"(["foo",1,2,3,false,{"one":1}])"; 289 json j; 290 j << ss; 291 CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); 292 } 293 294 SECTION("operator>>") 295 { 296 std::stringstream ss; 297 ss << R"(["foo",1,2,3,false,{"one":1}])"; 298 json j; 299 ss >> j; 300 CHECK(j == json({"foo", 1, 2, 3, false, {{"one", 1}}})); 301 } 302 303 SECTION("user-defined string literal") 304 { 305 CHECK("[\"foo\",1,2,3,false,{\"one\":1}]"_json == json({"foo", 1, 2, 3, false, {{"one", 1}}})); 306 } 307 } 308 309 SECTION("unsuccessful deserialization") 310 { 311 SECTION("stream") 312 { 313 std::stringstream ss1; 314 std::stringstream ss3; 315 std::stringstream ss4; 316 std::stringstream ss5; 317 ss1 << R"(["foo",1,2,3,false,{"one":1})"; 318 ss3 << R"(["foo",1,2,3,false,{"one":1})"; 319 ss4 << R"(["foo",1,2,3,false,{"one":1})"; 320 ss5 << R"(["foo",1,2,3,false,{"one":1})"; 321 322 json _; 323 CHECK_THROWS_WITH_AS(_ = json::parse(ss1), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); 324 CHECK(!json::accept(ss3)); 325 326 json j_error; 327 CHECK_NOTHROW(j_error = json::parse(ss4, nullptr, false)); 328 CHECK(j_error.is_discarded()); 329 330 SaxEventLogger l; 331 CHECK(!json::sax_parse(ss5, &l)); 332 CHECK(l.events.size() == 11); 333 CHECK(l.events == std::vector<std::string>( 334 { 335 "start_array()", "string(foo)", "number_unsigned(1)", 336 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)", 337 "start_object()", "key(one)", "number_unsigned(1)", 338 "end_object()", "parse_error(29)" 339 })); 340 } 341 342 SECTION("string") 343 { 344 json::string_t s = R"(["foo",1,2,3,false,{"one":1})"; 345 json _; 346 CHECK_THROWS_WITH_AS(_ = json::parse(s), "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); 347 CHECK(!json::accept(s)); 348 349 json j_error; 350 CHECK_NOTHROW(j_error = json::parse(s, nullptr, false)); 351 CHECK(j_error.is_discarded()); 352 353 SaxEventLogger l; 354 CHECK(!json::sax_parse(s, &l)); 355 CHECK(l.events.size() == 11); 356 CHECK(l.events == std::vector<std::string>( 357 { 358 "start_array()", "string(foo)", "number_unsigned(1)", 359 "number_unsigned(2)", "number_unsigned(3)", "boolean(false)", 360 "start_object()", "key(one)", "number_unsigned(1)", 361 "end_object()", "parse_error(29)" 362 })); 363 } 364 365 SECTION("operator<<") 366 { 367 std::stringstream ss; 368 ss << R"(["foo",1,2,3,false,{"one":1})"; 369 json j; 370 CHECK_THROWS_WITH_AS(j << ss, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); 371 } 372 373 SECTION("operator>>") 374 { 375 std::stringstream ss; 376 ss << R"(["foo",1,2,3,false,{"one":1})"; 377 json j; 378 CHECK_THROWS_WITH_AS(ss >> j, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); 379 } 380 381 SECTION("user-defined string literal") 382 { 383 CHECK_THROWS_WITH_AS("[\"foo\",1,2,3,false,{\"one\":1}"_json, "[json.exception.parse_error.101] parse error at line 1, column 29: syntax error while parsing array - unexpected end of input; expected ']'", json::parse_error&); 384 } 385 } 386 387 SECTION("contiguous containers") 388 { 389 SECTION("directly") 390 { 391 SECTION("from std::vector") 392 { 393 std::vector<uint8_t> v = {'t', 'r', 'u', 'e'}; 394 CHECK(json::parse(v) == json(true)); 395 CHECK(json::accept(v)); 396 397 SaxEventLogger l; 398 CHECK(json::sax_parse(v, &l)); 399 CHECK(l.events.size() == 1); 400 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 401 } 402 403 SECTION("from std::array") 404 { 405 std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} }; 406 CHECK(json::parse(v) == json(true)); 407 CHECK(json::accept(v)); 408 409 SaxEventLogger l; 410 CHECK(json::sax_parse(v, &l)); 411 CHECK(l.events.size() == 1); 412 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 413 } 414 415 SECTION("from array") 416 { 417 uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 418 CHECK(json::parse(v) == json(true)); 419 CHECK(json::accept(v)); 420 421 SaxEventLogger l; 422 CHECK(json::sax_parse(v, &l)); 423 CHECK(l.events.size() == 1); 424 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 425 } 426 427 SECTION("from chars") 428 { 429 auto* v = new uint8_t[5]; // NOLINT(cppcoreguidelines-owning-memory) 430 v[0] = 't'; 431 v[1] = 'r'; 432 v[2] = 'u'; 433 v[3] = 'e'; 434 v[4] = '\0'; 435 CHECK(json::parse(v) == json(true)); 436 CHECK(json::accept(v)); 437 438 SaxEventLogger l; 439 CHECK(json::sax_parse(v, &l)); 440 CHECK(l.events.size() == 1); 441 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 442 443 delete[] v; // NOLINT(cppcoreguidelines-owning-memory) 444 } 445 446 SECTION("from std::string") 447 { 448 std::string v = {'t', 'r', 'u', 'e'}; 449 CHECK(json::parse(v) == json(true)); 450 CHECK(json::accept(v)); 451 452 SaxEventLogger l; 453 CHECK(json::sax_parse(v, &l)); 454 CHECK(l.events.size() == 1); 455 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 456 } 457 458 SECTION("from std::initializer_list") 459 { 460 std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'}; 461 CHECK(json::parse(v) == json(true)); 462 CHECK(json::accept(v)); 463 464 SaxEventLogger l; 465 CHECK(json::sax_parse(v, &l)); 466 CHECK(l.events.size() == 1); 467 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 468 } 469 470 SECTION("empty container") 471 { 472 std::vector<uint8_t> v; 473 json _; 474 CHECK_THROWS_AS(_ = json::parse(v), json::parse_error&); 475 CHECK(!json::accept(v)); 476 477 SaxEventLogger l; 478 CHECK(!json::sax_parse(v, &l)); 479 CHECK(l.events.size() == 1); 480 CHECK(l.events == std::vector<std::string>({"parse_error(1)"})); 481 } 482 } 483 484 SECTION("via iterator range") 485 { 486 SECTION("from std::vector") 487 { 488 std::vector<uint8_t> v = {'t', 'r', 'u', 'e'}; 489 CHECK(json::parse(std::begin(v), std::end(v)) == json(true)); 490 CHECK(json::accept(std::begin(v), std::end(v))); 491 492 SaxEventLogger l; 493 CHECK(json::sax_parse(std::begin(v), std::end(v), &l)); 494 CHECK(l.events.size() == 1); 495 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 496 497 } 498 499 SECTION("from std::array") 500 { 501 std::array<uint8_t, 5> v { {'t', 'r', 'u', 'e'} }; 502 CHECK(json::parse(std::begin(v), std::end(v)) == json(true)); 503 CHECK(json::accept(std::begin(v), std::end(v))); 504 505 SaxEventLogger l; 506 CHECK(json::sax_parse(std::begin(v), std::end(v), &l)); 507 CHECK(l.events.size() == 1); 508 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 509 } 510 511 SECTION("from array") 512 { 513 uint8_t v[] = {'t', 'r', 'u', 'e'}; // NOLINT(cppcoreguidelines-avoid-c-arrays,hicpp-avoid-c-arrays,modernize-avoid-c-arrays) 514 CHECK(json::parse(std::begin(v), std::end(v)) == json(true)); 515 CHECK(json::accept(std::begin(v), std::end(v))); 516 517 SaxEventLogger l; 518 CHECK(json::sax_parse(std::begin(v), std::end(v), &l)); 519 CHECK(l.events.size() == 1); 520 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 521 } 522 523 SECTION("from std::string") 524 { 525 std::string v = {'t', 'r', 'u', 'e'}; 526 CHECK(json::parse(std::begin(v), std::end(v)) == json(true)); 527 CHECK(json::accept(std::begin(v), std::end(v))); 528 529 SaxEventLogger l; 530 CHECK(json::sax_parse(std::begin(v), std::end(v), &l)); 531 CHECK(l.events.size() == 1); 532 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 533 } 534 535 SECTION("from std::initializer_list") 536 { 537 std::initializer_list<uint8_t> v = {'t', 'r', 'u', 'e'}; 538 CHECK(json::parse(std::begin(v), std::end(v)) == json(true)); 539 CHECK(json::accept(std::begin(v), std::end(v))); 540 541 SaxEventLogger l; 542 CHECK(json::sax_parse(std::begin(v), std::end(v), &l)); 543 CHECK(l.events.size() == 1); 544 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 545 } 546 547 SECTION("from std::valarray") 548 { 549 std::valarray<uint8_t> v = {'t', 'r', 'u', 'e'}; 550 CHECK(json::parse(std::begin(v), std::end(v)) == json(true)); 551 CHECK(json::accept(std::begin(v), std::end(v))); 552 553 SaxEventLogger l; 554 CHECK(json::sax_parse(std::begin(v), std::end(v), &l)); 555 CHECK(l.events.size() == 1); 556 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 557 } 558 559 SECTION("with empty range") 560 { 561 std::vector<uint8_t> v; 562 json _; 563 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 564 CHECK(!json::accept(std::begin(v), std::end(v))); 565 566 SaxEventLogger l; 567 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 568 CHECK(l.events.size() == 1); 569 CHECK(l.events == std::vector<std::string>({"parse_error(1)"})); 570 } 571 572 SECTION("iterator_input_adapter advances iterators correctly") 573 { 574 using nlohmann::json; 575 using nlohmann::detail::input_format_t; 576 using nlohmann::detail::json_sax_dom_parser; 577 using proxy = proxy_iterator<std::string>; 578 579 std::string str1 = "[1]"; 580 std::string str2 = "[2]"; 581 std::string str = str1 + str2; 582 583 auto first = str.begin(); 584 auto last = str.end(); 585 json j; 586 json_sax_dom_parser<json> sax(j, true); 587 588 CHECK(json::sax_parse(proxy(first), proxy(last), &sax, 589 input_format_t::json, false)); 590 CHECK(j.dump() == str1); 591 CHECK(std::string(first, last) == str2); 592 } 593 } 594 595 // these cases are required for 100% line coverage 596 SECTION("error cases") 597 { 598 SECTION("case 1") 599 { 600 std::array<std::uint8_t, 9> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u'}}; 601 json _; 602 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 603 CHECK(!json::accept(std::begin(v), std::end(v))); 604 605 json j_error; 606 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 607 CHECK(j_error.is_discarded()); 608 609 SaxEventLogger l; 610 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 611 CHECK(l.events.size() == 1); 612 CHECK(l.events == std::vector<std::string>({"parse_error(10)"})); 613 } 614 615 SECTION("case 2") 616 { 617 std::array<std::uint8_t, 10> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1'}}; 618 json _; 619 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 620 CHECK(!json::accept(std::begin(v), std::end(v))); 621 622 json j_error; 623 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 624 CHECK(j_error.is_discarded()); 625 626 SaxEventLogger l; 627 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 628 CHECK(l.events.size() == 1); 629 CHECK(l.events == std::vector<std::string>({"parse_error(11)"})); 630 } 631 632 SECTION("case 3") 633 { 634 std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', '\\', 'u', '1', '1', '1', '1', '1', '1', '1', '1'}}; 635 json _; 636 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 637 CHECK(!json::accept(std::begin(v), std::end(v))); 638 639 json j_error; 640 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 641 CHECK(j_error.is_discarded()); 642 643 SaxEventLogger l; 644 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 645 CHECK(l.events.size() == 1); 646 CHECK(l.events == std::vector<std::string>({"parse_error(18)"})); 647 } 648 649 SECTION("case 4") 650 { 651 std::array<std::uint8_t, 17> v = {{'\"', 'a', 'a', 'a', 'a', 'a', 'a', 'u', '1', '1', '1', '1', '1', '1', '1', '1', '\\'}}; 652 json _; 653 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 654 CHECK(!json::accept(std::begin(v), std::end(v))); 655 656 json j_error; 657 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 658 CHECK(j_error.is_discarded()); 659 660 SaxEventLogger l; 661 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 662 CHECK(l.events.size() == 1); 663 CHECK(l.events == std::vector<std::string>({"parse_error(18)"})); 664 } 665 666 SECTION("case 5") 667 { 668 std::array<std::uint8_t, 3> v = {{'\"', 0x7F, 0xC1}}; 669 json _; 670 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 671 CHECK(!json::accept(std::begin(v), std::end(v))); 672 673 json j_error; 674 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 675 CHECK(j_error.is_discarded()); 676 677 SaxEventLogger l; 678 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 679 CHECK(l.events.size() == 1); 680 CHECK(l.events == std::vector<std::string>({"parse_error(3)"})); 681 } 682 683 SECTION("case 6") 684 { 685 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0x7F}}; 686 json _; 687 CHECK_THROWS_WITH_AS(_ = json::parse(std::begin(v), std::end(v)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - invalid string: ill-formed UTF-8 byte; last read: '\"\x7f\xdf\x7f'", json::parse_error&); 688 CHECK(!json::accept(std::begin(v), std::end(v))); 689 690 json j_error; 691 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 692 CHECK(j_error.is_discarded()); 693 694 SaxEventLogger l; 695 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 696 CHECK(l.events.size() == 1); 697 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 698 } 699 700 SECTION("case 7") 701 { 702 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xDF, 0xC0}}; 703 json _; 704 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 705 CHECK(!json::accept(std::begin(v), std::end(v))); 706 707 json j_error; 708 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 709 CHECK(j_error.is_discarded()); 710 711 SaxEventLogger l; 712 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 713 CHECK(l.events.size() == 1); 714 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 715 } 716 717 SECTION("case 8") 718 { 719 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xE0, 0x9F}}; 720 json _; 721 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 722 CHECK(!json::accept(std::begin(v), std::end(v))); 723 724 json j_error; 725 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 726 CHECK(j_error.is_discarded()); 727 728 SaxEventLogger l; 729 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 730 CHECK(l.events.size() == 1); 731 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 732 } 733 734 SECTION("case 9") 735 { 736 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xEF, 0xC0}}; 737 json _; 738 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 739 CHECK(!json::accept(std::begin(v), std::end(v))); 740 741 json j_error; 742 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 743 CHECK(j_error.is_discarded()); 744 745 SaxEventLogger l; 746 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 747 CHECK(l.events.size() == 1); 748 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 749 } 750 751 SECTION("case 10") 752 { 753 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xED, 0x7F}}; 754 json _; 755 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 756 CHECK(!json::accept(std::begin(v), std::end(v))); 757 758 json j_error; 759 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 760 CHECK(j_error.is_discarded()); 761 762 SaxEventLogger l; 763 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 764 CHECK(l.events.size() == 1); 765 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 766 } 767 768 SECTION("case 11") 769 { 770 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0x8F}}; 771 json _; 772 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 773 CHECK(!json::accept(std::begin(v), std::end(v))); 774 775 json j_error; 776 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 777 CHECK(j_error.is_discarded()); 778 779 SaxEventLogger l; 780 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 781 CHECK(l.events.size() == 1); 782 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 783 } 784 785 SECTION("case 12") 786 { 787 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF0, 0xC0}}; 788 json _; 789 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 790 CHECK(!json::accept(std::begin(v), std::end(v))); 791 792 json j_error; 793 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 794 CHECK(j_error.is_discarded()); 795 796 SaxEventLogger l; 797 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 798 CHECK(l.events.size() == 1); 799 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 800 } 801 802 SECTION("case 13") 803 { 804 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0x7F}}; 805 json _; 806 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 807 CHECK(!json::accept(std::begin(v), std::end(v))); 808 809 json j_error; 810 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 811 CHECK(j_error.is_discarded()); 812 813 SaxEventLogger l; 814 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 815 CHECK(l.events.size() == 1); 816 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 817 } 818 819 SECTION("case 14") 820 { 821 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF3, 0xC0}}; 822 json _; 823 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 824 CHECK(!json::accept(std::begin(v), std::end(v))); 825 826 json j_error; 827 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 828 CHECK(j_error.is_discarded()); 829 830 SaxEventLogger l; 831 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 832 CHECK(l.events.size() == 1); 833 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 834 } 835 836 SECTION("case 15") 837 { 838 std::array<std::uint8_t, 4> v = {{'\"', 0x7F, 0xF4, 0x7F}}; 839 json _; 840 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 841 CHECK(!json::accept(std::begin(v), std::end(v))); 842 843 json j_error; 844 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 845 CHECK(j_error.is_discarded()); 846 847 SaxEventLogger l; 848 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 849 CHECK(l.events.size() == 1); 850 CHECK(l.events == std::vector<std::string>({"parse_error(4)"})); 851 } 852 853 SECTION("case 16") 854 { 855 std::array<std::uint8_t, 6> v = {{'{', '\"', '\"', ':', '1', '1'}}; 856 json _; 857 CHECK_THROWS_AS(_ = json::parse(std::begin(v), std::end(v)), json::parse_error&); 858 CHECK(!json::accept(std::begin(v), std::end(v))); 859 860 json j_error; 861 CHECK_NOTHROW(j_error = json::parse(std::begin(v), std::end(v), nullptr, false)); 862 CHECK(j_error.is_discarded()); 863 864 SaxEventLogger l; 865 CHECK(!json::sax_parse(std::begin(v), std::end(v), &l)); 866 CHECK(l.events.size() == 4); 867 CHECK(l.events == std::vector<std::string>( 868 { 869 "start_object()", "key()", "number_unsigned(11)", 870 "parse_error(7)" 871 })); 872 } 873 } 874 } 875 876 SECTION("ignoring byte-order marks") 877 { 878 std::string bom = "\xEF\xBB\xBF"; 879 880 SECTION("BOM only") 881 { 882 json _; 883 CHECK_THROWS_WITH_AS(_ = json::parse(bom), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&); 884 885 CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom)), "[json.exception.parse_error.101] parse error at line 1, column 4: syntax error while parsing value - unexpected end of input; expected '[', '{', or a literal", json::parse_error&); 886 887 SaxEventLogger l; 888 CHECK(!json::sax_parse(bom, &l)); 889 CHECK(l.events.size() == 1); 890 CHECK(l.events == std::vector<std::string>( 891 { 892 "parse_error(4)" 893 })); 894 } 895 896 SECTION("BOM and content") 897 { 898 CHECK(json::parse(bom + "1") == 1); 899 CHECK(json::parse(std::istringstream(bom + "1")) == 1); 900 901 SaxEventLogger l1; 902 SaxEventLogger l2; 903 CHECK(json::sax_parse(std::istringstream(bom + "1"), &l1)); 904 CHECK(json::sax_parse(bom + "1", &l2)); 905 CHECK(l1.events.size() == 1); 906 CHECK(l1.events == std::vector<std::string>( 907 { 908 "number_unsigned(1)" 909 })); 910 CHECK(l2.events.size() == 1); 911 CHECK(l2.events == std::vector<std::string>( 912 { 913 "number_unsigned(1)" 914 })); 915 } 916 917 SECTION("2 byte of BOM") 918 { 919 json _; 920 CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 2)), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&); 921 922 CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 2))), "[json.exception.parse_error.101] parse error at line 1, column 3: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF\xBB'", json::parse_error&); 923 924 SaxEventLogger l1; 925 SaxEventLogger l2; 926 CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 2)), &l1)); 927 CHECK(!json::sax_parse(bom.substr(0, 2), &l2)); 928 CHECK(l1.events.size() == 1); 929 CHECK(l1.events == std::vector<std::string>( 930 { 931 "parse_error(3)" 932 })); 933 CHECK(l2.events.size() == 1); 934 CHECK(l2.events == std::vector<std::string>( 935 { 936 "parse_error(3)" 937 })); 938 } 939 940 SECTION("1 byte of BOM") 941 { 942 json _; 943 CHECK_THROWS_WITH_AS(_ = json::parse(bom.substr(0, 1)), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&); 944 945 CHECK_THROWS_WITH_AS(_ = json::parse(std::istringstream(bom.substr(0, 1))), "[json.exception.parse_error.101] parse error at line 1, column 2: syntax error while parsing value - invalid BOM; must be 0xEF 0xBB 0xBF if given; last read: '\xEF'", json::parse_error&); 946 947 SaxEventLogger l1; 948 SaxEventLogger l2; 949 CHECK(!json::sax_parse(std::istringstream(bom.substr(0, 1)), &l1)); 950 CHECK(!json::sax_parse(bom.substr(0, 1), &l2)); 951 CHECK(l1.events.size() == 1); 952 CHECK(l1.events == std::vector<std::string>( 953 { 954 "parse_error(2)" 955 })); 956 CHECK(l2.events.size() == 1); 957 CHECK(l2.events == std::vector<std::string>( 958 { 959 "parse_error(2)" 960 })); 961 } 962 963 SECTION("variations") 964 { 965 // calculate variations of each byte of the BOM to make sure 966 // that the BOM and only the BOM is skipped 967 for (int i0 = -1; i0 < 2; ++i0) 968 { 969 for (int i1 = -1; i1 < 2; ++i1) 970 { 971 for (int i2 = -1; i2 < 2; ++i2) 972 { 973 // debug output for the variations 974 CAPTURE(i0) 975 CAPTURE(i1) 976 CAPTURE(i2) 977 978 std::string s; 979 s.push_back(static_cast<char>(bom[0] + i0)); 980 s.push_back(static_cast<char>(bom[1] + i1)); 981 s.push_back(static_cast<char>(bom[2] + i2)); 982 983 if (i0 == 0 && i1 == 0 && i2 == 0) 984 { 985 // without any variation, we skip the BOM 986 CHECK(json::parse(s + "null") == json()); 987 CHECK(json::parse(std::istringstream(s + "null")) == json()); 988 989 SaxEventLogger l; 990 CHECK(json::sax_parse(s + "null", &l)); 991 CHECK(l.events.size() == 1); 992 CHECK(l.events == std::vector<std::string>( 993 { 994 "null()" 995 })); 996 } 997 else 998 { 999 // any variation is an error 1000 json _; 1001 CHECK_THROWS_AS(_ = json::parse(s + "null"), json::parse_error&); 1002 CHECK_THROWS_AS(_ = json::parse(std::istringstream(s + "null")), json::parse_error&); 1003 1004 SaxEventLogger l; 1005 CHECK(!json::sax_parse(s + "null", &l)); 1006 CHECK(l.events.size() == 1); 1007 1008 if (i0 != 0) 1009 { 1010 CHECK(l.events == std::vector<std::string>( 1011 { 1012 "parse_error(1)" 1013 })); 1014 } 1015 else if (i1 != 0) 1016 { 1017 CHECK(l.events == std::vector<std::string>( 1018 { 1019 "parse_error(2)" 1020 })); 1021 } 1022 else 1023 { 1024 CHECK(l.events == std::vector<std::string>( 1025 { 1026 "parse_error(3)" 1027 })); 1028 } 1029 } 1030 } 1031 } 1032 } 1033 } 1034 1035 SECTION("preserve state after parsing") 1036 { 1037 std::istringstream s(bom + "123 456"); 1038 json j; 1039 j << s; 1040 CHECK(j == 123); 1041 j << s; 1042 CHECK(j == 456); 1043 } 1044 } 1045 1046 SECTION("SAX and early abort") 1047 { 1048 std::string s = R"([1, ["string", 43.12], null, {"key1": true, "key2": false}])"; 1049 1050 SaxEventLogger default_logger; 1051 SaxEventLoggerExitAfterStartObject exit_after_start_object; 1052 SaxEventLoggerExitAfterKey exit_after_key; 1053 SaxEventLoggerExitAfterStartArray exit_after_start_array; 1054 1055 json::sax_parse(s, &default_logger); 1056 CHECK(default_logger.events.size() == 14); 1057 CHECK(default_logger.events == std::vector<std::string>( 1058 { 1059 "start_array()", "number_unsigned(1)", "start_array()", 1060 "string(string)", "number_float(43.12)", "end_array()", "null()", 1061 "start_object()", "key(key1)", "boolean(true)", "key(key2)", 1062 "boolean(false)", "end_object()", "end_array()" 1063 })); 1064 1065 json::sax_parse(s, &exit_after_start_object); 1066 CHECK(exit_after_start_object.events.size() == 8); 1067 CHECK(exit_after_start_object.events == std::vector<std::string>( 1068 { 1069 "start_array()", "number_unsigned(1)", "start_array()", 1070 "string(string)", "number_float(43.12)", "end_array()", "null()", 1071 "start_object()" 1072 })); 1073 1074 json::sax_parse(s, &exit_after_key); 1075 CHECK(exit_after_key.events.size() == 9); 1076 CHECK(exit_after_key.events == std::vector<std::string>( 1077 { 1078 "start_array()", "number_unsigned(1)", "start_array()", 1079 "string(string)", "number_float(43.12)", "end_array()", "null()", 1080 "start_object()", "key(key1)" 1081 })); 1082 1083 json::sax_parse(s, &exit_after_start_array); 1084 CHECK(exit_after_start_array.events.size() == 1); 1085 CHECK(exit_after_start_array.events == std::vector<std::string>( 1086 { 1087 "start_array()" 1088 })); 1089 } 1090 1091 SECTION("JSON Lines") 1092 { 1093 SECTION("Example file") 1094 { 1095 std::stringstream ss; 1096 ss << R"({"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]} 1097 {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]} 1098 {"name": "May", "wins": []} 1099 {"name": "Deloise", "wins": [["three of a kind", "5♣"]]} 1100)"; 1101 1102 std::string line; 1103 int object_count = 0; 1104 while (std::getline(ss, line)) 1105 { 1106 ++object_count; 1107 CHECK(json::accept(line)); 1108 } 1109 1110 CHECK(object_count == 4); 1111 } 1112 1113 SECTION("Example file without trailing newline") 1114 { 1115 std::stringstream ss; 1116 ss << R"({"name": "Gilbert", "wins": [["straight", "7♣"], ["one pair", "10♥"]]} 1117 {"name": "Alexa", "wins": [["two pair", "4♠"], ["two pair", "9♠"]]} 1118 {"name": "May", "wins": []} 1119 {"name": "Deloise", "wins": [["three of a kind", "5♣"]]})"; 1120 1121 std::string line; 1122 int object_count = 0; 1123 while (std::getline(ss, line)) 1124 { 1125 ++object_count; 1126 CHECK(json::accept(line)); 1127 } 1128 1129 CHECK(object_count == 4); 1130 } 1131 } 1132} 1133 1134TEST_CASE_TEMPLATE("deserialization of different character types (ASCII)", T, 1135 char, unsigned char, signed char, 1136 wchar_t, 1137 char16_t, char32_t, 1138 std::uint8_t, std::int8_t, 1139 std::int16_t, std::uint16_t, 1140 std::int32_t, std::uint32_t) 1141{ 1142 std::vector<T> v = {'t', 'r', 'u', 'e'}; 1143 CHECK(json::parse(v) == json(true)); 1144 CHECK(json::accept(v)); 1145 1146 SaxEventLogger l; 1147 CHECK(json::sax_parse(v, &l)); 1148 CHECK(l.events.size() == 1); 1149 CHECK(l.events == std::vector<std::string>({"boolean(true)"})); 1150} 1151 1152TEST_CASE_TEMPLATE("deserialization of different character types (UTF-8)", T, 1153 char, unsigned char, std::uint8_t) 1154{ 1155 // a star emoji 1156 std::vector<T> v = {'"', static_cast<T>(0xe2u), static_cast<T>(0xadu), static_cast<T>(0x90u), static_cast<T>(0xefu), static_cast<T>(0xb8u), static_cast<T>(0x8fu), '"'}; 1157 CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\""); 1158 CHECK(json::accept(v)); 1159 1160 SaxEventLogger l; 1161 CHECK(json::sax_parse(v, &l)); 1162 CHECK(l.events.size() == 1); 1163} 1164 1165TEST_CASE_TEMPLATE("deserialization of different character types (UTF-16)", T, 1166 char16_t, std::uint16_t) 1167{ 1168 // a star emoji 1169 std::vector<T> v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')}; 1170 CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\""); 1171 CHECK(json::accept(v)); 1172 1173 SaxEventLogger l; 1174 CHECK(json::sax_parse(v, &l)); 1175 CHECK(l.events.size() == 1); 1176} 1177 1178TEST_CASE_TEMPLATE("deserialization of different character types (UTF-32)", T, 1179 char32_t, std::uint32_t) 1180{ 1181 // a star emoji 1182 std::vector<T> v = {static_cast<T>('"'), static_cast<T>(0x2b50), static_cast<T>(0xfe0f), static_cast<T>('"')}; 1183 CHECK(json::parse(v).dump(-1, ' ', true) == "\"\\u2b50\\ufe0f\""); 1184 CHECK(json::accept(v)); 1185 1186 SaxEventLogger l; 1187 CHECK(json::sax_parse(v, &l)); 1188 CHECK(l.events.size() == 1); 1189} 1190