From mboxrd@z Thu Jan 1 00:00:00 1970 Received: from eggs.gnu.org ([2001:4830:134:3::10]:58056) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1btaYp-00050l-Rq for qemu-devel@nongnu.org; Mon, 10 Oct 2016 09:24:09 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1btaYo-0007Fk-80 for qemu-devel@nongnu.org; Mon, 10 Oct 2016 09:24:07 -0400 Received: from mx1.redhat.com ([209.132.183.28]:48536) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1btaYn-0007FS-UM for qemu-devel@nongnu.org; Mon, 10 Oct 2016 09:24:06 -0400 Received: from int-mx14.intmail.prod.int.phx2.redhat.com (int-mx14.intmail.prod.int.phx2.redhat.com [10.5.11.27]) (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 7D5C66CB50 for ; Mon, 10 Oct 2016 13:24:05 +0000 (UTC) From: Eric Blake Date: Mon, 10 Oct 2016 08:23:46 -0500 Message-Id: <1476105837-9861-5-git-send-email-eblake@redhat.com> In-Reply-To: <1476105837-9861-1-git-send-email-eblake@redhat.com> References: <1476105837-9861-1-git-send-email-eblake@redhat.com> Subject: [Qemu-devel] [PATCH v6 04/15] 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 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.) Unlike qstring_append_json_string() which has a return value to allow callers to detect when output was munged to produce valid JSON, this code either succeeds or triggers an assertion failure. Signed-off-by: Eric Blake --- v6: drop return value, now that we assert finite floats on any QObject converted to JSON [no v5 due to series split] 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/qjson.h | 1 + qobject/qjson.c | 57 +++++++++++++++++++++++++++++------------------- 2 files changed, 36 insertions(+), 22 deletions(-) diff --git a/include/qapi/qmp/qjson.h b/include/qapi/qmp/qjson.h index aa8ddd7..6fb912e 100644 --- a/include/qapi/qmp/qjson.h +++ b/include/qapi/qmp/qjson.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); +void qstring_append_json_number(QString *qstring, double number); #endif /* QJSON_H */ diff --git a/qobject/qjson.c b/qobject/qjson.c index 6810726..b47a361 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -181,29 +181,8 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) } case QTYPE_QFLOAT: { double val = qfloat_get_double(qobject_to_qfloat(obj)); - char buffer[1024]; - int len; - assert(isfinite(val)); - /* 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: 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", 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); + qstring_append_json_number(str, val); break; } case QTYPE_QBOOL: { @@ -304,3 +283,37 @@ int qstring_append_json_string(QString *qstring, const char *str) qstring_append(qstring, "\""); return result; } + +/** + * Append a JSON representation of @number to @qstring. + * + * Requires @number to be finite, per RFC 7159. + */ +void qstring_append_json_number(QString *qstring, double number) +{ + char buffer[1024]; + int len; + + assert(isfinite(number)); + + /* 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: 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); +} -- 2.7.4