mirror of
https://github.com/fastfloat/fast_float.git
synced 2026-01-01 03:12:18 +08:00
Merge pull request #358 from shikharish/uint8-base-fix
add base check for uint8
This commit is contained in:
commit
d5bc4e1b2e
@ -515,93 +515,95 @@ parse_int_string(UC const *p, UC const *pend, T &value,
|
|||||||
UC const *const start_digits = p;
|
UC const *const start_digits = p;
|
||||||
|
|
||||||
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
|
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
|
||||||
const size_t len = (size_t)(pend - p);
|
if (base == 10) {
|
||||||
if (len == 0) {
|
const size_t len = (size_t)(pend - p);
|
||||||
if (has_leading_zeros) {
|
if (len == 0) {
|
||||||
value = 0;
|
if (has_leading_zeros) {
|
||||||
answer.ec = std::errc();
|
value = 0;
|
||||||
answer.ptr = p;
|
answer.ec = std::errc();
|
||||||
} else {
|
answer.ptr = p;
|
||||||
answer.ec = std::errc::invalid_argument;
|
} else {
|
||||||
answer.ptr = first;
|
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);
|
|
||||||
#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);
|
|
||||||
}
|
|
||||||
|
|
||||||
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;
|
return answer;
|
||||||
}
|
}
|
||||||
answer.ec = std::errc::invalid_argument;
|
|
||||||
answer.ptr = first;
|
uint32_t digits;
|
||||||
return answer;
|
|
||||||
}
|
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST
|
||||||
if (nd > 3) {
|
if (std::is_constant_evaluated()) {
|
||||||
const UC *q = p + nd;
|
uint8_t str[4]{};
|
||||||
size_t rem = len - nd;
|
for (size_t j = 0; j < 4 && j < len; ++j) {
|
||||||
while (rem) {
|
str[j] = static_cast<uint8_t>(p[j]);
|
||||||
if (*q < UC('0') || *q > UC('9'))
|
}
|
||||||
break;
|
digits = std::bit_cast<uint32_t>(str);
|
||||||
++q;
|
#if FASTFLOAT_IS_BIG_ENDIAN
|
||||||
--rem;
|
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;
|
uint32_t magic =
|
||||||
digits <<= ((4 - nd) * 8);
|
((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 ^= 0x30303030u;
|
||||||
((digits << 8) & 0xff0000);
|
digits <<= ((4 - nd) * 8);
|
||||||
if (check > 0x00020505) {
|
|
||||||
answer.ec = std::errc::result_out_of_range;
|
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;
|
answer.ptr = p + nd;
|
||||||
return answer;
|
return answer;
|
||||||
}
|
}
|
||||||
value = (uint8_t)((0x640a01 * digits) >> 24);
|
|
||||||
answer.ec = std::errc();
|
|
||||||
answer.ptr = p + nd;
|
|
||||||
return answer;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
uint64_t i = 0;
|
uint64_t i = 0;
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user