[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-devel] [PATCH 06/21] json: learn to parse uint64 numbers
From: |
Marc-André Lureau |
Subject: |
[Qemu-devel] [PATCH 06/21] json: learn to parse uint64 numbers |
Date: |
Sat, 11 Mar 2017 17:22:41 +0400 |
If the parsed number doesn't fit in a int64, try with a uint64 before
falling back to double.
Switch strtoll() usage to qemu_strtoi64() helper while at it.
Add a few tests for large numbers.
Signed-off-by: Marc-André Lureau <address@hidden>
---
qobject/json-lexer.c | 4 ++++
qobject/json-parser.c | 19 +++++++++++++++++--
qobject/qjson.c | 8 ++++++++
tests/check-qjson.c | 28 ++++++++++++++++++++++++++++
4 files changed, 57 insertions(+), 2 deletions(-)
diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c
index af4a75e05b..a0beb0b106 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,
+ ['u'] = JSON_ESCAPE,
['l'] = IN_ESCAPE_LL,
},
[IN_ESCAPE_I64] = {
['d'] = JSON_ESCAPE,
+ ['u'] = JSON_ESCAPE,
},
[IN_ESCAPE_I6] = {
@@ -247,6 +250,7 @@ static const uint8_t json_lexer[][256] = {
},
[IN_ESCAPE] = {
+ ['u'] = JSON_ESCAPE,
['d'] = JSON_ESCAPE,
['i'] = JSON_ESCAPE,
['p'] = JSON_ESCAPE,
diff --git a/qobject/json-parser.c b/qobject/json-parser.c
index c18e48ab94..b39cb4d8d6 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(qint_from_int(va_arg(*ap, long long)));
+ } else if (!strcmp(token->str, "%u")) {
+ return QOBJECT(quint_from_uint(va_arg(*ap, unsigned int)));
+ } else if (!strcmp(token->str, "%lu")) {
+ return QOBJECT(quint_from_uint(va_arg(*ap, unsigned long)));
+ } else if (!strcmp(token->str, "%llu") ||
+ !strcmp(token->str, "%I64u")) {
+ return QOBJECT(quint_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")) {
@@ -504,14 +512,21 @@ static QObject *parse_literal(JSONParserContext *ctxt)
* strtoll() indicates these instances by setting errno to ERANGE
*/
int64_t value;
+ uint64_t uvalue;
- errno = 0; /* strtoll doesn't set errno on success */
- value = strtoll(token->str, NULL, 10);
+ qemu_strtoi64(token->str, NULL, 10, &value);
if (errno != ERANGE) {
return QOBJECT(qint_from_int(value));
}
+
+ qemu_strtou64(token->str, NULL, 10, &uvalue);
+ if (errno != ERANGE) {
+ return QOBJECT(quint_from_uint(uvalue));
+ }
+
/* fall through to JSON_FLOAT */
}
+
case JSON_FLOAT:
/* FIXME dependent on locale; a pervasive issue in QEMU */
/* FIXME our lexer matches RFC 7159 in forbidding Inf or NaN,
diff --git a/qobject/qjson.c b/qobject/qjson.c
index b2f3bfec53..6356cff594 100644
--- a/qobject/qjson.c
+++ b/qobject/qjson.c
@@ -140,6 +140,14 @@ static void to_json(const QObject *obj, QString *str, int
pretty, int indent)
qstring_append(str, buffer);
break;
}
+ case QTYPE_QUINT: {
+ QUInt *val = qobject_to_quint(obj);
+ char buffer[1024];
+
+ snprintf(buffer, sizeof(buffer), "%" PRIu64, quint_get_uint(val));
+ qstring_append(str, buffer);
+ break;
+ }
case QTYPE_QSTRING: {
QString *val = qobject_to_qstring(obj);
const char *ptr;
diff --git a/tests/check-qjson.c b/tests/check-qjson.c
index 963dd46f07..fd44cd6207 100644
--- a/tests/check-qjson.c
+++ b/tests/check-qjson.c
@@ -904,6 +904,33 @@ static void simple_number(void)
}
}
+static void large_number(void)
+{
+ const char *maxu64 = "18446744073709551615"; /* 2^64-1 */
+ const char *gtu64 = "18446744073709551616"; /* 2^64 */
+ QUInt *quint;
+ QFloat *qfloat;
+ QString *str;
+
+ quint = qobject_to_quint(qobject_from_json(maxu64, &error_abort));
+ g_assert(quint);
+ g_assert_cmpint(quint_get_uint(quint), ==, 18446744073709551615U);
+
+ str = qobject_to_json(QOBJECT(quint));
+ g_assert_cmpstr(qstring_get_str(str), ==, maxu64);
+ QDECREF(str);
+ QDECREF(quint);
+
+ qfloat = qobject_to_qfloat(qobject_from_json(gtu64, &error_abort));
+ g_assert(qfloat);
+ g_assert_cmpfloat(qfloat_get_double(qfloat), ==, 18446744073709551616.0);
+
+ str = qobject_to_json(QOBJECT(qfloat));
+ g_assert_cmpstr(qstring_get_str(str), ==, gtu64);
+ QDECREF(str);
+ QDECREF(qfloat);
+}
+
static void float_number(void)
{
int i;
@@ -1468,6 +1495,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.12.0.191.gc5d8de91d
- [Qemu-devel] [PATCH 00/21] WIP: dump: add kaslr support (for after 2.9), Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 01/21] qapi: add info comment for generated types, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 02/21] pci-host: use more specific type names, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 03/21] object: fix potential leak in getters, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 04/21] qobject: add quint type, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 05/21] qapi: update the qobject visitor to use QUInt, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 06/21] json: learn to parse uint64 numbers,
Marc-André Lureau <=
- [Qemu-devel] [PATCH 07/21] object: add uint property setter/getter, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 09/21] qdev: use appropriate type, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 08/21] qdev: use int and uint properties, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 10/21] Use uint property getter/setter where appropriate, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 11/21] qdict: learn to lookup quint, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 12/21] test-qga: drop everything until guest-sync, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 13/21] qga: report error on keyfile dump error, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 14/21] qga: add and populate VMDumpInfo, Marc-André Lureau, 2017/03/11
- [Qemu-devel] [PATCH 15/21] qga: register event emit function, Marc-André Lureau, 2017/03/11