Skip to content

Instantly share code, notes, and snippets.

@lpereira
Created June 7, 2015 22:04
Show Gist options
  • Save lpereira/06d980bbb3828090f9dd to your computer and use it in GitHub Desktop.
Save lpereira/06d980bbb3828090f9dd to your computer and use it in GitHub Desktop.
Number parsing using C11 _Generic
/* parse_number() using C11 _Generic */
/* @lafp, 2015-06-07 */
#include <stdlib.h>
#include <stdbool.h>
#include <stdio.h>
#include <errno.h>
#define parse_number(Input, Output) \
_Generic((*Output), \
int: parse_number_strtoint, \
unsigned int: parse_number_strtouint, \
long: parse_number_strtol, \
long long: parse_number_strtoll, \
unsigned long: parse_number_strtoul, \
unsigned long long: parse_number_strtoull, \
float: parse_number_strtof, \
double: parse_number_strtod, \
long double: parse_number_strtold)(Input, Output)
#define DECLARE_INT_PARSE_FN(Type, ParseFn) \
bool \
parse_number_ ## ParseFn(const char *input, Type *output) \
{ \
char *endptr = NULL; \
errno = 0; \
*output = ParseFn(input, &endptr, 0); \
return errno == 0 && endptr && *endptr == '\0'; \
}
int
strtoint(const char *input, char **endptr, int base)
{
if (sizeof(int) == sizeof(long long)) {
long long output = strtoll(input, endptr, base);
if ((long long)(int)output != output)
errno = ERANGE;
return (int)output;
}
long output = strtol(input, endptr, base);
if ((long)(int)output != output)
errno = ERANGE;
return (int)output;
}
unsigned int
strtouint(const char *input, char **endptr, int base)
{
if (sizeof(unsigned int) == sizeof(unsigned long long)) {
unsigned long long output = strtoull(input, endptr, base);
if ((unsigned long long)(unsigned int)output != output)
errno = ERANGE;
return (unsigned int)output;
}
unsigned long output = strtoul(input, endptr, base);
if ((unsigned long)(unsigned int)output != output)
errno = ERANGE;
return (unsigned int)output;
}
DECLARE_INT_PARSE_FN(long, strtol)
DECLARE_INT_PARSE_FN(long long, strtoll)
DECLARE_INT_PARSE_FN(unsigned long, strtoul)
DECLARE_INT_PARSE_FN(unsigned long long, strtoull)
DECLARE_INT_PARSE_FN(int, strtoint)
DECLARE_INT_PARSE_FN(unsigned int, strtouint)
#undef DECLARE_INT_PARSE_FN
#define DECLARE_FLOAT_PARSE_FN(Type, ParseFn) \
bool \
parse_number_ ## ParseFn(const char *input, Type *output) \
{ \
char *endptr = NULL; \
errno = 0; \
*output = ParseFn(input, &endptr); \
return errno == 0 && endptr && *endptr == '\0'; \
}
DECLARE_FLOAT_PARSE_FN(float, strtof)
DECLARE_FLOAT_PARSE_FN(double, strtod)
DECLARE_FLOAT_PARSE_FN(long double, strtold)
#undef DECLARE_FLOAT_PARSE_FN
int
main(void)
{
long loutput;
long long lloutput;
unsigned long uloutput;
unsigned long long ulloutput;
size_t soutput;
int ioutput;
unsigned int uioutput;
float foutput;
double doutput;
long double ldoutput;
if (!parse_number("0", &loutput))
return 1;
if (!parse_number("0", &lloutput))
return 1;
if (!parse_number("0", &uloutput))
return 1;
if (!parse_number("0", &ulloutput))
return 1;
if (!parse_number("0", &soutput))
return 1;
if (!parse_number("0", &ioutput))
return 1;
if (!parse_number("0", &uioutput))
return 1;
if (!parse_number("0", &foutput))
return 1;
if (!parse_number("0", &doutput))
return 1;
if (!parse_number("0", &ldoutput))
return 1;
printf("done!\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment