diff --git a/Makefile b/Makefile index 6756182e..d4b3336f 100644 --- a/Makefile +++ b/Makefile @@ -79,7 +79,7 @@ coverage: mkdir build_coverage cd build_coverage ; CXX=g++-5 cmake .. -GNinja -DJSON_Coverage=ON cd build_coverage ; ninja - cd build_coverage ; ctest + cd build_coverage ; ctest -j10 cd build_coverage ; ninja lcov_html open build_coverage/test/html/index.html diff --git a/develop/detail/parsing/binary_writer.hpp b/develop/detail/parsing/binary_writer.hpp index 1d2cf601..7bf894f6 100644 --- a/develop/detail/parsing/binary_writer.hpp +++ b/develop/detail/parsing/binary_writer.hpp @@ -813,7 +813,16 @@ class binary_writer } } - char ubjson_prefix(const BasicJsonType& j) + /*! + @brief determine the type prefix of container values + + @note This function does not need to be 100% accurate when it comes to + integer limits. In case a number exceeds the limits of int64_t, + this will be detected by a later call to function + write_number_with_ubjson_prefix. Therefore, we return 'L' for any + value that does not fit the previous limits. + */ + char ubjson_prefix(const BasicJsonType& j) const noexcept { switch (j.type()) { @@ -841,11 +850,10 @@ class binary_writer { return 'l'; } - else if ((std::numeric_limits::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits::max)()) + else // no check and assume int64_t (see note above) { return 'L'; } - break; } case value_t::number_unsigned: @@ -866,11 +874,10 @@ class binary_writer { return 'l'; } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else // no check and assume int64_t (see note above) { return 'L'; } - break; } case value_t::number_float: @@ -885,11 +892,9 @@ class binary_writer case value_t::object: return '{'; - default: - break; + default: // discarded values + return 'N'; } - - return '\0'; } private: diff --git a/src/json.hpp b/src/json.hpp index 9644eed6..731feb95 100644 --- a/src/json.hpp +++ b/src/json.hpp @@ -6965,7 +6965,16 @@ class binary_writer } } - char ubjson_prefix(const BasicJsonType& j) + /*! + @brief determine the type prefix of container values + + @note This function does not need to be 100% accurate when it comes to + integer limits. In case a number exceeds the limits of int64_t, + this will be detected by a later call to function + write_number_with_ubjson_prefix. Therefore, we return 'L' for any + value that does not fit the previous limits. + */ + char ubjson_prefix(const BasicJsonType& j) const noexcept { switch (j.type()) { @@ -6993,11 +7002,10 @@ class binary_writer { return 'l'; } - else if ((std::numeric_limits::min)() <= j.m_value.number_integer and j.m_value.number_integer <= (std::numeric_limits::max)()) + else // no check and assume int64_t (see note above) { return 'L'; } - break; } case value_t::number_unsigned: @@ -7018,11 +7026,10 @@ class binary_writer { return 'l'; } - else if (j.m_value.number_unsigned <= (std::numeric_limits::max)()) + else // no check and assume int64_t (see note above) { return 'L'; } - break; } case value_t::number_float: @@ -7037,11 +7044,9 @@ class binary_writer case value_t::object: return '{'; - default: - break; + default: // discarded values + return 'N'; } - - return '\0'; } private: diff --git a/test/src/unit-ubjson.cpp b/test/src/unit-ubjson.cpp index d7b7cde1..20c846cb 100644 --- a/test/src/unit-ubjson.cpp +++ b/test/src/unit-ubjson.cpp @@ -1386,8 +1386,8 @@ TEST_CASE("UBJSON") { SECTION("array of i") { - json j = {1, 2}; - std::vector expected = {'[', '$', 'i', '#', 'i', 2, 1, 2}; + json j = {1, -1}; + std::vector expected = {'[', '$', 'i', '#', 'i', 2, 1, 0xff}; CHECK(json::to_ubjson(j, true, true) == expected); } @@ -1400,22 +1400,22 @@ TEST_CASE("UBJSON") SECTION("array of I") { - json j = {30000, 30001}; - std::vector expected = {'[', '$', 'I', '#', 'i', 2, 0x75, 0x30, 0x75, 0x31}; + json j = {30000, -30000}; + std::vector expected = {'[', '$', 'I', '#', 'i', 2, 0x75, 0x30, 0x8a, 0xd0}; CHECK(json::to_ubjson(j, true, true) == expected); } SECTION("array of l") { - json j = {70000, 70001}; - std::vector expected = {'[', '$', 'l', '#', 'i', 2, 0x00, 0x01, 0x11, 0x70, 0x00, 0x01, 0x11, 0x71}; + json j = {70000, -70000}; + std::vector expected = {'[', '$', 'l', '#', 'i', 2, 0x00, 0x01, 0x11, 0x70, 0xFF, 0xFE, 0xEE, 0x90}; CHECK(json::to_ubjson(j, true, true) == expected); } SECTION("array of L") { - json j = {5000000000, 5000000001}; - std::vector expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x01}; + json j = {5000000000, -5000000000}; + std::vector expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 0xFF, 0xFF, 0xFF, 0xFE, 0xD5, 0xFA, 0x0E, 0x00}; CHECK(json::to_ubjson(j, true, true) == expected); } } @@ -1426,37 +1426,54 @@ TEST_CASE("UBJSON") { json j = {1u, 2u}; std::vector expected = {'[', '$', 'i', '#', 'i', 2, 1, 2}; + std::vector expected_size = {'[', '#', 'i', 2, 'i', 1, 'i', 2}; CHECK(json::to_ubjson(j, true, true) == expected); + CHECK(json::to_ubjson(j, true) == expected_size); } SECTION("array of U") { json j = {200u, 201u}; std::vector expected = {'[', '$', 'U', '#', 'i', 2, 0xC8, 0xC9}; + std::vector expected_size = {'[', '#', 'i', 2, 'U', 0xC8, 'U', 0xC9}; CHECK(json::to_ubjson(j, true, true) == expected); + CHECK(json::to_ubjson(j, true) == expected_size); } SECTION("array of I") { json j = {30000u, 30001u}; std::vector expected = {'[', '$', 'I', '#', 'i', 2, 0x75, 0x30, 0x75, 0x31}; + std::vector expected_size = {'[', '#', 'i', 2, 'I', 0x75, 0x30, 'I', 0x75, 0x31}; CHECK(json::to_ubjson(j, true, true) == expected); + CHECK(json::to_ubjson(j, true) == expected_size); } SECTION("array of l") { json j = {70000u, 70001u}; std::vector expected = {'[', '$', 'l', '#', 'i', 2, 0x00, 0x01, 0x11, 0x70, 0x00, 0x01, 0x11, 0x71}; + std::vector expected_size = {'[', '#', 'i', 2, 'l', 0x00, 0x01, 0x11, 0x70, 'l', 0x00, 0x01, 0x11, 0x71}; CHECK(json::to_ubjson(j, true, true) == expected); + CHECK(json::to_ubjson(j, true) == expected_size); } SECTION("array of L") { json j = {5000000000u, 5000000001u}; std::vector expected = {'[', '$', 'L', '#', 'i', 2, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x01}; + std::vector expected_size = {'[', '#', 'i', 2, 'L', 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x00, 'L', 0x00, 0x00, 0x00, 0x01, 0x2A, 0x05, 0xF2, 0x01}; CHECK(json::to_ubjson(j, true, true) == expected); + CHECK(json::to_ubjson(j, true) == expected_size); } } + + SECTION("discarded") + { + json j = {json::value_t::discarded, json::value_t::discarded}; + std::vector expected = {'[', '$', 'N', '#', 'i', 2}; + CHECK(json::to_ubjson(j, true, true) == expected); + } } }