mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-01-01 03:12:18 +08:00
Compare commits
10 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
011763f31c | ||
|
|
d5bc4e1b2e | ||
|
|
97b54ca9e7 | ||
|
|
6499e20cf9 | ||
|
|
4dc5225797 | ||
|
|
fb522b66d0 | ||
|
|
11ce67e5eb | ||
|
|
4f77642195 | ||
|
|
f4f9da1e6b | ||
|
|
fd85e52349 |
6
.github/workflows/s390x.yml
vendored
6
.github/workflows/s390x.yml
vendored
@ -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
|
||||
|
||||
|
||||
@ -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)
|
||||
|
||||
@ -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
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
@ -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)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user