Skip to content

Instantly share code, notes, and snippets.

@oguz-ismail
Last active March 13, 2023 16:19
Show Gist options
  • Save oguz-ismail/f964568ec4d576a23157eff93df7c2a8 to your computer and use it in GitHub Desktop.
Save oguz-ismail/f964568ec4d576a23157eff93df7c2a8 to your computer and use it in GitHub Desktop.
#include <errno.h>
#include <limits.h>
#include <stddef.h>
#include <stdint.h>
int
parse_signed(const char src[static 1], intmax_t min, intmax_t max,
intmax_t dest[static 1], char **endptr) {
int sign;
intmax_t value;
int got_sign;
int got_digit;
const char *p;
int digit;
if (min > max || min > INTMAX_MAX - 9 || max < INTMAX_MIN + 9) {
errno = EINVAL;
return 0;
}
sign = 1;
value = 0;
got_sign = 0;
got_digit = 0;
for (p = src; *p != '\0'; p++) {
if (*p >= '0' && *p <= '9') {
digit = *p - '0';
got_digit = 1;
if ((sign == 1 && value > (max - digit) / 10) ||
(sign == -1 && value < (min + digit) / 10)) {
errno = ERANGE;
return 0;
}
value *= 10;
value += sign * digit;
}
else if (!got_digit && !got_sign && (*p == '-' || *p == '+')) {
if (*p == '-')
sign = -1;
got_sign = 1;
}
else {
break;
}
}
if (!got_digit)
return 0;
*dest = value;
if (endptr != NULL)
*endptr = (char *)p;
return 1;
}
int
parse_unsigned(const char src[static 1], uintmax_t min, uintmax_t max,
uintmax_t dest[static 1], char **endptr) {
uintmax_t value;
int got_digit;
const char *p;
int digit;
if (min > max || min > INTMAX_MAX - 9 || max < 9) {
errno = EINVAL;
return 0;
}
value = 0;
got_digit = 0;
for (p = src; *p != '\0'; p++) {
if (*p >= '0' && *p <= '9') {
digit = *p - '0';
got_digit = 1;
if (value > (max - digit) / 10) {
errno = ERANGE;
return 0;
}
value *= 10;
value += digit;
}
else {
break;
}
}
if (!got_digit)
return 0;
if (value < min) {
errno = ERANGE;
return 0;
}
*dest = value;
if (endptr != NULL)
*endptr = (char *)p;
return 1;
}
#include <stdio.h>
#include <limits.h>
#include <errno.h>
int
read_int(FILE* src, int dest[static 1]) {
int sign;
int value;
int got_sign;
int got_digit;
int c;
int digit;
sign = 1;
value = 0;
got_sign = 0;
got_digit = 0;
while ((c = fgetc(src)) != EOF) {
if (c >= '0' && c <= '9') {
digit = c - '0';
got_digit = 1;
if ((sign == -1 && value < (INT_MIN + digit) / 10) ||
(sign == 1 && value > (INT_MAX - digit) / 10)) {
errno = ERANGE;
return 0;
}
value *= 10;
value += sign * digit;
}
else if (!got_digit && !got_sign && (c == '-' || c == '+')) {
if (c == '-')
sign = -1;
got_sign = 1;
}
else {
ungetc(c, src);
break;
}
}
if (ferror(src))
return 0;
*dest = value;
return 1;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment