aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/qemu-common.h2
-rw-r--r--tests/test-cutils.c320
-rw-r--r--util/cutils.c23
3 files changed, 345 insertions, 0 deletions
diff --git a/include/qemu-common.h b/include/qemu-common.h
index 558a14fa5f..29cf0a0765 100644
--- a/include/qemu-common.h
+++ b/include/qemu-common.h
@@ -207,6 +207,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,
+ int64_t *result);
int parse_uint(const char *s, unsigned long long *value, char **endptr,
int base);
diff --git a/tests/test-cutils.c b/tests/test-cutils.c
index 39b2e963b3..8b2afebdb0 100644
--- a/tests/test-cutils.c
+++ b/tests/test-cutils.c
@@ -802,6 +802,294 @@ static void test_qemu_strtoul_full_max(void)
g_assert_cmpint(res, ==, ULONG_MAX);
}
+static void test_qemu_strtoll_correct(void)
+{
+ const char *str = "12345 foo";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 12345);
+ g_assert(endptr == str + 5);
+}
+
+static void test_qemu_strtoll_null(void)
+{
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(NULL, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+ g_assert(endptr == NULL);
+}
+
+static void test_qemu_strtoll_empty(void)
+{
+ const char *str = "";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoll_whitespace(void)
+{
+ const char *str = " \t ";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoll_invalid(void)
+{
+ const char *str = " xxxx \t abc";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert(endptr == str);
+}
+
+static void test_qemu_strtoll_trailing(void)
+{
+ const char *str = "123xxx";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + 3);
+}
+
+static void test_qemu_strtoll_octal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 8, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_decimal(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 10, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "123";
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_hex(void)
+{
+ const char *str = "0123";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 16, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+
+ str = "0x123";
+ endptr = &f;
+ res = 999;
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0x123);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_max(void)
+{
+ const char *str = g_strdup_printf("%lld", LLONG_MAX);
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, LLONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_overflow(void)
+{
+ const char *str = "99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, LLONG_MAX);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_underflow(void)
+{
+ const char *str = "-99999999999999999999999999999999999999999999";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, -ERANGE);
+ g_assert_cmpint(res, ==, LLONG_MIN);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_negative(void)
+{
+ const char *str = " \t -321";
+ char f = 'X';
+ const char *endptr = &f;
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, &endptr, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+ g_assert(endptr == str + strlen(str));
+}
+
+static void test_qemu_strtoll_full_correct(void)
+{
+ const char *str = "123";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 123);
+}
+
+static void test_qemu_strtoll_full_null(void)
+{
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(NULL, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_full_empty(void)
+{
+ const char *str = "";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, 0);
+}
+
+static void test_qemu_strtoll_full_negative(void)
+{
+ const char *str = " \t -321";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, -321);
+}
+
+static void test_qemu_strtoll_full_trailing(void)
+{
+ const char *str = "123xxx";
+ int64_t res = 999;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, -EINVAL);
+}
+
+static void test_qemu_strtoll_full_max(void)
+{
+
+ const char *str = g_strdup_printf("%lld", LLONG_MAX);
+ int64_t res;
+ int err;
+
+ err = qemu_strtoll(str, NULL, 0, &res);
+
+ g_assert_cmpint(err, ==, 0);
+ g_assert_cmpint(res, ==, LLONG_MAX);
+}
+
int main(int argc, char **argv)
{
g_test_init(&argc, &argv, NULL);
@@ -884,5 +1172,37 @@ int main(int argc, char **argv)
g_test_add_func("/cutils/qemu_strtoul_full/max",
test_qemu_strtoul_full_max);
+ /* qemu_strtoll() tests */
+ g_test_add_func("/cutils/qemu_strtoll/correct", test_qemu_strtoll_correct);
+ g_test_add_func("/cutils/qemu_strtoll/null", test_qemu_strtoll_null);
+ g_test_add_func("/cutils/qemu_strtoll/empty", test_qemu_strtoll_empty);
+ g_test_add_func("/cutils/qemu_strtoll/whitespace",
+ test_qemu_strtoll_whitespace);
+ g_test_add_func("/cutils/qemu_strtoll/invalid", test_qemu_strtoll_invalid);
+ g_test_add_func("/cutils/qemu_strtoll/trailing",
+ test_qemu_strtoll_trailing);
+ g_test_add_func("/cutils/qemu_strtoll/octal", test_qemu_strtoll_octal);
+ g_test_add_func("/cutils/qemu_strtoll/decimal", test_qemu_strtoll_decimal);
+ g_test_add_func("/cutils/qemu_strtoll/hex", test_qemu_strtoll_hex);
+ g_test_add_func("/cutils/qemu_strtoll/max", test_qemu_strtoll_max);
+ g_test_add_func("/cutils/qemu_strtoll/overflow",
+ test_qemu_strtoll_overflow);
+ g_test_add_func("/cutils/qemu_strtoll/underflow",
+ test_qemu_strtoll_underflow);
+ g_test_add_func("/cutils/qemu_strtoll/negative",
+ test_qemu_strtoll_negative);
+ g_test_add_func("/cutils/qemu_strtoll_full/correct",
+ test_qemu_strtoll_full_correct);
+ g_test_add_func("/cutils/qemu_strtoll_full/null",
+ test_qemu_strtoll_full_null);
+ g_test_add_func("/cutils/qemu_strtoll_full/empty",
+ test_qemu_strtoll_full_empty);
+ g_test_add_func("/cutils/qemu_strtoll_full/negative",
+ test_qemu_strtoll_full_negative);
+ g_test_add_func("/cutils/qemu_strtoll_full/trailing",
+ test_qemu_strtoll_full_trailing);
+ g_test_add_func("/cutils/qemu_strtoll_full/max",
+ test_qemu_strtoll_full_max);
+
return g_test_run();
}
diff --git a/util/cutils.c b/util/cutils.c
index 8ee3d5ee9d..7084d6f1ce 100644
--- a/util/cutils.c
+++ b/util/cutils.c
@@ -449,6 +449,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,
+ int64_t *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