]> www.infradead.org Git - users/sagi/nvme-cli.git/commitdiff
util: Update suffix_binary_parse API
authorDaniel Wagner <dwagner@suse.de>
Thu, 2 Feb 2023 14:58:33 +0000 (15:58 +0100)
committerDaniel Wagner <dwagner@suse.de>
Tue, 7 Feb 2023 15:32:06 +0000 (16:32 +0100)
Use the same API type for suffix_binary_parse as we have
for suffix_si_parse. While at it also introduce a unit test
for it.

Reviewed-by: Tokunori Ikegami <ikegami.t@gmail.com>
Signed-off-by: Daniel Wagner <dwagner@suse.de>
unit/meson.build
unit/test-suffix-binary-parse.c [new file with mode: 0644]
util/argconfig.c
util/suffix.c
util/suffix.h

index d4ff925c971eb1d0083d2da6575f8ed597a12944..296f763796e151212f533f90c644708cfc647feb 100644 (file)
@@ -18,6 +18,15 @@ test_suffix_si_parse = executable(
 
 test('suffix_si_parse', test_suffix_si_parse)
 
+test_suffix_binary_parse = executable(
+    'test-suffix-binary-parse',
+    ['test-suffix-binary-parse.c', '../util/suffix.c'],
+    include_directories: [incdir, '..'],
+    dependencies: [libnvme_dep],
+)
+
+test('suffix_binary_parse', test_suffix_binary_parse)
+
 test_uint128_si = executable(
     'test-uint128-si',
     ['test-uint128-si.c', '../util/types.c', '../util/suffix.c'],
diff --git a/unit/test-suffix-binary-parse.c b/unit/test-suffix-binary-parse.c
new file mode 100644 (file)
index 0000000..41b0562
--- /dev/null
@@ -0,0 +1,68 @@
+// SPDX-License-Identifier: GPL-2.0-or-later
+
+#include <string.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <errno.h>
+
+#include "../util/suffix.h"
+#include "../util/types.h"
+
+#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
+
+static int test_rc;
+
+static void check_num(const char *val, __u64 exp, __u64 num)
+{
+       if (exp == num)
+               return;
+
+       printf("ERROR: printing {%s},  got '%llu', expected '%llu'\n",
+              val, (unsigned long long)num, (unsigned long long)exp);
+
+       test_rc = 1;
+}
+
+struct tonum_test {
+       const char *val;
+       const uint64_t exp;
+       int ret;
+};
+
+static struct tonum_test tonum_tests[] = {
+       { "1Ki", 1024, 0},
+       { "34Gi", 36507222016, 0 },
+       { "1234", 0, -EINVAL },
+       { "34.9Ki", 0, -EINVAL},
+       { "32Gii", 0, -EINVAL },
+};
+
+void tonum_test(struct tonum_test *test)
+{
+       char *endptr;
+       uint64_t num;
+       int ret;
+
+       ret = suffix_binary_parse(test->val, &endptr, &num);
+       if (ret != test->ret) {
+               printf("ERROR: converting {%s} failed\n", test->val);
+               test_rc = 1;
+               return;
+       }
+       if (ret)
+               return;
+
+       check_num(test->val, test->exp, num);
+}
+
+int main(void)
+{
+       unsigned int i;
+
+       test_rc = 0;
+
+       for (i = 0; i < ARRAY_SIZE(tonum_tests); i++)
+               tonum_test(&tonum_tests[i]);
+
+       return test_rc ? EXIT_FAILURE : EXIT_SUCCESS;
+}
index 231a704a57314d9013678419a31812dabcf0a62c..8743722899679e092a00c2084c0c5bb47e1393fb 100644 (file)
@@ -293,8 +293,7 @@ int argconfig_parse(int argc, char *argv[], const char *program_desc,
                                goto out;
                        }
                } else if (s->config_type == CFG_LONG_SUFFIX) {
-                       *((uint64_t *)value_addr) = suffix_binary_parse(optarg);
-                       if (errno) {
+                       if (suffix_binary_parse(optarg, &endptr, (uint64_t*)&value_addr)) {
                                fprintf(stderr,
                                        "Expected long suffixed integer argument for '%s' but got '%s'!\n",
                                        long_opts[option_index].name, optarg);
index 94bd279c69e86f556803135c2fe83c78af983e4d..1d753867668deb7efd8b4888a9133dfdb9d74259 100644 (file)
@@ -167,14 +167,15 @@ static struct binary_suffix {
        {30, "Gi"},
        {20, "Mi"},
        {10, "Ki"},
-       {0, ""}
 };
 
 const char *suffix_binary_get(long long *value)
 {
-       struct binary_suffix *s;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(binary_suffixes); i++) {
+               struct binary_suffix *s = &binary_suffixes[i];
 
-       for (s = binary_suffixes; s->shift != 0; s++) {
                if (llabs(*value) >= (1LL << s->shift)) {
                        *value =
                            (*value + (1LL << (s->shift - 1))) / (1LL << s->shift);
@@ -187,9 +188,11 @@ const char *suffix_binary_get(long long *value)
 
 const char *suffix_dbinary_get(double *value)
 {
-       struct binary_suffix *s;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(binary_suffixes); i++) {
+               struct binary_suffix *s = &binary_suffixes[i];
 
-       for (s = binary_suffixes; s->shift != 0; s++) {
                if (fabs(*value) >= (1LL << s->shift)) {
                        *value = *value / (1LL << s->shift);
                        return s->suffix;
@@ -199,24 +202,35 @@ const char *suffix_dbinary_get(double *value)
        return "";
 }
 
-uint64_t suffix_binary_parse(const char *value)
+int suffix_binary_parse(const char *str, char **endptr, uint64_t *val)
 {
-       char *suffix;
-       errno = 0;
-       uint64_t ret = strtoull(value, &suffix, 0);
-       if (errno)
+       uint64_t ret;
+       int i;
+
+       ret = strtoull(str, endptr, 0);
+       if (str == *endptr ||
+           ((ret == ULLONG_MAX) && errno == ERANGE))
+               return -EINVAL;
+
+       if (str == *endptr) {
+               *val = ret;
                return 0;
+       }
+
+       for (i = 0; i < ARRAY_SIZE(binary_suffixes); i++) {
+               struct binary_suffix *s = &binary_suffixes[i];
 
-       struct binary_suffix *s;
-       for (s = binary_suffixes; s->shift != 0; s++) {
-               if (tolower(suffix[0]) == tolower(s->suffix[0])) {
+               if (tolower((*endptr)[0]) == tolower(s->suffix[0]) &&
+                   (s->suffix[0] != '\0' &&
+                    (((*endptr)[0] != '\0' &&
+                      (*endptr)[1] != '\0' &&
+                      (*endptr)[2] == '\0') &&
+                     (tolower((*endptr)[1]) == tolower(s->suffix[1]))))) {
                        ret <<= s->shift;
-                       return ret;
+                       *val = ret;
+                       return 0;
                }
        }
 
-       if (suffix[0] != '\0')
-               errno = EINVAL;
-
-       return ret;
+       return -EINVAL;
 }
index 8fab823b1acb5b12e6970a0bf1af1262a124f26d..5ea58f48ac8192ba7fcb0761273db4516d6ba993 100644 (file)
@@ -40,6 +40,6 @@ int suffix_si_parse(const char *str, char **endptr, uint64_t *val);
 const char *suffix_si_get_ld(long double *value);
 const char *suffix_binary_get(long long *value);
 const char *suffix_dbinary_get(double *value);
-uint64_t suffix_binary_parse(const char *value);
+int suffix_binary_parse(const char *str, char **endptr, uint64_t *val);
 
 #endif