diff options
Diffstat (limited to 'lib/strtoul.c')
-rw-r--r-- | lib/strtoul.c | 104 |
1 files changed, 83 insertions, 21 deletions
diff --git a/lib/strtoul.c b/lib/strtoul.c index a5b11f68..e0c0142f 100644 --- a/lib/strtoul.c +++ b/lib/strtoul.c @@ -25,7 +25,7 @@ bstrtoul10(const char *str, char **end) errno = ERANGE; return UINT64_MAX; } - + out *= 10; out += (**end) - '0'; } @@ -60,29 +60,91 @@ bstrtoul16(const char *str, char **end) return UINT64_MAX; } -byte -bstrtobyte16(const char *str) +static int +fromxdigit(char c) { - byte out = 0; - for (int i=0; i<2; i++) { - switch (str[i]) { - case '0' ... '9': - out *= 16; - out += str[i] - '0'; - break; - case 'a' ... 'f': - out *= 16; - out += str[i] + 10 - 'a'; - break; - case 'A' ... 'F': - out *= 16; - out += str[i] + 10 - 'A'; - break; - default: - errno = ERANGE; + switch (c) + { + case '0' ... '9': + return c - '0'; + case 'a' ... 'f': + return c + 10 - 'a'; + case 'A' ... 'F': + return c + 10 - 'A'; + default: + return -1; + } +} + +int +bstrhextobin(const char *s, byte *b) +{ + int len = 0; + int hi = 0; + + for (; *s; s++) + { + int v = fromxdigit(*s); + if (v < 0) + { + if (strchr(" :-", *s) && !hi) + continue; + else return -1; } + + if (len == INT32_MAX) + return -1; + + if (b) + { + if (!hi) + b[len] = (v << 4); + else + b[len] |= v; + } + + len += hi; + hi = !hi; } - return out; + return !hi ? len : -1; +} + +static char +toxdigit(uint b) +{ + if (b < 10) + return ('0' + b); + else if (b < 16) + return ('a' + b - 10); + else + return 0; +} + +int +bstrbintohex(const byte *b, size_t len, char *buf, size_t size, char delim) +{ + ASSERT(size >= 6); + char *bound = buf + size - 3; + + size_t i; + for (i = 0; i < len; i++) + { + if (buf > bound) + { + strcpy(buf - 4, "..."); + return -1; + } + + uint x = b[i]; + buf[0] = toxdigit(x >> 4); + buf[1] = toxdigit(x & 0xF); + buf[2] = delim; + buf += 3; + } + + buf[i ? -1 : 0] = 0; + + return 0; } |