diff --git a/src/json.hpp b/src/json.hpp index fbab3fc6..436c91be 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -7085,25 +7085,25 @@ class basic_json { idx += 1; // skip content byte // must be uint8_t ! - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } case 0x39: // Negative integer -1-n (two-byte uint16_t follows) { idx += 2; // skip 2 content bytes - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) { idx += 4; // skip 4 content bytes - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) { idx += 8; // skip 8 content bytes - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } // UTF-8 string (0x00..0x17 bytes follow) diff --git a/src/json.hpp.re2c b/src/json.hpp.re2c index e6c74fcc..c3f85dcd 100644 --- a/src/json.hpp.re2c +++ b/src/json.hpp.re2c @@ -7085,25 +7085,25 @@ class basic_json { idx += 1; // skip content byte // must be uint8_t ! - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } case 0x39: // Negative integer -1-n (two-byte uint16_t follows) { idx += 2; // skip 2 content bytes - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } case 0x3a: // Negative integer -1-n (four-byte uint32_t follows) { idx += 4; // skip 4 content bytes - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } case 0x3b: // Negative integer -1-n (eight-byte uint64_t follows) { idx += 8; // skip 8 content bytes - return -1 - get_from_vector(v, current_idx); + return static_cast(-1) - get_from_vector(v, current_idx); } // UTF-8 string (0x00..0x17 bytes follow) diff --git a/test/src/unit-cbor.cpp b/test/src/unit-cbor.cpp index 28b0ecad..9c5f76e7 100644 --- a/test/src/unit-cbor.cpp +++ b/test/src/unit-cbor.cpp @@ -85,9 +85,117 @@ TEST_CASE("CBOR") { SECTION("signed") { - SECTION("-65535..-257") + SECTION("-9223372036854775808..-4294967297") { - for (int16_t i = -65535; i <= -257; ++i) + std::vector numbers; + numbers.push_back(INT64_MIN); + numbers.push_back(-1000000000000000000); + numbers.push_back(-100000000000000000); + numbers.push_back(-10000000000000000); + numbers.push_back(-1000000000000000); + numbers.push_back(-100000000000000); + numbers.push_back(-10000000000000); + numbers.push_back(-1000000000000); + numbers.push_back(-100000000000); + numbers.push_back(-10000000000); + numbers.push_back(-4294967297); + for (auto i : numbers) + { + CAPTURE(i); + + // create JSON value with integer number + json j = i; + + // check type + CHECK(j.is_number_integer()); + + // create expected byte vector + std::vector expected; + expected.push_back(static_cast(0x3b)); + uint64_t positive = static_cast(-1 - i); + expected.push_back(static_cast((positive >> 56) & 0xff)); + expected.push_back(static_cast((positive >> 48) & 0xff)); + expected.push_back(static_cast((positive >> 40) & 0xff)); + expected.push_back(static_cast((positive >> 32) & 0xff)); + expected.push_back(static_cast((positive >> 24) & 0xff)); + expected.push_back(static_cast((positive >> 16) & 0xff)); + expected.push_back(static_cast((positive >> 8) & 0xff)); + expected.push_back(static_cast(positive & 0xff)); + + // compare result + size + const auto result = json::to_cbor(j); + CHECK(result == expected); + CHECK(result.size() == 9); + + // check individual bytes + CHECK(result[0] == 0x3b); + uint64_t restored = static_cast((static_cast(result[1]) << 070) + + (static_cast(result[2]) << 060) + + (static_cast(result[3]) << 050) + + (static_cast(result[4]) << 040) + + (static_cast(result[5]) << 030) + + (static_cast(result[6]) << 020) + + (static_cast(result[7]) << 010) + + static_cast(result[8])); + CHECK(restored == positive); + CHECK(-1 - restored == i); + + // roundtrip + CHECK(json::from_cbor(result) == j); + } + } + + SECTION("-4294967296..-65537") + { + std::vector numbers; + numbers.push_back(-65537); + numbers.push_back(-100000); + numbers.push_back(-1000000); + numbers.push_back(-10000000); + numbers.push_back(-100000000); + numbers.push_back(-1000000000); + numbers.push_back(-4294967296); + for (auto i : numbers) + { + CAPTURE(i); + + // create JSON value with integer number + json j = i; + + // check type + CHECK(j.is_number_integer()); + + // create expected byte vector + std::vector expected; + expected.push_back(static_cast(0x3a)); + uint32_t positive = static_cast(static_cast(-1 - i) & 0x00000000ffffffff); + expected.push_back(static_cast((positive >> 24) & 0xff)); + expected.push_back(static_cast((positive >> 16) & 0xff)); + expected.push_back(static_cast((positive >> 8) & 0xff)); + expected.push_back(static_cast(positive & 0xff)); + + // compare result + size + const auto result = json::to_cbor(j); + CHECK(result == expected); + CHECK(result.size() == 5); + + // check individual bytes + CHECK(result[0] == 0x3a); + uint32_t restored = static_cast((static_cast(result[1]) << 030) + + (static_cast(result[2]) << 020) + + (static_cast(result[3]) << 010) + + static_cast(result[4])); + CHECK(restored == positive); + CHECK(-1ll - restored == i); + + // roundtrip + CHECK(json::from_cbor(result) == j); + } + } + + SECTION("-65536..-257") + { + for (int32_t i = -65536; i <= -257; ++i) { CAPTURE(i);