Compare commits

..
9 Commits
Author SHA1 Message Date
Niels Lohmann b8fd578873 Address review: std::any_of in has_nonzero_digit, comment punctuation
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 19:06:19 +02:00
Niels Lohmann 711093e7af Drop the position updates in the bulk \u path, which #5809 made unused
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:27:03 +02:00
Niels Lohmann 7074088d4f Regenerate the amalgamated headers
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:45 +02:00
Niels Lohmann 394058b752 Mark the unsigned long of the MSVC bit scans for cpplint
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:31 +02:00
Niels Lohmann 551a7f2a23 Fix clang-tidy 22 findings in unit-class_lexer.cpp
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:30 +02:00
Niels Lohmann 97b07d6f15 Reword float conversion notes for the string type and number_float_t docs
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:29 +02:00
Niels Lohmann e4449fd3f0 Load string scan words with memcpy and use MSVC bit-scan intrinsics
Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:29 +02:00
Niels Lohmann 5fddf930db Fix CI warnings in own float parser
- pow5_table.hpp: pow5_128_largest_power was unused in this branch's
  own code (GCC -Werror=unused-const-variable); tie it to the table
  size with a static_assert instead of removing it, since a later
  branch in the stack (json-view/23-zmij) uses it.
- number_parse.hpp: rename the local variable `copy` to `buffer` to
  satisfy cpplint's build/include_what_you_use check.
- unit-class_lexer.cpp: extend the NOLINT list on the seeded mt19937
  with bugprone-random-generator-seed, and parenthesize
  `8 * sizeof(Bits) - 1` for clang-tidy.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:28 +02:00
Niels Lohmann 6a023f469c Speed up the lexer: own float parser, string scan, and \u table
Give the library its own correctly rounded float converter for
binary32 and binary64 (IEEE 754), and speed up the lexer's string
and escape scanning.

The converter splits a number token into sign, significand, and
decimal exponent, then tries Clinger's fast path, then a templated
Eisel-Lemire step, and falls back to an exact big-integer digit
comparison for tokens with more than 19 significant digits whose two
candidate values round differently. This replaces std::from_chars
and strtod/strtof for both formats, so parsed values no longer
depend on the C/C++ library or the current locale. The strtold
fallback kept for other long double formats (x87, binary128) now
also copies a multi-byte decimal point correctly, fixing #5660.
eisel_lemire() and decimal_to_float() are always inlined so callers
keep the whole conversion in their hot loop.

The string-scanning kernels in string_scan.hpp find a stop byte with
the trailing-zero count of the SWAR mask instead of a byte loop, and
scalar_string_bulk_run() validates a run of multi-byte UTF-8
sequences one after another instead of re-searching after each one.

get_codepoint() decodes a contiguous \uXXXX escape with one table
lookup per byte instead of four range-checked get() calls; the
streaming path and all error positions are unchanged.

Adds 508 generated hard float-parsing cases with expected binary32
and binary64 bits, and kernel-comparison tests for the string scans
and the escape table against byte-by-byte references.

Signed-off-by: Niels Lohmann <mail@nlohmann.me>
2026-10-13 17:26:27 +02:00
6 changed files with 24 additions and 16 deletions

No files matched your search

@@ -11,10 +11,12 @@ template<typename ScalarType>
bool operator==(ScalarType lhs, const const_reference rhs) noexcept(/* see below */); // (2)
// since C++20
bool operator==(const_reference rhs) const noexcept; // (1)
class basic_json {
bool operator==(const_reference rhs) const noexcept; // (1)
template<typename ScalarType>
bool operator==(ScalarType rhs) const noexcept(/* see below */); // (2)
template<typename ScalarType>
bool operator==(ScalarType rhs) const noexcept(/* see below */); // (2)
};
```
1. Compares two JSON values for equality according to the following rules:
@@ -2,10 +2,12 @@
```cpp
// since C++20
std::partial_ordering operator<=>(const_reference rhs) const noexcept; // (1)
class basic_json {
std::partial_ordering operator<=>(const_reference rhs) const noexcept; // (1)
template<typename ScalarType>
std::partial_ordering operator<=>(const ScalarType rhs) const noexcept(/* see below */); // (2)
template<typename ScalarType>
std::partial_ordering operator<=>(const ScalarType rhs) const noexcept(/* see below */); // (2)
};
```
1. 3-way compares two JSON values producing a result of type `std::partial_ordering` according to the following rules:
@@ -18,11 +18,13 @@ bool operator==(
const json_pointer<RefStringTypeRhs>& rhs); // (2)
// since C++20
template<typename RefStringTypeRhs>
bool operator==(
const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // (1)
class json_pointer {
template<typename RefStringTypeRhs>
bool operator==(
const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // (1)
bool operator==(const string_t& rhs) const; // (2)
bool operator==(const string_t& rhs) const; // (2)
};
```
1. Compares two JSON pointers for equality by comparing their reference tokens.
@@ -2,8 +2,10 @@
```cpp
// since C++20
template<typename RefStringTypeRhs>
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // *NOPAD*
class json_pointer {
template<typename RefStringTypeRhs>
std::strong_ordering operator<=>(const json_pointer<RefStringTypeRhs>& rhs) const noexcept; // *NOPAD*
};
```
3-way compares two JSON pointers by lexicographically comparing their sequences of reference tokens: corresponding
@@ -986,8 +986,8 @@ void convert_float_locale_aware(StringType& token, std::size_t decimal_point_pos
{
std::string buffer(token.data(), token.size());
buffer.replace(decimal_point_position, 1, decimal_point);
strtof_by_type(value, buffer.data(), &endptr);
complete = endptr == buffer.data() + buffer.size();
strtof_by_type(value, buffer.c_str(), &endptr);
complete = endptr == buffer.c_str() + buffer.size();
}
if (JSON_HEDLEY_LIKELY(complete))
+2 -2
View File
@@ -10432,8 +10432,8 @@ void convert_float_locale_aware(StringType& token, std::size_t decimal_point_pos
{
std::string buffer(token.data(), token.size());
buffer.replace(decimal_point_position, 1, decimal_point);
strtof_by_type(value, buffer.data(), &endptr);
complete = endptr == buffer.data() + buffer.size();
strtof_by_type(value, buffer.c_str(), &endptr);
complete = endptr == buffer.c_str() + buffer.size();
}
if (JSON_HEDLEY_LIKELY(complete))