Skip to content

Commit d5bc4e1

Browse files
authored
Merge pull request #358 from shikharish/uint8-base-fix
add base check for uint8
2 parents 97b54ca + 4dc5225 commit d5bc4e1

File tree

1 file changed

+70
-68
lines changed

1 file changed

+70
-68
lines changed

include/fast_float/ascii_number.h

Lines changed: 70 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -515,93 +515,95 @@ parse_int_string(UC const *p, UC const *pend, T &value,
515515
UC const *const start_digits = p;
516516

517517
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
518-
const size_t len = (size_t)(pend - p);
519-
if (len == 0) {
520-
if (has_leading_zeros) {
521-
value = 0;
522-
answer.ec = std::errc();
523-
answer.ptr = p;
524-
} else {
525-
answer.ec = std::errc::invalid_argument;
526-
answer.ptr = first;
518+
if (base == 10) {
519+
const size_t len = (size_t)(pend - p);
520+
if (len == 0) {
521+
if (has_leading_zeros) {
522+
value = 0;
523+
answer.ec = std::errc();
524+
answer.ptr = p;
525+
} else {
526+
answer.ec = std::errc::invalid_argument;
527+
answer.ptr = first;
528+
}
529+
return answer;
527530
}
528-
return answer;
529-
}
530531

531-
uint32_t digits;
532+
uint32_t digits;
532533

533534
#if FASTFLOAT_HAS_IS_CONSTANT_EVALUATED && FASTFLOAT_HAS_BIT_CAST
534-
if (std::is_constant_evaluated()) {
535-
uint8_t str[4]{};
536-
for (size_t j = 0; j < 4 && j < len; ++j) {
537-
str[j] = static_cast<uint8_t>(p[j]);
538-
}
539-
digits = std::bit_cast<uint32_t>(str);
535+
if (std::is_constant_evaluated()) {
536+
uint8_t str[4]{};
537+
for (size_t j = 0; j < 4 && j < len; ++j) {
538+
str[j] = static_cast<uint8_t>(p[j]);
539+
}
540+
digits = std::bit_cast<uint32_t>(str);
540541
#if FASTFLOAT_IS_BIG_ENDIAN
541-
digits = byteswap_32(digits);
542+
digits = byteswap_32(digits);
542543
#endif
543-
}
544+
}
544545
#else
545-
if (false) {
546-
}
546+
if (false) {
547+
}
547548
#endif
548-
else if (len >= 4) {
549-
::memcpy(&digits, p, 4);
549+
else if (len >= 4) {
550+
::memcpy(&digits, p, 4);
550551
#if FASTFLOAT_IS_BIG_ENDIAN
551-
digits = byteswap_32(digits);
552+
digits = byteswap_32(digits);
552553
#endif
553-
} else {
554-
uint32_t b0 = static_cast<uint8_t>(p[0]);
555-
uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu;
556-
uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu;
557-
uint32_t b3 = 0xFFu;
558-
digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
559-
}
554+
} else {
555+
uint32_t b0 = static_cast<uint8_t>(p[0]);
556+
uint32_t b1 = (len > 1) ? static_cast<uint8_t>(p[1]) : 0xFFu;
557+
uint32_t b2 = (len > 2) ? static_cast<uint8_t>(p[2]) : 0xFFu;
558+
uint32_t b3 = 0xFFu;
559+
digits = b0 | (b1 << 8) | (b2 << 16) | (b3 << 24);
560+
}
560561

561-
uint32_t magic =
562-
((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u;
563-
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
564-
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
565-
nd = (uint32_t)std::min((size_t)nd, len);
566-
if (nd == 0) {
567-
if (has_leading_zeros) {
568-
value = 0;
569-
answer.ec = std::errc();
570-
answer.ptr = p;
562+
uint32_t magic =
563+
((digits + 0x46464646u) | (digits - 0x30303030u)) & 0x80808080u;
564+
uint32_t tz = (uint32_t)countr_zero_32(magic); // 7, 15, 23, 31, or 32
565+
uint32_t nd = (tz == 32) ? 4 : (tz >> 3);
566+
nd = (uint32_t)std::min((size_t)nd, len);
567+
if (nd == 0) {
568+
if (has_leading_zeros) {
569+
value = 0;
570+
answer.ec = std::errc();
571+
answer.ptr = p;
572+
return answer;
573+
}
574+
answer.ec = std::errc::invalid_argument;
575+
answer.ptr = first;
571576
return answer;
572577
}
573-
answer.ec = std::errc::invalid_argument;
574-
answer.ptr = first;
575-
return answer;
576-
}
577-
if (nd > 3) {
578-
const UC *q = p + nd;
579-
size_t rem = len - nd;
580-
while (rem) {
581-
if (*q < UC('0') || *q > UC('9'))
582-
break;
583-
++q;
584-
--rem;
578+
if (nd > 3) {
579+
const UC *q = p + nd;
580+
size_t rem = len - nd;
581+
while (rem) {
582+
if (*q < UC('0') || *q > UC('9'))
583+
break;
584+
++q;
585+
--rem;
586+
}
587+
answer.ec = std::errc::result_out_of_range;
588+
answer.ptr = q;
589+
return answer;
585590
}
586-
answer.ec = std::errc::result_out_of_range;
587-
answer.ptr = q;
588-
return answer;
589-
}
590591

591-
digits ^= 0x30303030u;
592-
digits <<= ((4 - nd) * 8);
592+
digits ^= 0x30303030u;
593+
digits <<= ((4 - nd) * 8);
593594

594-
uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) |
595-
((digits << 8) & 0xff0000);
596-
if (check > 0x00020505) {
597-
answer.ec = std::errc::result_out_of_range;
595+
uint32_t check = ((digits >> 24) & 0xff) | ((digits >> 8) & 0xff00) |
596+
((digits << 8) & 0xff0000);
597+
if (check > 0x00020505) {
598+
answer.ec = std::errc::result_out_of_range;
599+
answer.ptr = p + nd;
600+
return answer;
601+
}
602+
value = (uint8_t)((0x640a01 * digits) >> 24);
603+
answer.ec = std::errc();
598604
answer.ptr = p + nd;
599605
return answer;
600606
}
601-
value = (uint8_t)((0x640a01 * digits) >> 24);
602-
answer.ec = std::errc();
603-
answer.ptr = p + nd;
604-
return answer;
605607
}
606608

607609
uint64_t i = 0;

0 commit comments

Comments
 (0)