Skip to contentSkip to conversation

cutils: Add qemu_strto*l() wrappers

PATCH Superseded Carlos L. Torres 2 participants 8 messages Jul 8, 2015

v1 of 3 Superseded Latest is v3 →

lore
Share & tools
lore
#0 lore raw

cover cutils: Add qemu_strto*l() wrappers

From: "Carlos L. Torres" <[email protected]>

Introduce qemu_ wrappers for strtol/strtoul/strtoll/strtoull C functions, ensure that errno is checked, and if NULL is passed as the endptr argument, then whole string has to be a valid number on the given base, otherwise return appropriate error.

Different from the C strto*l() functions, these wrappers return through the 'result' out parameter.

Include unit-tests for each wrapper function.

Carlos L. Torres (4):
cutils: Add qemu_strtol() wrapper
cutils: Add qemu_strtoul() wrapper
cutils: Add qemu_strtoll() wrapper
cutils: Add qemu_strtoull() wrapper

 include/qemu-common.h |    8 +
 tests/test-cutils.c   | 1172 +++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  131 ++++++
 3 files changed, 1311 insertions(+)
Signature · 1 line
1.9.1
#1 lore raw

PATCH 1/4 cutils: Add qemu_strtol() wrapper

From: "Carlos L. Torres" <[email protected]>

Add wrapper for strtol() function. Include unit tests.

---
 include/qemu-common.h |   2 +
 tests/test-cutils.c   | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  58 ++++++++++
 3 files changed, 352 insertions(+)
include/qemu-common.h +2 -0
index 237d654..a0ce7d8 100644
@@ -161,6 +161,8 @@ int qemu_fls(int i);
 int qemu_fdatasync(int fd);
 int fcntl_setfl(int fd, int flag);
 int qemu_parse_fd(const char *param);
+int qemu_strtol(const char *nptr, const char **endptr, int base,
+                long *result);
 
 int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
tests/test-cutils.c +292 -0

303 lines not on this page · raw message

util/cutils.c +58 -0

64 lines not on this page · raw message

Signature · 1 line
1.9.1
#2 lore raw

Re: [Qemu-devel] [PATCH 1/4] cutils: Add qemu_strtol() wrapper

Quoted 5 lines · Carlos L. Torres

From: "Carlos L. Torres" <[email protected]>

Add wrapper for strtol() function. Include unit tests.

Very thorough work, just a couple comments below.

Quoted 57 lines
---
 include/qemu-common.h |   2 +
 tests/test-cutils.c   | 292 ++++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  58 ++++++++++
 3 files changed, 352 insertions(+)
include/qemu-common.h +2 -0
index 237d654..a0ce7d8 100644
@@ -161,6 +161,8 @@ int qemu_fls(int i);
 int qemu_fdatasync(int fd);
 int fcntl_setfl(int fd, int flag);
 int qemu_parse_fd(const char *param);
+int qemu_strtol(const char *nptr, const char **endptr, int base,
+                long *result);
 
 int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
tests/test-cutils.c +30 -0
index 2a4556d..0e8fdbf 100644
@@ -226,6 +226,269 @@ static void test_parse_uint_full_correct(void)
     g_assert_cmpint(i, ==, 123);
 }
 
+static void test_qemu_strtol_correct(void)
+{
+    const char *str = "12345 foo";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 12345);
+    g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtol_null(void)
+{
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(NULL, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtol_empty(void)
+{

tests/test-cutils.c static void test_parse_uint_full_correct(void) · line 268

Quoted 10 lines
tests/test-cutils.c +10 -0
+    const char *str = "";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 0);

Please assert that endptr == str.

Quoted 46 lines
tests/test-cutils.c +46 -0
+}
+
+static void test_qemu_strtol_whitespace(void)
+{
+    const char *str = "  \t  ";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 0);
+    g_assert(endptr == str);
+}
+
+static void test_qemu_strtol_invalid(void)
+{
+    const char *str = "   xxxx  \t abc";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 0);
+    g_assert(endptr == str);
+}
+
+static void test_qemu_strtol_trailing(void)
+{
+    const char *str = "123xxx";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 123);
+    g_assert(endptr == str + 3);
+}

tests/test-cutils.c static void test_parse_uint_full_correct(void) · line 324

Quoted 10 lines
tests/test-cutils.c +10 -0
+
+static void test_qemu_strtol_octal(void)
+{
+    const char *str = "0123";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 8, &res);

Add a testcase for str = "0123" and base = 0?

Quoted 225 lines
tests/test-cutils.c +196 -0
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 0123);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_decimal(void)
+{
+    const char *str = "0123";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 10, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 123);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_hex(void)
+{
+    const char *str = "0123";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 16, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 0x123);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_max(void)
+{
+    const char *str = g_strdup_printf("%ld", LONG_MAX);
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, LONG_MAX);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_overflow(void)
+{
+    const char *str = "99999999999999999999999999999999999999999999";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, -ERANGE);
+    g_assert_cmpint(res, ==, LONG_MAX);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_underflow(void)
+{
+    const char *str = "-99999999999999999999999999999999999999999999";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err  = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, -ERANGE);
+    g_assert_cmpint(res, ==, LONG_MIN);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_negative(void)
+{
+    const char *str = "  \t -321";
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, -321);
+    g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtol_full_correct(void)
+{
+    const char *str = "123";
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, NULL, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 123);
+}
+
+static void test_qemu_strtol_full_null(void)
+{
+    char f = 'X';
+    const char *endptr = &f;
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(NULL, &endptr, 0, &res);
+
+    g_assert_cmpint(err, ==, -EINVAL);
+    g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtol_full_empty(void)
+{
+    const char *str = "";
+    long res = 999L;
+    int err;
+
+    err =  qemu_strtol(str, NULL, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, 0);
+}
+
+static void test_qemu_strtol_full_negative(void)
+{
+    const char *str = " \t -321";
+    long res = 999;
+    int err;
+
+    err = qemu_strtol(str, NULL, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, -321);
+}
+
+static void test_qemu_strtol_full_trailing(void)
+{
+    const char *str = "123xxx";
+    long res;
+    int err;
+
+    err = qemu_strtol(str, NULL, 0, &res);
+
+    g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtol_full_max(void)
+{
+    const char *str = g_strdup_printf("%ld", LONG_MAX);
+    long res;
+    int err;
+
+    err = qemu_strtol(str, NULL, 0, &res);
+
+    g_assert_cmpint(err, ==, 0);
+    g_assert_cmpint(res, ==, LONG_MAX);
+}
 int main(int argc, char **argv)
 {
     g_test_init(&argc, &argv, NULL);
@@ -247,5 +510,34 @@ int main(int argc, char **argv)
     g_test_add_func("/cutils/parse_uint_full/correct",
                     test_parse_uint_full_correct);
 
+    /* qemu_strtol() tests */
+    g_test_add_func("/cutils/qemu_strtol/correct", test_qemu_strtol_correct);
+    g_test_add_func("/cutils/qemu_strtol/null", test_qemu_strtol_null);
+    g_test_add_func("/cutils/qemu_strtol/empty", test_qemu_strtol_empty);
+    g_test_add_func("/cutils/qemu_strtol/whitespace",
+                    test_qemu_strtol_whitespace);
+    g_test_add_func("/cutils/qemu_strtol/invalid", test_qemu_strtol_invalid);
+    g_test_add_func("/cutils/qemu_strtol/trailing", test_qemu_strtol_trailing);
+    g_test_add_func("/cutils/qemu_strtol/octal", test_qemu_strtol_octal);
+    g_test_add_func("/cutils/qemu_strtol/decimal", test_qemu_strtol_decimal);
+    g_test_add_func("/cutils/qemu_strtol/hex", test_qemu_strtol_hex);
+    g_test_add_func("/cutils/qemu_strtol/max", test_qemu_strtol_max);
+    g_test_add_func("/cutils/qemu_strtol/overflow", test_qemu_strtol_overflow);
+    g_test_add_func("/cutils/qemu_strtol/underflow",
+                    test_qemu_strtol_underflow);
+    g_test_add_func("/cutils/qemu_strtol/negative", test_qemu_strtol_negative);
+    g_test_add_func("/cutils/qemu_strtol_full/correct",
+                    test_qemu_strtol_full_correct);
+    g_test_add_func("/cutils/qemu_strtol_full/null",
+                    test_qemu_strtol_full_null);
+    g_test_add_func("/cutils/qemu_strtol_full/empty",
+                    test_qemu_strtol_full_empty);
+    g_test_add_func("/cutils/qemu_strtol_full/negative",
+                    test_qemu_strtol_full_negative);
+    g_test_add_func("/cutils/qemu_strtol_full/trailing",
+                    test_qemu_strtol_full_trailing);
+    g_test_add_func("/cutils/qemu_strtol_full/max",
+                    test_qemu_strtol_full_max);
+
     return g_test_run();
 }
util/cutils.c +12 -0
index 5d1c9eb..bfaccd3 100644
@@ -359,6 +359,64 @@ int64_t strtosz(const char *nptr, char **end)
 }
 
 /**
+ * Helper function for qemu_strto*l() functions.
+ */
+static int check_strtox_error(const char **next, char *endptr,
+                              int err)
+{
+    if (!next && *endptr) {
+        return -EINVAL;
+    }
+    if (next) {
+        *next = endptr;
+    }
+    return -err;

util/cutils.c int64_t strtosz(const char *nptr, char **end) · line 383

Quoted 10 lines
util/cutils.c +10 -0
+}
+
+/**
+ * QEMU wrappers for strtol(), strtoll(), strtoul(), strotull() C functions.
+ *
+ * Convert ASCII string @nptr to a long integer value
+ * from the given @base. Parameters @nptr, @endptr, @base
+ * follows same semantics as strtol() C function.
+ *
+ * Different from strtol() function, if @endptr is not NULL, this

"Unlike the strtol() function," ...

util/cutils.c int64_t strtosz(const char *nptr, char **end) · line 392

Quoted 9 lines
util/cutils.c +9 -0
+ * function will return -EINVAL whenever it cannot fully convert
+ * the string in @nptr with given @base to a long. This function returns
+ * the result of the conversion only through the @result parameter.
+ *
+ * If NULL is passed in @endptr, then the whole string in @ntpr
+ * is a number otherwise it returns -EINVAL.
+ *
+ * RETURN VALUE
+ * Different from strtol() function, this wrapper returns either

Same here.

Quoted 31 lines
util/cutils.c +27 -0
+ * -EINVAL or the errno set by strtol() function (e.g -ERANGE).
+ * If the conversion overflows, -ERANGE is returned, and @result
+ * is set to the max value of the desired type
+ * (e.g. LONG_MAX, LLONG_MAX, ULONG_MAX, ULLONG_MAX). If the case
+ * of underflow, -ERANGE is returned, and @result is set to the min
+ * value of the desired type. For strtol(), strtoll(), @result is set to
+ * LONG_MIN, LLONG_MIN, respectively, and for strtoul(), strtoull() it
+ * is set to 0.
+ */
+int qemu_strtol(const char *nptr, const char **endptr, int base,
+                long *result)
+{
+    char *p;
+    int err = 0;
+    if (!nptr) {
+        if (endptr) {
+            *endptr = nptr;
+        }
+        err = -EINVAL;
+    } else {
+        errno = 0;
+        *result = strtol(nptr, &p, base);
+        err = check_strtox_error(endptr, p, errno);
+    }
+    return err;
+}
+/**
  * parse_uint:
  *
  * @s: String to parse
#3 lore raw

PATCH 2/4 cutils: Add qemu_strtoul() wrapper

In reply to Carlos L. Torres

From: "Carlos L. Torres" <[email protected]>

Add wrapper for strtoul() function. Include unit tests.

---
 include/qemu-common.h |   2 +
 tests/test-cutils.c   | 291 ++++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  27 +++++
 3 files changed, 320 insertions(+)
include/qemu-common.h +2 -0
index a0ce7d8..28bd7d2 100644
@@ -163,6 +163,8 @@ int fcntl_setfl(int fd, int flag);
 int qemu_parse_fd(const char *param);
 int qemu_strtol(const char *nptr, const char **endptr, int base,
                 long *result);
+int qemu_strtoul(const char *nptr, const char **endptr, int base,
+                 unsigned long *result);
 
 int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
tests/test-cutils.c +291 -0

302 lines not on this page · raw message

util/cutils.c +27 -0
index bfaccd3..b2656f0 100644
@@ -416,6 +416,33 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
     }
     return err;
 }
+
+/**
+ * Converts ASCII string to an unsigned long integer.
+ *
+ * If string contains a negative number, value will be converted to
+ * the unsigned representation of the signed value.
+ *
+ * See qemu_strtol() documentation for more info.
+ */
+int qemu_strtoul(const char *nptr, const char **endptr, int base,
+                 unsigned long *result)
+{
+    char *p;
+    int err = 0;
+    if (!nptr) {
+        if (endptr) {
+            *endptr = nptr;
+        }
+        err = -EINVAL;
+    } else {
+        errno = 0;
+        *result = strtoul(nptr, &p, base);
+        err = check_strtox_error(endptr, p, errno);
+    }
+    return err;
+}
+
 /**
  * parse_uint:
  *
Signature · 1 line
1.9.1
#4 lore raw

Re: [Qemu-devel] [PATCH 2/4] cutils: Add qemu_strtoul() wrapper

util/cutils.c int qemu_strtol(const char *nptr, const char **endptr, int base, · line 424

Quoted 6 lines · Carlos L. Torres
util/cutils.c +6 -0
+
+/**
+ * Converts ASCII string to an unsigned long integer.
+ *
+ * If string contains a negative number, value will be converted to
+ * the unsigned representation of the signed value.

Please document overflow here, as it is slightly different between strtol and strtoul.

Paolo

Quoted 2 lines

+ * See qemu_strtol() documentation for more info.
+ */

#5 lore raw

PATCH 3/4 cutils: Add qemu_strtoll() wrapper

In reply to Carlos L. Torres

From: "Carlos L. Torres" <[email protected]>

Add wrapper for strtoll() function. Include unit tests.

---
 include/qemu-common.h |   2 +
 tests/test-cutils.c   | 293 ++++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  23 ++++
 3 files changed, 318 insertions(+)
include/qemu-common.h +2 -0
index 28bd7d2..6da87f7 100644
@@ -165,6 +165,8 @@ int qemu_strtol(const char *nptr, const char **endptr, int base,
                 long *result);
 int qemu_strtoul(const char *nptr, const char **endptr, int base,
                  unsigned long *result);
+int qemu_strtoll(const char *nptr, const char **endptr, int base,
+                 long long *result);
 
 int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
tests/test-cutils.c +293 -0

304 lines not on this page · raw message

util/cutils.c +23 -0
index b2656f0..2d9f5a9 100644
@@ -444,6 +444,29 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
 }
 
 /**
+ * Converts ASCII string to a long long integer.
+ *
+ * See qemu_strtol() documentation for more info.
+ */
+int qemu_strtoll(const char *nptr, const char **endptr, int base,
+                 long long *result)
+{
+    char *p;
+    int err = 0;
+    if (!nptr) {
+        if (endptr) {
+            *endptr = nptr;
+        }
+        err = -EINVAL;
+    } else {
+        errno = 0;
+        *result = strtoll(nptr, &p, base);
+        err = check_strtox_error(endptr, p, errno);
+    }
+    return err;
+}
+
+/**
  * parse_uint:
  *
  * @s: String to parse
Signature · 1 line
1.9.1
#6 lore raw

PATCH 4/4 cutils: Add qemu_strtoull() wrapper

In reply to Carlos L. Torres

From: "Carlos L. Torres" <[email protected]>

Add wrapper for strtoull() function. Include unit tests.

---
 include/qemu-common.h |   2 +
 tests/test-cutils.c   | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  23 ++++
 3 files changed, 321 insertions(+)
include/qemu-common.h +2 -0
index 6da87f7..421a47b 100644
@@ -167,6 +167,8 @@ int qemu_strtoul(const char *nptr, const char **endptr, int base,
                  unsigned long *result);
 int qemu_strtoll(const char *nptr, const char **endptr, int base,
                  long long *result);
+int qemu_strtoull(const char *nptr, const char **endptr, int base,
+                  unsigned long long *result);
 
 int parse_uint(const char *s, unsigned long long *value, char **endptr,
                int base);
tests/test-cutils.c +296 -0

307 lines not on this page · raw message

util/cutils.c +23 -0
index 2d9f5a9..65aa524 100644
@@ -467,6 +467,29 @@ int qemu_strtoll(const char *nptr, const char **endptr, int base,
 }
 
 /**
+ * Converts ASCII string to an unsigned long long integer.
+ *
+ * See qemu_strtol() documentation for more info.
+ */
+int qemu_strtoull(const char *nptr, const char **endptr, int base,
+                  unsigned long long *result)
+{
+    char *p;
+    int err = 0;
+    if (!nptr) {
+        if (endptr) {
+            *endptr = nptr;
+        }
+        err = -EINVAL;
+    } else {
+        errno = 0;
+        *result = strtoull(nptr, &p, base);
+        err = check_strtox_error(endptr, p, errno);
+    }
+    return err;
+}
+
+/**
  * parse_uint:
  *
  * @s: String to parse
Signature · 1 line
1.9.1
#7 lore raw
In reply to Carlos L. Torres
Quoted 22 lines · Carlos L. Torres

From: "Carlos L. Torres" <[email protected]>

Introduce qemu_ wrappers for strtol/strtoul/strtoll/strtoull C functions, ensure that errno is checked, and if NULL is passed as the endptr argument, then whole string has to be a valid number on the given base, otherwise return appropriate error.

Different from the C strto*l() functions, these wrappers return through the 'result' out parameter.

Include unit-tests for each wrapper function.

Carlos L. Torres (4):
cutils: Add qemu_strtol() wrapper
cutils: Add qemu_strtoul() wrapper
cutils: Add qemu_strtoll() wrapper
cutils: Add qemu_strtoull() wrapper

Quoted 5 lines
 include/qemu-common.h |    8 +
 tests/test-cutils.c   | 1172 +++++++++++++++++++++++++++++++++++++++++++++++++
 util/cutils.c         |  131 ++++++
 3 files changed, 1311 insertions(+)

This looks pretty much okay. Of course, you would include at least one conversion from strto* to qemu_strto* (not necessarily one per function, though one signed case and one unsigned case would be great).

Paolo