88 lines
1.8 KiB
C
88 lines
1.8 KiB
C
#include <stdlib.h>
|
|
#include <limits.h>
|
|
#include <errno.h>
|
|
#include <ctype.h>
|
|
|
|
static inline long long strtonum(const char *nptr, long long minval,
|
|
long long maxval, const char **errstr) {
|
|
const char *p = nptr;
|
|
char *endptr;
|
|
long long result;
|
|
int saved_errno;
|
|
|
|
if (errstr != NULL)
|
|
*errstr = NULL;
|
|
|
|
if (nptr == NULL || *nptr == '\0') {
|
|
if (errstr != NULL)
|
|
*errstr = "invalid";
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
if (minval > maxval) {
|
|
if (errstr != NULL)
|
|
*errstr = "invalid";
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
while (isspace((unsigned char)*p))
|
|
p++;
|
|
|
|
saved_errno = errno;
|
|
errno = 0;
|
|
|
|
result = strtoll(p, &endptr, 10);
|
|
|
|
if (errno == ERANGE) {
|
|
if (errstr != NULL) {
|
|
*errstr = (result == LLONG_MIN || result < minval) ?
|
|
"too small" : "too large";
|
|
}
|
|
errno = ERANGE;
|
|
return 0;
|
|
}
|
|
|
|
if (endptr == p) {
|
|
if (errstr != NULL)
|
|
*errstr = "invalid";
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
while (isspace((unsigned char)*endptr))
|
|
endptr++;
|
|
if (*endptr != '\0') {
|
|
if (errstr != NULL)
|
|
*errstr = "invalid";
|
|
errno = EINVAL;
|
|
return 0;
|
|
}
|
|
|
|
if (result < minval) {
|
|
if (errstr != NULL)
|
|
*errstr = "too small";
|
|
errno = ERANGE;
|
|
return 0;
|
|
}
|
|
if (result > maxval) {
|
|
if (errstr != NULL)
|
|
*errstr = "too large";
|
|
errno = ERANGE;
|
|
return 0;
|
|
}
|
|
|
|
if (errstr != NULL)
|
|
*errstr = NULL;
|
|
return result;
|
|
}
|
|
|
|
static inline void *reallocf(void *ptr, size_t size) {
|
|
void *new_ptr = realloc(ptr, size);
|
|
if (new_ptr == NULL && size != 0) {
|
|
free(ptr);
|
|
}
|
|
return new_ptr;
|
|
}
|