Skip to content

Commit 82882b2

Browse files
committed
gate uint8/uint16 base-10 fast paths to single-byte code units
1 parent 9371986 commit 82882b2

2 files changed

Lines changed: 61 additions & 2 deletions

File tree

include/fast_float/ascii_number.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,8 @@ parse_int_string(UC const *p, UC const *pend, T &value,
600600

601601
UC const *const start_digits = p;
602602

603-
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value)) {
603+
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint8_t>::value &&
604+
sizeof(UC) == 1)) {
604605
if (base == 10) {
605606
const size_t len = (size_t)(pend - p);
606607
if (len == 0) {
@@ -692,7 +693,8 @@ parse_int_string(UC const *p, UC const *pend, T &value,
692693
}
693694
}
694695

695-
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint16_t>::value)) {
696+
FASTFLOAT_IF_CONSTEXPR17((std::is_same<T, std::uint16_t>::value &&
697+
sizeof(UC) == 1)) {
696698
if (base == 10) {
697699
const size_t len = size_t(pend - p);
698700
if (len == 0) {

tests/fast_int.cpp

Lines changed: 57 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1295,6 +1295,63 @@ int main() {
12951295
return EXIT_FAILURE;
12961296
}
12971297
}
1298+
// The uint8_t and uint16_t base-10 paths use a byte-oriented fast path. A
1299+
// wider code unit whose low byte is an ASCII digit (e.g. U+2131..U+2139) must
1300+
// not be mistaken for that digit. The generic path already rejects these for
1301+
// int; the fixed-width fast paths must agree. Lengths of 1..5 exercise both
1302+
// the uint8_t path and the 4-digit uint16_t SWAR path.
1303+
{
1304+
const std::u16string bad16[] = {
1305+
u"",
1306+
u"ℱℲ",
1307+
u"ℱℲℳ",
1308+
u"ℱℲℳℴ",
1309+
u"ℱℲℳℴℵ",
1310+
};
1311+
const std::u32string bad32[] = {
1312+
U"",
1313+
U"ℱℲℳ",
1314+
U"ℱℲℳℴ",
1315+
U"ℱℲℳℴℵ",
1316+
};
1317+
bool failed = false;
1318+
for (auto const &s : bad16) {
1319+
uint8_t r8 = 123;
1320+
auto a8 = fast_float::from_chars(s.data(), s.data() + s.size(), r8);
1321+
if (a8.ec == std::errc()) {
1322+
failed = true;
1323+
std::cerr << "Incorrectly parsed wide units as uint8_t " << unsigned(r8)
1324+
<< "." << std::endl;
1325+
}
1326+
uint16_t r16 = 123;
1327+
auto a16 = fast_float::from_chars(s.data(), s.data() + s.size(), r16);
1328+
if (a16.ec == std::errc()) {
1329+
failed = true;
1330+
std::cerr << "Incorrectly parsed wide units as uint16_t " << r16 << "."
1331+
<< std::endl;
1332+
}
1333+
}
1334+
for (auto const &s : bad32) {
1335+
uint8_t r8 = 123;
1336+
auto a8 = fast_float::from_chars(s.data(), s.data() + s.size(), r8);
1337+
if (a8.ec == std::errc()) {
1338+
failed = true;
1339+
std::cerr << "Incorrectly parsed wide units as uint8_t " << unsigned(r8)
1340+
<< "." << std::endl;
1341+
}
1342+
uint16_t r16 = 123;
1343+
auto a16 = fast_float::from_chars(s.data(), s.data() + s.size(), r16);
1344+
if (a16.ec == std::errc()) {
1345+
failed = true;
1346+
std::cerr << "Incorrectly parsed wide units as uint16_t " << r16 << "."
1347+
<< std::endl;
1348+
}
1349+
}
1350+
1351+
if (failed) {
1352+
return EXIT_FAILURE;
1353+
}
1354+
}
12981355

12991356
return EXIT_SUCCESS;
13001357
}

0 commit comments

Comments
 (0)