From a83942778fc85ad92db9082cf0d7c2d958d98aaf Mon Sep 17 00:00:00 2001 From: Olivier Matz Date: Thu, 25 Apr 2019 19:55:36 +0200 Subject: [PATCH] factorize integer parsing --- include/ecoli_string.h | 38 ++++++++++++++++++++++ src/ecoli_node_int.c | 73 +++++++++++++----------------------------- src/ecoli_string.c | 66 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 126 insertions(+), 51 deletions(-) diff --git a/include/ecoli_string.h b/include/ecoli_string.h index a523b88..d611a13 100644 --- a/include/ecoli_string.h +++ b/include/ecoli_string.h @@ -7,6 +7,7 @@ #include #include +#include /* count the number of identical chars at the beginning of 2 strings */ size_t ec_strcmp_count(const char *s1, const char *s2); @@ -23,4 +24,41 @@ int ec_vasprintf(char **buf, const char *fmt, va_list ap); /* return true if string is only composed of spaces (' ', '\n', ...) */ bool ec_str_is_space(const char *s); +/** + * Parse a string for a signed integer. + * + * @param str + * The string to parse. + * @param base + * The base (0 means "guess"). + * @param min + * The minimum allowed value. + * @param max + * The maximum allowed value. + * @param val + * The pointer to the value to be set on success. + * @return + * On success, return 0. Else, return -1 and set errno. + */ +int ec_str_parse_llint(const char *str, unsigned int base, int64_t min, + int64_t max, int64_t *val); + +/** + * Parse a string for an unsigned integer. + * + * @param str + * The string to parse. + * @param base + * The base (0 means "guess"). + * @param min + * The minimum allowed value. + * @param max + * The maximum allowed value. + * @param val + * The pointer to the value to be set on success. + * @return + * On success, return 0. Else, return -1 and set errno. + */ +int ec_str_parse_ullint(const char *str, unsigned int base, uint64_t min, + uint64_t max, uint64_t *val); #endif diff --git a/src/ecoli_node_int.c b/src/ecoli_node_int.c index 9b56e22..80f2fd5 100644 --- a/src/ecoli_node_int.c +++ b/src/ecoli_node_int.c @@ -18,8 +18,9 @@ #include #include #include -#include +#include #include +#include EC_LOG_TYPE_REGISTER(node_int); @@ -40,68 +41,38 @@ struct ec_node_int_uint { unsigned int base; }; -/* XXX to utils.c ? */ static int parse_llint(struct ec_node_int_uint *node, const char *str, int64_t *val) { - char *endptr; - int save_errno = errno; - - errno = 0; - *val = strtoll(str, &endptr, node->base); - - if ((errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN)) || - (errno != 0 && *val == 0)) - return -1; - - if (node->check_min && *val < node->min) { - errno = ERANGE; - return -1; - } + int64_t min, max; - if (node->check_max && *val > node->max) { - errno = ERANGE; - return -1; - } - - if (*endptr != 0) { - errno = EINVAL; - return -1; - } + if (node->check_min) + min = node->min; + else + min = LLONG_MIN; + if (node->check_max) + max = node->max; + else + max = LLONG_MAX; - errno = save_errno; - return 0; + return ec_str_parse_llint(str, node->base, min, max, val); } static int parse_ullint(struct ec_node_int_uint *node, const char *str, uint64_t *val) { - char *endptr; - int save_errno = errno; - - /* since a negative input is silently converted to a positive - * one by strtoull(), first check that it is positive */ - if (strchr(str, '-')) - return -1; + uint64_t min, max; - errno = 0; - *val = strtoull(str, &endptr, node->base); - - if ((errno == ERANGE && *val == ULLONG_MAX) || - (errno != 0 && *val == 0)) - return -1; - - if (node->check_min && *val < node->umin) - return -1; - - if (node->check_max && *val > node->umax) - return -1; - - if (*endptr != 0) - return -1; + if (node->check_min) + min = node->min; + else + min = 0; + if (node->check_max) + max = node->max; + else + max = ULLONG_MAX; - errno = save_errno; - return 0; + return ec_str_parse_ullint(str, node->base, min, max, val); } static int ec_node_int_uint_parse(const struct ec_node *gen_node, diff --git a/src/ecoli_string.c b/src/ecoli_string.c index fd427b4..c823664 100644 --- a/src/ecoli_string.c +++ b/src/ecoli_string.c @@ -6,6 +6,9 @@ #include #include #include +#include +#include +#include #include #include @@ -87,3 +90,66 @@ bool ec_str_is_space(const char *s) } return true; } + +int ec_str_parse_llint(const char *str, unsigned int base, int64_t min, + int64_t max, int64_t *val) +{ + char *endptr; + int save_errno = errno; + + errno = 0; + *val = strtoll(str, &endptr, base); + + if ((errno == ERANGE && (*val == LLONG_MAX || *val == LLONG_MIN)) || + (errno != 0 && *val == 0)) + return -1; + + if (*val < min) { + errno = ERANGE; + return -1; + } + + if (*val > max) { + errno = ERANGE; + return -1; + } + + if (*endptr != 0) { + errno = EINVAL; + return -1; + } + + errno = save_errno; + return 0; +} + +int ec_str_parse_ullint(const char *str, unsigned int base, uint64_t min, + uint64_t max, uint64_t *val) +{ + char *endptr; + int save_errno = errno; + + /* since a negative input is silently converted to a positive + * one by strtoull(), first check that it is positive */ + if (strchr(str, '-')) + return -1; + + errno = 0; + *val = strtoull(str, &endptr, base); + + if ((errno == ERANGE && *val == ULLONG_MAX) || + (errno != 0 && *val == 0)) + return -1; + + if (*val < min) + return -1; + + if (*val > max) + return -1; + + if (*endptr != 0) + return -1; + + errno = save_errno; + return 0; +} -- 2.20.1