Compare commits

...

10 Commits
v8.2.0 ... main

Author SHA1 Message Date
Daniel Lemire
011763f31c adding tests 2025-12-31 13:46:53 -05:00
Daniel Lemire
d5bc4e1b2e
Merge pull request #358 from shikharish/uint8-base-fix
add base check for uint8
2025-12-31 13:44:12 -05:00
Daniel Lemire
97b54ca9e7 v8.2.2 2025-12-31 13:12:46 -05:00
Daniel Lemire
6499e20cf9
Merge pull request #357 from shikharish/endian-uint8-fix
fix endianess bug in uint8 parsing
2025-12-31 13:11:58 -05:00
Shikhar
4dc5225797 add base check for uint8 parsing
Signed-off-by: Shikhar <shikharish05@gmail.com>
2025-12-31 22:07:45 +05:30
Shikhar
fb522b66d0 fix endianess bug in uint8 parsing
Signed-off-by: Shikhar <shikharish05@gmail.com>
2025-12-31 21:51:23 +05:30
Daniel Lemire
11ce67e5eb v8.2.1 2025-12-29 11:09:40 -05:00
Daniel Lemire
4f77642195
Merge pull request #355 from fastfloat/issue354
fix for issue 354
2025-12-29 11:08:58 -05:00
Daniel Lemire
f4f9da1e6b fix for issue 354 2025-12-29 10:55:20 -05:00
Daniel Lemire
fd85e52349
Change branch name from 'master' to 'main' 2025-12-29 10:47:36 -05:00
5 changed files with 94 additions and 85 deletions

View File

@ -3,10 +3,10 @@ name: Ubuntu s390x (GCC 11)
on:
push:
branches:
- master
- main
pull_request:
branches:
- master
- main
jobs:
build:
@ -24,7 +24,7 @@ jobs:
apt-get update -q -y
apt-get install -y cmake make g++
run: |
cmake -DCMAKE_BUILD_TYPE=Release -B build
cmake -DCMAKE_BUILD_TYPE=Release -B build -DFASTFLOAT_TEST=ON
cmake --build build -j=2
ctest --output-on-failure --test-dir build

View File

@ -1,7 +1,7 @@
cmake_minimum_required(VERSION 3.14)
project(fast_float VERSION 8.2.0 LANGUAGES CXX)
project(fast_float VERSION 8.2.2 LANGUAGES CXX)
set(FASTFLOAT_CXX_STANDARD 11 CACHE STRING "the C++ standard to use for fastfloat")
set(CMAKE_CXX_STANDARD ${FASTFLOAT_CXX_STANDARD})
option(FASTFLOAT_TEST "Enable tests" OFF)

View File

@ -533,7 +533,7 @@ sufficiently recent version of CMake (3.11 or better at least):
FetchContent_Declare(
fast_float
GIT_REPOSITORY https://github.com/fastfloat/fast_float.git
GIT_TAG tags/v8.2.0
GIT_TAG tags/v8.2.2
GIT_SHALLOW TRUE)
FetchContent_MakeAvailable(fast_float)
@ -549,7 +549,7 @@ You may also use [CPM](https://github.com/cpm-cmake/CPM.cmake), like so:
CPMAddPackage(
NAME fast_float
GITHUB_REPOSITORY "fastfloat/fast_float"
GIT_TAG v8.2.0)
GIT_TAG v8.2.2)
```
## Using as single header
@ -561,7 +561,7 @@ if desired as described in the command line help.
You may directly download automatically generated single-header files:
<https://github.com/fastfloat/fast_float/releases/download/v8.2.0/fast_float.h>
<https://github.com/fastfloat/fast_float/releases/download/v8.2.2/fast_float.h>
## Benchmarking

View File

@ -42,6 +42,11 @@ fastfloat_really_inline constexpr uint64_t byteswap(uint64_t val) {
(val & 0x000000000000FF00) << 40 | (val & 0x00000000000000FF) << 56;
}
fastfloat_really_inline constexpr uint32_t byteswap_32(uint32_t val) {
return (val >> 24) | ((val >> 8) & 0x0000FF00u) | ((val << 8) & 0x00FF0000u) |
(val << 24);
}
// Read 8 UC into a u64. Truncates UC if not char.
template <typename UC>
fastfloat_really_inline FASTFLOAT_CONSTEXPR20 uint64_t
@ -510,91 +515,95 @@ parse_int_string(UC const *p, UC const *pend, T &value,
UC const *const start_digits = p;
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
const size_t len = (size_t)(pend - p);
if (len == 0) {
if (has_leading_zeros) {
value = 0;
answer.ec = std::errc();
answer.ptr = p;
} else {
answer.ec = std::errc::invalid_argument;
answer.ptr = first;
}
return answer;
}
uint32_t digits;
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST
if (std::is_constant_evaluated()) {
uint8_t str[4]{};
for (size_t j = 0; j < 4 && j < len; ++j) {
str[j] = static_cast<uint8_t>(p[j]);
}
digits = std::bit_cast<uint32_t>(str);
}
#else
if (false) {
}
#endif
else if (len >= 4) {
::memcpy(&digits, p, 4);
} else {
uint32_t b0 = static_cast<uint8_t>(p[0]);
uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu;
uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu;
uint32_t b3 = 0xFFu;
#if FASTFLOAT_IS_BIG_ENDIAN
digits = (b0 << 24) | (b1 << 16) | (b2 << 8) | b3;
#else
digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
#endif
}
uint32_t magic =
((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u;
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
nd = (uint32_t)std::min((size_t)nd, len);
if (nd == 0) {
if (has_leading_zeros) {
value = 0;
answer.ec = std::errc();
answer.ptr = p;
if (base == 10) {
const size_t len = (size_t)(pend - p);
if (len == 0) {
if (has_leading_zeros) {
value = 0;
answer.ec = std::errc();
answer.ptr = p;
} else {
answer.ec = std::errc::invalid_argument;
answer.ptr = first;
}
return answer;
}
answer.ec = std::errc::invalid_argument;
answer.ptr = first;
return answer;
}
if (nd > 3) {
const UC *q = p + nd;
size_t rem = len - nd;
while (rem) {
if (*q < UC('0') || *q > UC('9'))
break;
++q;
--rem;
uint32_t digits;
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST
if (std::is_constant_evaluated()) {
uint8_t str[4]{};
for (size_t j = 0; j < 4 && j < len; ++j) {
str[j] = static_cast<uint8_t>(p[j]);
}
digits = std::bit_cast<uint32_t>(str);
#if FASTFLOAT_IS_BIG_ENDIAN
digits = byteswap_32(digits);
#endif
}
#else
if (false) {
}
#endif
else if (len >= 4) {
::memcpy(&digits, p, 4);
#if FASTFLOAT_IS_BIG_ENDIAN
digits = byteswap_32(digits);
#endif
} else {
uint32_t b0 = static_cast<uint8_t>(p[0]);
uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu;
uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu;
uint32_t b3 = 0xFFu;
digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
}
answer.ec = std::errc::result_out_of_range;
answer.ptr = q;
return answer;
}
digits ^= 0x30303030u;
digits <<= ((4 - nd) * 8);
uint32_t magic =
((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u;
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
nd = (uint32_t)std::min((size_t)nd, len);
if (nd == 0) {
if (has_leading_zeros) {
value = 0;
answer.ec = std::errc();
answer.ptr = p;
return answer;
}
answer.ec = std::errc::invalid_argument;
answer.ptr = first;
return answer;
}
if (nd > 3) {
const UC *q = p + nd;
size_t rem = len - nd;
while (rem) {
if (*q < UC('0') || *q > UC('9'))
break;
++q;
--rem;
}
answer.ec = std::errc::result_out_of_range;
answer.ptr = q;
return answer;
}
uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) |
((digits << 8) & 0xff0000);
if (check > 0x00020505) {
answer.ec = std::errc::result_out_of_range;
digits ^= 0x30303030u;
digits <<= ((4 - nd) * 8);
uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) |
((digits << 8) & 0xff0000);
if (check > 0x00020505) {
answer.ec = std::errc::result_out_of_range;
answer.ptr = p + nd;
return answer;
}
value = (uint8_t)((0x640a01 * digits) >> 24);
answer.ec = std::errc();
answer.ptr = p + nd;
return answer;
}
value = (uint8_t)((0x640a01 * digits) >> 24);
answer.ec = std::errc();
answer.ptr = p + nd;
return answer;
}
uint64_t i = 0;

View File

@ -17,7 +17,7 @@
#define FASTFLOAT_VERSION_MAJOR 8
#define FASTFLOAT_VERSION_MINOR 2
#define FASTFLOAT_VERSION_PATCH 0
#define FASTFLOAT_VERSION_PATCH 2
#define FASTFLOAT_STRINGIZE_IMPL(x) #x
#define FASTFLOAT_STRINGIZE(x) FASTFLOAT_STRINGIZE_IMPL(x)