From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:44012) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aBArI-0000Pi-P5 for qemu-devel@nongnu.org; Mon, 21 Dec 2015 19:31:24 -0500 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1aBArH-000241-H5 for qemu-devel@nongnu.org; Mon, 21 Dec 2015 19:31:20 -0500 Received: from mx1.redhat.com ([209.132.183.28]:59439) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1aBArH-00023j-AL for qemu-devel@nongnu.org; Mon, 21 Dec 2015 19:31:19 -0500 Received: from int-mx13.intmail.prod.int.phx2.redhat.com (int-mx13.intmail.prod.int.phx2.redhat.com [10.5.11.26]) by mx1.redhat.com (Postfix) with ESMTPS id 03A628F4E2 for ; Tue, 22 Dec 2015 00:31:19 +0000 (UTC) From: Eric Blake Date: Mon, 21 Dec 2015 17:30:58 -0700 Message-Id: <1450744268-25052-5-git-send-email-eblake@redhat.com> In-Reply-To: <1450744268-25052-1-git-send-email-eblake@redhat.com> References: <1450744268-25052-1-git-send-email-eblake@redhat.com> Subject: [Qemu-devel] [PATCH v2 04/14] qapi: Factor out JSON number formatting List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: pbonzini@redhat.com, armbru@redhat.com, Luiz Capitulino Pull out a new qstring_append_json_number() helper, so that all JSON output producers can use a consistent style for printing floating point without duplicating code (since we are doing more data massaging than a simple printf format can handle). Address one FIXME by adding an Error parameter and warning the caller if the requested number cannot be represented in JSON; but add another FIXME in its place because we have no way to report the problem higher up the stack. Signed-off-by: Eric Blake --- v2: minor wording tweaks --- include/qapi/qmp/qstring.h | 4 +++- qobject/qobject-json.c | 24 +++--------------------- qobject/qstring.c | 37 ++++++++++++++++++++++++++++++++++++- 3 files changed, 42 insertions(+), 23 deletions(-) diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index 1a938f6..cab1faf 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -1,7 +1,7 @@ /* * QString Module * - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009, 2015 Red Hat Inc. * * Authors: * Luiz Capitulino @@ -15,6 +15,7 @@ #include #include "qapi/qmp/qobject.h" +#include "qapi/error.h" typedef struct QString { QObject base; @@ -32,6 +33,7 @@ void qstring_append_int(QString *qstring, int64_t value); void qstring_append(QString *qstring, const char *str); void qstring_append_chr(QString *qstring, int c); void qstring_append_json_string(QString *qstring, const char *raw); +void qstring_append_json_number(QString *qstring, double number, Error **errp); QString *qobject_to_qstring(const QObject *obj); void qstring_destroy_obj(QObject *obj); diff --git a/qobject/qobject-json.c b/qobject/qobject-json.c index 1557ec6..dbe0ab8 100644 --- a/qobject/qobject-json.c +++ b/qobject/qobject-json.c @@ -176,27 +176,9 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) } case QTYPE_QFLOAT: { QFloat *val = qobject_to_qfloat(obj); - char buffer[1024]; - int len; - - /* FIXME: snprintf() is locale dependent; but JSON requires - * numbers to be formatted as if in the C locale. */ - /* FIXME: This risks printing Inf or NaN, which are not valid - * JSON values. */ - /* FIXME: the default precision of %f may be insufficient to - * tell this number apart from others. */ - len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val)); - while (len > 0 && buffer[len - 1] == '0') { - len--; - } - - if (len && buffer[len - 1] == '.') { - buffer[len - 1] = 0; - } else { - buffer[len] = 0; - } - - qstring_append(str, buffer); + /* FIXME: no way to report invalid JSON to caller, so for now + * we just ignore it */ + qstring_append_json_number(str, qfloat_get_double(val), NULL); break; } case QTYPE_QBOOL: { diff --git a/qobject/qstring.c b/qobject/qstring.c index 2882c47..b06f290 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -1,7 +1,7 @@ /* * QString Module * - * Copyright (C) 2009 Red Hat Inc. + * Copyright (C) 2009, 2015 Red Hat Inc. * * Authors: * Luiz Capitulino @@ -13,6 +13,7 @@ #include "qapi/qmp/qobject.h" #include "qapi/qmp/qstring.h" #include "qemu-common.h" +#include /** * qstring_new(): Create a new empty QString @@ -165,6 +166,40 @@ void qstring_append_json_string(QString *qstring, const char *raw) } /** + * qstring_append_json_number(): Append a JSON number to a QString. + * Set @errp if the number is not representable in JSON, but append the + * output anyway (callers can then choose to ignore the warning). + */ +void qstring_append_json_number(QString *qstring, double number, Error **errp) +{ + char buffer[1024]; + int len; + + /* JSON does not allow Inf or NaN; append it but set errp */ + if (!isfinite(number)) { + error_setg(errp, "Non-finite number %f is not valid JSON", number); + } + + /* FIXME: snprintf() is locale dependent; but JSON requires + * numbers to be formatted as if in the C locale. */ + /* FIXME: the default precision of %f may be insufficient to + * tell this number apart from others. */ + len = snprintf(buffer, sizeof(buffer), "%f", number); + assert(len > 0 && len < sizeof(buffer)); + while (len > 0 && buffer[len - 1] == '0') { + len--; + } + + if (len && buffer[len - 1] == '.') { + buffer[len - 1] = 0; + } else { + buffer[len] = 0; + } + + qstring_append(qstring, buffer); +} + +/** * qobject_to_qstring(): Convert a QObject to a QString */ QString *qobject_to_qstring(const QObject *obj) -- 2.4.3