5 ms·
The SWAR algorithm accepts the 6 ASCII characters after '9'. It'll parse ":>" as 114. int res = parse_uint8_fastswar(":>\0", 2, &num); Returns true and nu
by vinkelhake 3y ago
The SWAR algorithm accepts the 6 ASCII characters after '9'. It'll parse ":>" as 114.
int res = parse_uint8_fastswar(":>\0", 2, &num);
Returns true and num is 114.
- 1letterunixname 3y agoYep ":>" does parse as 114. ";;" parses as 121. "<>" as 134. "999" parses as 231. Lots of work to do and nowhere close to being a magically clever and correct solution. Note: \0 is implicit and redundant in C string literals. There is a fudge factor in some string handling semantics and it sort-of works without it with some UB risks that are platform specific. (It worked on GCC-13 on Linux on AMD EPYC.) #include <stdio.h> #include <stdint.h> #include <string.h> int parse_uint8_fastswar(const char *str, size_t len, uint8_t *num) { union { uint8_t as_str[4]; uint32_t as_int; } digits; memcpy(&digits.as_int, str, sizeof(digits)); digits.as_int ^= 0x30303030lu; digits.as_int <<= (4 - (len & 0x3)) * 8; uint32_t y = ((UINT64_C(0x640a0100) * digits.as_int)>>32)&0xff; *num = (uint8_t)(y); return (digits.as_int & 0xf0f0f0f0) == 0 && y < 256 && len != 0 && len < 4; } int main(int argc, char **argv) { uint8_t num; if (argc != 2 || !parse_uint8_fastswar(argv[1], strlen(argv[1]), &num)) return 1; printf("parsed as %d (%02Xh)\n", num, num); return 0; }
- vinkelhake 3y agoThe literal ":>\0" gives us a 4 byte char array with the last two bytes being 0. I did this since the algorithm always does a 4 byte read from the passed pointer.
- RaisingSpear 3y agoMy attempt to fix it: https://godbolt.org/z/P3e8q45qx https://godbolt.org/z/P3e8q45qx (also removes the 64-bit multiply, which might be slow on 32-bit machines)