]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
include/strutils: cleanup strto..() functions
authorKarel Zak <kzak@redhat.com>
Tue, 22 Jun 2021 12:20:42 +0000 (14:20 +0200)
committerKarel Zak <kzak@redhat.com>
Tue, 22 Jun 2021 12:42:15 +0000 (14:42 +0200)
* add ul_strtos64() and ul_strtou64()
* add simple test

Addresses: https://github.com/karelzak/util-linux/issues/1358
Signed-off-by: Karel Zak <kzak@redhat.com>
include/strutils.h
lib/strutils.c

index e75a2f0e17eebb8c1c975a2c6376566291c65d0a..389e8499051c740480e6db070140ece9257005d9 100644 (file)
@@ -19,6 +19,9 @@ extern int parse_size(const char *str, uintmax_t *res, int *power);
 extern int strtosize(const char *str, uintmax_t *res);
 extern uintmax_t strtosize_or_err(const char *str, const char *errmesg);
 
+extern int ul_strtos64(const char *str, int64_t *num, int base);
+extern int ul_strtou64(const char *str, uint64_t *num, int base);
+
 extern int16_t strtos16_or_err(const char *str, const char *errmesg);
 extern uint16_t strtou16_or_err(const char *str, const char *errmesg);
 extern uint16_t strtox16_or_err(const char *str, const char *errmesg);
index ee2c8354954c8be010862cc36ee2378a19bf0998..d9976dca702c8af8a8eefd310f1faa5468de2e8b 100644 (file)
@@ -319,39 +319,80 @@ char *strndup(const char *s, size_t n)
 }
 #endif
 
-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base);
-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base);
+/*
+ * convert strings to numbers; returns <0 on error, and 0 on success
+ */
+int ul_strtos64(const char *str, int64_t *num, int base)
+{
+       char *end = NULL;
 
-int16_t strtos16_or_err(const char *str, const char *errmesg)
+       errno = 0;
+       if (str == NULL || *str == '\0')
+               return -EINVAL;
+       *num = (int64_t) strtoimax(str, &end, base);
+
+       if (errno || str == end || (end && *end))
+               return -EINVAL;
+       return 0;
+}
+
+int ul_strtou64(const char *str, uint64_t *num, int base)
 {
-       int32_t num = strtos32_or_err(str, errmesg);
+       char *end = NULL;
 
-       if (num < INT16_MIN || num > INT16_MAX) {
-               errno = ERANGE;
-               err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-       }
-       return num;
+       errno = 0;
+       if (str == NULL || *str == '\0')
+               return -EINVAL;
+       *num = (uint64_t) strtoumax(str, &end, base);
+
+       if (errno || str == end || (end && *end))
+               return -EINVAL;
+       return 0;
 }
 
-static uint16_t _strtou16_or_err(const char *str, const char *errmesg, int base)
+/*
+ * Covert strings to numbers and print message on error.
+ *
+ * Note that hex functions (strtox..()) returns unsigned numbers, if you need
+ * something else then use ul_strtos64(s, &n, 16).
+ */
+int64_t strtos64_or_err(const char *str, const char *errmesg)
 {
-       uint32_t num = _strtou32_or_err(str, errmesg, base);
+       int64_t num = 0;
 
-       if (num > UINT16_MAX) {
-               errno = ERANGE;
-               err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       if (ul_strtos64(str, &num, 10) != 0) {
+               if (errno == ERANGE)
+                       err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+
+               errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
        }
        return num;
 }
 
-uint16_t strtou16_or_err(const char *str, const char *errmesg)
+uint64_t strtou64_or_err(const char *str, const char *errmesg)
 {
-       return _strtou16_or_err(str, errmesg, 10);
+       uint64_t num = 0;
+
+       if (ul_strtou64(str, &num, 10)) {
+               if (errno == ERANGE)
+                       err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+
+               errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       }
+       return num;
 }
 
-uint16_t strtox16_or_err(const char *str, const char *errmesg)
+uint64_t strtox64_or_err(const char *str, const char *errmesg)
 {
-       return _strtou16_or_err(str, errmesg, 16);
+       uint64_t num = 0;
+
+       if (ul_strtou64(str, &num, 16)) {
+               if (errno == ERANGE)
+                       err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+
+               errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       }
+       return num;
 }
 
 int32_t strtos32_or_err(const char *str, const char *errmesg)
@@ -365,9 +406,9 @@ int32_t strtos32_or_err(const char *str, const char *errmesg)
        return num;
 }
 
-static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
+uint32_t strtou32_or_err(const char *str, const char *errmesg)
 {
-       uint64_t num = _strtou64_or_err(str, errmesg, base);
+       uint64_t num = strtou64_or_err(str, errmesg);
 
        if (num > UINT32_MAX) {
                errno = ERANGE;
@@ -376,66 +417,48 @@ static uint32_t _strtou32_or_err(const char *str, const char *errmesg, int base)
        return num;
 }
 
-uint32_t strtou32_or_err(const char *str, const char *errmesg)
-{
-       return _strtou32_or_err(str, errmesg, 10);
-}
-
 uint32_t strtox32_or_err(const char *str, const char *errmesg)
 {
-       return _strtou32_or_err(str, errmesg, 16);
+       uint64_t num = strtox64_or_err(str, errmesg);
+
+       if (num > UINT32_MAX) {
+               errno = ERANGE;
+               err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       }
+       return num;
 }
 
-int64_t strtos64_or_err(const char *str, const char *errmesg)
+int16_t strtos16_or_err(const char *str, const char *errmesg)
 {
-       int64_t num;
-       char *end = NULL;
-
-       errno = 0;
-       if (str == NULL || *str == '\0')
-               goto err;
-       num = strtoimax(str, &end, 10);
-
-       if (errno || str == end || (end && *end))
-               goto err;
+       int64_t num = strtos64_or_err(str, errmesg);
 
-       return num;
-err:
-       if (errno == ERANGE)
+       if (num < INT16_MIN || num > INT16_MAX) {
+               errno = ERANGE;
                err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
-       errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       }
+       return num;
 }
 
-static uint64_t _strtou64_or_err(const char *str, const char *errmesg, int base)
+uint16_t strtou16_or_err(const char *str, const char *errmesg)
 {
-       uintmax_t num;
-       char *end = NULL;
-
-       errno = 0;
-       if (str == NULL || *str == '\0')
-               goto err;
-       num = strtoumax(str, &end, base);
-
-       if (errno || str == end || (end && *end))
-               goto err;
+       uint64_t num = strtou64_or_err(str, errmesg);
 
-       return num;
-err:
-       if (errno == ERANGE)
+       if (num > UINT16_MAX) {
+               errno = ERANGE;
                err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
-
-       errx(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       }
+       return num;
 }
 
-uint64_t strtou64_or_err(const char *str, const char *errmesg)
+uint16_t strtox16_or_err(const char *str, const char *errmesg)
 {
-       return _strtou64_or_err(str, errmesg, 10);
-}
+       uint64_t num = strtox64_or_err(str, errmesg);
 
-uint64_t strtox64_or_err(const char *str, const char *errmesg)
-{
-       return _strtou64_or_err(str, errmesg, 16);
+       if (num > UINT16_MAX) {
+               errno = ERANGE;
+               err(STRTOXX_EXIT_CODE, "%s: '%s'", errmesg, str);
+       }
+       return num;
 }
 
 double strtod_or_err(const char *str, const char *errmesg)
@@ -1207,29 +1230,36 @@ done:
 
 int main(int argc, char *argv[])
 {
-       if (argc == 3 && strcmp(argv[1], "--size") == 0)
+       if (argc == 3 && strcmp(argv[1], "--size") == 0) {
                return test_strutils_sizes(argc - 1, argv + 1);
 
-       if (argc == 4 && strcmp(argv[1], "--cmp-paths") == 0)
+       } else if (argc == 4 && strcmp(argv[1], "--cmp-paths") == 0) {
                return test_strutils_cmp_paths(argc - 1, argv + 1);
 
-       if (argc == 4 && strcmp(argv[1], "--strdup-member") == 0)
+       } else if (argc == 4 && strcmp(argv[1], "--strdup-member") == 0) {
                return test_strdup_to_member(argc - 1, argv + 1);
 
-       if  (argc == 4 && strcmp(argv[1], "--stralnumcmp") == 0) {
+       } else if  (argc == 4 && strcmp(argv[1], "--stralnumcmp") == 0) {
                printf("%s\n", ul_stralnumcmp(argv[2], argv[3]) == 0 ?
                                "match" : "dismatch");
                return EXIT_SUCCESS;
-
-       } else if (argc == 3 && strcmp(argv[1], "--normalize") == 0)
+       } else if (argc == 3 && strcmp(argv[1], "--normalize") == 0) {
                return test_strutils_normalize(argc - 1, argv + 1);
 
-       else {
+       } else if (argc == 3 && strcmp(argv[1], "--str2num") == 0) {
+               uint64_t n;
+
+               if (ul_strtou64(argv[2], &n, 10) == 0) {
+                       printf("'%s' --> %ju\n", argv[2], (uintmax_t) n);
+                       return EXIT_SUCCESS;
+               }
+       } else {
                fprintf(stderr, "usage: %1$s --size <number>[suffix]\n"
                                "       %1$s --cmp-paths <path> <path>\n"
                                "       %1$s --strdup-member <str> <str>\n"
                                "       %1$s --stralnumcmp <str> <str>\n"
-                               "       %1$s --normalize <str>\n",
+                               "       %1$s --normalize <str>\n"
+                               "       %1$s --num2num <str>\n",
                                argv[0]);
                exit(EXIT_FAILURE);
        }