1// __ _____ _____ _____ 2// __| | __| | | | JSON for Modern C++ (supporting code) 3// | | |__ | | | | | | version 3.11.2 4// |_____|_____|_____|_|___| https://github.com/nlohmann/json 5// 6// SPDX-FileCopyrightText: 2013-2022 Niels Lohmann <https://nlohmann.me> 7// SPDX-License-Identifier: MIT 8 9#include "doctest_compatibility.h" 10 11#define JSON_TESTS_PRIVATE 12#include <nlohmann/json.hpp> 13using nlohmann::json; 14 15#include <algorithm> 16#include <climits> 17#include <limits> 18#include <iostream> 19#include <fstream> 20#include <set> 21#include "make_test_data_available.hpp" 22#include "test_utils.hpp" 23 24namespace 25{ 26class SaxCountdown 27{ 28 public: 29 explicit SaxCountdown(const int count) : events_left(count) 30 {} 31 32 bool null() 33 { 34 return events_left-- > 0; 35 } 36 37 bool boolean(bool /*unused*/) 38 { 39 return events_left-- > 0; 40 } 41 42 bool number_integer(json::number_integer_t /*unused*/) 43 { 44 return events_left-- > 0; 45 } 46 47 bool number_unsigned(json::number_unsigned_t /*unused*/) 48 { 49 return events_left-- > 0; 50 } 51 52 bool number_float(json::number_float_t /*unused*/, const std::string& /*unused*/) 53 { 54 return events_left-- > 0; 55 } 56 57 bool string(std::string& /*unused*/) 58 { 59 return events_left-- > 0; 60 } 61 62 bool binary(std::vector<std::uint8_t>& /*unused*/) 63 { 64 return events_left-- > 0; 65 } 66 67 bool start_object(std::size_t /*unused*/) 68 { 69 return events_left-- > 0; 70 } 71 72 bool key(std::string& /*unused*/) 73 { 74 return events_left-- > 0; 75 } 76 77 bool end_object() 78 { 79 return events_left-- > 0; 80 } 81 82 bool start_array(std::size_t /*unused*/) 83 { 84 return events_left-- > 0; 85 } 86 87 bool end_array() 88 { 89 return events_left-- > 0; 90 } 91 92 bool parse_error(std::size_t /*unused*/, const std::string& /*unused*/, const json::exception& /*unused*/) // NOLINT(readability-convert-member-functions-to-static) 93 { 94 return false; 95 } 96 97 private: 98 int events_left = 0; 99}; 100} // namespace 101 102// at some point in the future, a unit test dedicated to type traits might be a good idea 103template <typename OfType, typename T, bool MinInRange, bool MaxInRange> 104struct trait_test_arg 105{ 106 using of_type = OfType; 107 using type = T; 108 static constexpr bool min_in_range = MinInRange; 109 static constexpr bool max_in_range = MaxInRange; 110}; 111 112TEST_CASE_TEMPLATE_DEFINE("value_in_range_of trait", T, value_in_range_of_test) 113{ 114 using nlohmann::detail::value_in_range_of; 115 116 using of_type = typename T::of_type; 117 using type = typename T::type; 118 constexpr bool min_in_range = T::min_in_range; 119 constexpr bool max_in_range = T::max_in_range; 120 121 type val_min = std::numeric_limits<type>::min(); 122 type val_min2 = val_min + 1; 123 type val_max = std::numeric_limits<type>::max(); 124 type val_max2 = val_max - 1; 125 126 REQUIRE(CHAR_BIT == 8); 127 128 std::string of_type_str; 129 if (std::is_unsigned<of_type>::value) 130 { 131 of_type_str += "u"; 132 } 133 of_type_str += "int"; 134 of_type_str += std::to_string(sizeof(of_type) * 8); 135 136 INFO("of_type := ", of_type_str); 137 138 std::string type_str; 139 if (std::is_unsigned<type>::value) 140 { 141 type_str += "u"; 142 } 143 type_str += "int"; 144 type_str += std::to_string(sizeof(type) * 8); 145 146 INFO("type := ", type_str); 147 148 CAPTURE(val_min); 149 CAPTURE(min_in_range); 150 CAPTURE(val_max); 151 CAPTURE(max_in_range); 152 153 if (min_in_range) 154 { 155 CHECK(value_in_range_of<of_type>(val_min)); 156 CHECK(value_in_range_of<of_type>(val_min2)); 157 } 158 else 159 { 160 CHECK_FALSE(value_in_range_of<of_type>(val_min)); 161 CHECK_FALSE(value_in_range_of<of_type>(val_min2)); 162 } 163 164 if (max_in_range) 165 { 166 CHECK(value_in_range_of<of_type>(val_max)); 167 CHECK(value_in_range_of<of_type>(val_max2)); 168 } 169 else 170 { 171 CHECK_FALSE(value_in_range_of<of_type>(val_max)); 172 CHECK_FALSE(value_in_range_of<of_type>(val_max2)); 173 } 174} 175 176TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \ 177 trait_test_arg<std::int32_t, std::int32_t, true, true>, \ 178 trait_test_arg<std::int32_t, std::uint32_t, true, false>, \ 179 trait_test_arg<std::uint32_t, std::int32_t, false, true>, \ 180 trait_test_arg<std::uint32_t, std::uint32_t, true, true>, \ 181 trait_test_arg<std::int32_t, std::int64_t, false, false>, \ 182 trait_test_arg<std::int32_t, std::uint64_t, true, false>, \ 183 trait_test_arg<std::uint32_t, std::int64_t, false, false>, \ 184 trait_test_arg<std::uint32_t, std::uint64_t, true, false>, \ 185 trait_test_arg<std::int64_t, std::int32_t, true, true>, \ 186 trait_test_arg<std::int64_t, std::uint32_t, true, true>, \ 187 trait_test_arg<std::uint64_t, std::int32_t, false, true>, \ 188 trait_test_arg<std::uint64_t, std::uint32_t, true, true>, \ 189 trait_test_arg<std::int64_t, std::int64_t, true, true>, \ 190 trait_test_arg<std::int64_t, std::uint64_t, true, false>, \ 191 trait_test_arg<std::uint64_t, std::int64_t, false, true>, \ 192 trait_test_arg<std::uint64_t, std::uint64_t, true, true>); 193 194#if SIZE_MAX == 0xffffffff 195TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \ 196 trait_test_arg<std::size_t, std::int32_t, false, true>, \ 197 trait_test_arg<std::size_t, std::uint32_t, true, true>, \ 198 trait_test_arg<std::size_t, std::int64_t, false, false>, \ 199 trait_test_arg<std::size_t, std::uint64_t, true, false>); 200#else 201TEST_CASE_TEMPLATE_INVOKE(value_in_range_of_test, \ 202 trait_test_arg<std::size_t, std::int32_t, false, true>, \ 203 trait_test_arg<std::size_t, std::uint32_t, true, true>, \ 204 trait_test_arg<std::size_t, std::int64_t, false, true>, \ 205 trait_test_arg<std::size_t, std::uint64_t, true, true>); 206#endif 207 208TEST_CASE("BJData") 209{ 210 SECTION("binary_reader BJData LUT arrays are sorted") 211 { 212 std::vector<std::uint8_t> data; 213 auto ia = nlohmann::detail::input_adapter(data); 214 // NOLINTNEXTLINE(hicpp-move-const-arg,performance-move-const-arg) 215 nlohmann::detail::binary_reader<json, decltype(ia)> br{std::move(ia), json::input_format_t::bjdata}; 216 217 CHECK(std::is_sorted(br.bjd_optimized_type_markers.begin(), br.bjd_optimized_type_markers.end())); 218 CHECK(std::is_sorted(br.bjd_types_map.begin(), br.bjd_types_map.end())); 219 } 220 221 SECTION("individual values") 222 { 223 SECTION("discarded") 224 { 225 // discarded values are not serialized 226 json j = json::value_t::discarded; 227 const auto result = json::to_bjdata(j); 228 CHECK(result.empty()); 229 } 230 231 SECTION("null") 232 { 233 json j = nullptr; 234 std::vector<uint8_t> expected = {'Z'}; 235 const auto result = json::to_bjdata(j); 236 CHECK(result == expected); 237 238 // roundtrip 239 CHECK(json::from_bjdata(result) == j); 240 CHECK(json::from_bjdata(result, true, false) == j); 241 } 242 243 SECTION("boolean") 244 { 245 SECTION("true") 246 { 247 json j = true; 248 std::vector<uint8_t> expected = {'T'}; 249 const auto result = json::to_bjdata(j); 250 CHECK(result == expected); 251 252 // roundtrip 253 CHECK(json::from_bjdata(result) == j); 254 CHECK(json::from_bjdata(result, true, false) == j); 255 } 256 257 SECTION("false") 258 { 259 json j = false; 260 std::vector<uint8_t> expected = {'F'}; 261 const auto result = json::to_bjdata(j); 262 CHECK(result == expected); 263 264 // roundtrip 265 CHECK(json::from_bjdata(result) == j); 266 CHECK(json::from_bjdata(result, true, false) == j); 267 } 268 } 269 270 SECTION("number") 271 { 272 SECTION("signed") 273 { 274 SECTION("-9223372036854775808..-2147483649 (int64)") 275 { 276 std::vector<int64_t> numbers; 277 numbers.push_back((std::numeric_limits<int64_t>::min)()); 278 numbers.push_back(-1000000000000000000LL); 279 numbers.push_back(-100000000000000000LL); 280 numbers.push_back(-10000000000000000LL); 281 numbers.push_back(-1000000000000000LL); 282 numbers.push_back(-100000000000000LL); 283 numbers.push_back(-10000000000000LL); 284 numbers.push_back(-1000000000000LL); 285 numbers.push_back(-100000000000LL); 286 numbers.push_back(-10000000000LL); 287 numbers.push_back(-2147483649LL); 288 for (auto i : numbers) 289 { 290 CAPTURE(i) 291 292 // create JSON value with integer number 293 json j = i; 294 295 // check type 296 CHECK(j.is_number_integer()); 297 298 // create expected byte vector 299 std::vector<uint8_t> expected; 300 expected.push_back(static_cast<uint8_t>('L')); 301 expected.push_back(static_cast<uint8_t>(i & 0xff)); 302 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 303 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff)); 304 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff)); 305 expected.push_back(static_cast<uint8_t>((i >> 32) & 0xff)); 306 expected.push_back(static_cast<uint8_t>((i >> 40) & 0xff)); 307 expected.push_back(static_cast<uint8_t>((i >> 48) & 0xff)); 308 expected.push_back(static_cast<uint8_t>((i >> 56) & 0xff)); 309 310 // compare result + size 311 const auto result = json::to_bjdata(j); 312 CHECK(result == expected); 313 CHECK(result.size() == 9); 314 315 // check individual bytes 316 CHECK(result[0] == 'L'); 317 int64_t restored = (static_cast<int64_t>(result[8]) << 070) + 318 (static_cast<int64_t>(result[7]) << 060) + 319 (static_cast<int64_t>(result[6]) << 050) + 320 (static_cast<int64_t>(result[5]) << 040) + 321 (static_cast<int64_t>(result[4]) << 030) + 322 (static_cast<int64_t>(result[3]) << 020) + 323 (static_cast<int64_t>(result[2]) << 010) + 324 static_cast<int64_t>(result[1]); 325 CHECK(restored == i); 326 327 // roundtrip 328 CHECK(json::from_bjdata(result) == j); 329 CHECK(json::from_bjdata(result, true, false) == j); 330 } 331 } 332 333 SECTION("-2147483648..-32769 (int32)") 334 { 335 std::vector<int32_t> numbers; 336 numbers.push_back(-32769); 337 numbers.push_back(-100000); 338 numbers.push_back(-1000000); 339 numbers.push_back(-10000000); 340 numbers.push_back(-100000000); 341 numbers.push_back(-1000000000); 342 numbers.push_back(-2147483647 - 1); // https://stackoverflow.com/a/29356002/266378 343 for (auto i : numbers) 344 { 345 CAPTURE(i) 346 347 // create JSON value with integer number 348 json j = i; 349 350 // check type 351 CHECK(j.is_number_integer()); 352 353 // create expected byte vector 354 std::vector<uint8_t> expected; 355 expected.push_back(static_cast<uint8_t>('l')); 356 expected.push_back(static_cast<uint8_t>(i & 0xff)); 357 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 358 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff)); 359 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff)); 360 361 // compare result + size 362 const auto result = json::to_bjdata(j); 363 CHECK(result == expected); 364 CHECK(result.size() == 5); 365 366 // check individual bytes 367 CHECK(result[0] == 'l'); 368 int32_t restored = (static_cast<int32_t>(result[4]) << 030) + 369 (static_cast<int32_t>(result[3]) << 020) + 370 (static_cast<int32_t>(result[2]) << 010) + 371 static_cast<int32_t>(result[1]); 372 CHECK(restored == i); 373 374 // roundtrip 375 CHECK(json::from_bjdata(result) == j); 376 CHECK(json::from_bjdata(result, true, false) == j); 377 } 378 } 379 380 SECTION("-32768..-129 (int16)") 381 { 382 for (int32_t i = -32768; i <= -129; ++i) 383 { 384 CAPTURE(i) 385 386 // create JSON value with integer number 387 json j = i; 388 389 // check type 390 CHECK(j.is_number_integer()); 391 392 // create expected byte vector 393 std::vector<uint8_t> expected; 394 expected.push_back(static_cast<uint8_t>('I')); 395 expected.push_back(static_cast<uint8_t>(i & 0xff)); 396 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 397 398 // compare result + size 399 const auto result = json::to_bjdata(j); 400 CHECK(result == expected); 401 CHECK(result.size() == 3); 402 403 // check individual bytes 404 CHECK(result[0] == 'I'); 405 auto restored = static_cast<int16_t>(((result[2] << 8) + result[1])); 406 CHECK(restored == i); 407 408 // roundtrip 409 CHECK(json::from_bjdata(result) == j); 410 CHECK(json::from_bjdata(result, true, false) == j); 411 } 412 } 413 414 SECTION("-9263 (int16)") 415 { 416 json j = -9263; 417 std::vector<uint8_t> expected = {'I', 0xd1, 0xdb}; 418 419 // compare result + size 420 const auto result = json::to_bjdata(j); 421 CHECK(result == expected); 422 CHECK(result.size() == 3); 423 424 // check individual bytes 425 CHECK(result[0] == 'I'); 426 auto restored = static_cast<int16_t>(((result[2] << 8) + result[1])); 427 CHECK(restored == -9263); 428 429 // roundtrip 430 CHECK(json::from_bjdata(result) == j); 431 CHECK(json::from_bjdata(result, true, false) == j); 432 } 433 434 SECTION("-128..-1 (int8)") 435 { 436 for (auto i = -128; i <= -1; ++i) 437 { 438 CAPTURE(i) 439 440 // create JSON value with integer number 441 json j = i; 442 443 // check type 444 CHECK(j.is_number_integer()); 445 446 // create expected byte vector 447 std::vector<uint8_t> expected; 448 expected.push_back('i'); 449 expected.push_back(static_cast<uint8_t>(i)); 450 451 // compare result + size 452 const auto result = json::to_bjdata(j); 453 CHECK(result == expected); 454 CHECK(result.size() == 2); 455 456 // check individual bytes 457 CHECK(result[0] == 'i'); 458 CHECK(static_cast<int8_t>(result[1]) == i); 459 460 // roundtrip 461 CHECK(json::from_bjdata(result) == j); 462 CHECK(json::from_bjdata(result, true, false) == j); 463 } 464 } 465 466 SECTION("0..127 (int8)") 467 { 468 for (size_t i = 0; i <= 127; ++i) 469 { 470 CAPTURE(i) 471 472 // create JSON value with integer number 473 json j = -1; 474 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 475 476 // check type 477 CHECK(j.is_number_integer()); 478 479 // create expected byte vector 480 std::vector<uint8_t> expected; 481 expected.push_back(static_cast<uint8_t>('i')); 482 expected.push_back(static_cast<uint8_t>(i)); 483 484 // compare result + size 485 const auto result = json::to_bjdata(j); 486 CHECK(result == expected); 487 CHECK(result.size() == 2); 488 489 // check individual bytes 490 CHECK(result[0] == 'i'); 491 CHECK(result[1] == i); 492 493 // roundtrip 494 CHECK(json::from_bjdata(result) == j); 495 CHECK(json::from_bjdata(result, true, false) == j); 496 } 497 } 498 499 SECTION("128..255 (uint8)") 500 { 501 for (size_t i = 128; i <= 255; ++i) 502 { 503 CAPTURE(i) 504 505 // create JSON value with integer number 506 json j = -1; 507 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 508 509 // check type 510 CHECK(j.is_number_integer()); 511 512 // create expected byte vector 513 std::vector<uint8_t> expected; 514 expected.push_back(static_cast<uint8_t>('U')); 515 expected.push_back(static_cast<uint8_t>(i)); 516 517 // compare result + size 518 const auto result = json::to_bjdata(j); 519 CHECK(result == expected); 520 CHECK(result.size() == 2); 521 522 // check individual bytes 523 CHECK(result[0] == 'U'); 524 CHECK(result[1] == i); 525 526 // roundtrip 527 CHECK(json::from_bjdata(result) == j); 528 CHECK(json::from_bjdata(result, true, false) == j); 529 } 530 } 531 532 SECTION("256..32767 (int16)") 533 { 534 for (size_t i = 256; i <= 32767; ++i) 535 { 536 CAPTURE(i) 537 538 // create JSON value with integer number 539 json j = -1; 540 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 541 542 // check type 543 CHECK(j.is_number_integer()); 544 545 // create expected byte vector 546 std::vector<uint8_t> expected; 547 expected.push_back(static_cast<uint8_t>('I')); 548 expected.push_back(static_cast<uint8_t>(i & 0xff)); 549 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 550 551 // compare result + size 552 const auto result = json::to_bjdata(j); 553 CHECK(result == expected); 554 CHECK(result.size() == 3); 555 556 // check individual bytes 557 CHECK(result[0] == 'I'); 558 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1])); 559 CHECK(restored == i); 560 561 // roundtrip 562 CHECK(json::from_bjdata(result) == j); 563 CHECK(json::from_bjdata(result, true, false) == j); 564 } 565 } 566 567 SECTION("32768..65535 (uint16)") 568 { 569 for (uint32_t i : 570 { 571 32768u, 55555u, 65535u 572 }) 573 { 574 CAPTURE(i) 575 576 // create JSON value with integer number 577 json j = -1; 578 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 579 580 // check type 581 CHECK(j.is_number_integer()); 582 583 // create expected byte vector 584 std::vector<uint8_t> expected; 585 expected.push_back(static_cast<uint8_t>('u')); 586 expected.push_back(static_cast<uint8_t>(i & 0xff)); 587 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 588 589 // compare result + size 590 const auto result = json::to_bjdata(j); 591 CHECK(result == expected); 592 CHECK(result.size() == 3); 593 594 // check individual bytes 595 CHECK(result[0] == 'u'); 596 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1])); 597 CHECK(restored == i); 598 599 // roundtrip 600 CHECK(json::from_bjdata(result) == j); 601 CHECK(json::from_bjdata(result, true, false) == j); 602 } 603 } 604 605 SECTION("65536..2147483647 (int32)") 606 { 607 for (uint32_t i : 608 { 609 65536u, 77777u, 2147483647u 610 }) 611 { 612 CAPTURE(i) 613 614 // create JSON value with integer number 615 json j = -1; 616 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 617 618 // check type 619 CHECK(j.is_number_integer()); 620 621 // create expected byte vector 622 std::vector<uint8_t> expected; 623 expected.push_back('l'); 624 expected.push_back(static_cast<uint8_t>(i & 0xff)); 625 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 626 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff)); 627 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff)); 628 629 // compare result + size 630 const auto result = json::to_bjdata(j); 631 CHECK(result == expected); 632 CHECK(result.size() == 5); 633 634 // check individual bytes 635 CHECK(result[0] == 'l'); 636 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) + 637 (static_cast<uint32_t>(result[3]) << 020) + 638 (static_cast<uint32_t>(result[2]) << 010) + 639 static_cast<uint32_t>(result[1]); 640 CHECK(restored == i); 641 642 // roundtrip 643 CHECK(json::from_bjdata(result) == j); 644 CHECK(json::from_bjdata(result, true, false) == j); 645 } 646 } 647 648 SECTION("2147483648..4294967295 (uint32)") 649 { 650 for (uint32_t i : 651 { 652 2147483648u, 3333333333u, 4294967295u 653 }) 654 { 655 CAPTURE(i) 656 657 // create JSON value with integer number 658 json j = -1; 659 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 660 661 // check type 662 CHECK(j.is_number_integer()); 663 664 // create expected byte vector 665 std::vector<uint8_t> expected; 666 expected.push_back('m'); 667 expected.push_back(static_cast<uint8_t>(i & 0xff)); 668 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 669 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff)); 670 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff)); 671 672 // compare result + size 673 const auto result = json::to_bjdata(j); 674 CHECK(result == expected); 675 CHECK(result.size() == 5); 676 677 // check individual bytes 678 CHECK(result[0] == 'm'); 679 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) + 680 (static_cast<uint32_t>(result[3]) << 020) + 681 (static_cast<uint32_t>(result[2]) << 010) + 682 static_cast<uint32_t>(result[1]); 683 CHECK(restored == i); 684 685 // roundtrip 686 CHECK(json::from_bjdata(result) == j); 687 CHECK(json::from_bjdata(result, true, false) == j); 688 } 689 } 690 691 SECTION("4294967296..9223372036854775807 (int64)") 692 { 693 std::vector<uint64_t> v = {4294967296LU, 9223372036854775807LU}; 694 for (uint64_t i : v) 695 { 696 CAPTURE(i) 697 698 // create JSON value with integer number 699 json j = -1; 700 j.get_ref<json::number_integer_t&>() = static_cast<json::number_integer_t>(i); 701 702 // check type 703 CHECK(j.is_number_integer()); 704 705 // create expected byte vector 706 std::vector<uint8_t> expected; 707 expected.push_back('L'); 708 expected.push_back(static_cast<uint8_t>(i & 0xff)); 709 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff)); 710 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff)); 711 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff)); 712 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff)); 713 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff)); 714 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff)); 715 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff)); 716 717 // compare result + size 718 const auto result = json::to_bjdata(j); 719 CHECK(result == expected); 720 CHECK(result.size() == 9); 721 722 // check individual bytes 723 CHECK(result[0] == 'L'); 724 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) + 725 (static_cast<uint64_t>(result[7]) << 060) + 726 (static_cast<uint64_t>(result[6]) << 050) + 727 (static_cast<uint64_t>(result[5]) << 040) + 728 (static_cast<uint64_t>(result[4]) << 030) + 729 (static_cast<uint64_t>(result[3]) << 020) + 730 (static_cast<uint64_t>(result[2]) << 010) + 731 static_cast<uint64_t>(result[1]); 732 CHECK(restored == i); 733 734 // roundtrip 735 CHECK(json::from_bjdata(result) == j); 736 CHECK(json::from_bjdata(result, true, false) == j); 737 } 738 } 739 740 SECTION("9223372036854775808..18446744073709551615 (uint64)") 741 { 742 std::vector<uint64_t> v = {9223372036854775808ull, 18446744073709551615ull}; 743 for (uint64_t i : v) 744 { 745 CAPTURE(i) 746 747 // create JSON value with integer number 748 json j = i; 749 750 // check type 751 CHECK(j.is_number_unsigned()); 752 753 // create expected byte vector 754 std::vector<uint8_t> expected; 755 expected.push_back('M'); 756 expected.push_back(static_cast<uint8_t>(i & 0xff)); 757 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff)); 758 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff)); 759 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff)); 760 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff)); 761 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff)); 762 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff)); 763 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff)); 764 765 // compare result + size 766 const auto result = json::to_bjdata(j); 767 CHECK(result == expected); 768 CHECK(result.size() == 9); 769 770 // check individual bytes 771 CHECK(result[0] == 'M'); 772 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) + 773 (static_cast<uint64_t>(result[7]) << 060) + 774 (static_cast<uint64_t>(result[6]) << 050) + 775 (static_cast<uint64_t>(result[5]) << 040) + 776 (static_cast<uint64_t>(result[4]) << 030) + 777 (static_cast<uint64_t>(result[3]) << 020) + 778 (static_cast<uint64_t>(result[2]) << 010) + 779 static_cast<uint64_t>(result[1]); 780 CHECK(restored == i); 781 782 // roundtrip 783 CHECK(json::from_bjdata(result) == j); 784 CHECK(json::from_bjdata(result, true, false) == j); 785 } 786 } 787 } 788 789 SECTION("unsigned") 790 { 791 SECTION("0..127 (int8)") 792 { 793 for (size_t i = 0; i <= 127; ++i) 794 { 795 CAPTURE(i) 796 797 // create JSON value with unsigned integer number 798 json j = i; 799 800 // check type 801 CHECK(j.is_number_unsigned()); 802 803 // create expected byte vector 804 std::vector<uint8_t> expected; 805 expected.push_back('i'); 806 expected.push_back(static_cast<uint8_t>(i)); 807 808 // compare result + size 809 const auto result = json::to_bjdata(j); 810 CHECK(result == expected); 811 CHECK(result.size() == 2); 812 813 // check individual bytes 814 CHECK(result[0] == 'i'); 815 auto restored = static_cast<uint8_t>(result[1]); 816 CHECK(restored == i); 817 818 // roundtrip 819 CHECK(json::from_bjdata(result) == j); 820 CHECK(json::from_bjdata(result, true, false) == j); 821 } 822 } 823 824 SECTION("128..255 (uint8)") 825 { 826 for (size_t i = 128; i <= 255; ++i) 827 { 828 CAPTURE(i) 829 830 // create JSON value with unsigned integer number 831 json j = i; 832 833 // check type 834 CHECK(j.is_number_unsigned()); 835 836 // create expected byte vector 837 std::vector<uint8_t> expected; 838 expected.push_back('U'); 839 expected.push_back(static_cast<uint8_t>(i)); 840 841 // compare result + size 842 const auto result = json::to_bjdata(j); 843 CHECK(result == expected); 844 CHECK(result.size() == 2); 845 846 // check individual bytes 847 CHECK(result[0] == 'U'); 848 auto restored = static_cast<uint8_t>(result[1]); 849 CHECK(restored == i); 850 851 // roundtrip 852 CHECK(json::from_bjdata(result) == j); 853 CHECK(json::from_bjdata(result, true, false) == j); 854 } 855 } 856 857 SECTION("256..32767 (int16)") 858 { 859 for (size_t i = 256; i <= 32767; ++i) 860 { 861 CAPTURE(i) 862 863 // create JSON value with unsigned integer number 864 json j = i; 865 866 // check type 867 CHECK(j.is_number_unsigned()); 868 869 // create expected byte vector 870 std::vector<uint8_t> expected; 871 expected.push_back('I'); 872 expected.push_back(static_cast<uint8_t>(i & 0xff)); 873 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 874 875 // compare result + size 876 const auto result = json::to_bjdata(j); 877 CHECK(result == expected); 878 CHECK(result.size() == 3); 879 880 // check individual bytes 881 CHECK(result[0] == 'I'); 882 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1])); 883 CHECK(restored == i); 884 885 // roundtrip 886 CHECK(json::from_bjdata(result) == j); 887 CHECK(json::from_bjdata(result, true, false) == j); 888 } 889 } 890 891 SECTION("32768..65535 (uint16)") 892 { 893 for (uint32_t i : 894 { 895 32768u, 55555u, 65535u 896 }) 897 { 898 CAPTURE(i) 899 900 // create JSON value with unsigned integer number 901 json j = i; 902 903 // check type 904 CHECK(j.is_number_unsigned()); 905 906 // create expected byte vector 907 std::vector<uint8_t> expected; 908 expected.push_back('u'); 909 expected.push_back(static_cast<uint8_t>(i & 0xff)); 910 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 911 912 // compare result + size 913 const auto result = json::to_bjdata(j); 914 CHECK(result == expected); 915 CHECK(result.size() == 3); 916 917 // check individual bytes 918 CHECK(result[0] == 'u'); 919 auto restored = static_cast<uint16_t>(static_cast<uint8_t>(result[2]) * 256 + static_cast<uint8_t>(result[1])); 920 CHECK(restored == i); 921 922 // roundtrip 923 CHECK(json::from_bjdata(result) == j); 924 CHECK(json::from_bjdata(result, true, false) == j); 925 } 926 } 927 SECTION("65536..2147483647 (int32)") 928 { 929 for (uint32_t i : 930 { 931 65536u, 77777u, 2147483647u 932 }) 933 { 934 CAPTURE(i) 935 936 // create JSON value with unsigned integer number 937 json j = i; 938 939 // check type 940 CHECK(j.is_number_unsigned()); 941 942 // create expected byte vector 943 std::vector<uint8_t> expected; 944 expected.push_back('l'); 945 expected.push_back(static_cast<uint8_t>(i & 0xff)); 946 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 947 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff)); 948 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff)); 949 950 // compare result + size 951 const auto result = json::to_bjdata(j); 952 CHECK(result == expected); 953 CHECK(result.size() == 5); 954 955 // check individual bytes 956 CHECK(result[0] == 'l'); 957 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) + 958 (static_cast<uint32_t>(result[3]) << 020) + 959 (static_cast<uint32_t>(result[2]) << 010) + 960 static_cast<uint32_t>(result[1]); 961 CHECK(restored == i); 962 963 // roundtrip 964 CHECK(json::from_bjdata(result) == j); 965 CHECK(json::from_bjdata(result, true, false) == j); 966 } 967 } 968 969 SECTION("2147483648..4294967295 (uint32)") 970 { 971 for (uint32_t i : 972 { 973 2147483648u, 3333333333u, 4294967295u 974 }) 975 { 976 CAPTURE(i) 977 978 // create JSON value with unsigned integer number 979 json j = i; 980 981 // check type 982 CHECK(j.is_number_unsigned()); 983 984 // create expected byte vector 985 std::vector<uint8_t> expected; 986 expected.push_back('m'); 987 expected.push_back(static_cast<uint8_t>(i & 0xff)); 988 expected.push_back(static_cast<uint8_t>((i >> 8) & 0xff)); 989 expected.push_back(static_cast<uint8_t>((i >> 16) & 0xff)); 990 expected.push_back(static_cast<uint8_t>((i >> 24) & 0xff)); 991 992 // compare result + size 993 const auto result = json::to_bjdata(j); 994 CHECK(result == expected); 995 CHECK(result.size() == 5); 996 997 // check individual bytes 998 CHECK(result[0] == 'm'); 999 uint32_t restored = (static_cast<uint32_t>(result[4]) << 030) + 1000 (static_cast<uint32_t>(result[3]) << 020) + 1001 (static_cast<uint32_t>(result[2]) << 010) + 1002 static_cast<uint32_t>(result[1]); 1003 CHECK(restored == i); 1004 1005 // roundtrip 1006 CHECK(json::from_bjdata(result) == j); 1007 CHECK(json::from_bjdata(result, true, false) == j); 1008 } 1009 } 1010 1011 SECTION("4294967296..9223372036854775807 (int64)") 1012 { 1013 std::vector<uint64_t> v = {4294967296ul, 9223372036854775807ul}; 1014 for (uint64_t i : v) 1015 { 1016 CAPTURE(i) 1017 1018 // create JSON value with integer number 1019 json j = i; 1020 1021 // check type 1022 CHECK(j.is_number_unsigned()); 1023 1024 // create expected byte vector 1025 std::vector<uint8_t> expected; 1026 expected.push_back('L'); 1027 expected.push_back(static_cast<uint8_t>(i & 0xff)); 1028 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff)); 1029 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff)); 1030 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff)); 1031 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff)); 1032 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff)); 1033 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff)); 1034 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff)); 1035 1036 // compare result + size 1037 const auto result = json::to_bjdata(j); 1038 CHECK(result == expected); 1039 CHECK(result.size() == 9); 1040 1041 // check individual bytes 1042 CHECK(result[0] == 'L'); 1043 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) + 1044 (static_cast<uint64_t>(result[7]) << 060) + 1045 (static_cast<uint64_t>(result[6]) << 050) + 1046 (static_cast<uint64_t>(result[5]) << 040) + 1047 (static_cast<uint64_t>(result[4]) << 030) + 1048 (static_cast<uint64_t>(result[3]) << 020) + 1049 (static_cast<uint64_t>(result[2]) << 010) + 1050 static_cast<uint64_t>(result[1]); 1051 CHECK(restored == i); 1052 1053 // roundtrip 1054 CHECK(json::from_bjdata(result) == j); 1055 CHECK(json::from_bjdata(result, true, false) == j); 1056 } 1057 } 1058 1059 SECTION("9223372036854775808..18446744073709551615 (uint64)") 1060 { 1061 std::vector<uint64_t> v = {9223372036854775808ull, 18446744073709551615ull}; 1062 for (uint64_t i : v) 1063 { 1064 CAPTURE(i) 1065 1066 // create JSON value with integer number 1067 json j = i; 1068 1069 // check type 1070 CHECK(j.is_number_unsigned()); 1071 1072 // create expected byte vector 1073 std::vector<uint8_t> expected; 1074 expected.push_back('M'); 1075 expected.push_back(static_cast<uint8_t>(i & 0xff)); 1076 expected.push_back(static_cast<uint8_t>((i >> 010) & 0xff)); 1077 expected.push_back(static_cast<uint8_t>((i >> 020) & 0xff)); 1078 expected.push_back(static_cast<uint8_t>((i >> 030) & 0xff)); 1079 expected.push_back(static_cast<uint8_t>((i >> 040) & 0xff)); 1080 expected.push_back(static_cast<uint8_t>((i >> 050) & 0xff)); 1081 expected.push_back(static_cast<uint8_t>((i >> 060) & 0xff)); 1082 expected.push_back(static_cast<uint8_t>((i >> 070) & 0xff)); 1083 1084 // compare result + size 1085 const auto result = json::to_bjdata(j); 1086 CHECK(result == expected); 1087 CHECK(result.size() == 9); 1088 1089 // check individual bytes 1090 CHECK(result[0] == 'M'); 1091 uint64_t restored = (static_cast<uint64_t>(result[8]) << 070) + 1092 (static_cast<uint64_t>(result[7]) << 060) + 1093 (static_cast<uint64_t>(result[6]) << 050) + 1094 (static_cast<uint64_t>(result[5]) << 040) + 1095 (static_cast<uint64_t>(result[4]) << 030) + 1096 (static_cast<uint64_t>(result[3]) << 020) + 1097 (static_cast<uint64_t>(result[2]) << 010) + 1098 static_cast<uint64_t>(result[1]); 1099 CHECK(restored == i); 1100 1101 // roundtrip 1102 CHECK(json::from_bjdata(result) == j); 1103 CHECK(json::from_bjdata(result, true, false) == j); 1104 } 1105 } 1106 } 1107 SECTION("float64") 1108 { 1109 SECTION("3.1415925") 1110 { 1111 double v = 3.1415925; 1112 json j = v; 1113 std::vector<uint8_t> expected = 1114 { 1115 'D', 0xfc, 0xde, 0xa6, 0x3f, 0xfb, 0x21, 0x09, 0x40 1116 }; 1117 const auto result = json::to_bjdata(j); 1118 CHECK(result == expected); 1119 1120 // roundtrip 1121 CHECK(json::from_bjdata(result) == j); 1122 CHECK(json::from_bjdata(result) == v); 1123 CHECK(json::from_bjdata(result, true, false) == j); 1124 } 1125 } 1126 1127 SECTION("half-precision float") 1128 { 1129 SECTION("simple half floats") 1130 { 1131 CHECK(json::parse("0.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x00}))); 1132 CHECK(json::parse("-0.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x80}))); 1133 CHECK(json::parse("1.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3c}))); 1134 CHECK(json::parse("1.5") == json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3e}))); 1135 CHECK(json::parse("65504.0") == json::from_bjdata(std::vector<uint8_t>({'h', 0xff, 0x7b}))); 1136 } 1137 1138 SECTION("errors") 1139 { 1140 SECTION("no byte follows") 1141 { 1142 json _; 1143 std::vector<uint8_t> vec0 = {'h'}; 1144 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec0), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 1145 CHECK(json::from_bjdata(vec0, true, false).is_discarded()); 1146 } 1147 1148 SECTION("only one byte follows") 1149 { 1150 json _; 1151 std::vector<uint8_t> vec1 = {'h', 0x00}; 1152 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec1), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 1153 CHECK(json::from_bjdata(vec1, true, false).is_discarded()); 1154 } 1155 } 1156 } 1157 1158 SECTION("half-precision float (edge cases)") 1159 { 1160 SECTION("exp = 0b00000") 1161 { 1162 SECTION("0 (0 00000 0000000000)") 1163 { 1164 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x00})); 1165 json::number_float_t d{j}; 1166 CHECK(d == 0.0); 1167 } 1168 1169 SECTION("-0 (1 00000 0000000000)") 1170 { 1171 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x80})); 1172 json::number_float_t d{j}; 1173 CHECK(d == -0.0); 1174 } 1175 1176 SECTION("2**-24 (0 00000 0000000001)") 1177 { 1178 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x01, 0x00})); 1179 json::number_float_t d{j}; 1180 CHECK(d == std::pow(2.0, -24.0)); 1181 } 1182 } 1183 1184 SECTION("exp = 0b11111") 1185 { 1186 SECTION("infinity (0 11111 0000000000)") 1187 { 1188 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7c})); 1189 json::number_float_t d{j}; 1190 CHECK(d == std::numeric_limits<json::number_float_t>::infinity()); 1191 CHECK(j.dump() == "null"); 1192 } 1193 1194 SECTION("-infinity (1 11111 0000000000)") 1195 { 1196 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0xfc})); 1197 json::number_float_t d{j}; 1198 CHECK(d == -std::numeric_limits<json::number_float_t>::infinity()); 1199 CHECK(j.dump() == "null"); 1200 } 1201 } 1202 1203 SECTION("other values from https://en.wikipedia.org/wiki/Half-precision_floating-point_format") 1204 { 1205 SECTION("1 (0 01111 0000000000)") 1206 { 1207 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x3c})); 1208 json::number_float_t d{j}; 1209 CHECK(d == 1); 1210 } 1211 1212 SECTION("-2 (1 10000 0000000000)") 1213 { 1214 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0xc0})); 1215 json::number_float_t d{j}; 1216 CHECK(d == -2); 1217 } 1218 1219 SECTION("65504 (0 11110 1111111111)") 1220 { 1221 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0xff, 0x7b})); 1222 json::number_float_t d{j}; 1223 CHECK(d == 65504); 1224 } 1225 } 1226 1227 SECTION("infinity") 1228 { 1229 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7c})); 1230 json::number_float_t d{j}; 1231 CHECK_FALSE(std::isfinite(d)); 1232 CHECK(j.dump() == "null"); 1233 } 1234 1235 SECTION("NaN") 1236 { 1237 json j = json::from_bjdata(std::vector<uint8_t>({'h', 0x00, 0x7e })); 1238 json::number_float_t d{j}; 1239 CHECK(std::isnan(d)); 1240 CHECK(j.dump() == "null"); 1241 } 1242 } 1243 1244 SECTION("high-precision number") 1245 { 1246 SECTION("unsigned integer number") 1247 { 1248 std::vector<uint8_t> vec = {'H', 'i', 0x14, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0'}; 1249 const auto j = json::from_bjdata(vec); 1250 CHECK(j.is_number_unsigned()); 1251 CHECK(j.dump() == "12345678901234567890"); 1252 } 1253 1254 SECTION("signed integer number") 1255 { 1256 std::vector<uint8_t> vec = {'H', 'i', 0x13, '-', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8'}; 1257 const auto j = json::from_bjdata(vec); 1258 CHECK(j.is_number_integer()); 1259 CHECK(j.dump() == "-123456789012345678"); 1260 } 1261 1262 SECTION("floating-point number") 1263 { 1264 std::vector<uint8_t> vec = {'H', 'i', 0x16, '3', '.', '1', '4', '1', '5', '9', '2', '6', '5', '3', '5', '8', '9', '7', '9', '3', '2', '3', '8', '4', '6'}; 1265 const auto j = json::from_bjdata(vec); 1266 CHECK(j.is_number_float()); 1267 CHECK(j.dump() == "3.141592653589793"); 1268 } 1269 1270 SECTION("errors") 1271 { 1272 // error while parsing length 1273 std::vector<uint8_t> vec0 = {'H', 'i'}; 1274 CHECK(json::from_bjdata(vec0, true, false).is_discarded()); 1275 // error while parsing string 1276 std::vector<uint8_t> vec1 = {'H', 'i', '1'}; 1277 CHECK(json::from_bjdata(vec1, true, false).is_discarded()); 1278 1279 json _; 1280 std::vector<uint8_t> vec2 = {'H', 'i', 2, '1', 'A', '3'}; 1281 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec2), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1A", json::parse_error); 1282 std::vector<uint8_t> vec3 = {'H', 'i', 2, '1', '.'}; 1283 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec3), "[json.exception.parse_error.115] parse error at byte 5: syntax error while parsing BJData high-precision number: invalid number text: 1.", json::parse_error); 1284 std::vector<uint8_t> vec4 = {'H', 2, '1', '0'}; 1285 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec4), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x02", json::parse_error); 1286 } 1287 } 1288 } 1289 1290 SECTION("string") 1291 { 1292 SECTION("N = 0..127") 1293 { 1294 for (size_t N = 0; N <= 127; ++N) 1295 { 1296 CAPTURE(N) 1297 1298 // create JSON value with string containing of N * 'x' 1299 const auto s = std::string(N, 'x'); 1300 json j = s; 1301 1302 // create expected byte vector 1303 std::vector<uint8_t> expected; 1304 expected.push_back('S'); 1305 expected.push_back('i'); 1306 expected.push_back(static_cast<uint8_t>(N)); 1307 for (size_t i = 0; i < N; ++i) 1308 { 1309 expected.push_back('x'); 1310 } 1311 1312 // compare result + size 1313 const auto result = json::to_bjdata(j); 1314 CHECK(result == expected); 1315 CHECK(result.size() == N + 3); 1316 // check that no null byte is appended 1317 if (N > 0) 1318 { 1319 CHECK(result.back() != '\x00'); 1320 } 1321 1322 // roundtrip 1323 CHECK(json::from_bjdata(result) == j); 1324 CHECK(json::from_bjdata(result, true, false) == j); 1325 } 1326 } 1327 1328 SECTION("N = 128..255") 1329 { 1330 for (size_t N = 128; N <= 255; ++N) 1331 { 1332 CAPTURE(N) 1333 1334 // create JSON value with string containing of N * 'x' 1335 const auto s = std::string(N, 'x'); 1336 json j = s; 1337 1338 // create expected byte vector 1339 std::vector<uint8_t> expected; 1340 expected.push_back('S'); 1341 expected.push_back('U'); 1342 expected.push_back(static_cast<uint8_t>(N)); 1343 for (size_t i = 0; i < N; ++i) 1344 { 1345 expected.push_back('x'); 1346 } 1347 1348 // compare result + size 1349 const auto result = json::to_bjdata(j); 1350 CHECK(result == expected); 1351 CHECK(result.size() == N + 3); 1352 // check that no null byte is appended 1353 CHECK(result.back() != '\x00'); 1354 1355 // roundtrip 1356 CHECK(json::from_bjdata(result) == j); 1357 CHECK(json::from_bjdata(result, true, false) == j); 1358 } 1359 } 1360 1361 SECTION("N = 256..32767") 1362 { 1363 for (size_t N : 1364 { 1365 256u, 999u, 1025u, 3333u, 2048u, 32767u 1366 }) 1367 { 1368 CAPTURE(N) 1369 1370 // create JSON value with string containing of N * 'x' 1371 const auto s = std::string(N, 'x'); 1372 json j = s; 1373 1374 // create expected byte vector (hack: create string first) 1375 std::vector<uint8_t> expected(N, 'x'); 1376 // reverse order of commands, because we insert at begin() 1377 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff)); 1378 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff)); 1379 expected.insert(expected.begin(), 'I'); 1380 expected.insert(expected.begin(), 'S'); 1381 1382 // compare result + size 1383 const auto result = json::to_bjdata(j); 1384 CHECK(result == expected); 1385 CHECK(result.size() == N + 4); 1386 // check that no null byte is appended 1387 CHECK(result.back() != '\x00'); 1388 1389 // roundtrip 1390 CHECK(json::from_bjdata(result) == j); 1391 CHECK(json::from_bjdata(result, true, false) == j); 1392 } 1393 } 1394 1395 SECTION("N = 32768..65535") 1396 { 1397 for (size_t N : 1398 { 1399 32768u, 55555u, 65535u 1400 }) 1401 { 1402 CAPTURE(N) 1403 1404 // create JSON value with string containing of N * 'x' 1405 const auto s = std::string(N, 'x'); 1406 json j = s; 1407 1408 // create expected byte vector (hack: create string first) 1409 std::vector<uint8_t> expected(N, 'x'); 1410 // reverse order of commands, because we insert at begin() 1411 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff)); 1412 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff)); 1413 expected.insert(expected.begin(), 'u'); 1414 expected.insert(expected.begin(), 'S'); 1415 1416 // compare result + size 1417 const auto result = json::to_bjdata(j); 1418 CHECK(result == expected); 1419 CHECK(result.size() == N + 4); 1420 // check that no null byte is appended 1421 CHECK(result.back() != '\x00'); 1422 1423 // roundtrip 1424 CHECK(json::from_bjdata(result) == j); 1425 CHECK(json::from_bjdata(result, true, false) == j); 1426 } 1427 } 1428 1429 SECTION("N = 65536..2147483647") 1430 { 1431 for (size_t N : 1432 { 1433 65536u, 77777u, 1048576u 1434 }) 1435 { 1436 CAPTURE(N) 1437 1438 // create JSON value with string containing of N * 'x' 1439 const auto s = std::string(N, 'x'); 1440 json j = s; 1441 1442 // create expected byte vector (hack: create string first) 1443 std::vector<uint8_t> expected(N, 'x'); 1444 // reverse order of commands, because we insert at begin() 1445 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 24) & 0xff)); 1446 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 16) & 0xff)); 1447 expected.insert(expected.begin(), static_cast<uint8_t>((N >> 8) & 0xff)); 1448 expected.insert(expected.begin(), static_cast<uint8_t>(N & 0xff)); 1449 expected.insert(expected.begin(), 'l'); 1450 expected.insert(expected.begin(), 'S'); 1451 1452 // compare result + size 1453 const auto result = json::to_bjdata(j); 1454 CHECK(result == expected); 1455 CHECK(result.size() == N + 6); 1456 // check that no null byte is appended 1457 CHECK(result.back() != '\x00'); 1458 1459 // roundtrip 1460 CHECK(json::from_bjdata(result) == j); 1461 CHECK(json::from_bjdata(result, true, false) == j); 1462 } 1463 } 1464 } 1465 1466 1467 SECTION("binary") 1468 { 1469 SECTION("N = 0..127") 1470 { 1471 for (std::size_t N = 0; N <= 127; ++N) 1472 { 1473 CAPTURE(N) 1474 1475 // create JSON value with byte array containing of N * 'x' 1476 const auto s = std::vector<std::uint8_t>(N, 'x'); 1477 json j = json::binary(s); 1478 1479 // create expected byte vector 1480 std::vector<std::uint8_t> expected; 1481 expected.push_back(static_cast<std::uint8_t>('[')); 1482 if (N != 0) 1483 { 1484 expected.push_back(static_cast<std::uint8_t>('$')); 1485 expected.push_back(static_cast<std::uint8_t>('U')); 1486 } 1487 expected.push_back(static_cast<std::uint8_t>('#')); 1488 expected.push_back(static_cast<std::uint8_t>('i')); 1489 expected.push_back(static_cast<std::uint8_t>(N)); 1490 for (size_t i = 0; i < N; ++i) 1491 { 1492 expected.push_back(0x78); 1493 } 1494 1495 // compare result + size 1496 const auto result = json::to_bjdata(j, true, true); 1497 CHECK(result == expected); 1498 if (N == 0) 1499 { 1500 CHECK(result.size() == N + 4); 1501 } 1502 else 1503 { 1504 CHECK(result.size() == N + 6); 1505 } 1506 1507 // check that no null byte is appended 1508 if (N > 0) 1509 { 1510 CHECK(result.back() != '\x00'); 1511 } 1512 1513 // roundtrip only works to an array of numbers 1514 json j_out = s; 1515 CHECK(json::from_bjdata(result) == j_out); 1516 CHECK(json::from_bjdata(result, true, false) == j_out); 1517 } 1518 } 1519 1520 SECTION("N = 128..255") 1521 { 1522 for (std::size_t N = 128; N <= 255; ++N) 1523 { 1524 CAPTURE(N) 1525 1526 // create JSON value with byte array containing of N * 'x' 1527 const auto s = std::vector<std::uint8_t>(N, 'x'); 1528 json j = json::binary(s); 1529 1530 // create expected byte vector 1531 std::vector<uint8_t> expected; 1532 expected.push_back(static_cast<std::uint8_t>('[')); 1533 expected.push_back(static_cast<std::uint8_t>('$')); 1534 expected.push_back(static_cast<std::uint8_t>('U')); 1535 expected.push_back(static_cast<std::uint8_t>('#')); 1536 expected.push_back(static_cast<std::uint8_t>('U')); 1537 expected.push_back(static_cast<std::uint8_t>(N)); 1538 for (size_t i = 0; i < N; ++i) 1539 { 1540 expected.push_back(0x78); 1541 } 1542 1543 // compare result + size 1544 const auto result = json::to_bjdata(j, true, true); 1545 CHECK(result == expected); 1546 CHECK(result.size() == N + 6); 1547 // check that no null byte is appended 1548 CHECK(result.back() != '\x00'); 1549 1550 // roundtrip only works to an array of numbers 1551 json j_out = s; 1552 CHECK(json::from_bjdata(result) == j_out); 1553 CHECK(json::from_bjdata(result, true, false) == j_out); 1554 } 1555 } 1556 1557 SECTION("N = 256..32767") 1558 { 1559 for (std::size_t N : 1560 { 1561 256u, 999u, 1025u, 3333u, 2048u, 32767u 1562 }) 1563 { 1564 CAPTURE(N) 1565 1566 // create JSON value with byte array containing of N * 'x' 1567 const auto s = std::vector<std::uint8_t>(N, 'x'); 1568 json j = json::binary(s); 1569 1570 // create expected byte vector 1571 std::vector<std::uint8_t> expected(N + 7, 'x'); 1572 expected[0] = '['; 1573 expected[1] = '$'; 1574 expected[2] = 'U'; 1575 expected[3] = '#'; 1576 expected[4] = 'I'; 1577 expected[5] = static_cast<std::uint8_t>(N & 0xFF); 1578 expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF); 1579 1580 // compare result + size 1581 const auto result = json::to_bjdata(j, true, true); 1582 CHECK(result == expected); 1583 CHECK(result.size() == N + 7); 1584 // check that no null byte is appended 1585 CHECK(result.back() != '\x00'); 1586 1587 // roundtrip only works to an array of numbers 1588 json j_out = s; 1589 CHECK(json::from_bjdata(result) == j_out); 1590 CHECK(json::from_bjdata(result, true, false) == j_out); 1591 } 1592 } 1593 1594 SECTION("N = 32768..65535") 1595 { 1596 for (std::size_t N : 1597 { 1598 32768u, 55555u, 65535u 1599 }) 1600 { 1601 CAPTURE(N) 1602 1603 // create JSON value with byte array containing of N * 'x' 1604 const auto s = std::vector<std::uint8_t>(N, 'x'); 1605 json j = json::binary(s); 1606 1607 // create expected byte vector 1608 std::vector<std::uint8_t> expected(N + 7, 'x'); 1609 expected[0] = '['; 1610 expected[1] = '$'; 1611 expected[2] = 'U'; 1612 expected[3] = '#'; 1613 expected[4] = 'u'; 1614 expected[5] = static_cast<std::uint8_t>(N & 0xFF); 1615 expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF); 1616 1617 // compare result + size 1618 const auto result = json::to_bjdata(j, true, true); 1619 CHECK(result == expected); 1620 CHECK(result.size() == N + 7); 1621 // check that no null byte is appended 1622 CHECK(result.back() != '\x00'); 1623 1624 // roundtrip only works to an array of numbers 1625 json j_out = s; 1626 CHECK(json::from_bjdata(result) == j_out); 1627 CHECK(json::from_bjdata(result, true, false) == j_out); 1628 } 1629 } 1630 1631 SECTION("N = 65536..2147483647") 1632 { 1633 for (std::size_t N : 1634 { 1635 65536u, 77777u, 1048576u 1636 }) 1637 { 1638 CAPTURE(N) 1639 1640 // create JSON value with byte array containing of N * 'x' 1641 const auto s = std::vector<std::uint8_t>(N, 'x'); 1642 json j = json::binary(s); 1643 1644 // create expected byte vector 1645 std::vector<std::uint8_t> expected(N + 9, 'x'); 1646 expected[0] = '['; 1647 expected[1] = '$'; 1648 expected[2] = 'U'; 1649 expected[3] = '#'; 1650 expected[4] = 'l'; 1651 expected[5] = static_cast<std::uint8_t>(N & 0xFF); 1652 expected[6] = static_cast<std::uint8_t>((N >> 8) & 0xFF); 1653 expected[7] = static_cast<std::uint8_t>((N >> 16) & 0xFF); 1654 expected[8] = static_cast<std::uint8_t>((N >> 24) & 0xFF); 1655 1656 // compare result + size 1657 const auto result = json::to_bjdata(j, true, true); 1658 CHECK(result == expected); 1659 CHECK(result.size() == N + 9); 1660 // check that no null byte is appended 1661 CHECK(result.back() != '\x00'); 1662 1663 // roundtrip only works to an array of numbers 1664 json j_out = s; 1665 CHECK(json::from_bjdata(result) == j_out); 1666 CHECK(json::from_bjdata(result, true, false) == j_out); 1667 } 1668 } 1669 1670 SECTION("Other Serializations") 1671 { 1672 const std::size_t N = 10; 1673 const auto s = std::vector<std::uint8_t>(N, 'x'); 1674 json j = json::binary(s); 1675 1676 SECTION("No Count No Type") 1677 { 1678 std::vector<uint8_t> expected; 1679 expected.push_back(static_cast<std::uint8_t>('[')); 1680 for (std::size_t i = 0; i < N; ++i) 1681 { 1682 expected.push_back(static_cast<std::uint8_t>('U')); 1683 expected.push_back(static_cast<std::uint8_t>(0x78)); 1684 } 1685 expected.push_back(static_cast<std::uint8_t>(']')); 1686 1687 // compare result + size 1688 const auto result = json::to_bjdata(j, false, false); 1689 CHECK(result == expected); 1690 CHECK(result.size() == N + 12); 1691 // check that no null byte is appended 1692 CHECK(result.back() != '\x00'); 1693 1694 // roundtrip only works to an array of numbers 1695 json j_out = s; 1696 CHECK(json::from_bjdata(result) == j_out); 1697 CHECK(json::from_bjdata(result, true, false) == j_out); 1698 } 1699 1700 SECTION("Yes Count No Type") 1701 { 1702 std::vector<std::uint8_t> expected; 1703 expected.push_back(static_cast<std::uint8_t>('[')); 1704 expected.push_back(static_cast<std::uint8_t>('#')); 1705 expected.push_back(static_cast<std::uint8_t>('i')); 1706 expected.push_back(static_cast<std::uint8_t>(N)); 1707 1708 for (size_t i = 0; i < N; ++i) 1709 { 1710 expected.push_back(static_cast<std::uint8_t>('U')); 1711 expected.push_back(static_cast<std::uint8_t>(0x78)); 1712 } 1713 1714 // compare result + size 1715 const auto result = json::to_bjdata(j, true, false); 1716 CHECK(result == expected); 1717 CHECK(result.size() == N + 14); 1718 // check that no null byte is appended 1719 CHECK(result.back() != '\x00'); 1720 1721 // roundtrip only works to an array of numbers 1722 json j_out = s; 1723 CHECK(json::from_bjdata(result) == j_out); 1724 CHECK(json::from_bjdata(result, true, false) == j_out); 1725 } 1726 } 1727 } 1728 SECTION("array") 1729 { 1730 SECTION("empty") 1731 { 1732 SECTION("size=false type=false") 1733 { 1734 json j = json::array(); 1735 std::vector<uint8_t> expected = {'[', ']'}; 1736 const auto result = json::to_bjdata(j); 1737 CHECK(result == expected); 1738 1739 // roundtrip 1740 CHECK(json::from_bjdata(result) == j); 1741 CHECK(json::from_bjdata(result, true, false) == j); 1742 } 1743 1744 SECTION("size=true type=false") 1745 { 1746 json j = json::array(); 1747 std::vector<uint8_t> expected = {'[', '#', 'i', 0}; 1748 const auto result = json::to_bjdata(j, true); 1749 CHECK(result == expected); 1750 1751 // roundtrip 1752 CHECK(json::from_bjdata(result) == j); 1753 CHECK(json::from_bjdata(result, true, false) == j); 1754 } 1755 1756 SECTION("size=true type=true") 1757 { 1758 json j = json::array(); 1759 std::vector<uint8_t> expected = {'[', '#', 'i', 0}; 1760 const auto result = json::to_bjdata(j, true, true); 1761 CHECK(result == expected); 1762 1763 // roundtrip 1764 CHECK(json::from_bjdata(result) == j); 1765 CHECK(json::from_bjdata(result, true, false) == j); 1766 } 1767 } 1768 1769 SECTION("[null]") 1770 { 1771 SECTION("size=false type=false") 1772 { 1773 json j = {nullptr}; 1774 std::vector<uint8_t> expected = {'[', 'Z', ']'}; 1775 const auto result = json::to_bjdata(j); 1776 CHECK(result == expected); 1777 1778 // roundtrip 1779 CHECK(json::from_bjdata(result) == j); 1780 CHECK(json::from_bjdata(result, true, false) == j); 1781 } 1782 1783 SECTION("size=true type=false") 1784 { 1785 json j = {nullptr}; 1786 std::vector<uint8_t> expected = {'[', '#', 'i', 1, 'Z'}; 1787 const auto result = json::to_bjdata(j, true); 1788 CHECK(result == expected); 1789 1790 // roundtrip 1791 CHECK(json::from_bjdata(result) == j); 1792 CHECK(json::from_bjdata(result, true, false) == j); 1793 } 1794 1795 SECTION("size=true type=true") 1796 { 1797 json j = {nullptr}; 1798 std::vector<uint8_t> expected = {'[', '#', 'i', 1, 'Z'}; 1799 const auto result = json::to_bjdata(j, true, true); 1800 CHECK(result == expected); 1801 1802 // roundtrip 1803 CHECK(json::from_bjdata(result) == j); 1804 CHECK(json::from_bjdata(result, true, false) == j); 1805 } 1806 } 1807 1808 SECTION("[1,2,3,4,5]") 1809 { 1810 SECTION("size=false type=false") 1811 { 1812 json j = json::parse("[1,2,3,4,5]"); 1813 std::vector<uint8_t> expected = {'[', 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5, ']'}; 1814 const auto result = json::to_bjdata(j); 1815 CHECK(result == expected); 1816 1817 // roundtrip 1818 CHECK(json::from_bjdata(result) == j); 1819 CHECK(json::from_bjdata(result, true, false) == j); 1820 } 1821 1822 SECTION("size=true type=false") 1823 { 1824 json j = json::parse("[1,2,3,4,5]"); 1825 std::vector<uint8_t> expected = {'[', '#', 'i', 5, 'i', 1, 'i', 2, 'i', 3, 'i', 4, 'i', 5}; 1826 const auto result = json::to_bjdata(j, true); 1827 CHECK(result == expected); 1828 1829 // roundtrip 1830 CHECK(json::from_bjdata(result) == j); 1831 CHECK(json::from_bjdata(result, true, false) == j); 1832 } 1833 1834 SECTION("size=true type=true") 1835 { 1836 json j = json::parse("[1,2,3,4,5]"); 1837 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 5, 1, 2, 3, 4, 5}; 1838 const auto result = json::to_bjdata(j, true, true); 1839 CHECK(result == expected); 1840 1841 // roundtrip 1842 CHECK(json::from_bjdata(result) == j); 1843 CHECK(json::from_bjdata(result, true, false) == j); 1844 } 1845 } 1846 1847 SECTION("[[[[]]]]") 1848 { 1849 SECTION("size=false type=false") 1850 { 1851 json j = json::parse("[[[[]]]]"); 1852 std::vector<uint8_t> expected = {'[', '[', '[', '[', ']', ']', ']', ']'}; 1853 const auto result = json::to_bjdata(j); 1854 CHECK(result == expected); 1855 1856 // roundtrip 1857 CHECK(json::from_bjdata(result) == j); 1858 CHECK(json::from_bjdata(result, true, false) == j); 1859 } 1860 1861 SECTION("size=true type=false") 1862 { 1863 json j = json::parse("[[[[]]]]"); 1864 std::vector<uint8_t> expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0}; 1865 const auto result = json::to_bjdata(j, true); 1866 CHECK(result == expected); 1867 1868 // roundtrip 1869 CHECK(json::from_bjdata(result) == j); 1870 CHECK(json::from_bjdata(result, true, false) == j); 1871 } 1872 1873 SECTION("size=true type=true") 1874 { 1875 json j = json::parse("[[[[]]]]"); 1876 std::vector<uint8_t> expected = {'[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 1, '[', '#', 'i', 0}; 1877 const auto result = json::to_bjdata(j, true, true); 1878 CHECK(result == expected); 1879 1880 // roundtrip 1881 CHECK(json::from_bjdata(result) == j); 1882 CHECK(json::from_bjdata(result, true, false) == j); 1883 } 1884 } 1885 1886 SECTION("array with int16_t elements") 1887 { 1888 SECTION("size=false type=false") 1889 { 1890 json j(257, nullptr); 1891 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null 1892 expected[0] = '['; // opening array 1893 expected[258] = ']'; // closing array 1894 const auto result = json::to_bjdata(j); 1895 CHECK(result == expected); 1896 1897 // roundtrip 1898 CHECK(json::from_bjdata(result) == j); 1899 CHECK(json::from_bjdata(result, true, false) == j); 1900 } 1901 1902 SECTION("size=true type=false") 1903 { 1904 json j(257, nullptr); 1905 std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null 1906 expected[0] = '['; // opening array 1907 expected[1] = '#'; // array size 1908 expected[2] = 'I'; // int16 1909 expected[3] = 0x01; // 0x0101, first byte 1910 expected[4] = 0x01; // 0x0101, second byte 1911 const auto result = json::to_bjdata(j, true); 1912 CHECK(result == expected); 1913 1914 // roundtrip 1915 CHECK(json::from_bjdata(result) == j); 1916 CHECK(json::from_bjdata(result, true, false) == j); 1917 } 1918 } 1919 1920 SECTION("array with uint16_t elements") 1921 { 1922 SECTION("size=false type=false") 1923 { 1924 json j(32768, nullptr); 1925 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null 1926 expected[0] = '['; // opening array 1927 expected[32769] = ']'; // closing array 1928 const auto result = json::to_bjdata(j); 1929 CHECK(result == expected); 1930 1931 // roundtrip 1932 CHECK(json::from_bjdata(result) == j); 1933 CHECK(json::from_bjdata(result, true, false) == j); 1934 } 1935 1936 SECTION("size=true type=false") 1937 { 1938 json j(32768, nullptr); 1939 std::vector<uint8_t> expected(j.size() + 5, 'Z'); // all null 1940 expected[0] = '['; // opening array 1941 expected[1] = '#'; // array size 1942 expected[2] = 'u'; // int16 1943 expected[3] = 0x00; // 0x0101, first byte 1944 expected[4] = 0x80; // 0x0101, second byte 1945 const auto result = json::to_bjdata(j, true); 1946 CHECK(result == expected); 1947 1948 // roundtrip 1949 CHECK(json::from_bjdata(result) == j); 1950 CHECK(json::from_bjdata(result, true, false) == j); 1951 } 1952 } 1953 1954 SECTION("array with int32_t elements") 1955 { 1956 SECTION("size=false type=false") 1957 { 1958 json j(65793, nullptr); 1959 std::vector<uint8_t> expected(j.size() + 2, 'Z'); // all null 1960 expected[0] = '['; // opening array 1961 expected[65794] = ']'; // closing array 1962 const auto result = json::to_bjdata(j); 1963 CHECK(result == expected); 1964 1965 // roundtrip 1966 CHECK(json::from_bjdata(result) == j); 1967 CHECK(json::from_bjdata(result, true, false) == j); 1968 } 1969 1970 SECTION("size=true type=false") 1971 { 1972 json j(65793, nullptr); 1973 std::vector<uint8_t> expected(j.size() + 7, 'Z'); // all null 1974 expected[0] = '['; // opening array 1975 expected[1] = '#'; // array size 1976 expected[2] = 'l'; // int32 1977 expected[3] = 0x01; // 0x00010101, fourth byte 1978 expected[4] = 0x01; // 0x00010101, third byte 1979 expected[5] = 0x01; // 0x00010101, second byte 1980 expected[6] = 0x00; // 0x00010101, first byte 1981 const auto result = json::to_bjdata(j, true); 1982 CHECK(result == expected); 1983 1984 // roundtrip 1985 CHECK(json::from_bjdata(result) == j); 1986 CHECK(json::from_bjdata(result, true, false) == j); 1987 } 1988 } 1989 } 1990 1991 SECTION("object") 1992 { 1993 SECTION("empty") 1994 { 1995 SECTION("size=false type=false") 1996 { 1997 json j = json::object(); 1998 std::vector<uint8_t> expected = {'{', '}'}; 1999 const auto result = json::to_bjdata(j); 2000 CHECK(result == expected); 2001 2002 // roundtrip 2003 CHECK(json::from_bjdata(result) == j); 2004 CHECK(json::from_bjdata(result, true, false) == j); 2005 } 2006 2007 SECTION("size=true type=false") 2008 { 2009 json j = json::object(); 2010 std::vector<uint8_t> expected = {'{', '#', 'i', 0}; 2011 const auto result = json::to_bjdata(j, true); 2012 CHECK(result == expected); 2013 2014 // roundtrip 2015 CHECK(json::from_bjdata(result) == j); 2016 CHECK(json::from_bjdata(result, true, false) == j); 2017 } 2018 2019 SECTION("size=true type=true") 2020 { 2021 json j = json::object(); 2022 std::vector<uint8_t> expected = {'{', '#', 'i', 0}; 2023 const auto result = json::to_bjdata(j, true, true); 2024 CHECK(result == expected); 2025 2026 // roundtrip 2027 CHECK(json::from_bjdata(result) == j); 2028 CHECK(json::from_bjdata(result, true, false) == j); 2029 } 2030 } 2031 2032 SECTION("{\"\":null}") 2033 { 2034 SECTION("size=false type=false") 2035 { 2036 json j = {{"", nullptr}}; 2037 std::vector<uint8_t> expected = {'{', 'i', 0, 'Z', '}'}; 2038 const auto result = json::to_bjdata(j); 2039 CHECK(result == expected); 2040 2041 // roundtrip 2042 CHECK(json::from_bjdata(result) == j); 2043 CHECK(json::from_bjdata(result, true, false) == j); 2044 } 2045 2046 SECTION("size=true type=false") 2047 { 2048 json j = {{"", nullptr}}; 2049 std::vector<uint8_t> expected = {'{', '#', 'i', 1, 'i', 0, 'Z'}; 2050 const auto result = json::to_bjdata(j, true); 2051 CHECK(result == expected); 2052 2053 // roundtrip 2054 CHECK(json::from_bjdata(result) == j); 2055 CHECK(json::from_bjdata(result, true, false) == j); 2056 } 2057 } 2058 2059 SECTION("{\"a\": {\"b\": {\"c\": {}}}}") 2060 { 2061 SECTION("size=false type=false") 2062 { 2063 json j = json::parse(R"({"a": {"b": {"c": {}}}})"); 2064 std::vector<uint8_t> expected = 2065 { 2066 '{', 'i', 1, 'a', '{', 'i', 1, 'b', '{', 'i', 1, 'c', '{', '}', '}', '}', '}' 2067 }; 2068 const auto result = json::to_bjdata(j); 2069 CHECK(result == expected); 2070 2071 // roundtrip 2072 CHECK(json::from_bjdata(result) == j); 2073 CHECK(json::from_bjdata(result, true, false) == j); 2074 } 2075 2076 SECTION("size=true type=false") 2077 { 2078 json j = json::parse(R"({"a": {"b": {"c": {}}}})"); 2079 std::vector<uint8_t> expected = 2080 { 2081 '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0 2082 }; 2083 const auto result = json::to_bjdata(j, true); 2084 CHECK(result == expected); 2085 2086 // roundtrip 2087 CHECK(json::from_bjdata(result) == j); 2088 CHECK(json::from_bjdata(result, true, false) == j); 2089 } 2090 2091 SECTION("size=true type=true ignore object type marker") 2092 { 2093 json j = json::parse(R"({"a": {"b": {"c": {}}}})"); 2094 std::vector<uint8_t> expected = 2095 { 2096 '{', '#', 'i', 1, 'i', 1, 'a', '{', '#', 'i', 1, 'i', 1, 'b', '{', '#', 'i', 1, 'i', 1, 'c', '{', '#', 'i', 0 2097 }; 2098 const auto result = json::to_bjdata(j, true, true); 2099 CHECK(result == expected); 2100 2101 // roundtrip 2102 CHECK(json::from_bjdata(result) == j); 2103 CHECK(json::from_bjdata(result, true, false) == j); 2104 } 2105 } 2106 } 2107 } 2108 2109 SECTION("errors") 2110 { 2111 SECTION("strict mode") 2112 { 2113 std::vector<uint8_t> vec = {'Z', 'Z'}; 2114 SECTION("non-strict mode") 2115 { 2116 const auto result = json::from_bjdata(vec, false); 2117 CHECK(result == json()); 2118 } 2119 2120 SECTION("strict mode") 2121 { 2122 json _; 2123 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vec), 2124 "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: expected end of input; last byte: 0x5A", json::parse_error&); 2125 } 2126 } 2127 } 2128 2129 SECTION("SAX aborts") 2130 { 2131 SECTION("start_array()") 2132 { 2133 std::vector<uint8_t> v = {'[', 'T', 'F', ']'}; 2134 SaxCountdown scp(0); 2135 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2136 } 2137 2138 SECTION("start_object()") 2139 { 2140 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'}; 2141 SaxCountdown scp(0); 2142 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2143 } 2144 2145 SECTION("key() in object") 2146 { 2147 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'}; 2148 SaxCountdown scp(1); 2149 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2150 } 2151 2152 SECTION("start_array(len)") 2153 { 2154 std::vector<uint8_t> v = {'[', '#', 'i', '2', 'T', 'F'}; 2155 SaxCountdown scp(0); 2156 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2157 } 2158 2159 SECTION("start_object(len)") 2160 { 2161 std::vector<uint8_t> v = {'{', '#', 'i', '1', 3, 'f', 'o', 'o', 'F'}; 2162 SaxCountdown scp(0); 2163 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2164 } 2165 2166 SECTION("key() in object with length") 2167 { 2168 std::vector<uint8_t> v = {'{', 'i', 3, 'f', 'o', 'o', 'F', '}'}; 2169 SaxCountdown scp(1); 2170 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2171 } 2172 2173 SECTION("start_array() in ndarray _ArraySize_") 2174 { 2175 std::vector<uint8_t> v = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 1, 2}; 2176 SaxCountdown scp(2); 2177 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2178 } 2179 2180 SECTION("number_integer() in ndarray _ArraySize_") 2181 { 2182 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 1, 2}; 2183 SaxCountdown scp(3); 2184 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2185 } 2186 2187 SECTION("key() in ndarray _ArrayType_") 2188 { 2189 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4}; 2190 SaxCountdown scp(6); 2191 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2192 } 2193 2194 SECTION("string() in ndarray _ArrayType_") 2195 { 2196 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4}; 2197 SaxCountdown scp(7); 2198 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2199 } 2200 2201 SECTION("key() in ndarray _ArrayData_") 2202 { 2203 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4}; 2204 SaxCountdown scp(8); 2205 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2206 } 2207 2208 SECTION("string() in ndarray _ArrayData_") 2209 { 2210 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'U', '#', 'i', 2, 2, 2, 1, 2, 3, 4}; 2211 SaxCountdown scp(9); 2212 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2213 } 2214 2215 SECTION("string() in ndarray _ArrayType_") 2216 { 2217 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 3, 2, 6, 5, 4, 3, 2, 1}; 2218 SaxCountdown scp(11); 2219 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2220 } 2221 2222 SECTION("start_array() in ndarray _ArrayData_") 2223 { 2224 std::vector<uint8_t> v = {'[', '$', 'U', '#', '[', 'i', 2, 'i', 3, ']', 6, 5, 4, 3, 2, 1}; 2225 SaxCountdown scp(13); 2226 CHECK_FALSE(json::sax_parse(v, &scp, json::input_format_t::bjdata)); 2227 } 2228 } 2229 2230 SECTION("parsing values") 2231 { 2232 SECTION("strings") 2233 { 2234 // create a single-character string for all number types 2235 std::vector<uint8_t> s_i = {'S', 'i', 1, 'a'}; 2236 std::vector<uint8_t> s_U = {'S', 'U', 1, 'a'}; 2237 std::vector<uint8_t> s_I = {'S', 'I', 1, 0, 'a'}; 2238 std::vector<uint8_t> s_u = {'S', 'u', 1, 0, 'a'}; 2239 std::vector<uint8_t> s_l = {'S', 'l', 1, 0, 0, 0, 'a'}; 2240 std::vector<uint8_t> s_m = {'S', 'm', 1, 0, 0, 0, 'a'}; 2241 std::vector<uint8_t> s_L = {'S', 'L', 1, 0, 0, 0, 0, 0, 0, 0, 'a'}; 2242 std::vector<uint8_t> s_M = {'S', 'M', 1, 0, 0, 0, 0, 0, 0, 0, 'a'}; 2243 2244 // check if string is parsed correctly to "a" 2245 CHECK(json::from_bjdata(s_i) == "a"); 2246 CHECK(json::from_bjdata(s_U) == "a"); 2247 CHECK(json::from_bjdata(s_I) == "a"); 2248 CHECK(json::from_bjdata(s_u) == "a"); 2249 CHECK(json::from_bjdata(s_l) == "a"); 2250 CHECK(json::from_bjdata(s_m) == "a"); 2251 CHECK(json::from_bjdata(s_L) == "a"); 2252 CHECK(json::from_bjdata(s_M) == "a"); 2253 2254 // roundtrip: output should be optimized 2255 CHECK(json::to_bjdata(json::from_bjdata(s_i)) == s_i); 2256 CHECK(json::to_bjdata(json::from_bjdata(s_U)) == s_i); 2257 CHECK(json::to_bjdata(json::from_bjdata(s_I)) == s_i); 2258 CHECK(json::to_bjdata(json::from_bjdata(s_u)) == s_i); 2259 CHECK(json::to_bjdata(json::from_bjdata(s_l)) == s_i); 2260 CHECK(json::to_bjdata(json::from_bjdata(s_m)) == s_i); 2261 CHECK(json::to_bjdata(json::from_bjdata(s_L)) == s_i); 2262 CHECK(json::to_bjdata(json::from_bjdata(s_M)) == s_i); 2263 } 2264 2265 SECTION("number") 2266 { 2267 SECTION("float") 2268 { 2269 // float32 2270 std::vector<uint8_t> v_d = {'d', 0xd0, 0x0f, 0x49, 0x40}; 2271 CHECK(json::from_bjdata(v_d) == 3.14159f); 2272 2273 // float64 2274 std::vector<uint8_t> v_D = {'D', 0x6e, 0x86, 0x1b, 0xf0, 0xf9, 0x21, 0x09, 0x40}; 2275 CHECK(json::from_bjdata(v_D) == 3.14159); 2276 2277 // float32 is serialized as float64 as the library does not support float32 2278 CHECK(json::to_bjdata(json::from_bjdata(v_d)) == json::to_bjdata(3.14159f)); 2279 } 2280 } 2281 2282 SECTION("array") 2283 { 2284 SECTION("optimized version (length only)") 2285 { 2286 // create vector with two elements of the same type 2287 std::vector<uint8_t> v_TU = {'[', '#', 'U', 2, 'T', 'T'}; 2288 std::vector<uint8_t> v_T = {'[', '#', 'i', 2, 'T', 'T'}; 2289 std::vector<uint8_t> v_F = {'[', '#', 'i', 2, 'F', 'F'}; 2290 std::vector<uint8_t> v_Z = {'[', '#', 'i', 2, 'Z', 'Z'}; 2291 std::vector<uint8_t> v_i = {'[', '#', 'i', 2, 'i', 0x7F, 'i', 0x7F}; 2292 std::vector<uint8_t> v_U = {'[', '#', 'i', 2, 'U', 0xFF, 'U', 0xFF}; 2293 std::vector<uint8_t> v_I = {'[', '#', 'i', 2, 'I', 0xFF, 0x7F, 'I', 0xFF, 0x7F}; 2294 std::vector<uint8_t> v_u = {'[', '#', 'i', 2, 'u', 0x0F, 0xA7, 'u', 0x0F, 0xA7}; 2295 std::vector<uint8_t> v_l = {'[', '#', 'i', 2, 'l', 0xFF, 0xFF, 0xFF, 0x7F, 'l', 0xFF, 0xFF, 0xFF, 0x7F}; 2296 std::vector<uint8_t> v_m = {'[', '#', 'i', 2, 'm', 0xFF, 0xC9, 0x9A, 0xBB, 'm', 0xFF, 0xC9, 0x9A, 0xBB}; 2297 std::vector<uint8_t> v_L = {'[', '#', 'i', 2, 'L', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 'L', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}; 2298 std::vector<uint8_t> v_M = {'[', '#', 'i', 2, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 2299 std::vector<uint8_t> v_D = {'[', '#', 'i', 2, 'D', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 'D', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40}; 2300 std::vector<uint8_t> v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'}; 2301 std::vector<uint8_t> v_C = {'[', '#', 'i', 2, 'C', 'a', 'C', 'a'}; 2302 2303 // check if vector is parsed correctly 2304 CHECK(json::from_bjdata(v_TU) == json({true, true})); 2305 CHECK(json::from_bjdata(v_T) == json({true, true})); 2306 CHECK(json::from_bjdata(v_F) == json({false, false})); 2307 CHECK(json::from_bjdata(v_Z) == json({nullptr, nullptr})); 2308 CHECK(json::from_bjdata(v_i) == json({127, 127})); 2309 CHECK(json::from_bjdata(v_U) == json({255, 255})); 2310 CHECK(json::from_bjdata(v_I) == json({32767, 32767})); 2311 CHECK(json::from_bjdata(v_u) == json({42767, 42767})); 2312 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647})); 2313 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647})); 2314 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807})); 2315 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull})); 2316 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926})); 2317 CHECK(json::from_bjdata(v_S) == json({"a", "a"})); 2318 CHECK(json::from_bjdata(v_C) == json({"a", "a"})); 2319 2320 // roundtrip: output should be optimized 2321 CHECK(json::to_bjdata(json::from_bjdata(v_T), true) == v_T); 2322 CHECK(json::to_bjdata(json::from_bjdata(v_F), true) == v_F); 2323 CHECK(json::to_bjdata(json::from_bjdata(v_Z), true) == v_Z); 2324 CHECK(json::to_bjdata(json::from_bjdata(v_i), true) == v_i); 2325 CHECK(json::to_bjdata(json::from_bjdata(v_U), true) == v_U); 2326 CHECK(json::to_bjdata(json::from_bjdata(v_I), true) == v_I); 2327 CHECK(json::to_bjdata(json::from_bjdata(v_u), true) == v_u); 2328 CHECK(json::to_bjdata(json::from_bjdata(v_l), true) == v_l); 2329 CHECK(json::to_bjdata(json::from_bjdata(v_m), true) == v_m); 2330 CHECK(json::to_bjdata(json::from_bjdata(v_L), true) == v_L); 2331 CHECK(json::to_bjdata(json::from_bjdata(v_M), true) == v_M); 2332 CHECK(json::to_bjdata(json::from_bjdata(v_D), true) == v_D); 2333 CHECK(json::to_bjdata(json::from_bjdata(v_S), true) == v_S); 2334 CHECK(json::to_bjdata(json::from_bjdata(v_C), true) == v_S); // char is serialized to string 2335 } 2336 2337 SECTION("optimized version (type and length)") 2338 { 2339 // create vector with two elements of the same type 2340 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', 'i', 2, 0x7F, 0x7F}; 2341 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', 'i', 2, 0xFF, 0xFF}; 2342 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', 'i', 2, 0xFF, 0x7F, 0xFF, 0x7F}; 2343 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', 'i', 2, 0x0F, 0xA7, 0x0F, 0xA7}; 2344 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', 'i', 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F}; 2345 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB}; 2346 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', 'i', 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}; 2347 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 2348 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', 'i', 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40}; 2349 std::vector<uint8_t> v_S = {'[', '#', 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'}; 2350 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', 'i', 2, 'a', 'a'}; 2351 2352 // check if vector is parsed correctly 2353 CHECK(json::from_bjdata(v_i) == json({127, 127})); 2354 CHECK(json::from_bjdata(v_U) == json({255, 255})); 2355 CHECK(json::from_bjdata(v_I) == json({32767, 32767})); 2356 CHECK(json::from_bjdata(v_u) == json({42767, 42767})); 2357 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647})); 2358 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647})); 2359 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807})); 2360 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull})); 2361 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926})); 2362 CHECK(json::from_bjdata(v_S) == json({"a", "a"})); 2363 CHECK(json::from_bjdata(v_C) == json({"a", "a"})); 2364 2365 // roundtrip: output should be optimized 2366 std::vector<uint8_t> v_empty = {'[', '#', 'i', 0}; 2367 CHECK(json::to_bjdata(json::from_bjdata(v_i), true, true) == v_i); 2368 CHECK(json::to_bjdata(json::from_bjdata(v_U), true, true) == v_U); 2369 CHECK(json::to_bjdata(json::from_bjdata(v_I), true, true) == v_I); 2370 CHECK(json::to_bjdata(json::from_bjdata(v_u), true, true) == v_u); 2371 CHECK(json::to_bjdata(json::from_bjdata(v_l), true, true) == v_l); 2372 CHECK(json::to_bjdata(json::from_bjdata(v_m), true, true) == v_m); 2373 CHECK(json::to_bjdata(json::from_bjdata(v_L), true, true) == v_L); 2374 CHECK(json::to_bjdata(json::from_bjdata(v_M), true, true) == v_M); 2375 CHECK(json::to_bjdata(json::from_bjdata(v_D), true, true) == v_D); 2376 CHECK(json::to_bjdata(json::from_bjdata(v_S), true, true) == v_S); 2377 CHECK(json::to_bjdata(json::from_bjdata(v_C), true, true) == v_S); // char is serialized to string 2378 } 2379 2380 SECTION("optimized ndarray (type and vector-size as optimized 1D array)") 2381 { 2382 // create vector with two elements of the same type 2383 std::vector<uint8_t> v_0 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 1, 0}; 2384 std::vector<uint8_t> v_1 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 1, 2, 0x7F, 0x7F}; 2385 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x7F, 0x7F}; 2386 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF}; 2387 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0x7F, 0xFF, 0x7F}; 2388 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x0F, 0xA7, 0x0F, 0xA7}; 2389 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F}; 2390 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB}; 2391 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}; 2392 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 2393 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40}; 2394 std::vector<uint8_t> v_S = {'[', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'}; 2395 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', '$', 'i', '#', 'i', 2, 1, 2, 'a', 'a'}; 2396 2397 // check if vector is parsed correctly 2398 CHECK(json::from_bjdata(v_0) == json::array()); 2399 CHECK(json::from_bjdata(v_1) == json({127, 127})); 2400 CHECK(json::from_bjdata(v_i) == json({127, 127})); 2401 CHECK(json::from_bjdata(v_U) == json({255, 255})); 2402 CHECK(json::from_bjdata(v_I) == json({32767, 32767})); 2403 CHECK(json::from_bjdata(v_u) == json({42767, 42767})); 2404 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647})); 2405 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647})); 2406 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807})); 2407 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull})); 2408 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926})); 2409 CHECK(json::from_bjdata(v_S) == json({"a", "a"})); 2410 CHECK(json::from_bjdata(v_C) == json({"a", "a"})); 2411 } 2412 2413 SECTION("optimized ndarray (type and vector-size ndarray with JData annotations)") 2414 { 2415 // create vector with 0, 1, 2 elements of the same type 2416 std::vector<uint8_t> v_e = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 1, 0xFE, 0xFF}; 2417 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; 2418 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06}; 2419 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00}; 2420 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x02, 0x00, 0x03, 0x00, 0x04, 0x00, 0x05, 0x00, 0x06, 0x00}; 2421 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00}; 2422 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00}; 2423 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 2424 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00}; 2425 std::vector<uint8_t> v_d = {'[', '$', 'd', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x00, 0x00, 0x80, 0x3F, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x40, 0x40, 0x00, 0x00, 0x80, 0x40, 0x00, 0x00, 0xA0, 0x40, 0x00, 0x00, 0xC0, 0x40}; 2426 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF0, 0x3F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x10, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x14, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x18, 0x40}; 2427 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 'a', 'b', 'c', 'd', 'e', 'f'}; 2428 2429 // check if vector is parsed correctly 2430 CHECK(json::from_bjdata(v_e) == json({{"_ArrayData_", {254, 255}}, {"_ArraySize_", {2, 1}}, {"_ArrayType_", "uint8"}})); 2431 CHECK(json::from_bjdata(v_U) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint8"}})); 2432 CHECK(json::from_bjdata(v_i) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int8"}})); 2433 CHECK(json::from_bjdata(v_i) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int8"}})); 2434 CHECK(json::from_bjdata(v_u) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint16"}})); 2435 CHECK(json::from_bjdata(v_I) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int16"}})); 2436 CHECK(json::from_bjdata(v_m) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint32"}})); 2437 CHECK(json::from_bjdata(v_l) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int32"}})); 2438 CHECK(json::from_bjdata(v_M) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint64"}})); 2439 CHECK(json::from_bjdata(v_L) == json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "int64"}})); 2440 CHECK(json::from_bjdata(v_d) == json({{"_ArrayData_", {1.f, 2.f, 3.f, 4.f, 5.f, 6.f}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "single"}})); 2441 CHECK(json::from_bjdata(v_D) == json({{"_ArrayData_", {1., 2., 3., 4., 5., 6.}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "double"}})); 2442 CHECK(json::from_bjdata(v_C) == json({{"_ArrayData_", {'a', 'b', 'c', 'd', 'e', 'f'}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "char"}})); 2443 2444 // roundtrip: output should be optimized 2445 CHECK(json::to_bjdata(json::from_bjdata(v_e), true, true) == v_e); 2446 CHECK(json::to_bjdata(json::from_bjdata(v_U), true, true) == v_U); 2447 CHECK(json::to_bjdata(json::from_bjdata(v_i), true, true) == v_i); 2448 CHECK(json::to_bjdata(json::from_bjdata(v_u), true, true) == v_u); 2449 CHECK(json::to_bjdata(json::from_bjdata(v_I), true, true) == v_I); 2450 CHECK(json::to_bjdata(json::from_bjdata(v_m), true, true) == v_m); 2451 CHECK(json::to_bjdata(json::from_bjdata(v_l), true, true) == v_l); 2452 CHECK(json::to_bjdata(json::from_bjdata(v_M), true, true) == v_M); 2453 CHECK(json::to_bjdata(json::from_bjdata(v_L), true, true) == v_L); 2454 CHECK(json::to_bjdata(json::from_bjdata(v_d), true, true) == v_d); 2455 CHECK(json::to_bjdata(json::from_bjdata(v_D), true, true) == v_D); 2456 CHECK(json::to_bjdata(json::from_bjdata(v_C), true, true) == v_C); 2457 } 2458 2459 SECTION("optimized ndarray (type and vector-size as 1D array)") 2460 { 2461 // create vector with two elements of the same type 2462 std::vector<uint8_t> v_0 = {'[', '$', 'i', '#', '[', ']'}; 2463 std::vector<uint8_t> v_E = {'[', '$', 'i', '#', '[', 'i', 2, 'i', 0, ']'}; 2464 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', 'i', 1, 'i', 2, ']', 0x7F, 0x7F}; 2465 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF}; 2466 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0x7F, 0xFF, 0x7F}; 2467 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', 'i', 1, 'i', 2, ']', 0x0F, 0xA7, 0x0F, 0xA7}; 2468 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F}; 2469 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB}; 2470 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}; 2471 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 2472 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', 'i', 1, 'i', 2, ']', 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40}; 2473 std::vector<uint8_t> v_S = {'[', '#', '[', 'i', 1, 'i', 2, ']', 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'}; 2474 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', 'i', 1, 'i', 2, ']', 'a', 'a'}; 2475 std::vector<uint8_t> v_R = {'[', '#', '[', 'i', 2, ']', 'i', 6, 'U', 7}; 2476 2477 // check if vector is parsed correctly 2478 CHECK(json::from_bjdata(v_0) == json::array()); 2479 CHECK(json::from_bjdata(v_E) == json::array()); 2480 CHECK(json::from_bjdata(v_i) == json({127, 127})); 2481 CHECK(json::from_bjdata(v_U) == json({255, 255})); 2482 CHECK(json::from_bjdata(v_I) == json({32767, 32767})); 2483 CHECK(json::from_bjdata(v_u) == json({42767, 42767})); 2484 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647})); 2485 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647})); 2486 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807})); 2487 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull})); 2488 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926})); 2489 CHECK(json::from_bjdata(v_S) == json({"a", "a"})); 2490 CHECK(json::from_bjdata(v_C) == json({"a", "a"})); 2491 CHECK(json::from_bjdata(v_R) == json({6, 7})); 2492 } 2493 2494 SECTION("optimized ndarray (type and vector-size as size-optimized array)") 2495 { 2496 // create vector with two elements of the same type 2497 std::vector<uint8_t> v_i = {'[', '$', 'i', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x7F, 0x7F}; 2498 std::vector<uint8_t> v_U = {'[', '$', 'U', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF}; 2499 std::vector<uint8_t> v_I = {'[', '$', 'I', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0x7F, 0xFF, 0x7F}; 2500 std::vector<uint8_t> v_u = {'[', '$', 'u', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x0F, 0xA7, 0x0F, 0xA7}; 2501 std::vector<uint8_t> v_l = {'[', '$', 'l', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0x7F}; 2502 std::vector<uint8_t> v_m = {'[', '$', 'm', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0xFF, 0xC9, 0x9A, 0xBB}; 2503 std::vector<uint8_t> v_L = {'[', '$', 'L', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x7F}; 2504 std::vector<uint8_t> v_M = {'[', '$', 'M', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 2505 std::vector<uint8_t> v_D = {'[', '$', 'D', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40, 0x4a, 0xd8, 0x12, 0x4d, 0xfb, 0x21, 0x09, 0x40}; 2506 std::vector<uint8_t> v_S = {'[', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 'S', 'i', 1, 'a', 'S', 'i', 1, 'a'}; 2507 std::vector<uint8_t> v_C = {'[', '$', 'C', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2, 'a', 'a'}; 2508 2509 // check if vector is parsed correctly 2510 CHECK(json::from_bjdata(v_i) == json({127, 127})); 2511 CHECK(json::from_bjdata(v_U) == json({255, 255})); 2512 CHECK(json::from_bjdata(v_I) == json({32767, 32767})); 2513 CHECK(json::from_bjdata(v_u) == json({42767, 42767})); 2514 CHECK(json::from_bjdata(v_l) == json({2147483647, 2147483647})); 2515 CHECK(json::from_bjdata(v_m) == json({3147483647, 3147483647})); 2516 CHECK(json::from_bjdata(v_L) == json({9223372036854775807, 9223372036854775807})); 2517 CHECK(json::from_bjdata(v_M) == json({10223372036854775807ull, 10223372036854775807ull})); 2518 CHECK(json::from_bjdata(v_D) == json({3.1415926, 3.1415926})); 2519 CHECK(json::from_bjdata(v_S) == json({"a", "a"})); 2520 CHECK(json::from_bjdata(v_C) == json({"a", "a"})); 2521 } 2522 2523 SECTION("invalid ndarray annotations remains as object") 2524 { 2525 // check if invalid ND array annotations stay as object 2526 json j_type = json({{"_ArrayData_", {1, 2, 3, 4, 5, 6}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "invalidtype"}}); 2527 json j_size = json({{"_ArrayData_", {1, 2, 3, 4, 5}}, {"_ArraySize_", {2, 3}}, {"_ArrayType_", "uint8"}}); 2528 2529 // roundtrip: output should stay as object 2530 CHECK(json::from_bjdata(json::to_bjdata(j_type), true, true) == j_type); 2531 CHECK(json::from_bjdata(json::to_bjdata(j_size), true, true) == j_size); 2532 } 2533 } 2534 } 2535 2536 SECTION("parse errors") 2537 { 2538 SECTION("empty byte vector") 2539 { 2540 json _; 2541 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(std::vector<uint8_t>()), 2542 "[json.exception.parse_error.110] parse error at byte 1: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2543 } 2544 2545 SECTION("char") 2546 { 2547 SECTION("eof after C byte") 2548 { 2549 std::vector<uint8_t> v = {'C'}; 2550 json _; 2551 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData char: unexpected end of input", json::parse_error&); 2552 } 2553 2554 SECTION("byte out of range") 2555 { 2556 std::vector<uint8_t> v = {'C', 130}; 2557 json _; 2558 CHECK_THROWS_WITH(_ = json::from_bjdata(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData char: byte after 'C' must be in range 0x00..0x7F; last byte: 0x82"); 2559 } 2560 } 2561 2562 SECTION("strings") 2563 { 2564 SECTION("eof after S byte") 2565 { 2566 std::vector<uint8_t> v = {'S'}; 2567 json _; 2568 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2569 } 2570 2571 SECTION("invalid byte") 2572 { 2573 std::vector<uint8_t> v = {'S', '1', 'a'}; 2574 json _; 2575 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing BJData string: expected length type specification (U, i, u, I, m, l, M, L); last byte: 0x31", json::parse_error&); 2576 } 2577 2578 SECTION("parse bjdata markers in ubjson") 2579 { 2580 // create a single-character string for all number types 2581 std::vector<uint8_t> s_u = {'S', 'u', 1, 0, 'a'}; 2582 std::vector<uint8_t> s_m = {'S', 'm', 1, 0, 0, 0, 'a'}; 2583 std::vector<uint8_t> s_M = {'S', 'M', 1, 0, 0, 0, 0, 0, 0, 0, 'a'}; 2584 2585 json _; 2586 // check if string is parsed correctly to "a" 2587 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_u), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x75", json::parse_error&); 2588 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_m), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x6D", json::parse_error&); 2589 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(s_M), "[json.exception.parse_error.113] parse error at byte 2: syntax error while parsing UBJSON string: expected length type specification (U, i, I, l, L); last byte: 0x4D", json::parse_error&); 2590 } 2591 } 2592 2593 SECTION("array") 2594 { 2595 SECTION("optimized array: no size following type") 2596 { 2597 std::vector<uint8_t> v = {'[', '$', 'i', 2}; 2598 json _; 2599 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x02", json::parse_error&); 2600 } 2601 2602 SECTION("optimized array: negative size") 2603 { 2604 std::vector<uint8_t> v1 = {'[', '#', 'i', 0xF1}; 2605 std::vector<uint8_t> v2 = {'[', '$', 'I', '#', 'i', 0xF2}; 2606 std::vector<uint8_t> v3 = {'[', '$', 'I', '#', '[', 'i', 0xF4, 'i', 0x02, ']'}; 2607 std::vector<uint8_t> v4 = {'[', '$', 0xF6, '#', 'i', 0xF7}; 2608 std::vector<uint8_t> v5 = {'[', '$', 'I', '#', '[', 'i', 0xF5, 'i', 0xF1, ']'}; 2609 std::vector<uint8_t> v6 = {'[', '#', '[', 'i', 0xF3, 'i', 0x02, ']'}; 2610 2611 std::vector<uint8_t> vI = {'[', '#', 'I', 0x00, 0xF1}; 2612 std::vector<uint8_t> vl = {'[', '#', 'l', 0x00, 0x00, 0x00, 0xF2}; 2613 std::vector<uint8_t> vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xF3}; 2614 std::vector<uint8_t> vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'}; 2615 std::vector<uint8_t> vMX = {'[', '$', 'U', '#', '[', 'M', 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 'U', 0x01, ']'}; 2616 2617 json _; 2618 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v1), "[json.exception.parse_error.113] parse error at byte 4: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2619 CHECK(json::from_bjdata(v1, true, false).is_discarded()); 2620 2621 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v2), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2622 CHECK(json::from_bjdata(v2, true, false).is_discarded()); 2623 2624 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v3), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2625 CHECK(json::from_bjdata(v3, true, false).is_discarded()); 2626 2627 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v4), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2628 CHECK(json::from_bjdata(v4, true, false).is_discarded()); 2629 2630 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v5), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2631 CHECK(json::from_bjdata(v5, true, false).is_discarded()); 2632 2633 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v6), "[json.exception.parse_error.113] parse error at byte 5: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2634 CHECK(json::from_bjdata(v6, true, false).is_discarded()); 2635 2636 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vI), "[json.exception.parse_error.113] parse error at byte 5: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2637 CHECK(json::from_bjdata(vI, true, false).is_discarded()); 2638 2639 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vl), "[json.exception.parse_error.113] parse error at byte 7: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2640 CHECK(json::from_bjdata(vl, true, false).is_discarded()); 2641 2642 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.parse_error.113] parse error at byte 11: syntax error while parsing BJData size: count in an optimized container must be positive", json::parse_error&); 2643 CHECK(json::from_bjdata(vL, true, false).is_discarded()); 2644 2645#if SIZE_MAX != 0xffffffff 2646 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: excessive ndarray size caused overflow", json::out_of_range&); 2647#else 2648 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&); 2649#endif 2650 CHECK(json::from_bjdata(vM, true, false).is_discarded()); 2651 2652#if SIZE_MAX != 0xffffffff 2653 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: excessive ndarray size caused overflow", json::out_of_range&); 2654#else 2655 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vMX), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&); 2656#endif 2657 CHECK(json::from_bjdata(vMX, true, false).is_discarded()); 2658 } 2659 2660 SECTION("optimized array: integer value overflow") 2661 { 2662 std::vector<uint8_t> vL = {'[', '#', 'L', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x7F}; 2663 std::vector<uint8_t> vM = {'[', '$', 'M', '#', '[', 'I', 0x00, 0x20, 'M', 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0xFF, ']'}; 2664 2665 json _; 2666#if SIZE_MAX == 0xffffffff 2667 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&); 2668 CHECK(json::from_bjdata(vL, true, false).is_discarded()); 2669#endif 2670 2671#if SIZE_MAX == 0xffffffff 2672 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.out_of_range.408] syntax error while parsing BJData size: integer value overflow", json::out_of_range&); 2673 CHECK(json::from_bjdata(vM, true, false).is_discarded()); 2674#endif 2675 } 2676 2677 SECTION("do not accept NTFZ markers in ndarray optimized type (with count)") 2678 { 2679 json _; 2680 std::vector<uint8_t> v_N = {'[', '$', 'N', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2}; 2681 std::vector<uint8_t> v_T = {'[', '$', 'T', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2}; 2682 std::vector<uint8_t> v_F = {'[', '$', 'F', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2}; 2683 std::vector<uint8_t> v_Z = {'[', '$', 'Z', '#', '[', '#', 'i', 2, 'i', 1, 'i', 2}; 2684 2685 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_N), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&); 2686 CHECK(json::from_bjdata(v_N, true, false).is_discarded()); 2687 2688 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_T), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x54 is not a permitted optimized array type", json::parse_error&); 2689 CHECK(json::from_bjdata(v_T, true, false).is_discarded()); 2690 2691 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_F), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x46 is not a permitted optimized array type", json::parse_error&); 2692 CHECK(json::from_bjdata(v_F, true, false).is_discarded()); 2693 2694 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_Z), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&); 2695 CHECK(json::from_bjdata(v_Z, true, false).is_discarded()); 2696 } 2697 2698 SECTION("do not accept NTFZ markers in ndarray optimized type (without count)") 2699 { 2700 json _; 2701 std::vector<uint8_t> v_N = {'[', '$', 'N', '#', '[', 'i', 1, 'i', 2, ']'}; 2702 std::vector<uint8_t> v_T = {'[', '$', 'T', '#', '[', 'i', 1, 'i', 2, ']'}; 2703 std::vector<uint8_t> v_F = {'[', '$', 'F', '#', '[', 'i', 1, 'i', 2, ']'}; 2704 std::vector<uint8_t> v_Z = {'[', '$', 'Z', '#', '[', 'i', 1, 'i', 2, ']'}; 2705 2706 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_N), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&); 2707 CHECK(json::from_bjdata(v_N, true, false).is_discarded()); 2708 2709 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_T), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x54 is not a permitted optimized array type", json::parse_error&); 2710 CHECK(json::from_bjdata(v_T, true, false).is_discarded()); 2711 2712 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_F), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x46 is not a permitted optimized array type", json::parse_error&); 2713 CHECK(json::from_bjdata(v_F, true, false).is_discarded()); 2714 2715 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v_Z), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&); 2716 CHECK(json::from_bjdata(v_Z, true, false).is_discarded()); 2717 } 2718 } 2719 2720 SECTION("strings") 2721 { 2722 std::vector<uint8_t> vS = {'S'}; 2723 json _; 2724 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2725 CHECK(json::from_bjdata(vS, true, false).is_discarded()); 2726 2727 std::vector<uint8_t> v = {'S', 'i', '2', 'a'}; 2728 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BJData string: unexpected end of input", json::parse_error&); 2729 CHECK(json::from_bjdata(v, true, false).is_discarded()); 2730 2731 std::vector<uint8_t> vC = {'C'}; 2732 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vC), "[json.exception.parse_error.110] parse error at byte 2: syntax error while parsing BJData char: unexpected end of input", json::parse_error&); 2733 CHECK(json::from_bjdata(vC, true, false).is_discarded()); 2734 } 2735 2736 SECTION("sizes") 2737 { 2738 std::vector<uint8_t> vU = {'[', '#', 'U'}; 2739 json _; 2740 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2741 CHECK(json::from_bjdata(vU, true, false).is_discarded()); 2742 2743 std::vector<uint8_t> vi = {'[', '#', 'i'}; 2744 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2745 CHECK(json::from_bjdata(vi, true, false).is_discarded()); 2746 2747 std::vector<uint8_t> vI = {'[', '#', 'I'}; 2748 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vI), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2749 CHECK(json::from_bjdata(vI, true, false).is_discarded()); 2750 2751 std::vector<uint8_t> vu = {'[', '#', 'u'}; 2752 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vu), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2753 CHECK(json::from_bjdata(vu, true, false).is_discarded()); 2754 2755 std::vector<uint8_t> vl = {'[', '#', 'l'}; 2756 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vl), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2757 CHECK(json::from_bjdata(vl, true, false).is_discarded()); 2758 2759 std::vector<uint8_t> vm = {'[', '#', 'm'}; 2760 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vm), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2761 CHECK(json::from_bjdata(vm, true, false).is_discarded()); 2762 2763 std::vector<uint8_t> vL = {'[', '#', 'L'}; 2764 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vL), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2765 CHECK(json::from_bjdata(vL, true, false).is_discarded()); 2766 2767 std::vector<uint8_t> vM = {'[', '#', 'M'}; 2768 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2769 CHECK(json::from_bjdata(vM, true, false).is_discarded()); 2770 2771 std::vector<uint8_t> v0 = {'[', '#', 'T', ']'}; 2772 CHECK_THROWS_WITH(_ = json::from_bjdata(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x54"); 2773 CHECK(json::from_bjdata(v0, true, false).is_discarded()); 2774 } 2775 2776 SECTION("parse bjdata markers as array size in ubjson") 2777 { 2778 json _; 2779 std::vector<uint8_t> vu = {'[', '#', 'u'}; 2780 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vu), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x75", json::parse_error&); 2781 CHECK(json::from_ubjson(vu, true, false).is_discarded()); 2782 2783 std::vector<uint8_t> vm = {'[', '#', 'm'}; 2784 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vm), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x6D", json::parse_error&); 2785 CHECK(json::from_ubjson(vm, true, false).is_discarded()); 2786 2787 std::vector<uint8_t> vM = {'[', '#', 'M'}; 2788 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(vM), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x4D", json::parse_error&); 2789 CHECK(json::from_ubjson(vM, true, false).is_discarded()); 2790 2791 std::vector<uint8_t> v0 = {'[', '#', '['}; 2792 CHECK_THROWS_WITH_AS(_ = json::from_ubjson(v0), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing UBJSON size: expected length type specification (U, i, I, l, L) after '#'; last byte: 0x5B", json::parse_error&); 2793 CHECK(json::from_ubjson(v0, true, false).is_discarded()); 2794 } 2795 2796 SECTION("types") 2797 { 2798 std::vector<uint8_t> v0 = {'[', '$'}; 2799 json _; 2800 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v0), "[json.exception.parse_error.110] parse error at byte 3: syntax error while parsing BJData type: unexpected end of input", json::parse_error&); 2801 CHECK(json::from_bjdata(v0, true, false).is_discarded()); 2802 2803 std::vector<uint8_t> vi = {'[', '$', '#'}; 2804 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vi), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2805 CHECK(json::from_bjdata(vi, true, false).is_discarded()); 2806 2807 std::vector<uint8_t> vU = {'[', '$', 'U'}; 2808 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 4: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2809 CHECK(json::from_bjdata(vU, true, false).is_discarded()); 2810 2811 std::vector<uint8_t> v1 = {'[', '$', '['}; 2812 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v1), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5B is not a permitted optimized array type", json::parse_error&); 2813 CHECK(json::from_bjdata(v1, true, false).is_discarded()); 2814 } 2815 2816 SECTION("arrays") 2817 { 2818 std::vector<uint8_t> vST = {'[', '$', 'i', '#', 'i', 2, 1}; 2819 json _; 2820 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2821 CHECK(json::from_bjdata(vST, true, false).is_discarded()); 2822 2823 std::vector<uint8_t> vS = {'[', '#', 'i', 2, 'i', 1}; 2824 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2825 CHECK(json::from_bjdata(vS, true, false).is_discarded()); 2826 2827 std::vector<uint8_t> v = {'[', 'i', 2, 'i', 1}; 2828 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 6: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2829 CHECK(json::from_bjdata(v, true, false).is_discarded()); 2830 } 2831 2832 SECTION("ndarrays") 2833 { 2834 std::vector<uint8_t> vST = {'[', '$', 'i', '#', '[', '$', 'i', '#'}; 2835 json _; 2836 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.113] parse error at byte 9: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0xFF", json::parse_error&); 2837 CHECK(json::from_bjdata(vST, true, false).is_discarded()); 2838 2839 std::vector<uint8_t> v = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1, 2}; 2840 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 13: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2841 CHECK(json::from_bjdata(v, true, false).is_discarded()); 2842 2843 std::vector<uint8_t> vS0 = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'i', 2, 1}; 2844 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS0), "[json.exception.parse_error.110] parse error at byte 12: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2845 CHECK(json::from_bjdata(vS0, true, false).is_discarded()); 2846 2847 std::vector<uint8_t> vS = {'[', '$', 'i', '#', '[', '#', 'i', 2, 1, 2, 1}; 2848 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.113] parse error at byte 9: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x01", json::parse_error&); 2849 CHECK(json::from_bjdata(vS, true, false).is_discarded()); 2850 2851 std::vector<uint8_t> vT = {'[', '$', 'i', '#', '[', 'i', 2, 'i'}; 2852 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vT), "[json.exception.parse_error.110] parse error at byte 9: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2853 CHECK(json::from_bjdata(vT, true, false).is_discarded()); 2854 2855 std::vector<uint8_t> vT0 = {'[', '$', 'i', '#', '[', 'i'}; 2856 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vT0), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2857 CHECK(json::from_bjdata(vT0, true, false).is_discarded()); 2858 2859 std::vector<uint8_t> vu = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'u', 1, 0}; 2860 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vu), "[json.exception.parse_error.110] parse error at byte 12: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2861 CHECK(json::from_bjdata(vu, true, false).is_discarded()); 2862 2863 std::vector<uint8_t> vm = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'm', 1, 0, 0, 0}; 2864 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vm), "[json.exception.parse_error.110] parse error at byte 14: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2865 CHECK(json::from_bjdata(vm, true, false).is_discarded()); 2866 2867 std::vector<uint8_t> vM = {'[', '$', 'i', '#', '[', '$', 'i', '#', 'M', 1, 0, 0, 0, 0, 0, 0, 0}; 2868 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2869 CHECK(json::from_bjdata(vM, true, false).is_discarded()); 2870 2871 std::vector<uint8_t> vU = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 1, 2, 3, 4, 5}; 2872 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2873 CHECK(json::from_bjdata(vU, true, false).is_discarded()); 2874 2875 std::vector<uint8_t> vT1 = {'[', '$', 'T', '#', '[', '$', 'i', '#', 'i', 2, 2, 3}; 2876 CHECK(json::from_bjdata(vT1, true, false).is_discarded()); 2877 2878 std::vector<uint8_t> vh = {'[', '$', 'h', '#', '[', '$', 'i', '#', 'i', 2, 2, 3}; 2879 CHECK(json::from_bjdata(vh, true, false).is_discarded()); 2880 2881 std::vector<uint8_t> vR = {'[', '$', 'i', '#', '[', 'i', 1, '[', ']', ']', 1}; 2882 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR), "[json.exception.parse_error.113] parse error at byte 8: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&); 2883 CHECK(json::from_bjdata(vR, true, false).is_discarded()); 2884 2885 std::vector<uint8_t> vRo = {'[', '$', 'i', '#', '[', 'i', 0, '{', '}', ']', 1}; 2886 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vRo), "[json.exception.parse_error.113] parse error at byte 8: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x7B", json::parse_error&); 2887 CHECK(json::from_bjdata(vRo, true, false).is_discarded()); 2888 2889 std::vector<uint8_t> vR1 = {'[', '$', 'i', '#', '[', '[', 'i', 1, ']', ']', 1}; 2890 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR1), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&); 2891 CHECK(json::from_bjdata(vR1, true, false).is_discarded()); 2892 2893 std::vector<uint8_t> vR2 = {'[', '$', 'i', '#', '[', '#', '[', 'i', 1, ']', ']', 1}; 2894 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR2), "[json.exception.parse_error.113] parse error at byte 11: syntax error while parsing BJData size: expected length type specification (U, i, u, I, m, l, M, L) after '#'; last byte: 0x5D", json::parse_error&); 2895 CHECK(json::from_bjdata(vR2, true, false).is_discarded()); 2896 2897 std::vector<uint8_t> vR3 = {'[', '#', '[', 'i', '2', 'i', 2, ']'}; 2898 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR3), "[json.exception.parse_error.112] parse error at byte 8: syntax error while parsing BJData size: ndarray requires both type and size", json::parse_error&); 2899 CHECK(json::from_bjdata(vR3, true, false).is_discarded()); 2900 2901 std::vector<uint8_t> vR4 = {'[', '$', 'i', '#', '[', '$', 'i', '#', '[', 'i', 1, ']', 1}; 2902 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR4), "[json.exception.parse_error.110] parse error at byte 14: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2903 CHECK(json::from_bjdata(vR4, true, false).is_discarded()); 2904 2905 std::vector<uint8_t> vR5 = {'[', '$', 'i', '#', '[', '[', '[', ']', ']', ']'}; 2906 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR5), "[json.exception.parse_error.113] parse error at byte 6: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&); 2907 CHECK(json::from_bjdata(vR5, true, false).is_discarded()); 2908 2909 std::vector<uint8_t> vR6 = {'[', '$', 'i', '#', '[', '$', 'i', '#', '[', 'i', '2', 'i', 2, ']'}; 2910 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vR6), "[json.exception.parse_error.112] parse error at byte 14: syntax error while parsing BJData size: ndarray can not be recursive", json::parse_error&); 2911 CHECK(json::from_bjdata(vR6, true, false).is_discarded()); 2912 2913 std::vector<uint8_t> vH = {'[', 'H', '[', '#', '[', '$', 'i', '#', '[', 'i', '2', 'i', 2, ']'}; 2914 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vH), "[json.exception.parse_error.113] parse error at byte 3: syntax error while parsing BJData size: ndarray dimentional vector is not allowed", json::parse_error&); 2915 CHECK(json::from_bjdata(vH, true, false).is_discarded()); 2916 } 2917 2918 SECTION("objects") 2919 { 2920 std::vector<uint8_t> vST = {'{', '$', 'i', '#', 'i', 2, 'i', 1, 'a', 1}; 2921 json _; 2922 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST), "[json.exception.parse_error.110] parse error at byte 11: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2923 CHECK(json::from_bjdata(vST, true, false).is_discarded()); 2924 2925 std::vector<uint8_t> vT = {'{', '$', 'i', 'i', 1, 'a', 1}; 2926 CHECK_THROWS_WITH(_ = json::from_bjdata(vT), "[json.exception.parse_error.112] parse error at byte 4: syntax error while parsing BJData size: expected '#' after type information; last byte: 0x69"); 2927 CHECK(json::from_bjdata(vT, true, false).is_discarded()); 2928 2929 std::vector<uint8_t> vS = {'{', '#', 'i', 2, 'i', 1, 'a', 'i', 1}; 2930 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vS), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2931 CHECK(json::from_bjdata(vS, true, false).is_discarded()); 2932 2933 std::vector<uint8_t> v = {'{', 'i', 1, 'a', 'i', 1}; 2934 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.110] parse error at byte 7: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2935 CHECK(json::from_bjdata(v, true, false).is_discarded()); 2936 2937 std::vector<uint8_t> v2 = {'{', 'i', 1, 'a', 'i', 1, 'i'}; 2938 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2939 CHECK(json::from_bjdata(v2, true, false).is_discarded()); 2940 2941 std::vector<uint8_t> v3 = {'{', 'i', 1, 'a'}; 2942 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v3), "[json.exception.parse_error.110] parse error at byte 5: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2943 CHECK(json::from_bjdata(v3, true, false).is_discarded()); 2944 2945 std::vector<uint8_t> vST1 = {'{', '$', 'd', '#', 'i', 2, 'i', 1, 'a'}; 2946 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST1), "[json.exception.parse_error.110] parse error at byte 10: syntax error while parsing BJData number: unexpected end of input", json::parse_error&); 2947 CHECK(json::from_bjdata(vST1, true, false).is_discarded()); 2948 2949 std::vector<uint8_t> vST2 = {'{', '#', 'i', 2, 'i', 1, 'a'}; 2950 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vST2), "[json.exception.parse_error.110] parse error at byte 8: syntax error while parsing BJData value: unexpected end of input", json::parse_error&); 2951 CHECK(json::from_bjdata(vST2, true, false).is_discarded()); 2952 2953 std::vector<uint8_t> vO = {'{', '#', '[', 'i', 2, 'i', 1, ']', 'i', 1, 'a', 'i', 1, 'i', 1, 'b', 'i', 2}; 2954 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vO), "[json.exception.parse_error.112] parse error at byte 8: syntax error while parsing BJData size: ndarray requires both type and size", json::parse_error&); 2955 CHECK(json::from_bjdata(vO, true, false).is_discarded()); 2956 2957 std::vector<uint8_t> vO2 = {'{', '$', 'i', '#', '[', 'i', 2, 'i', 1, ']', 'i', 1, 'a', 1, 'i', 1, 'b', 2}; 2958 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(vO2), "[json.exception.parse_error.112] parse error at byte 10: syntax error while parsing BJData object: BJData object does not support ND-array size in optimized format", json::parse_error&); 2959 CHECK(json::from_bjdata(vO2, true, false).is_discarded()); 2960 } 2961 } 2962 2963 SECTION("writing optimized values") 2964 { 2965 SECTION("integer") 2966 { 2967 SECTION("array of i") 2968 { 2969 json j = {1, -1}; 2970 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 2, 1, 0xff}; 2971 CHECK(json::to_bjdata(j, true, true) == expected); 2972 } 2973 2974 SECTION("array of U") 2975 { 2976 json j = {200, 201}; 2977 std::vector<uint8_t> expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9}; 2978 CHECK(json::to_bjdata(j, true, true) == expected); 2979 } 2980 2981 SECTION("array of I") 2982 { 2983 json j = {30000, -30000}; 2984 std::vector<uint8_t> expected = {'[', '$', 'I', '#', 'i', 2, 0x30, 0x75, 0xd0, 0x8a}; 2985 CHECK(json::to_bjdata(j, true, true) == expected); 2986 } 2987 2988 SECTION("array of u") 2989 { 2990 json j = {50000, 50001}; 2991 std::vector<uint8_t> expected = {'[', '$', 'u', '#', 'i', 2, 0x50, 0xC3, 0x51, 0xC3}; 2992 CHECK(json::to_bjdata(j, true, true) == expected); 2993 } 2994 2995 SECTION("array of l") 2996 { 2997 json j = {70000, -70000}; 2998 std::vector<uint8_t> expected = {'[', '$', 'l', '#', 'i', 2, 0x70, 0x11, 0x01, 0x00, 0x90, 0xEE, 0xFE, 0xFF}; 2999 CHECK(json::to_bjdata(j, true, true) == expected); 3000 } 3001 3002 SECTION("array of m") 3003 { 3004 json j = {3147483647, 3147483648}; 3005 std::vector<uint8_t> expected = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0x00, 0xCA, 0x9A, 0xBB}; 3006 CHECK(json::to_bjdata(j, true, true) == expected); 3007 } 3008 3009 SECTION("array of L") 3010 { 3011 json j = {5000000000, -5000000000}; 3012 std::vector<uint8_t> expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x00, 0x0E, 0xFA, 0xD5, 0xFE, 0xFF, 0xFF, 0xFF}; 3013 CHECK(json::to_bjdata(j, true, true) == expected); 3014 } 3015 } 3016 3017 SECTION("unsigned integer") 3018 { 3019 SECTION("array of i") 3020 { 3021 json j = {1u, 2u}; 3022 std::vector<uint8_t> expected = {'[', '$', 'i', '#', 'i', 2, 1, 2}; 3023 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'i', 1, 'i', 2}; 3024 CHECK(json::to_bjdata(j, true, true) == expected); 3025 CHECK(json::to_bjdata(j, true) == expected_size); 3026 } 3027 3028 SECTION("array of U") 3029 { 3030 json j = {200u, 201u}; 3031 std::vector<uint8_t> expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9}; 3032 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'U', 0xC8, 'U', 0xC9}; 3033 CHECK(json::to_bjdata(j, true, true) == expected); 3034 CHECK(json::to_bjdata(j, true) == expected_size); 3035 } 3036 3037 SECTION("array of I") 3038 { 3039 json j = {30000u, 30001u}; 3040 std::vector<uint8_t> expected = {'[', '$', 'I', '#', 'i', 2, 0x30, 0x75, 0x31, 0x75}; 3041 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'I', 0x30, 0x75, 'I', 0x31, 0x75}; 3042 CHECK(json::to_bjdata(j, true, true) == expected); 3043 CHECK(json::to_bjdata(j, true) == expected_size); 3044 } 3045 3046 SECTION("array of u") 3047 { 3048 json j = {50000u, 50001u}; 3049 std::vector<uint8_t> expected = {'[', '$', 'u', '#', 'i', 2, 0x50, 0xC3, 0x51, 0xC3}; 3050 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'u', 0x50, 0xC3, 'u', 0x51, 0xC3}; 3051 CHECK(json::to_bjdata(j, true, true) == expected); 3052 CHECK(json::to_bjdata(j, true) == expected_size); 3053 } 3054 3055 SECTION("array of l") 3056 { 3057 json j = {70000u, 70001u}; 3058 std::vector<uint8_t> expected = {'[', '$', 'l', '#', 'i', 2, 0x70, 0x11, 0x01, 0x00, 0x71, 0x11, 0x01, 0x00}; 3059 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'l', 0x70, 0x11, 0x01, 0x00, 'l', 0x71, 0x11, 0x01, 0x00}; 3060 CHECK(json::to_bjdata(j, true, true) == expected); 3061 CHECK(json::to_bjdata(j, true) == expected_size); 3062 } 3063 3064 SECTION("array of m") 3065 { 3066 json j = {3147483647u, 3147483648u}; 3067 std::vector<uint8_t> expected = {'[', '$', 'm', '#', 'i', 2, 0xFF, 0xC9, 0x9A, 0xBB, 0x00, 0xCA, 0x9A, 0xBB}; 3068 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'm', 0xFF, 0xC9, 0x9A, 0xBB, 'm', 0x00, 0xCA, 0x9A, 0xBB}; 3069 CHECK(json::to_bjdata(j, true, true) == expected); 3070 CHECK(json::to_bjdata(j, true) == expected_size); 3071 } 3072 3073 SECTION("array of L") 3074 { 3075 json j = {5000000000u, 5000000001u}; 3076 std::vector<uint8_t> expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 0x01, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00}; 3077 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'L', 0x00, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00, 'L', 0x01, 0xF2, 0x05, 0x2A, 0x01, 0x00, 0x00, 0x00}; 3078 CHECK(json::to_bjdata(j, true, true) == expected); 3079 CHECK(json::to_bjdata(j, true) == expected_size); 3080 } 3081 3082 SECTION("array of M") 3083 { 3084 json j = {10223372036854775807ull, 10223372036854775808ull}; 3085 std::vector<uint8_t> expected = {'[', '$', 'M', '#', 'i', 2, 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 0x00, 0x00, 0x64, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 3086 std::vector<uint8_t> expected_size = {'[', '#', 'i', 2, 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 'M', 0x00, 0x00, 0x64, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D}; 3087 CHECK(json::to_bjdata(j, true, true) == expected); 3088 CHECK(json::to_bjdata(j, true) == expected_size); 3089 } 3090 } 3091 } 3092} 3093 3094TEST_CASE("Universal Binary JSON Specification Examples 1") 3095{ 3096 SECTION("Null Value") 3097 { 3098 json j = {{"passcode", nullptr}}; 3099 std::vector<uint8_t> v = {'{', 'i', 8, 'p', 'a', 's', 's', 'c', 'o', 'd', 'e', 'Z', '}'}; 3100 CHECK(json::to_bjdata(j) == v); 3101 CHECK(json::from_bjdata(v) == j); 3102 } 3103 3104 SECTION("No-Op Value") 3105 { 3106 json j = {"foo", "bar", "baz"}; 3107 std::vector<uint8_t> v = {'[', 'S', 'i', 3, 'f', 'o', 'o', 3108 'S', 'i', 3, 'b', 'a', 'r', 3109 'S', 'i', 3, 'b', 'a', 'z', ']' 3110 }; 3111 std::vector<uint8_t> v2 = {'[', 'S', 'i', 3, 'f', 'o', 'o', 'N', 3112 'S', 'i', 3, 'b', 'a', 'r', 'N', 'N', 'N', 3113 'S', 'i', 3, 'b', 'a', 'z', 'N', 'N', ']' 3114 }; 3115 CHECK(json::to_bjdata(j) == v); 3116 CHECK(json::from_bjdata(v) == j); 3117 CHECK(json::from_bjdata(v2) == j); 3118 } 3119 3120 SECTION("Boolean Types") 3121 { 3122 json j = {{"authorized", true}, {"verified", false}}; 3123 std::vector<uint8_t> v = {'{', 'i', 10, 'a', 'u', 't', 'h', 'o', 'r', 'i', 'z', 'e', 'd', 'T', 3124 'i', 8, 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', 'F', '}' 3125 }; 3126 CHECK(json::to_bjdata(j) == v); 3127 CHECK(json::from_bjdata(v) == j); 3128 } 3129 3130 SECTION("Numeric Types") 3131 { 3132 json j = 3133 { 3134 {"int8", 16}, 3135 {"uint8", 255}, 3136 {"int16", 32767}, 3137 {"uint16", 42767}, 3138 {"int32", 2147483647}, 3139 {"uint32", 3147483647}, 3140 {"int64", 9223372036854775807}, 3141 {"uint64", 10223372036854775807ull}, 3142 {"float64", 113243.7863123} 3143 }; 3144 std::vector<uint8_t> v = {'{', 3145 'i', 7, 'f', 'l', 'o', 'a', 't', '6', '4', 'D', 0xcf, 0x34, 0xbc, 0x94, 0xbc, 0xa5, 0xfb, 0x40, 3146 'i', 5, 'i', 'n', 't', '1', '6', 'I', 0xff, 0x7f, 3147 'i', 5, 'i', 'n', 't', '3', '2', 'l', 0xff, 0xff, 0xff, 0x7f, 3148 'i', 5, 'i', 'n', 't', '6', '4', 'L', 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x7f, 3149 'i', 4, 'i', 'n', 't', '8', 'i', 16, 3150 'i', 6, 'u', 'i', 'n', 't', '1', '6', 'u', 0x0F, 0xA7, 3151 'i', 6, 'u', 'i', 'n', 't', '3', '2', 'm', 0xFF, 0xC9, 0x9A, 0xBB, 3152 'i', 6, 'u', 'i', 'n', 't', '6', '4', 'M', 0xFF, 0xFF, 0x63, 0xA7, 0xB3, 0xB6, 0xE0, 0x8D, 3153 'i', 5, 'u', 'i', 'n', 't', '8', 'U', 0xff, 3154 '}' 3155 }; 3156 CHECK(json::to_bjdata(j) == v); 3157 CHECK(json::from_bjdata(v) == j); 3158 } 3159 3160 SECTION("Char Type") 3161 { 3162 json j = {{"rolecode", "a"}, {"delim", ";"}}; 3163 std::vector<uint8_t> v = {'{', 'i', 5, 'd', 'e', 'l', 'i', 'm', 'C', ';', 'i', 8, 'r', 'o', 'l', 'e', 'c', 'o', 'd', 'e', 'C', 'a', '}'}; 3164 //CHECK(json::to_bjdata(j) == v); 3165 CHECK(json::from_bjdata(v) == j); 3166 } 3167 3168 SECTION("String Type") 3169 { 3170 SECTION("English") 3171 { 3172 json j = "hello"; 3173 std::vector<uint8_t> v = {'S', 'i', 5, 'h', 'e', 'l', 'l', 'o'}; 3174 CHECK(json::to_bjdata(j) == v); 3175 CHECK(json::from_bjdata(v) == j); 3176 } 3177 3178 SECTION("Russian") 3179 { 3180 json j = "привет"; 3181 std::vector<uint8_t> v = {'S', 'i', 12, 0xD0, 0xBF, 0xD1, 0x80, 0xD0, 0xB8, 0xD0, 0xB2, 0xD0, 0xB5, 0xD1, 0x82}; 3182 CHECK(json::to_bjdata(j) == v); 3183 CHECK(json::from_bjdata(v) == j); 3184 } 3185 3186 SECTION("Russian") 3187 { 3188 json j = "مرحبا"; 3189 std::vector<uint8_t> v = {'S', 'i', 10, 0xD9, 0x85, 0xD8, 0xB1, 0xD8, 0xAD, 0xD8, 0xA8, 0xD8, 0xA7}; 3190 CHECK(json::to_bjdata(j) == v); 3191 CHECK(json::from_bjdata(v) == j); 3192 } 3193 } 3194 3195 SECTION("Array Type") 3196 { 3197 SECTION("size=false type=false") 3198 { 3199 // note the float has been replaced by a double 3200 json j = {nullptr, true, false, 4782345193, 153.132, "ham"}; 3201 std::vector<uint8_t> v = {'[', 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm', ']'}; 3202 CHECK(json::to_bjdata(j) == v); 3203 CHECK(json::from_bjdata(v) == j); 3204 } 3205 3206 SECTION("size=true type=false") 3207 { 3208 // note the float has been replaced by a double 3209 json j = {nullptr, true, false, 4782345193, 153.132, "ham"}; 3210 std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm'}; 3211 CHECK(json::to_bjdata(j, true) == v); 3212 CHECK(json::from_bjdata(v) == j); 3213 } 3214 3215 SECTION("size=true type=true") 3216 { 3217 // note the float has been replaced by a double 3218 json j = {nullptr, true, false, 4782345193, 153.132, "ham"}; 3219 std::vector<uint8_t> v = {'[', '#', 'i', 6, 'Z', 'T', 'F', 'L', 0xE9, 0xCB, 0x0C, 0x1D, 0x01, 0x00, 0x00, 0x00, 'D', 0x4e, 0x62, 0x10, 0x58, 0x39, 0x24, 0x63, 0x40, 'S', 'i', 3, 'h', 'a', 'm'}; 3220 CHECK(json::to_bjdata(j, true, true) == v); 3221 CHECK(json::from_bjdata(v) == j); 3222 } 3223 } 3224 3225 SECTION("Object Type") 3226 { 3227 SECTION("size=false type=false") 3228 { 3229 json j = 3230 { 3231 { 3232 "post", { 3233 {"id", 1137}, 3234 {"author", "rkalla"}, 3235 {"timestamp", 1364482090592}, 3236 {"body", "I totally agree!"} 3237 } 3238 } 3239 }; 3240 std::vector<uint8_t> v = {'{', 'i', 4, 'p', 'o', 's', 't', '{', 3241 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a', 3242 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!', 3243 'i', 2, 'i', 'd', 'I', 0x71, 0x04, 3244 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00, 3245 '}', '}' 3246 }; 3247 CHECK(json::to_bjdata(j) == v); 3248 CHECK(json::from_bjdata(v) == j); 3249 } 3250 3251 SECTION("size=true type=false") 3252 { 3253 json j = 3254 { 3255 { 3256 "post", { 3257 {"id", 1137}, 3258 {"author", "rkalla"}, 3259 {"timestamp", 1364482090592}, 3260 {"body", "I totally agree!"} 3261 } 3262 } 3263 }; 3264 std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4, 3265 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a', 3266 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!', 3267 'i', 2, 'i', 'd', 'I', 0x71, 0x04, 3268 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00, 3269 }; 3270 CHECK(json::to_bjdata(j, true) == v); 3271 CHECK(json::from_bjdata(v) == j); 3272 } 3273 3274 SECTION("size=true type=true") 3275 { 3276 json j = 3277 { 3278 { 3279 "post", { 3280 {"id", 1137}, 3281 {"author", "rkalla"}, 3282 {"timestamp", 1364482090592}, 3283 {"body", "I totally agree!"} 3284 } 3285 } 3286 }; 3287 std::vector<uint8_t> v = {'{', '#', 'i', 1, 'i', 4, 'p', 'o', 's', 't', '{', '#', 'i', 4, 3288 'i', 6, 'a', 'u', 't', 'h', 'o', 'r', 'S', 'i', 6, 'r', 'k', 'a', 'l', 'l', 'a', 3289 'i', 4, 'b', 'o', 'd', 'y', 'S', 'i', 16, 'I', ' ', 't', 'o', 't', 'a', 'l', 'l', 'y', ' ', 'a', 'g', 'r', 'e', 'e', '!', 3290 'i', 2, 'i', 'd', 'I', 0x71, 0x04, 3291 'i', 9, 't', 'i', 'm', 'e', 's', 't', 'a', 'm', 'p', 'L', 0x60, 0x66, 0x78, 0xB1, 0x3D, 0x01, 0x00, 0x00, 3292 }; 3293 CHECK(json::to_bjdata(j, true, true) == v); 3294 CHECK(json::from_bjdata(v) == j); 3295 } 3296 } 3297 3298 SECTION("Optimized Format") 3299 { 3300 SECTION("Array Example") 3301 { 3302 SECTION("No Optimization") 3303 { 3304 // note the floats have been replaced by doubles 3305 json j = {29.97, 31.13, 67.0, 2.113, 23.888}; 3306 std::vector<uint8_t> v = {'[', 3307 'D', 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40, 3308 'D', 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40, 3309 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40, 3310 'D', 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40, 3311 'D', 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40, 3312 ']' 3313 }; 3314 CHECK(json::to_bjdata(j) == v); 3315 CHECK(json::from_bjdata(v) == j); 3316 } 3317 3318 SECTION("Optimized with count") 3319 { 3320 // note the floats have been replaced by doubles 3321 json j = {29.97, 31.13, 67.0, 2.113, 23.888}; 3322 std::vector<uint8_t> v = {'[', '#', 'i', 5, 3323 'D', 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40, 3324 'D', 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40, 3325 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40, 3326 'D', 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40, 3327 'D', 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40, 3328 }; 3329 CHECK(json::to_bjdata(j, true) == v); 3330 CHECK(json::from_bjdata(v) == j); 3331 } 3332 3333 SECTION("Optimized with type & count") 3334 { 3335 // note the floats have been replaced by doubles 3336 json j = {29.97, 31.13, 67.0, 2.113, 23.888}; 3337 std::vector<uint8_t> v = {'[', '$', 'D', '#', 'i', 5, 3338 0xb8, 0x1e, 0x85, 0xeb, 0x51, 0xf8, 0x3d, 0x40, 3339 0xe1, 0x7a, 0x14, 0xae, 0x47, 0x21, 0x3f, 0x40, 3340 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40, 3341 0x81, 0x95, 0x43, 0x8b, 0x6c, 0xe7, 0x00, 0x40, 3342 0x17, 0xd9, 0xce, 0xf7, 0x53, 0xe3, 0x37, 0x40, 3343 }; 3344 CHECK(json::to_bjdata(j, true, true) == v); 3345 CHECK(json::from_bjdata(v) == j); 3346 } 3347 } 3348 3349 SECTION("Object Example") 3350 { 3351 SECTION("No Optimization") 3352 { 3353 // note the floats have been replaced by doubles 3354 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} }; 3355 std::vector<uint8_t> v = {'{', 3356 'i', 3, 'a', 'l', 't', 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40, 3357 'i', 3, 'l', 'a', 't', 'D', 0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40, 3358 'i', 4, 'l', 'o', 'n', 'g', 'D', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40, 3359 '}' 3360 }; 3361 CHECK(json::to_bjdata(j) == v); 3362 CHECK(json::from_bjdata(v) == j); 3363 } 3364 3365 SECTION("Optimized with count") 3366 { 3367 // note the floats have been replaced by doubles 3368 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} }; 3369 std::vector<uint8_t> v = {'{', '#', 'i', 3, 3370 'i', 3, 'a', 'l', 't', 'D', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40, 3371 'i', 3, 'l', 'a', 't', 'D', 0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40, 3372 'i', 4, 'l', 'o', 'n', 'g', 'D', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40, 3373 }; 3374 CHECK(json::to_bjdata(j, true) == v); 3375 CHECK(json::from_bjdata(v) == j); 3376 } 3377 3378 SECTION("Optimized with type & count") 3379 { 3380 // note the floats have been replaced by doubles 3381 json j = { {"lat", 29.976}, {"long", 31.131}, {"alt", 67.0} }; 3382 std::vector<uint8_t> v = {'{', '$', 'D', '#', 'i', 3, 3383 'i', 3, 'a', 'l', 't', 0x00, 0x00, 0x00, 0x00, 0x00, 0xc0, 0x50, 0x40, 3384 'i', 3, 'l', 'a', 't', 0x60, 0xe5, 0xd0, 0x22, 0xdb, 0xf9, 0x3d, 0x40, 3385 'i', 4, 'l', 'o', 'n', 'g', 0xa8, 0xc6, 0x4b, 0x37, 0x89, 0x21, 0x3f, 0x40, 3386 }; 3387 CHECK(json::to_bjdata(j, true, true) == v); 3388 CHECK(json::from_bjdata(v) == j); 3389 } 3390 } 3391 3392 SECTION("Special Cases (Null, No-Op and Boolean)") 3393 { 3394 SECTION("Array") 3395 { 3396 json _; 3397 std::vector<uint8_t> v = {'[', '$', 'N', '#', 'I', 0x00, 0x02}; 3398 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x4E is not a permitted optimized array type", json::parse_error&); 3399 CHECK(json::from_bjdata(v, true, false).is_discarded()); 3400 } 3401 3402 SECTION("Object") 3403 { 3404 json _; 3405 std::vector<uint8_t> v = {'{', '$', 'Z', '#', 'i', 3, 'i', 4, 'n', 'a', 'm', 'e', 'i', 8, 'p', 'a', 's', 's', 'w', 'o', 'r', 'd', 'i', 5, 'e', 'm', 'a', 'i', 'l'}; 3406 CHECK_THROWS_WITH_AS(_ = json::from_bjdata(v), "[json.exception.parse_error.112] parse error at byte 3: syntax error while parsing BJData type: marker 0x5A is not a permitted optimized array type", json::parse_error&); 3407 CHECK(json::from_bjdata(v, true, false).is_discarded()); 3408 } 3409 } 3410 } 3411} 3412 3413#if !defined(JSON_NOEXCEPTION) 3414TEST_CASE("all BJData first bytes") 3415{ 3416 // these bytes will fail immediately with exception parse_error.112 3417 std::set<uint8_t> supported = 3418 { 3419 'T', 'F', 'Z', 'U', 'i', 'I', 'l', 'L', 'd', 'D', 'C', 'S', '[', '{', 'N', 'H', 'u', 'm', 'M', 'h' 3420 }; 3421 3422 for (auto i = 0; i < 256; ++i) 3423 { 3424 const auto byte = static_cast<uint8_t>(i); 3425 CAPTURE(byte) 3426 3427 try 3428 { 3429 auto res = json::from_bjdata(std::vector<uint8_t>(1, byte)); 3430 } 3431 catch (const json::parse_error& e) 3432 { 3433 // check that parse_error.112 is only thrown if the 3434 // first byte is not in the supported set 3435 INFO_WITH_TEMP(e.what()); 3436 if (supported.find(byte) == supported.end()) 3437 { 3438 CHECK(e.id == 112); 3439 } 3440 else 3441 { 3442 CHECK(e.id != 112); 3443 } 3444 } 3445 } 3446} 3447#endif 3448 3449TEST_CASE("BJData roundtrips" * doctest::skip()) 3450{ 3451 SECTION("input from self-generated BJData files") 3452 { 3453 for (std::string filename : 3454 { 3455 TEST_DATA_DIRECTORY "/json_nlohmann_tests/all_unicode.json", 3456 TEST_DATA_DIRECTORY "/json.org/1.json", 3457 TEST_DATA_DIRECTORY "/json.org/2.json", 3458 TEST_DATA_DIRECTORY "/json.org/3.json", 3459 TEST_DATA_DIRECTORY "/json.org/4.json", 3460 TEST_DATA_DIRECTORY "/json.org/5.json", 3461 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip01.json", 3462 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip02.json", 3463 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip03.json", 3464 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip04.json", 3465 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip05.json", 3466 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip06.json", 3467 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip07.json", 3468 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip08.json", 3469 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip09.json", 3470 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip10.json", 3471 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip11.json", 3472 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip12.json", 3473 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip13.json", 3474 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip14.json", 3475 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip15.json", 3476 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip16.json", 3477 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip17.json", 3478 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip18.json", 3479 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip19.json", 3480 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip20.json", 3481 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip21.json", 3482 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip22.json", 3483 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip23.json", 3484 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip24.json", 3485 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip25.json", 3486 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip26.json", 3487 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip27.json", 3488 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip28.json", 3489 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip29.json", 3490 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip30.json", 3491 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip31.json", 3492 TEST_DATA_DIRECTORY "/json_roundtrip/roundtrip32.json", 3493 TEST_DATA_DIRECTORY "/json_testsuite/sample.json", 3494 TEST_DATA_DIRECTORY "/json_tests/pass1.json", 3495 TEST_DATA_DIRECTORY "/json_tests/pass2.json", 3496 TEST_DATA_DIRECTORY "/json_tests/pass3.json" 3497 }) 3498 { 3499 CAPTURE(filename) 3500 3501 { 3502 INFO_WITH_TEMP(filename + ": std::vector<uint8_t>"); 3503 // parse JSON file 3504 std::ifstream f_json(filename); 3505 json j1 = json::parse(f_json); 3506 3507 // parse BJData file 3508 auto packed = utils::read_binary_file(filename + ".bjdata"); 3509 json j2; 3510 CHECK_NOTHROW(j2 = json::from_bjdata(packed)); 3511 3512 // compare parsed JSON values 3513 CHECK(j1 == j2); 3514 } 3515 3516 { 3517 INFO_WITH_TEMP(filename + ": std::ifstream"); 3518 // parse JSON file 3519 std::ifstream f_json(filename); 3520 json j1 = json::parse(f_json); 3521 3522 // parse BJData file 3523 std::ifstream f_bjdata(filename + ".bjdata", std::ios::binary); 3524 json j2; 3525 CHECK_NOTHROW(j2 = json::from_bjdata(f_bjdata)); 3526 3527 // compare parsed JSON values 3528 CHECK(j1 == j2); 3529 } 3530 3531 { 3532 INFO_WITH_TEMP(filename + ": output to output adapters"); 3533 // parse JSON file 3534 std::ifstream f_json(filename); 3535 json j1 = json::parse(f_json); 3536 3537 // parse BJData file 3538 auto packed = utils::read_binary_file(filename + ".bjdata"); 3539 3540 { 3541 INFO_WITH_TEMP(filename + ": output adapters: std::vector<uint8_t>"); 3542 std::vector<uint8_t> vec; 3543 json::to_bjdata(j1, vec); 3544 CHECK(vec == packed); 3545 } 3546 } 3547 } 3548 } 3549} 3550