accept(): skip digits without computing their value
accept() needs the value of a number only for a float whose exponent may reach the largest value. skip_digits() finds the end of the digits without the multiply-adds of accumulate_digits(), and once an 8-byte word fails the digit test, the remaining loop needs no bounds check: a non-digit is in that word. The value is computed afterwards for the rare floats that need it. accept() of canada.json: -16 % on Apple M1, -22 % with GCC 15 and -21 % with Clang 21 on x86-64; files with many numbers -9 to -15 %. Signed-off-by: Niels Lohmann <mail@nlohmann.me>
This commit is contained in:
4 files changed
+103
-4
No files matched your search
@@ -518,6 +518,33 @@ TEST_CASE("contiguous parser")
|
||||
}
|
||||
}
|
||||
|
||||
SECTION("accept() of floats near the largest value")
|
||||
{
|
||||
// accept() skips digits without their value and computes it only for
|
||||
// a float whose exponent may reach the largest value
|
||||
for (const char* number :
|
||||
{"17976931348623158e292", "17976931348623159e292", "1797693134862315.8e293", "1797693134862315.9e293",
|
||||
"0.17976931348623158e309", "0.17976931348623159e309", "-17976931348623159e292", "9999999999999999999e289"
|
||||
})
|
||||
{
|
||||
check_both(number);
|
||||
check_both(std::string("[") + number + "]");
|
||||
}
|
||||
CHECK(json::accept("17976931348623158e292"));
|
||||
CHECK_FALSE(json::accept("17976931348623159e292"));
|
||||
CHECK(json::accept("[1797693134862315.8e293]"));
|
||||
CHECK_FALSE(json::accept("[1797693134862315.9e293]"));
|
||||
CHECK(json::accept("0.17976931348623158e309"));
|
||||
CHECK_FALSE(json::accept("0.17976931348623159e309"));
|
||||
CHECK_FALSE(json::accept("-17976931348623159e292"));
|
||||
|
||||
using narrow_json = nlohmann::basic_json<std::map, std::vector, std::string, bool, std::int32_t, std::uint32_t, float>;
|
||||
check_same<narrow_json>("34028235e31");
|
||||
check_same<narrow_json>("34028236e31");
|
||||
CHECK(narrow_json::accept("34028235e31"));
|
||||
CHECK_FALSE(narrow_json::accept("34028236e31"));
|
||||
}
|
||||
|
||||
SECTION("callbacks, comments and trailing commas take the library parser")
|
||||
{
|
||||
// (the results are those of the options; the contiguous parser does not support them)
|
||||
|
||||
Reference in new issue
Block a user