unsigned long long strtoull(FAR const char *nptr, FAR char **endptr, int base) { unsigned long long accum = 0; int value; if (nptr) { /* Skip leading spaces */ lib_skipspace(&nptr); /* Check for unspecified base */ base = lib_checkbase(base, &nptr); /* Accumulate each "digit" */ while (lib_isbasedigit(*nptr, base, &value)) { accum = accum*base + value; nptr++; } /* Return the final pointer to the unused value */ if (endptr) { *endptr = (char *)nptr; } } return accum; }
int lib_checkbase(int base, FAR const char **pptr) { FAR const char *ptr = *pptr; /* Check for unspecified base */ if (!base) { /* Assume base 10 */ base = 10; /* Check for leading '0' - that would signify octal or hex (or binary) */ if (*ptr == '0') { /* Assume octal */ base = 8; ptr++; /* Check for hexadecimal */ if ((*ptr == 'X' || *ptr == 'x') && lib_isbasedigit(ptr[1], 16, NULL)) { base = 16; ptr++; } } } /* If it a hexadecimal representation, than discard any leading "0X" or "0x" */ else if (base == 16) { if (ptr[0] == '0' && (ptr[1] == 'X' || ptr[1] == 'x')) { ptr += 2; } } /* Check for incorrect bases. */ else if (base < 2 || base > 26) { return -1; /* Means incorrect base */ } /* Return the updated pointer and base */ *pptr = ptr; return base; }
unsigned long long strtoull(const char *nptr, char **endptr, int base) { unsigned long long prev, accum = 0; int value; if (nptr) { /* Skip leading spaces */ lib_skipspace(&nptr); /* Check for unspecified base */ base = lib_checkbase(base, &nptr); if (base < 0) { set_errno(EINVAL); return 0; } /* Accumulate each "digit" */ while (lib_isbasedigit(*nptr, base, &value)) { prev = accum; accum = accum * base + value; nptr++; /* Check for overflow */ if (accum < prev) { set_errno(ERANGE); accum = 0; break; } } /* Return the final pointer to the unused value */ if (endptr) { *endptr = (char *)nptr; } } return accum; }