The only format specifier left in any client of qmp() and friends is %s. Rather than having to make our JSON parser support varargs, and use a conversion from string to QObject and back to string, we can instead just directly build the string and substitute %s ourselves. With this, the final caller of qobject_from_jsonv() is eliminated, and followup patches can simplify the parser.
Signed-off-by: Eric Blake <ebl...@redhat.com> --- Too bad glibc's strchrnul() is not universal; also, this patch could avoid "%.*s" format shenanigans (with the nastiness of converting ptrdiff_t to int) if we want to first enhance QString to support a length-limited append primitive. --- tests/libqtest.c | 42 ++++++++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 16 deletions(-) diff --git a/tests/libqtest.c b/tests/libqtest.c index 22bf0ad..a9559d8 100644 --- a/tests/libqtest.c +++ b/tests/libqtest.c @@ -427,27 +427,37 @@ QDict *qtest_qmp_receive(QTestState *s) */ static void qmp_fd_sendv(int fd, const char *fmt, va_list ap) { - va_list ap_copy; - QObject *qobj; + QString *qstr; - /* Going through qobject ensures we escape strings properly. - * This seemingly unnecessary copy is required in case va_list - * is an array type. + if (!strchr(fmt, '%')) { + return qmp_fd_send(fd, fmt); + } + + /* Construct a single string, turning %s in fmt into proper JSON + * strings. For now, we don't support any other format specifiers. */ - va_copy(ap_copy, ap); - qobj = qobject_from_jsonv(fmt, &ap_copy); - va_end(ap_copy); + qstr = qstring_new(); + while (*fmt) { + /* Too bad strchrnul() is not universal */ + const char *p = strchr(fmt, '%'); - /* No need to send anything for an empty QObject. */ - if (qobj) { - QString *qstr = qobject_to_json(qobj); - const char *str = qstring_get_str(qstr); + if (!p) { + p = strchr(fmt, '\0'); + } - qmp_fd_send(fd, str); - - QDECREF(qstr); - qobject_decref(qobj); + assert(p - fmt < INT_MAX); + qstring_append_printf(qstr, "%.*s", (int)(p - fmt), fmt); + if (*p) { + assert(p[1] == 's'); + p += 2; + qstring_append_json_string(qstr, va_arg(ap, const char *)); + } + fmt = p; } + + qmp_fd_send(fd, qstring_get_str(qstr)); + + QDECREF(qstr); } QDict *qtest_qmpv(QTestState *s, const char *fmt, va_list ap) -- 2.7.4