diff --git a/str.c b/str.c index a85ec39f..cdff8d6f 100644 --- a/str.c +++ b/str.c @@ -753,9 +753,35 @@ char *str_str(char *haystack, const char *needle, size_t haystack_len) return NULL; } -int str_is_uint64_decimal(const char *str) +int str_to_uint16(const char *str, unsigned base, uint16_t *result, const char **afterp) { - return str_to_uint64(str, 10, NULL, NULL); + return strn_to_uint16(str, 0, base, result, afterp); +} + +int strn_to_uint16(const char *str, size_t strlen, unsigned base, uint16_t *result, const char **afterp) +{ + assert(base > 0); + assert(base <= 16); + uint16_t value = 0; + uint16_t newvalue = 0; + const char *const end = str + strlen; + const char *s; + for (s = str; strlen ? s < end : *s; ++s) { + int digit = hexvalue(*s); + if (digit < 0 || (unsigned)digit >= base) + break; + newvalue = value * base + digit; + if (newvalue / base != value) // overflow + break; + value = newvalue; + } + if (afterp) + *afterp = s; + if (s == str || value != newvalue || (!afterp && (strlen ? s != end : *s))) + return 0; + if (result) + *result = value; + return 1; } int str_to_int32(const char *str, unsigned base, int32_t *result, const char **afterp) @@ -805,6 +831,11 @@ int strn_to_uint32(const char *str, size_t strlen, unsigned base, uint32_t *resu return 1; } +int str_is_uint64_decimal(const char *str) +{ + return str_to_uint64(str, 10, NULL, NULL); +} + int str_to_int64(const char *str, unsigned base, int64_t *result, const char **afterp) { if (isspace(*str)) diff --git a/str.h b/str.h index b08408b3..2112792b 100644 --- a/str.h +++ b/str.h @@ -431,6 +431,7 @@ int str_is_uint64_decimal(const char *str); * * @author Andrew Bettison */ +int str_to_uint16(const char *str, unsigned base, uint16_t *result, const char **afterp); int str_to_int32(const char *str, unsigned base, int32_t *result, const char **afterp); int str_to_uint32(const char *str, unsigned base, uint32_t *result, const char **afterp); int str_to_int64(const char *str, unsigned base, int64_t *result, const char **afterp); @@ -447,6 +448,7 @@ int str_to_uint64(const char *str, unsigned base, uint64_t *result, const char * * * @author Andrew Bettison */ +int strn_to_uint16(const char *str, size_t strlen, unsigned base, uint16_t *result, const char **afterp); int strn_to_uint32(const char *str, size_t strlen, unsigned base, uint32_t *result, const char **afterp); int strn_to_uint64(const char *str, size_t strlen, unsigned base, uint64_t *result, const char **afterp);