From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:45197) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b3FmN-0002m3-5d for qemu-devel@nongnu.org; Thu, 19 May 2016 00:41:51 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1b3FmH-00058b-0e for qemu-devel@nongnu.org; Thu, 19 May 2016 00:41:47 -0400 Received: from mx1.redhat.com ([209.132.183.28]:43055) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1b3FmG-00058V-O8 for qemu-devel@nongnu.org; Thu, 19 May 2016 00:41:40 -0400 Received: from int-mx09.intmail.prod.int.phx2.redhat.com (int-mx09.intmail.prod.int.phx2.redhat.com [10.5.11.22]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mx1.redhat.com (Postfix) with ESMTPS id 50385C05B1E6 for ; Thu, 19 May 2016 04:41:40 +0000 (UTC) From: Eric Blake Date: Wed, 18 May 2016 22:41:03 -0600 Message-Id: <1463632874-28559-18-git-send-email-eblake@redhat.com> In-Reply-To: <1463632874-28559-1-git-send-email-eblake@redhat.com> References: <1463632874-28559-1-git-send-email-eblake@redhat.com> Subject: [Qemu-devel] [PATCH v4 17/28] qapi: Factor out JSON number formatting List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , To: qemu-devel@nongnu.org Cc: 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). (For now, there is only one client, but later patches will use it.) Adding a return value will let callers that care diagnose the situation where an attempt was made to output invalid JSON (which does not specify Infinity or NaN). None of the current callers care, but a future patch wants to make it possible to turn this situation into an error. Signed-off-by: Eric Blake --- v4: keep helper in qobject-json.[ch], don't use Error **errp for inf/NaN handling, drop R-b v3: rebase to latest; even though the patch differs quite a bit from v2, the changes are due to prior comment changes that are just moving between files, so R-b kept v2: minor wording tweaks --- include/qapi/qmp/qobject-json.h | 1 + qobject/qobject-json.c | 63 +++++++++++++++++++++++++---------------- 2 files changed, 40 insertions(+), 24 deletions(-) diff --git a/include/qapi/qmp/qobject-json.h b/include/qapi/qmp/qobject-json.h index aa8ddd7..0749e7e 100644 --- a/include/qapi/qmp/qobject-json.h +++ b/include/qapi/qmp/qobject-json.h @@ -25,5 +25,6 @@ QString *qobject_to_json(const QObject *obj); QString *qobject_to_json_pretty(const QObject *obj); int qstring_append_json_string(QString *qstring, const char *str); +int qstring_append_json_number(QString *qstring, double number); #endif /* QJSON_H */ diff --git a/qobject/qobject-json.c b/qobject/qobject-json.c index bc3634f..08daeed 100644 --- a/qobject/qobject-json.c +++ b/qobject/qobject-json.c @@ -18,6 +18,7 @@ #include "qapi/qmp/qobject-json.h" #include "qemu/unicode.h" #include "qapi/qmp/types.h" +#include typedef struct JSONParsingState { @@ -180,30 +181,8 @@ 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. Dependence - * on C locale is a pervasive issue in QEMU. */ - /* FIXME: This risks printing Inf or NaN, which are not valid - * JSON values. */ - /* FIXME: the default precision of 6 for %f often causes - * rounding errors; we should be using DBL_DECIMAL_DIG (17), - * and only rounding to a shorter number if the result would - * still produce the same floating point value. */ - 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 inform user if we generated invalid JSON */ + qstring_append_json_number(str, qfloat_get_double(val)); break; } case QTYPE_QBOOL: { @@ -303,3 +282,39 @@ int qstring_append_json_string(QString *qstring, const char *str) qstring_append(qstring, "\""); return result; } + +/** + * Append a JSON representation of @number to @qstring. + * + * Returns -1 if the added text is not strict JSON, or 0 if the number + * was finite. + */ +int qstring_append_json_number(QString *qstring, double number) +{ + char buffer[1024]; + int len; + + /* FIXME: snprintf() is locale dependent; but JSON requires + * numbers to be formatted as if in the C locale. Dependence + * on C locale is a pervasive issue in QEMU. */ + /* FIXME: This risks printing Inf or NaN, which are not valid + * JSON values. */ + /* FIXME: the default precision of 6 for %f often causes + * rounding errors; we should be using DBL_DECIMAL_DIG (17), + * and only rounding to a shorter number if the result would + * still produce the same floating point value. */ + 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); + return isfinite(number) ? 0 : -1; +} -- 2.5.5