|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* An implementation of strtoull() for compilers that do not have this
|
|
Packit |
fcad23 |
* function, e.g. MSVC.
|
|
Packit |
fcad23 |
* See also http://www.opengroup.org/onlinepubs/000095399/functions/strtoul.html
|
|
Packit |
fcad23 |
* for more information about strtoull().
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* For MSVC, disable the warning "unary minus operator applied to unsigned
|
|
Packit |
fcad23 |
* type, result still unsigned"
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
#ifdef _MSC_VER
|
|
Packit |
fcad23 |
#pragma warning (disable: 4146)
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#define __STDC_CONSTANT_MACROS /* Enable UINT64_C in <stdint.h> */
|
|
Packit |
fcad23 |
#define __STDC_FORMAT_MACROS /* Enable PRIu64 in <inttypes.h> */
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/net-snmp-config.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#ifndef HAVE_STRTOULL
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <errno.h>
|
|
Packit |
fcad23 |
#include <ctype.h>
|
|
Packit |
fcad23 |
#include <limits.h>
|
|
Packit |
fcad23 |
#ifdef HAVE_INTTYPES_H
|
|
Packit |
fcad23 |
#include <inttypes.h>
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#include <net-snmp/types.h>
|
|
Packit |
fcad23 |
#include <net-snmp/library/system.h>
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* UINT64_C: C99 macro for the suffix for uint64_t constants.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
#ifndef UINT64_C
|
|
Packit |
fcad23 |
#ifdef _MSC_VER
|
|
Packit |
fcad23 |
#define UINT64_C(c) c##ui64
|
|
Packit |
fcad23 |
#else
|
|
Packit |
fcad23 |
#define UINT64_C(c) c##ULL
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* According to the C99 standard, the constant ULLONG_MAX must be defined in
|
|
Packit |
fcad23 |
* <limits.h>. Define it here for pre-C99 compilers.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
#ifndef ULLONG_MAX
|
|
Packit |
fcad23 |
#define ULLONG_MAX UINT64_C(0xffffffffffffffff)
|
|
Packit |
fcad23 |
#endif
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
uint64_t
|
|
Packit |
fcad23 |
strtoull(const char *nptr, char **endptr, int base)
|
|
Packit |
fcad23 |
{
|
|
Packit |
fcad23 |
uint64_t result = 0;
|
|
Packit |
fcad23 |
const char *p;
|
|
Packit |
fcad23 |
const char *first_nonspace;
|
|
Packit |
fcad23 |
const char *digits_start;
|
|
Packit |
fcad23 |
int sign = 1;
|
|
Packit |
fcad23 |
int out_of_range = 0;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (base != 0 && (base < 2 || base > 36))
|
|
Packit |
fcad23 |
goto invalid_input;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
p = nptr;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Process the initial, possibly empty, sequence of white-space characters.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
while (isspace((unsigned char) (*p)))
|
|
Packit |
fcad23 |
p++;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
first_nonspace = p;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Determine sign.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (*p == '+')
|
|
Packit |
fcad23 |
p++;
|
|
Packit |
fcad23 |
else if (*p == '-') {
|
|
Packit |
fcad23 |
p++;
|
|
Packit |
fcad23 |
sign = -1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (base == 0) {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Determine base.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (*p == '0') {
|
|
Packit |
fcad23 |
if ((p[1] == 'x' || p[1] == 'X')) {
|
|
Packit |
fcad23 |
if (isxdigit((unsigned char)(p[2]))) {
|
|
Packit |
fcad23 |
base = 16;
|
|
Packit |
fcad23 |
p += 2;
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* Special case: treat the string "0x" without any further
|
|
Packit |
fcad23 |
* hex digits as a decimal number.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
base = 10;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
base = 8;
|
|
Packit |
fcad23 |
p++;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
} else {
|
|
Packit |
fcad23 |
base = 10;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
} else if (base == 16) {
|
|
Packit |
fcad23 |
/*
|
|
Packit |
fcad23 |
* For base 16, skip the optional "0x" / "0X" prefix.
|
|
Packit |
fcad23 |
*/
|
|
Packit |
fcad23 |
if (*p == '0' && (p[1] == 'x' || p[1] == 'X')
|
|
Packit |
fcad23 |
&& isxdigit((unsigned char)(p[2]))) {
|
|
Packit |
fcad23 |
p += 2;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
digits_start = p;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
for (; *p; p++) {
|
|
Packit |
fcad23 |
int digit;
|
|
Packit |
fcad23 |
digit = ('0' <= *p && *p <= '9') ? *p - '0'
|
|
Packit |
fcad23 |
: ('a' <= *p && *p <= 'z') ? (*p - 'a' + 10)
|
|
Packit |
fcad23 |
: ('A' <= *p && *p <= 'Z') ? (*p - 'A' + 10) : 36;
|
|
Packit |
fcad23 |
if (digit < base) {
|
|
Packit |
fcad23 |
if (! out_of_range) {
|
|
Packit |
fcad23 |
if (result > ULLONG_MAX / base
|
|
Packit |
fcad23 |
|| result * base > ULLONG_MAX - digit) {
|
|
Packit |
fcad23 |
out_of_range = 1;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
result = result * base + digit;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
} else
|
|
Packit |
fcad23 |
break;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (p > first_nonspace && p == digits_start)
|
|
Packit |
fcad23 |
goto invalid_input;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (p == first_nonspace)
|
|
Packit |
fcad23 |
p = nptr;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (endptr)
|
|
Packit |
fcad23 |
*endptr = (char *) p;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
if (out_of_range) {
|
|
Packit |
fcad23 |
errno = ERANGE;
|
|
Packit |
fcad23 |
return ULLONG_MAX;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
return sign > 0 ? result : -result;
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
invalid_input:
|
|
Packit |
fcad23 |
errno = EINVAL;
|
|
Packit |
fcad23 |
if (endptr)
|
|
Packit |
fcad23 |
*endptr = (char *) nptr;
|
|
Packit |
fcad23 |
return 0;
|
|
Packit |
fcad23 |
}
|
|
Packit |
fcad23 |
|
|
Packit |
fcad23 |
#endif /* HAVE_STRTOULL */
|