diff --git a/include/nlohmann/detail/input/binary_reader.hpp b/include/nlohmann/detail/input/binary_reader.hpp index cd7e58946..fa6eeffc0 100644 --- a/include/nlohmann/detail/input/binary_reader.hpp +++ b/include/nlohmann/detail/input/binary_reader.hpp @@ -12,6 +12,7 @@ #include // char_traits, string #include // make_pair, move #include // vector +#include // map #include #include @@ -2111,15 +2112,15 @@ class binary_reader { return false; } - if (dim.size() == 1 || (dim.size() > 1 && dim.at(0) == 1)) // return normal array size if 1D vector + if (dim.size() == 1 || (dim.size() > 1 && dim.at(0) == 1)) // return normal array size if 1D row vector { result = dim.at(dim.size() - 1); return true; } - if (!dim.empty()) // if ndarray, convert to a object in JData annotated array format + if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format { string_t key = "_ArraySize_"; - if (JSON_HEDLEY_UNLIKELY((!sax->start_object(static_cast(-1)) || !sax->key(key) || !sax->start_array(dim.size())))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) { return false; } @@ -2127,12 +2128,12 @@ class binary_reader for (auto i : dim) { result *= i; - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(i))) + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(static_cast(i)))) { return false; } } - result |= 0x8000000000000000ull; // low 63 bit of result stores the total element count, sign-bit indicates ndarray + result |= (1ull << (sizeof(result) * 8 - 1)); // low 63 bit of result stores the total element count, sign-bit indicates ndarray return sax->end_array(); } result = 0; @@ -2402,14 +2403,14 @@ class binary_reader // detect and encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} - if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && size_and_type.first >= 0x8000000000000000ull) + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && size_and_type.first >= (1ull << (sizeof(std::size_t) * 8 - 1))) { std::map bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"}, {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"} }; string_t key = "_ArrayType_"; - if (JSON_HEDLEY_UNLIKELY(bjdtype.find(size_and_type.second) == bjdtype.end() || !sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) + if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0 || !sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) { return false; } @@ -2419,7 +2420,7 @@ class binary_reader size_and_type.second = 'U'; } - size_and_type.first -= 0x8000000000000000ull; + size_and_type.first &= ~(1ull << (sizeof(std::size_t) * 8 - 1)); key = "_ArrayData_"; if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) { diff --git a/include/nlohmann/detail/output/binary_writer.hpp b/include/nlohmann/detail/output/binary_writer.hpp index 9e45cb3de..f80b9418e 100644 --- a/include/nlohmann/detail/output/binary_writer.hpp +++ b/include/nlohmann/detail/output/binary_writer.hpp @@ -2,6 +2,7 @@ #include // reverse #include // array +#include // map #include // isnan, isinf #include // uint8_t, uint16_t, uint32_t, uint64_t #include // memcpy @@ -1618,7 +1619,7 @@ class binary_writer std::size_t len = (value.at(key).empty() ? 0 : 1); for (const auto& el : value.at(key)) { - len *= el.m_value.number_unsigned; + len *= static_cast(el.m_value.number_unsigned); } key = "_ArrayData_"; diff --git a/single_include/nlohmann/json.hpp b/single_include/nlohmann/json.hpp index e03c8a58d..e9885148b 100644 --- a/single_include/nlohmann/json.hpp +++ b/single_include/nlohmann/json.hpp @@ -5402,6 +5402,7 @@ std::size_t hash(const BasicJsonType& j) #include // char_traits, string #include // make_pair, move #include // vector +#include // map // #include @@ -10487,15 +10488,15 @@ class binary_reader { return false; } - if (dim.size() == 1 || (dim.size() > 1 && dim.at(0) == 1)) // return normal array size if 1D vector + if (dim.size() == 1 || (dim.size() > 1 && dim.at(0) == 1)) // return normal array size if 1D row vector { result = dim.at(dim.size() - 1); return true; } - if (!dim.empty()) // if ndarray, convert to a object in JData annotated array format + if (!dim.empty()) // if ndarray, convert to an object in JData annotated array format { string_t key = "_ArraySize_"; - if (JSON_HEDLEY_UNLIKELY((!sax->start_object(static_cast(-1)) || !sax->key(key) || !sax->start_array(dim.size())))) + if (JSON_HEDLEY_UNLIKELY(!sax->start_object(3) || !sax->key(key) || !sax->start_array(dim.size()))) { return false; } @@ -10503,12 +10504,12 @@ class binary_reader for (auto i : dim) { result *= i; - if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(i))) + if (JSON_HEDLEY_UNLIKELY(!sax->number_integer(static_cast(i)))) { return false; } } - result |= 0x8000000000000000ull; // low 63 bit of result stores the total element count, sign-bit indicates ndarray + result |= (1ull << (sizeof(result) * 8 - 1)); // low 63 bit of result stores the total element count, sign-bit indicates ndarray return sax->end_array(); } result = 0; @@ -10778,14 +10779,14 @@ class binary_reader // detect and encode bjdata ndarray as an object in JData annotated array format (https://github.com/NeuroJSON/jdata): // {"_ArrayType_" : "typeid", "_ArraySize_" : [n1, n2, ...], "_ArrayData_" : [v1, v2, ...]} - if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && size_and_type.first >= 0x8000000000000000ull) + if (input_format == input_format_t::bjdata && size_and_type.first != string_t::npos && size_and_type.first >= (1ull << (sizeof(std::size_t) * 8 - 1))) { std::map bjdtype = {{'U', "uint8"}, {'i', "int8"}, {'u', "uint16"}, {'I', "int16"}, {'m', "uint32"}, {'l', "int32"}, {'M', "uint64"}, {'L', "int64"}, {'d', "single"}, {'D', "double"}, {'C', "char"} }; string_t key = "_ArrayType_"; - if (JSON_HEDLEY_UNLIKELY(bjdtype.find(size_and_type.second) == bjdtype.end() || !sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) + if (JSON_HEDLEY_UNLIKELY(bjdtype.count(size_and_type.second) == 0 || !sax->key(key) || !sax->string(bjdtype[size_and_type.second]) )) { return false; } @@ -10795,7 +10796,7 @@ class binary_reader size_and_type.second = 'U'; } - size_and_type.first -= 0x8000000000000000ull; + size_and_type.first &= ~(1ull << (sizeof(std::size_t) * 8 - 1)); key = "_ArrayData_"; if (JSON_HEDLEY_UNLIKELY(!sax->key(key) || !sax->start_array(size_and_type.first) )) { @@ -13754,6 +13755,7 @@ class json_ref #include // reverse #include // array +#include // map #include // isnan, isinf #include // uint8_t, uint16_t, uint32_t, uint64_t #include // memcpy @@ -15513,7 +15515,7 @@ class binary_writer std::size_t len = (value.at(key).empty() ? 0 : 1); for (const auto& el : value.at(key)) { - len *= el.m_value.number_unsigned; + len *= static_cast(el.m_value.number_unsigned); } key = "_ArrayData_"; diff --git a/test/src/unit-bjdata.cpp b/test/src/unit-bjdata.cpp index de7a224fb..e8477b268 100644 --- a/test/src/unit-bjdata.cpp +++ b/test/src/unit-bjdata.cpp @@ -2409,6 +2409,7 @@ TEST_CASE("BJData") std::vector v_T = {'[', '$', 'T', '#', '[', 'i', 1, 'i', 2, ']'}; std::vector v_F = {'[', '$', 'F', '#', '[', 'i', 1, 'i', 2, ']'}; std::vector v_Z = {'[', '$', 'Z', '#', '[', 'i', 1, 'i', 2, ']'}; + std::vector v_0 = {'[', '$', 'i', '#', '[', ']'}; std::vector v_i = {'[', '$', 'i', '#', '[', 'i', 1, 'i', 2, ']', 0x7F, 0x7F}; std::vector v_U = {'[', '$', 'U', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0xFF}; std::vector v_I = {'[', '$', 'I', '#', '[', 'i', 1, 'i', 2, ']', 0xFF, 0x7F, 0xFF, 0x7F}; @@ -2426,6 +2427,7 @@ TEST_CASE("BJData") CHECK(json::from_bjdata(v_T) == json({true, true})); CHECK(json::from_bjdata(v_F) == json({false, false})); CHECK(json::from_bjdata(v_Z) == json({nullptr, nullptr})); + CHECK(json::from_bjdata(v_0) == json::array()); CHECK(json::from_bjdata(v_i) == json({127, 127})); CHECK(json::from_bjdata(v_U) == json({255, 255})); CHECK(json::from_bjdata(v_I) == json({32767, 32767})); @@ -2744,6 +2746,11 @@ TEST_CASE("BJData") CHECK_THROWS_AS(_ = json::from_bjdata(vM), json::parse_error&); CHECK_THROWS_WITH(_ = json::from_bjdata(vM), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input"); CHECK(json::from_bjdata(vM, true, false).is_discarded()); + + std::vector vU = {'[', '$', 'U', '#', '[', '$', 'i', '#', 'i', 2, 2, 3, 1, 2, 3, 4, 5}; + CHECK_THROWS_AS(_ = json::from_bjdata(vU), json::parse_error&); + CHECK_THROWS_WITH(_ = json::from_bjdata(vU), "[json.exception.parse_error.110] parse error at byte 18: syntax error while parsing BJData number: unexpected end of input"); + CHECK(json::from_bjdata(vU, true, false).is_discarded()); } SECTION("objects")