// util/strtou.c // String conversion source file from libutil // Copyright (C) 2021, Jakob Wakeling // MIT Licence #include "util.h" #include #include /* Convert a string to an unsigned 8-bit integer */ u8 strtou8(const char *nptr, char **endptr, register int base) { register const char *s = nptr; register u8 i = 0, c; for (; isspace(*s); ++s); if (*s == '+') { ++s; } else if (*s == '-') { errno = EINVAL; goto end; } if ((!base || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { s += 2; base = 16; } else if (base == 0) { base = s[0] == '0' ? 8 : 10; } else if (base < 2 || base > 36) { errno = EINVAL; goto end; } for (;; ++s) { if (*s >= '0' && *s <= '9') { c = *s - '0'; } else if (*s >= 'A' && *s <= 'Z') { c = *s - ('A' - 10); } else if (*s >= 'a' && *s <= 'z') { c = *s - ('a' - 10); } else { break; } if (c >= base) { break; } if (i > (U8_MAX - c) / base) { errno = ERANGE; i = U8_MAX; goto end; } i = i * base + c; } end:; if (endptr) { *endptr = (char *)s; } return i; } /* Convert a string to an unsigned 16-bit integer */ u16 strtou16(const char *nptr, char **endptr, register int base) { register const char *s = nptr; register u16 i = 0, c; for (; isspace(*s); ++s); if (*s == '+') { ++s; } else if (*s == '-') { errno = EINVAL; goto end; } if ((!base || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { s += 2; base = 16; } else if (base == 0) { base = s[0] == '0' ? 8 : 10; } else if (base < 2 || base > 36) { errno = EINVAL; goto end; } for (;; ++s) { if (*s >= '0' && *s <= '9') { c = *s - '0'; } else if (*s >= 'A' && *s <= 'Z') { c = *s - ('A' - 10); } else if (*s >= 'a' && *s <= 'z') { c = *s - ('a' - 10); } else { break; } if (c >= base) { break; } if (i > (U16_MAX - c) / base) { errno = ERANGE; i = U16_MAX; goto end; } i = i * base + c; } end:; if (endptr) { *endptr = (char *)s; } return i; } /* Convert a string to an unsigned 32-bit integer */ u32 strtou32(const char *nptr, char **endptr, register int base) { register const char *s = nptr; register u32 i = 0, c; for (; isspace(*s); ++s); if (*s == '+') { ++s; } else if (*s == '-') { errno = EINVAL; goto end; } if ((!base || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { s += 2; base = 16; } else if (base == 0) { base = s[0] == '0' ? 8 : 10; } else if (base < 2 || base > 36) { errno = EINVAL; goto end; } for (;; ++s) { if (*s >= '0' && *s <= '9') { c = *s - '0'; } else if (*s >= 'A' && *s <= 'Z') { c = *s - ('A' - 10); } else if (*s >= 'a' && *s <= 'z') { c = *s - ('a' - 10); } else { break; } if (c >= base) { break; } if (i > (U32_MAX - c) / base) { errno = ERANGE; i = U32_MAX; goto end; } i = i * base + c; } end:; if (endptr) { *endptr = (char *)s; } return i; } /* Convert a string to an unsigned 64-bit integer */ u64 strtou64(const char *nptr, char **endptr, register int base) { register const char *s = nptr; register u64 i = 0, c; for (; isspace(*s); ++s); if (*s == '+') { ++s; } else if (*s == '-') { errno = EINVAL; goto end; } if ((!base || base == 16) && s[0] == '0' && (s[1] == 'x' || s[1] == 'X')) { s += 2; base = 16; } else if (base == 0) { base = s[0] == '0' ? 8 : 10; } else if (base < 2 || base > 36) { errno = EINVAL; goto end; } for (;; ++s) { if (*s >= '0' && *s <= '9') { c = *s - '0'; } else if (*s >= 'A' && *s <= 'Z') { c = *s - ('A' - 10); } else if (*s >= 'a' && *s <= 'z') { c = *s - ('a' - 10); } else { break; } if (c >= base) { break; } if (i > (U64_MAX - c) / base) { errno = ERANGE; i = U64_MAX; goto end; } i = i * base + c; } end:; if (endptr) { *endptr = (char *)s; } return i; }