@@ -211,10 +211,10 @@ qemu-img-cmds.h: $(SRC_PATH)/qemu-img-cmds.hx
$(call quiet-command,sh $(SRC_PATH)/hxtool -h < $< > $@," GEN $@")
check-json: check-json.o qint.o qstring.o qdict.o qlist.o qemu-malloc.o
-check-qint: check-qint.o qint.o qstring.o qemu-malloc.o
-check-qstring: check-qstring.o qstring.o qemu-malloc.o
+check-qint: check-qint.o qint.o qstring.o qdict.o qemu-malloc.o
+check-qstring: check-qstring.o qint.o qstring.o qdict.o qemu-malloc.o
check-qdict: check-qdict.o qdict.o qint.o qstring.o qemu-malloc.o
-check-qlist: check-qlist.o qlist.o qint.o qstring.o qemu-malloc.o
+check-qlist: check-qlist.o qlist.o qint.o qstring.o qdict.o qemu-malloc.o
clean:
# avoid old build problems by removing potentially incorrect old files
@@ -21,6 +21,13 @@
QDECREF(result); \
} while (0)
+#define format_expect(qobj, format, expected) \
+ do { \
+ QString *result = qstring_format (format, qobj); \
+ fail_unless (!strcmp (qstring_get_str (result), expected)); \
+ QDECREF(result); \
+ } while (0)
+
START_TEST(qint_json_test)
{
QInt *qi;
@@ -88,6 +95,37 @@ START_TEST(nested_json_test)
}
END_TEST
+START_TEST(format_test)
+{
+ QDict *qdict_in, *qdict_out;
+ QList *qlist;
+
+ format_expect(NULL, "test", "test");
+ format_expect(NULL, "test %%", "test %");
+
+ qdict_in = qdict_new();
+ format_expect(qdict_in, "test %%", "test %");
+ format_expect(qdict_in, "test %{} test", "test {} test");
+ format_expect(qdict_in, "%%%{}%%", "%{}%");
+
+ qdict_put_obj(qdict_in, "in", QOBJECT(qint_from_int(42)));
+ format_expect(qdict_in, "%{}", "{\"in\":42}");
+ format_expect(qdict_in, "test %{in} test", "test 42 test");
+
+ qlist = qlist_new();
+ qlist_append(qlist, qdict_in);
+ QINCREF(qlist);
+
+ qdict_out = qdict_new();
+ qdict_put_obj(qdict_out, "list", QOBJECT(qlist));
+ qdict_put_obj(qdict_out, "in", QOBJECT(qdict_in));
+ format_expect(qdict_out, "%{list}", "[{\"in\":42}]");
+ format_expect(qdict_out, "%{in.in}", "42");
+ format_expect(qdict_out, "%{in.in}%{in.in}", "4242");
+ QDECREF(qdict_out);
+}
+END_TEST
+
static Suite *QObject_json_suite(void)
{
Suite *s;
@@ -102,6 +140,7 @@ static Suite *QObject_json_suite(void)
tcase_add_test(qobject_json_tcase, qdict_json_test);
tcase_add_test(qobject_json_tcase, qlist_json_test);
tcase_add_test(qobject_json_tcase, nested_json_test);
+ tcase_add_test(qobject_json_tcase, format_test);
return s;
}
@@ -11,6 +11,7 @@
*/
#include "qobject.h"
#include "qstring.h"
+#include "qdict.h"
#include "qemu-common.h"
static void qstring_destroy_obj(QObject *obj);
@@ -79,6 +80,14 @@ QString *qstring_json_from_qobject_obj(const QObject *qobject)
return qstring;
}
+QString *qstring_format(const char *format, const QDict *root)
+{
+ QString *qstring;
+
+ qstring = qstring_new();
+ qstring_append_format(qstring, format, root);
+ return qstring;
+}
/**
* qstring_append(): Append a regular C string to a QString
@@ -137,6 +146,48 @@ void qstring_append_escaped(QString *qstring, const char *str)
}
}
+void qstring_append_format(QString *qstring, const char *format,
+ const struct QDict *root)
+{
+ char buf[256], *p;
+ while (format && *format) {
+ const QObject *next = QOBJECT(root);
+
+ if (*format != '%' || *++format == '%') {
+ qstring_append_ch (qstring, *format++);
+ continue;
+ }
+ if (*format++ != '{')
+ abort ();
+
+ next = QOBJECT(root);
+ if (*format == '}') {
+ format++;
+ } else {
+ do {
+ if (qobject_type(next) != QTYPE_QDICT) {
+ format = strchr (format, '}');
+ if (!format) {
+ return;
+ }
+ next = NULL;
+ } else {
+ p = buf;
+ while (*format != '.' && *format != '}')
+ *p++ = *format++;
+ *p = 0;
+ next = qdict_get(qobject_to_qdict(next), buf);
+ }
+ } while (*format++ != '}');
+ }
+
+ if (next) {
+ qobject_encode_json(next, qstring);
+ }
+ }
+}
+
+
/**
* qstring_append_ch(): Append a character to a QString
*/
@@ -11,6 +11,7 @@ typedef struct QString {
QString *qstring_new(void);
QString *qstring_from_str(const char *str);
+QString *qstring_format(const char *format, const struct QDict *qdict);
QString *qstring_json_from_qobject_obj(const QObject *obj);
#define qstring_json_from_qobject(obj) \
@@ -18,6 +19,8 @@ QString *qstring_json_from_qobject_obj(const QObject *obj);
const char *qstring_get_str(const QString *qstring);
void qstring_append(QString *qstring, const char *str);
+void qstring_append_format(QString *qstring, const char *format,
+ const struct QDict *qdict);
void qstring_append_escaped(QString *qstring, const char *str);
void qstring_append_ch(QString *qstring, char c);
QString *qobject_to_qstring(const QObject *obj);
This patch adds a function to format a QDict according to a string that is printf like but specifies how to navigate the QDict. All parts are printed as JSON, but this is fine since this will auto-escape strings and integers print naturally. More sophisticated flags can be added later, e.g. %#{foo} would print a string without escaping. Cc: Luiz Capitulino <lcapitulino@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- Makefile | 6 +++--- check-json.c | 39 +++++++++++++++++++++++++++++++++++++++ qstring.c | 51 +++++++++++++++++++++++++++++++++++++++++++++++++++ qstring.h | 3 +++ 4 files changed, 96 insertions(+), 3 deletions(-)