factorize integer parsing
authorOlivier Matz <zer0@droids-corp.org>
Thu, 25 Apr 2019 17:55:36 +0000 (19:55 +0200)
committerOlivier Matz <zer0@droids-corp.org>
Thu, 25 Apr 2019 17:55:36 +0000 (19:55 +0200)
include/ecoli_string.h
src/ecoli_node_int.c
src/ecoli_string.c

index a523b88..d611a13 100644 (file)
@@ -7,6 +7,7 @@
 
 #include <stddef.h>
 #include <stdbool.h>
+#include <stdint.h>
 
 /* 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
index 9b56e22..80f2fd5 100644 (file)
@@ -18,8 +18,9 @@
 #include <ecoli_config.h>
 #include <ecoli_parse.h>
 #include <ecoli_complete.h>
-#include <ecoli_node_int.h>
+#include <ecoli_string.h>
 #include <ecoli_test.h>
+#include <ecoli_node_int.h>
 
 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,
index fd427b4..c823664 100644 (file)
@@ -6,6 +6,9 @@
 #include <stddef.h>
 #include <string.h>
 #include <stdio.h>
+#include <errno.h>
+#include <limits.h>
+#include <stdint.h>
 #include <ctype.h>
 
 #include <ecoli_assert.h>
@@ -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;
+}