Back in commit 764c1ca (Nov 2009), we added qstring_append_int(). However, it did not see any use until commit 190c882 (Jan 2015). Furthermore, it has a rather limited use case - to print anything else, callers still have to format into a temporary buffer, unless we want to introduce an explosion of new qstring_append_* methods for each useful type to print.
A much better approach is to add a wrapper that merges printf behavior onto qstring_append, via the new qstring_append_format() (and its vararg counterpart). In fact, with that in place, we no longer need qstring_append_int(). Other immediate uses for the new function include simplifying an existing client of qstring_append() on a just-formatted buffer, and the fact that we can take advantage of printf width manipulations for more efficient indentation. Signed-off-by: Eric Blake <ebl...@redhat.com> --- include/qapi/qmp/qstring.h | 7 ++++++- qjson.c | 2 +- qobject/qobject-json.c | 25 +++++-------------------- qobject/qstring.c | 23 +++++++++++++++++++---- 4 files changed, 31 insertions(+), 26 deletions(-) diff --git a/include/qapi/qmp/qstring.h b/include/qapi/qmp/qstring.h index cab1faf..1b1e130 100644 --- a/include/qapi/qmp/qstring.h +++ b/include/qapi/qmp/qstring.h @@ -14,6 +14,8 @@ #define QSTRING_H #include <stdint.h> +#include <stdarg.h> +#include "qemu/compiler.h" #include "qapi/qmp/qobject.h" #include "qapi/error.h" @@ -29,9 +31,12 @@ QString *qstring_from_str(const char *str); QString *qstring_from_substr(const char *str, int start, int end); size_t qstring_get_length(const QString *qstring); const char *qstring_get_str(const QString *qstring); -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_format(QString *qstring, const char *fmt, ...) + GCC_FMT_ATTR(2, 3); +void qstring_append_vformat(QString *qstring, const char *fmt, va_list ap) + GCC_FMT_ATTR(2, 0); 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); diff --git a/qjson.c b/qjson.c index 25afaff..8c93c1b 100644 --- a/qjson.c +++ b/qjson.c @@ -70,7 +70,7 @@ void json_end_array(QJSON *json) void json_prop_int(QJSON *json, const char *name, int64_t val) { json_emit_element(json, name); - qstring_append_int(json->str, val); + qstring_append_format(json->str, "%" PRId64, val); } void json_prop_str(QJSON *json, const char *name, const char *str) diff --git a/qobject/qobject-json.c b/qobject/qobject-json.c index dbe0ab8..3a7b26b 100644 --- a/qobject/qobject-json.c +++ b/qobject/qobject-json.c @@ -79,16 +79,13 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent); static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) { ToJsonIterState *s = opaque; - int j; if (s->count) { qstring_append(s->str, s->pretty ? "," : ", "); } if (s->pretty) { - qstring_append(s->str, "\n"); - for (j = 0 ; j < s->indent ; j++) - qstring_append(s->str, " "); + qstring_append_format(s->str, "\n%*s", 4 * s->indent, ""); } qstring_append_json_string(s->str, key); @@ -101,16 +98,13 @@ static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) static void to_json_list_iter(QObject *obj, void *opaque) { ToJsonIterState *s = opaque; - int j; if (s->count) { qstring_append(s->str, s->pretty ? "," : ", "); } if (s->pretty) { - qstring_append(s->str, "\n"); - for (j = 0 ; j < s->indent ; j++) - qstring_append(s->str, " "); + qstring_append_format(s->str, "\n%*s", 4 * s->indent, ""); } to_json(obj, s->str, s->pretty, s->indent); @@ -125,10 +119,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) break; case QTYPE_QINT: { QInt *val = qobject_to_qint(obj); - char buffer[1024]; - - snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val)); - qstring_append(str, buffer); + qstring_append_format(str, "%" PRId64, qint_get_int(val)); break; } case QTYPE_QSTRING: { @@ -147,10 +138,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) qstring_append(str, "{"); qdict_iter(val, to_json_dict_iter, &s); if (pretty) { - int j; - qstring_append(str, "\n"); - for (j = 0 ; j < indent ; j++) - qstring_append(str, " "); + qstring_append_format(str, "\n%*s", 4 * indent, ""); } qstring_append(str, "}"); break; @@ -166,10 +154,7 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) qstring_append(str, "["); qlist_iter(val, (void *)to_json_list_iter, &s); if (pretty) { - int j; - qstring_append(str, "\n"); - for (j = 0 ; j < indent ; j++) - qstring_append(str, " "); + qstring_append_format(str, "\n%*s", 4 * indent, ""); } qstring_append(str, "]"); break; diff --git a/qobject/qstring.c b/qobject/qstring.c index c83e63c..a348ae3 100644 --- a/qobject/qstring.c +++ b/qobject/qstring.c @@ -88,12 +88,27 @@ void qstring_append(QString *qstring, const char *str) qstring->string[qstring->length] = 0; } -void qstring_append_int(QString *qstring, int64_t value) +void qstring_append_format(QString *qstring, const char *fmt, ...) { - char num[32]; + va_list ap; - snprintf(num, sizeof(num), "%" PRId64, value); - qstring_append(qstring, num); + va_start(ap, fmt); + qstring_append_vformat(qstring, fmt, ap); + va_end(ap); +} + +void qstring_append_vformat(QString *qstring, const char *fmt, va_list ap) +{ + va_list ap2; + size_t len; + + va_copy(ap2, ap); + len = vsnprintf(qstring->string + qstring->length, 0, fmt, ap2); + va_end(ap2); + + capacity_increase(qstring, len); + vsnprintf(qstring->string + qstring->length, len + 1, fmt, ap); + qstring->length += len; } /** -- 2.4.3