From 01b2ffcedd94ad7b42bc870e4c6936c87ad03429 Mon Sep 17 00:00:00 2001 From: Marc-André Lureau Date: Wed, 7 Jun 2017 20:35:58 +0400 Subject: qapi: merge QInt and QFloat in QNum MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We would like to use a same QObject type to represent numbers, whether they are int, uint, or floats. Getters will allow some compatibility between the various types if the number fits other representations. Add a few more tests while at it. Signed-off-by: Marc-André Lureau Message-Id: <20170607163635.17635-7-marcandre.lureau@redhat.com> Reviewed-by: Markus Armbruster [parse_stats_intervals() simplified a bit, comment in test_visitor_in_int_overflow() tidied up, suppress bogus warnings] Signed-off-by: Markus Armbruster --- qobject/json-parser.c | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'qobject/json-parser.c') diff --git a/qobject/json-parser.c b/qobject/json-parser.c index c18e48ab94..5e808289f5 100644 --- a/qobject/json-parser.c +++ b/qobject/json-parser.c @@ -466,16 +466,16 @@ static QObject *parse_escape(JSONParserContext *ctxt, va_list *ap) } else if (!strcmp(token->str, "%i")) { return QOBJECT(qbool_from_bool(va_arg(*ap, int))); } else if (!strcmp(token->str, "%d")) { - return QOBJECT(qint_from_int(va_arg(*ap, int))); + return QOBJECT(qnum_from_int(va_arg(*ap, int))); } else if (!strcmp(token->str, "%ld")) { - return QOBJECT(qint_from_int(va_arg(*ap, long))); + return QOBJECT(qnum_from_int(va_arg(*ap, long))); } else if (!strcmp(token->str, "%lld") || !strcmp(token->str, "%I64d")) { - return QOBJECT(qint_from_int(va_arg(*ap, long long))); + return QOBJECT(qnum_from_int(va_arg(*ap, long long))); } else if (!strcmp(token->str, "%s")) { return QOBJECT(qstring_from_str(va_arg(*ap, const char *))); } else if (!strcmp(token->str, "%f")) { - return QOBJECT(qfloat_from_double(va_arg(*ap, double))); + return QOBJECT(qnum_from_double(va_arg(*ap, double))); } return NULL; } @@ -491,24 +491,22 @@ static QObject *parse_literal(JSONParserContext *ctxt) case JSON_STRING: return QOBJECT(qstring_from_escaped_str(ctxt, token)); case JSON_INTEGER: { - /* A possibility exists that this is a whole-valued float where the - * fractional part was left out due to being 0 (.0). It's not a big - * deal to treat these as ints in the parser, so long as users of the - * resulting QObject know to expect a QInt in place of a QFloat in - * cases like these. + /* + * Represent JSON_INTEGER as QNUM_I64 if possible, else as + * QNUM_DOUBLE. Note that strtoll() fails with ERANGE when + * it's not possible. * - * However, in some cases these values will overflow/underflow a - * QInt/int64 container, thus we should assume these are to be handled - * as QFloats/doubles rather than silently changing their values. - * - * strtoll() indicates these instances by setting errno to ERANGE + * 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) */ int64_t value; errno = 0; /* strtoll doesn't set errno on success */ value = strtoll(token->str, NULL, 10); if (errno != ERANGE) { - return QOBJECT(qint_from_int(value)); + return QOBJECT(qnum_from_int(value)); } /* fall through to JSON_FLOAT */ } @@ -516,7 +514,7 @@ static QObject *parse_literal(JSONParserContext *ctxt) /* FIXME dependent on locale; a pervasive issue in QEMU */ /* FIXME our lexer matches RFC 7159 in forbidding Inf or NaN, * but those might be useful extensions beyond JSON */ - return QOBJECT(qfloat_from_double(strtod(token->str, NULL))); + return QOBJECT(qnum_from_double(strtod(token->str, NULL))); default: abort(); } -- cgit 1.4.1