Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 9 additions & 6 deletions changelog/current.md
Original file line number Diff line number Diff line change
@@ -1,9 +1,5 @@
- [PR#169](https://github.com/biojppm/c4core/pull/169) atof()/atod():
- disable assertions that prevent returning false
- c4/std/std.hpp: remove tuple.hpp
- [PR#171](https://github.com/biojppm/c4core/pull/171):
- fix warnings from names with underscores (clang: -Wreserved-identifier)
- c4/std/std.hpp: remove tuple.hpp
- [PR#175](https://github.com/biojppm/c4core/pull/175): update fastfloat to 8.2.10
- [PR#174](https://github.com/biojppm/c4core/pull/174): improve amalgamate_utils.py
- [PR#172](https://github.com/biojppm/c4core/pull/172):
- [**BREAKING**] `C4_LIKELY()` and `C4_UNLIKELY()` now use `[[likely]]` and `[[unlikely]]` in C++20. Every use of this macro needs to refactored:
```c++
Expand All @@ -14,3 +10,10 @@
```
- Add `C4_LIKELY20` and `C4_UNLIKELY20`, which resolve directly into `[[likely]]` and `[[unlikely]]` when C++ is 20 or later, or nothing otherwise.
- Add C++23 detection (`C4_CPP` and `C4_CPP23`)
- [PR#171](https://github.com/biojppm/c4core/pull/171):
- fix warnings from names with underscores (clang: -Wreserved-identifier)
- c4/std/std.hpp: remove tuple.hpp
- [PR#170](https://github.com/biojppm/c4core/pull/170) add option to use fastfloat from system: `C4CORE_WITH_FASTFLOAT_SYSTEM`
- [PR#169](https://github.com/biojppm/c4core/pull/169) `atof()`/`atod()`:
- disable assertions that prevent returning false
- c4/std/std.hpp: remove tuple.hpp
26 changes: 22 additions & 4 deletions src/c4/ext/fast_float_all.h
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@

#define FASTFLOAT_VERSION_MAJOR 8
#define FASTFLOAT_VERSION_MINOR 2
#define FASTFLOAT_VERSION_PATCH 9
#define FASTFLOAT_VERSION_PATCH 10

#define FASTFLOAT_STRINGIZE_IMPL(x) #x
#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)
Expand Down Expand Up @@ -2430,9 +2430,27 @@ parse_int_string(UC const *p, UC const *pend, T &value,
}
// this check can be eliminated for all other types, but they will all require
// a max_digits(base) equivalent
if (digit_count == max_digits && i < min_safe_u64(base)) {
answer.ec = std::errc::result_out_of_range;
return answer;
if (digit_count == max_digits) {
// At the max_digits boundary the accumulator `i` may have wrapped around
// 2^64. A plain `i < min_safe_u64(base)` test is not sufficient: for any
// base whose max_digits-length range exceeds 2^64 (base 10 reaches
// ~5.4 * 2^64 at 20 digits) the value can wrap a whole multiple of 2^64 and
// land back above min_safe, slipping through. Decide exactly in O(1) using
// the leading digit, following the approach used in simdjson:
// ms == min_safe_u64(base) == base^(max_digits-1), the smallest
// max_digits-length value.
// dmax == the largest leading digit whose number can still fit in u64.
// The leading-digit band [d*ms, (d+1)*ms) has width ms < 2^64, so within
// the single band where d == dmax the value straddles 2^64 at most once,
// and a single threshold separates wrapped from non-wrapped values. A
// leading digit above dmax always overflows; below dmax always fits.
uint64_t const ms = min_safe_u64(base);
uint64_t const dmax = (std::numeric_limits<uint64_t>::max)() / ms;
uint64_t const lead = ch_to_digit(*start_digits);
if (lead > dmax || (lead == dmax && i < dmax * ms)) {
answer.ec = std::errc::result_out_of_range;
return answer;
}
}

// check other types overflow
Expand Down
Loading