diff options
author | Marc-André Lureau <marcandre.lureau@redhat.com> | 2017-06-07 20:36:02 +0400 |
---|---|---|
committer | Markus Armbruster <armbru@redhat.com> | 2017-06-20 14:31:31 +0200 |
commit | 2bc7cfea095dc0ab7fae17e0a620f93ce042cafa (patch) | |
tree | 0e436e3079f2083ae1f7f59493f8c0da7f834249 /qobject | |
parent | 61a8f418b26a2d974e38e4ae55020aca8d402d88 (diff) |
json: learn to parse uint64 numbers
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>
Diffstat (limited to 'qobject')
-rw-r--r-- | qobject/json-lexer.c | 4 | ||||
-rw-r--r-- | qobject/json-parser.c | 36 |
2 files changed, 32 insertions, 8 deletions
diff --git a/qobject/json-lexer.c b/qobject/json-lexer.c index af4a75e05b..980ba159d6 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 5e808289f5..7a417f20cd 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: |