#include #include #include #include unsigned long long int strtoull(char const * restrict ptr, char ** restrict endptr, int base) { /* Save the value of ptr in endptr now in case the format is invalid */ if(endptr) *endptr = (char *)ptr; /* Skip initial whitespace */ while(isspace(*ptr)) ptr++; /* Accept a sign character */ bool negative = false; if(*ptr == '-') negative = true; if(*ptr == '-' || *ptr == '+') ptr++; unsigned long long x = 0; bool valid = false; /* Read prefixes and determine base */ if((base == 0 || base == 16) && ptr[0]=='0' && tolower(ptr[1])=='x') { ptr += 2; base = 16; } else if(base == 0 && ptr[0] == '0') { ptr++; base = 8; } else if(base == 0) { base = 10; } /* Read digits */ while(1) { int v = -1; if(isdigit(*ptr)) v = *ptr - '0'; if(islower(*ptr)) v = *ptr - 'a' + 10; if(v == -1 || v >= base) break; /* The value is valid as long as there is at least one digit */ valid = true; /* (x = base*x + v) but with overflow checks */ if(__builtin_umulll_overflow(x, base, &x)) errno = ERANGE; if(__builtin_uaddll_overflow(x, v, &x)) errno = ERANGE; ptr++; } if(negative) { if(x != 0) errno = ERANGE; x = -x; } if(endptr && valid) *endptr = (char *)ptr; return x; }