#include #include // This function assumes you have called is_valid_digit_for_base() to validate the digit first. static isize parse_digit_unchecked(char c) { if (_isdigit(c)) return c - '0'; if (_islower(c)) return (c - 'a') + 10; return (c - 'A') + 10; } static bool is_valid_digit_for_base(int base, char c) { if (!_isalnum(c)) return false; if (parse_digit_unchecked(c) >= (isize)base) return false; return true; } usize _strtou(const char* str, const char** endptr, int base) { usize val = 0; while (_isspace(*str)) str++; if ((base == 0 || base == 16) && *str == '0') { str++; if (_tolower(*str) == 'x') { base = 16; str++; } else if (base == 0) base = 8; } else if (base == 0) base = 10; while (is_valid_digit_for_base(base, *str)) { val = ((usize)base * val) + (usize)parse_digit_unchecked(*str); str++; } if (endptr) *endptr = str; return val; } isize _strtoi(const char* str, const char** endptr, int base) { bool negative = false; while (_isspace(*str)) str++; if (*str == '-' || *str == '+') { if (*str == '-') negative = true; str++; } usize rc = _strtou(str, endptr, base); // FIXME: Check for overflow (the unsigned usize value might not fit into a signed isize) return negative ? -(isize)rc : (isize)rc; } usize _atou(const char** str) { return _strtou(*str, str, 10); } isize _atos(const char** str) { return _strtoi(*str, str, 10); }