qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Markus Armbruster <armbru@redhat.com>
To: qemu-devel@nongnu.org
Cc: "Marc-André Lureau" <marcandre.lureau@redhat.com>
Subject: [Qemu-devel] [PULL 10/41] json: learn to parse uint64 numbers
Date: Fri,  9 Jun 2017 15:46:54 +0200	[thread overview]
Message-ID: <1497016045-6009-11-git-send-email-armbru@redhat.com> (raw)
In-Reply-To: <1497016045-6009-1-git-send-email-armbru@redhat.com>

From: Marc-André Lureau <marcandre.lureau@redhat.com>

Switch strtoll() usage to qemu_strtoi64() helper while at it.

Add a few tests for large numbers.

Signed-off-by: Marc-André Lureau <marcandre.lureau@redhat.com>
Message-Id: <20170607163635.17635-11-marcandre.lureau@redhat.com>
Reviewed-by: Markus Armbruster <armbru@redhat.com>
Signed-off-by: Markus Armbruster <armbru@redhat.com>
---
 qobject/json-lexer.c  |  4 ++++
 qobject/json-parser.c | 36 ++++++++++++++++++++++++++++--------
 tests/check-qjson.c   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 76 insertions(+), 8 deletions(-)

diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
index af4a75e..980ba15 100644
--- a/qobject/json-lexer.c
+++ b/qobject/json-lexer.c
@@ -227,15 +227,18 @@ static const uint8_t json_lexer[][256] =  {
     /* escape */
     [IN_ESCAPE_LL] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_L] = {
         ['d'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_LL,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_I64] = {
         ['d'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
     },
 
     [IN_ESCAPE_I6] = {
@@ -251,6 +254,7 @@ static const uint8_t json_lexer[][256] =  {
         ['i'] = JSON_ESCAPE,
         ['p'] = JSON_ESCAPE,
         ['s'] = JSON_ESCAPE,
+        ['u'] = JSON_ESCAPE,
         ['f'] = JSON_ESCAPE,
         ['l'] = IN_ESCAPE_L,
         ['I'] = IN_ESCAPE_I,
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index 5e80828..7a417f2 100644
--- a/qobject/json-parser.c
+++ b/qobject/json-parser.c
@@ -12,6 +12,7 @@
  */
 
 #include "qemu/osdep.h"
+#include "qemu/cutils.h"
 #include "qapi/error.h"
 #include "qemu-common.h"
 #include "qapi/qmp/types.h"
@@ -472,6 +473,13 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap)
     } else if (!strcmp(token->str, "%lld") ||
                !strcmp(token->str, "%I64d")) {
         return QOBJECT(qnum_from_int(va_arg(*ap, long long)));
+    } else if (!strcmp(token->str, "%u")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned int)));
+    } else if (!strcmp(token->str, "%lu")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long)));
+    } else if (!strcmp(token->str, "%llu") ||
+               !strcmp(token->str, "%I64u")) {
+        return QOBJECT(qnum_from_uint(va_arg(*ap, unsigned long long)));
     } else if (!strcmp(token->str, "%s")) {
         return QOBJECT(qstring_from_str(va_arg(*ap, const char *)));
     } else if (!strcmp(token->str, "%f")) {
@@ -493,21 +501,33 @@ static QObject *parse_literal(JSONParserContext *ctxt)
     case JSON_INTEGER: {
         /*
          * Represent JSON_INTEGER as QNUM_I64 if possible, else as
-         * QNUM_DOUBLE.  Note that strtoll() fails with ERANGE when
-         * it's not possible.
+         * QNUM_U64, else as QNUM_DOUBLE.  Note that qemu_strtoi64()
+         * and qemu_strtou64() fail with ERANGE when it's not
+         * possible.
          *
          * qnum_get_int() will then work for any signed 64-bit
-         * JSON_INTEGER, and qnum_get_double() both for any
-         * JSON_INTEGER and any JSON_FLOAT (with precision loss for
-         * integers beyond 53 bits)
+         * JSON_INTEGER, qnum_get_uint() for any unsigned 64-bit
+         * integer, and qnum_get_double() both for any JSON_INTEGER
+         * and any JSON_FLOAT (with precision loss for integers beyond
+         * 53 bits)
          */
+        int ret;
         int64_t value;
+        uint64_t uvalue;
 
-        errno = 0; /* strtoll doesn't set errno on success */
-        value = strtoll(token->str, NULL, 10);
-        if (errno != ERANGE) {
+        ret = qemu_strtoi64(token->str, NULL, 10, &value);
+        if (!ret) {
             return QOBJECT(qnum_from_int(value));
         }
+        assert(ret == -ERANGE);
+
+        if (token->str[0] != '-') {
+            ret = qemu_strtou64(token->str, NULL, 10, &uvalue);
+            if (!ret) {
+                return QOBJECT(qnum_from_uint(uvalue));
+            }
+            assert(ret == -ERANGE);
+        }
         /* fall through to JSON_FLOAT */
     }
     case JSON_FLOAT:
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index f0a89f7..53f2275 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -906,6 +906,49 @@ static void simple_number(void)
     }
 }
 
+static void large_number(void)
+{
+    const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
+    const char *gtu64 = "18446744073709551616"; /* 2^64 */
+    const char *lti64 = "-9223372036854775809"; /* -2^63 - 1 */
+    QNum *qnum;
+    QString *str;
+    uint64_t val;
+    int64_t ival;
+
+    qnum = qobject_to_qnum(qobject_from_json(maxu64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpuint(qnum_get_uint(qnum), ==, 18446744073709551615U);
+    g_assert(!qnum_get_try_int(qnum, &ival));
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
+    QDECREF(str);
+    QDECREF(qnum);
+
+    qnum = qobject_to_qnum(qobject_from_json(gtu64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpfloat(qnum_get_double(qnum), ==, 18446744073709552e3);
+    g_assert(!qnum_get_try_uint(qnum, &val));
+    g_assert(!qnum_get_try_int(qnum, &ival));
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
+    QDECREF(str);
+    QDECREF(qnum);
+
+    qnum = qobject_to_qnum(qobject_from_json(lti64, &error_abort));
+    g_assert(qnum);
+    g_assert_cmpfloat(qnum_get_double(qnum), ==, -92233720368547758e2);
+    g_assert(!qnum_get_try_uint(qnum, &val));
+    g_assert(!qnum_get_try_int(qnum, &ival));
+
+    str = qobject_to_json(QOBJECT(qnum));
+    g_assert_cmpstr(qstring_get_str(str), ==, "-9223372036854775808");
+    QDECREF(str);
+    QDECREF(qnum);
+}
+
 static void float_number(void)
 {
     int i;
@@ -1475,6 +1518,7 @@ int main(int argc, char **argv)
     g_test_add_func("/literals/string/vararg", vararg_string);
 
     g_test_add_func("/literals/number/simple", simple_number);
+    g_test_add_func("/literals/number/large", large_number);
     g_test_add_func("/literals/number/float", float_number);
     g_test_add_func("/literals/number/vararg", vararg_number);
 
-- 
2.7.5

  parent reply	other threads:[~2017-06-09 13:47 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2017-06-09 13:46 [Qemu-devel] [PULL 00/41] QAPI patches for 2017-06-09 Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 01/41] qdev: remove PropertyInfo.qtype field Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 02/41] object: fix potential leak in getters Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 03/41] tests: Remove test cases for alternates of 'number' and 'int' Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 04/41] tests: add more int/number ranges checks Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 05/41] qapi: Clean up qobject_input_type_number() control flow Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 06/41] qapi: merge QInt and QFloat in QNum Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 07/41] qapi: Remove visit_start_alternate() parameter promote_int Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 08/41] tests: remove /{qnum, qlist, dict}/destroy test Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 09/41] qnum: add uint type Markus Armbruster
2017-06-09 13:46 ` Markus Armbruster [this message]
2017-06-09 13:46 ` [Qemu-devel] [PULL 11/41] qapi: update the qobject visitor to use QNUM_U64 Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 12/41] object: add uint property setter/getter Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 13/41] q35: fix get_mmcfg_size to use uint64 visitor Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 14/41] object: use more specific property type names Markus Armbruster
2017-06-09 13:46 ` [Qemu-devel] [PULL 15/41] qdev: Rename DEFINE_PROP_DEFAULT() to DEFINE_PROP_SIGNED() Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 16/41] qdev: wrap default property value in an union Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 17/41] qdev: avoid type casts between signed and unsigned Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 18/41] apic-common: make "id" property a uint32 Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 19/41] qdev: Use appropriate getter/setters type Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 20/41] isa: use get_uint() for "io-base" Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 21/41] pc-dimm: use get_uint() for dimm properties Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 22/41] pc-dimm: make "size" property uint64 Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 23/41] pcihp: use get_uint() for "bsel" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 24/41] aspeed: use {set, get}_uint() for "ram-size" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 25/41] bcm2835_fb: use {get, set}_uint() for "vcram-size" and "vcram-base" Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 26/41] platform-bus: use get_uint() for "addr" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 27/41] acpi: use get_uint() for "acpi-pcihp-io*" properties Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 28/41] acpi: use get_uint() for various acpi properties Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 29/41] acpi: use get_uint() for "pci-hole*" properties Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 30/41] pc: use get_uint() for "iobase" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 31/41] pc: use get_uint() for "apic-id" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 32/41] pc: use get_uint() for "hpet-intcap" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 33/41] xen: use get_uint() for "max-ram-below-4g" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 34/41] arm: use get_uint() for "mp-affinity" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 35/41] auxbus: use get_uint() for "addr" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 36/41] pvpanic: use get_uint() for "ioport" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 37/41] pnv-core: use get_uint() for "core-pir" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 38/41] numa: use get_uint() for "size" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 39/41] i386/cpu: use get_uint() for "min-level"/"min-xlevel" properties Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 40/41] console: use get_uint() for "head" property Markus Armbruster
2017-06-09 13:47 ` [Qemu-devel] [PULL 41/41] tests/qdict: check more get_try_int() cases Markus Armbruster
2017-06-09 15:05 ` [Qemu-devel] [PULL 00/41] QAPI patches for 2017-06-09 no-reply
2017-06-09 15:38 ` no-reply
2017-06-12 10:39 ` Peter Maydell
2017-06-12 10:52   ` Marc-André Lureau
2017-06-12 11:50     ` Peter Maydell
2017-06-20 11:59   ` Markus Armbruster

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1497016045-6009-11-git-send-email-armbru@redhat.com \
    --to=armbru@redhat.com \
    --cc=marcandre.lureau@redhat.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).