Re-implements the optional digit-separator and base-prefix parsing
(originally PR #369) on top of the current store_spans hot-path
architecture, with the goal of zero overhead when the features are not
used.
Key changes vs. the original PR:
- has_separator is now a *compile-time* template parameter on
parse_number_string, dispatched once (from_chars_advanced ->
parse_number_string_options) based on options.digit_separator. The
has_separator==false instantiation that every default caller uses is
byte-for-byte the separator-free parser: no separator comparison ever
enters a digit loop and the SIMD eight-digit fast path is preserved.
The separator-aware code lives only in the cold true instantiation.
- The store_spans no-span hot path (added to main after the original PR
was branched) is preserved.
- parse_options_t fields are ordered so the two new single-byte fields
(digit_separator, format_options) fall into the existing padding for
UC == char. sizeof(parse_options_t<char>) stays 16 bytes, so the
struct is still register-passed and the call boundary is unchanged.
Result: for the default (no separator, no prefix) path, the generated
assembly of from_chars<double> is identical to main, and benchmarks show
no measurable regression (the original PR was 5-10% slower).
Adds basictest coverage for digit separators (including the >19-digit
overflow re-scan paths) and prefix skipping.
manually checked modified files for errors, but not committing .clang-format due to the following warning:
>>> Setting `QualifierAlignment` to something other than `Leave`, COULD lead to incorrect code formatting due to incorrect decisions made due to clang-formats lack of complete semantic information. As such extra care should be taken to review code changes made by the use of this option.
As the supplemental_test_files are quite large, it is useful to make
running the tests depending on it optional.
By default, the tests are kept enabled, but can be switched of by setting
`FASTFLOAT_SUPPLEMENTAL_TEST=OFF`.
Fixes: #232
Best-effort values are still returned, such as 0 for underflow and infinity for overflow, but now the returned ec is set to std::errc::result_out_of_range instead of std::errc().