mirror of
https://github.com/nlohmann/json.git
synced 2026-10-17 03:28:12 +00:00
Test parse_float_native() at the guard page
parse_float_eisel_lemire() was removed by #5738, so the test no longer compiled. The lexer converts floats from its token buffer, so the JSON section never places a float token at the page boundary; the section now calls parse_float_native() for float and double on every complete number token directly and compares the result bit for bit with converting the same token from a std::string. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
1 file changed
+35
-8
@@ -309,6 +309,23 @@ void check_binary(guarded_buffer& guard, const std::vector<std::uint8_t>& bytes,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// parse_float_native() at both ends of the guarded page, compared bit for bit
|
||||||
|
// with converting the same token from a std::string
|
||||||
|
template<typename FloatType>
|
||||||
|
void check_float_native(guarded_buffer& guard, const std::string& token)
|
||||||
|
{
|
||||||
|
const std::size_t decimal_point = token.find('.');
|
||||||
|
const std::size_t exponent = token.find_first_of("eE");
|
||||||
|
const std::size_t mantissa_end = exponent == std::string::npos ? token.size() : exponent;
|
||||||
|
const FloatType expected = nlohmann::detail::parse_float_native<FloatType>(token.data(), token.data() + token.size(), decimal_point, mantissa_end);
|
||||||
|
for (int placement = 0; placement < 2; ++placement)
|
||||||
|
{
|
||||||
|
const char* const first = reinterpret_cast<const char*>(placement == 0 ? guard.at_end(token) : guard.at_start(token));
|
||||||
|
const FloatType value = nlohmann::detail::parse_float_native<FloatType>(first, first + token.size(), decimal_point, mantissa_end);
|
||||||
|
CHECK(std::memcmp(&value, &expected, sizeof(value)) == 0);
|
||||||
|
}
|
||||||
|
}
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
TEST_CASE("guard page")
|
TEST_CASE("guard page")
|
||||||
@@ -371,22 +388,32 @@ TEST_CASE("guard page")
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SECTION("Eisel-Lemire")
|
SECTION("float conversion")
|
||||||
{
|
{
|
||||||
const std::vector<std::string> numbers = all_prefixes(
|
// the lexer converts floats from its token buffer, so the JSON section
|
||||||
|
// below never places a float token at the page boundary; this calls the
|
||||||
|
// conversion directly: the 8-digit loops of parse_float_significand()
|
||||||
|
// and digit_comparison() read up to the end of the token
|
||||||
|
const std::vector<std::string> tokens = all_prefixes(
|
||||||
{
|
{
|
||||||
"1234567812345678123456781234567812345678",
|
"1234567812345678123456781234567812345678",
|
||||||
"-1.2345678901234567890123456789e-123",
|
"-1.2345678901234567890123456789e-123",
|
||||||
"0.00000000000000000000000000000000000001",
|
"0.00000000000000000000000000000000000001",
|
||||||
"98765432.10987654",
|
"98765432.10987654",
|
||||||
|
"123456789012345678901234567890e-30",
|
||||||
|
// halfway between 1 and the next double, then just above it
|
||||||
|
"1.00000000000000011102230246251565404236316680908203125",
|
||||||
|
"1.000000000000000111022302462515654042363166809082031250000000001",
|
||||||
});
|
});
|
||||||
for (const auto& number : numbers)
|
for (const auto& token : tokens)
|
||||||
{
|
{
|
||||||
double out = 0;
|
// only complete number tokens: the conversion expects validated input
|
||||||
const char* const end = reinterpret_cast<const char*>(guard.at_end(number));
|
if (!token.empty() && json::accept(token))
|
||||||
static_cast<void>(nlohmann::detail::parse_float_eisel_lemire(end, end + number.size(), out));
|
{
|
||||||
const char* const start = reinterpret_cast<const char*>(guard.at_start(number));
|
CAPTURE(token)
|
||||||
static_cast<void>(nlohmann::detail::parse_float_eisel_lemire(start, start + number.size(), out));
|
check_float_native<double>(guard, token);
|
||||||
|
check_float_native<float>(guard, token);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in new issue
Block a user