HelenOS sources
This source file includes following definitions.
- _digit_value
- _max_value
- _prefixbase
- _strtoumax
- _strtosigned
- _strtounsigned
- strtol
- strtoul
- strtoll
- strtoull
- strtoimax
- strtoumax
- atoi
- atol
- atoll
- str_uint8_t
- str_uint16_t
- str_uint32_t
- str_uint64_t
- str_int64_t
- str_size_t
#include <assert.h>
#include <ctype.h>
#include <errno.h>
#include <inttypes.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
#include <str.h>
static inline int _digit_value(int c)
{
if (isdigit(c)) {
return c - '0';
} else if (islower(c)) {
return c - 'a' + 10;
} else if (isupper(c)) {
return c - 'A' + 10;
}
return INT_MAX;
}
__attribute__((noinline)) static uintmax_t _max_value(int base)
{
return UINTMAX_MAX / base;
}
static inline int _prefixbase(const char *restrict *nptrptr, bool nonstd)
{
const char *nptr = *nptrptr;
if (nptr[0] != '0')
return 10;
if (nptr[1] == 'x' || nptr[1] == 'X') {
if (_digit_value(nptr[2]) < 16) {
*nptrptr += 2;
return 16;
}
}
if (nonstd) {
switch (nptr[1]) {
case 'b':
case 'B':
if (_digit_value(nptr[2]) < 2) {
*nptrptr += 2;
return 2;
}
break;
case 'o':
case 'O':
if (_digit_value(nptr[2]) < 8) {
*nptrptr += 2;
return 8;
}
break;
case 'd':
case 'D':
case 't':
case 'T':
if (_digit_value(nptr[2]) < 10) {
*nptrptr += 2;
return 10;
}
break;
}
}
return 8;
}
static inline uintmax_t _strtoumax(
const char *restrict nptr, char **restrict endptr, int base,
bool *restrict sgn, errno_t *err, bool nonstd)
{
assert(nptr != NULL);
assert(sgn != NULL);
const char *first = nptr;
while (isspace(*nptr)) {
nptr++;
}
switch (*nptr) {
case '-':
*sgn = true;
nptr++;
break;
case '+':
nptr++;
break;
}
if (base == 0)
base = _prefixbase(&nptr, nonstd);
if (base == 16 && !nonstd) {
if (nptr[0] == '0' && (nptr[1] == 'x' || nptr[1] == 'X') &&
_digit_value(nptr[2]) < base)
nptr += 2;
}
if (base < 2 || base > 36) {
*err = EINVAL;
return 0;
}
if (_digit_value(*nptr) >= base) {
if (endptr != NULL)
*endptr = (char *) first;
return 0;
}
uintmax_t result = 0;
uintmax_t max = _max_value(base);
int digit;
while (digit = _digit_value(*nptr), digit < base) {
if (result > max ||
__builtin_add_overflow(result * base, digit, &result)) {
*err = nonstd ? EOVERFLOW : ERANGE;
result = UINTMAX_MAX;
break;
}
nptr++;
}
if (endptr != NULL) {
while (_digit_value(*nptr) < base) {
nptr++;
}
*endptr = (char *) nptr;
}
return result;
}
static inline intmax_t _strtosigned(const char *nptr, char **endptr, int base,
intmax_t min, intmax_t max, errno_t *err, bool nonstd)
{
bool sgn = false;
uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
if (number > (uintmax_t) max) {
if (sgn && (number - 1 == (uintmax_t) max)) {
return min;
}
*err = nonstd ? EOVERFLOW : ERANGE;
return (sgn ? min : max);
}
return (sgn ? -number : number);
}
static inline uintmax_t _strtounsigned(const char *nptr, char **endptr, int base,
uintmax_t max, errno_t *err, bool nonstd)
{
bool sgn = false;
uintmax_t number = _strtoumax(nptr, endptr, base, &sgn, err, nonstd);
if (nonstd && sgn) {
*err = EINVAL;
return 0;
}
if (number > max) {
*err = nonstd ? EOVERFLOW : ERANGE;
return max;
}
return (sgn ? -number : number);
}
long strtol(const char *nptr, char **endptr, int base)
{
#if !__STDC_HOSTED__
errno_t errno;
#endif
return _strtosigned(nptr, endptr, base, LONG_MIN, LONG_MAX, &errno, false);
}
unsigned long strtoul(const char *nptr, char **endptr, int base)
{
#if !__STDC_HOSTED__
errno_t errno;
#endif
return _strtounsigned(nptr, endptr, base, ULONG_MAX, &errno, false);
}
long long strtoll(const char *nptr, char **endptr, int base)
{
#if !__STDC_HOSTED__
errno_t errno;
#endif
return _strtosigned(nptr, endptr, base, LLONG_MIN, LLONG_MAX, &errno, false);
}
unsigned long long strtoull(const char *nptr, char **endptr, int base)
{
#if !__STDC_HOSTED__
errno_t errno;
#endif
return _strtounsigned(nptr, endptr, base, ULLONG_MAX, &errno, false);
}
intmax_t strtoimax(const char *nptr, char **endptr, int base)
{
#if !__STDC_HOSTED__
errno_t errno;
#endif
return _strtosigned(nptr, endptr, base, INTMAX_MIN, INTMAX_MAX, &errno, false);
}
uintmax_t strtoumax(const char *nptr, char **endptr, int base)
{
#if !__STDC_HOSTED__
errno_t errno;
#endif
return _strtounsigned(nptr, endptr, base, UINTMAX_MAX, &errno, false);
}
int atoi(const char *nptr)
{
return (int)strtol(nptr, NULL, 10);
}
long atol(const char *nptr)
{
return strtol(nptr, NULL, 10);
}
long long atoll(const char *nptr)
{
return strtoll(nptr, NULL, 10);
}
errno_t str_uint8_t(const char *nptr, const char **endptr, unsigned int base,
bool strict, uint8_t *result)
{
assert(result != NULL);
errno_t rc = EOK;
char *lendptr = (char *) nptr;
uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT8_MAX, &rc, true);
if (endptr)
*endptr = lendptr;
if (rc != EOK)
return rc;
if (strict && *lendptr != '\0')
return EINVAL;
*result = r;
return EOK;
}
errno_t str_uint16_t(const char *nptr, const char **endptr, unsigned int base,
bool strict, uint16_t *result)
{
assert(result != NULL);
errno_t rc = EOK;
char *lendptr = (char *) nptr;
uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT16_MAX, &rc, true);
if (endptr)
*endptr = lendptr;
if (rc != EOK)
return rc;
if (strict && *lendptr != '\0')
return EINVAL;
*result = r;
return EOK;
}
errno_t str_uint32_t(const char *nptr, const char **endptr, unsigned int base,
bool strict, uint32_t *result)
{
assert(result != NULL);
errno_t rc = EOK;
char *lendptr = (char *) nptr;
uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT32_MAX, &rc, true);
if (endptr)
*endptr = lendptr;
if (rc != EOK)
return rc;
if (strict && *lendptr != '\0')
return EINVAL;
*result = r;
return EOK;
}
errno_t str_uint64_t(const char *nptr, const char **endptr, unsigned int base,
bool strict, uint64_t *result)
{
assert(result != NULL);
errno_t rc = EOK;
char *lendptr = (char *) nptr;
uintmax_t r = _strtounsigned(nptr, &lendptr, base, UINT64_MAX, &rc, true);
if (endptr)
*endptr = lendptr;
if (rc != EOK)
return rc;
if (strict && *lendptr != '\0')
return EINVAL;
*result = r;
return EOK;
}
errno_t str_int64_t(const char *nptr, const char **endptr, unsigned int base,
bool strict, int64_t *result)
{
assert(result != NULL);
errno_t rc = EOK;
char *lendptr = (char *) nptr;
intmax_t r = _strtosigned(nptr, &lendptr, base, INT64_MIN, INT64_MAX, &rc, true);
if (endptr)
*endptr = lendptr;
if (rc != EOK)
return rc;
if (strict && *lendptr != '\0')
return EINVAL;
*result = r;
return EOK;
}
errno_t str_size_t(const char *nptr, const char **endptr, unsigned int base,
bool strict, size_t *result)
{
assert(result != NULL);
errno_t rc = EOK;
char *lendptr = (char *) nptr;
uintmax_t r = _strtounsigned(nptr, &lendptr, base, SIZE_MAX, &rc, true);
if (endptr)
*endptr = lendptr;
if (rc != EOK)
return rc;
if (strict && *lendptr != '\0')
return EINVAL;
*result = r;
return EOK;
}
HelenOS homepage, sources at GitHub