Skip to content

Instantly share code, notes, and snippets.

@gusteivos
Last active August 17, 2024 19:38
Show Gist options
  • Save gusteivos/3f2ef3be423be5fcf9dfc7646bfeb80c to your computer and use it in GitHub Desktop.
Save gusteivos/3f2ef3be423be5fcf9dfc7646bfeb80c to your computer and use it in GitHub Desktop.
#include <stdlib.h>
#include <ctype.h>
#include <limits.h>
#include <errno.h>
/* https://github.com/gcc-mirror/gcc/blob/master/libiberty/strtoul.c */
unsigned long
strntoul(const char *nptr, size_t n, char **endptr, register int base)
{
register const char *s = nptr;
register size_t mn = n;
register unsigned long acc;
register int c;
register unsigned long cutoff;
register int neg = 0, any, cutlim;
/*
* See strtol for comments as to the logic used.
*/
do {
c = *s++;
/* --mn; */ /* Use if you want to count spaces. */
} while (isspace(c));
if (c == '-') {
neg = 1;
c = *s++;
--mn;
} else if (c == '+') {
c = *s++;
--mn;
}
if ((base == 0 || base == 16) &&
c == '0' && (*s == 'x' || *s == 'X')) {
c = s[1];
s += 2;
base = 16;
mn -= 2; /* Maybe not. */
}
if (base == 0)
base = c == '0' ? 8 : 10;
cutoff = (unsigned long)ULONG_MAX / (unsigned long)base;
cutlim = (unsigned long)ULONG_MAX % (unsigned long)base;
for (acc = 0, any = 0; mn > 0; c = *s++, --mn) {
if (isdigit(c))
c -= '0';
else if (isalpha(c))
c -= isupper(c) ? 'A' - 10 : 'a' - 10;
else
break;
if (c >= base)
break;
if (any < 0 || acc > cutoff || (acc == cutoff && c > cutlim))
any = -1;
else {
any = 1;
acc *= base;
acc += c;
}
}
if (any < 0) {
acc = ULONG_MAX;
errno = ERANGE;
} else if (neg)
acc = -acc;
if (endptr != 0)
*endptr = (char *) (any ? s - 1 : nptr);
return (acc);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment