diff options
Diffstat (limited to 'qobject/qjson.c')
-rw-r--r-- | qobject/qjson.c | 146 |
1 files changed, 33 insertions, 113 deletions
diff --git a/qobject/qjson.c b/qobject/qjson.c index f1f2c69704..bcc376e626 100644 --- a/qobject/qjson.c +++ b/qobject/qjson.c @@ -14,13 +14,13 @@ #include "qemu/osdep.h" #include "qapi/error.h" #include "qapi/qmp/json-parser.h" +#include "qapi/qmp/json-writer.h" #include "qapi/qmp/qjson.h" #include "qapi/qmp/qbool.h" #include "qapi/qmp/qdict.h" #include "qapi/qmp/qlist.h" #include "qapi/qmp/qnum.h" #include "qapi/qmp/qstring.h" -#include "qemu/unicode.h" typedef struct JSONParsingState { @@ -149,144 +149,69 @@ QDict *qdict_from_jsonf_nofail(const char *string, ...) return qdict; } -static void to_json(const QObject *obj, QString *str, int pretty, int indent); - -static void json_pretty_newline(QString *str, bool pretty, int indent) -{ - int i; - - if (pretty) { - qstring_append(str, "\n"); - for (i = 0; i < indent; i++) { - qstring_append(str, " "); - } - } -} - -static void to_json(const QObject *obj, QString *str, int pretty, int indent) +static void to_json(JSONWriter *writer, const char *name, + const QObject *obj) { switch (qobject_type(obj)) { case QTYPE_QNULL: - qstring_append(str, "null"); + json_writer_null(writer, name); break; case QTYPE_QNUM: { QNum *val = qobject_to(QNum, obj); - char *buffer = qnum_to_string(val); - qstring_append(str, buffer); - g_free(buffer); + + switch (val->kind) { + case QNUM_I64: + json_writer_int64(writer, name, val->u.i64); + break; + case QNUM_U64: + json_writer_uint64(writer, name, val->u.u64); + break; + case QNUM_DOUBLE: + json_writer_double(writer, name, val->u.dbl); + break; + default: + abort(); + } break; } case QTYPE_QSTRING: { QString *val = qobject_to(QString, obj); - const char *ptr; - int cp; - char buf[16]; - char *end; - - ptr = qstring_get_str(val); - qstring_append(str, "\""); - - for (; *ptr; ptr = end) { - cp = mod_utf8_codepoint(ptr, 6, &end); - switch (cp) { - case '\"': - qstring_append(str, "\\\""); - break; - case '\\': - qstring_append(str, "\\\\"); - break; - case '\b': - qstring_append(str, "\\b"); - break; - case '\f': - qstring_append(str, "\\f"); - break; - case '\n': - qstring_append(str, "\\n"); - break; - case '\r': - qstring_append(str, "\\r"); - break; - case '\t': - qstring_append(str, "\\t"); - break; - default: - if (cp < 0) { - cp = 0xFFFD; /* replacement character */ - } - if (cp > 0xFFFF) { - /* beyond BMP; need a surrogate pair */ - snprintf(buf, sizeof(buf), "\\u%04X\\u%04X", - 0xD800 + ((cp - 0x10000) >> 10), - 0xDC00 + ((cp - 0x10000) & 0x3FF)); - } else if (cp < 0x20 || cp >= 0x7F) { - snprintf(buf, sizeof(buf), "\\u%04X", cp); - } else { - buf[0] = cp; - buf[1] = 0; - } - qstring_append(str, buf); - } - }; - - qstring_append(str, "\""); + + json_writer_str(writer, name, qstring_get_str(val)); break; } case QTYPE_QDICT: { QDict *val = qobject_to(QDict, obj); - const char *comma = pretty ? "," : ", "; - const char *sep = ""; const QDictEntry *entry; - QString *qkey; - qstring_append(str, "{"); + json_writer_start_object(writer, name); for (entry = qdict_first(val); entry; entry = qdict_next(val, entry)) { - qstring_append(str, sep); - json_pretty_newline(str, pretty, indent + 1); - - qkey = qstring_from_str(qdict_entry_key(entry)); - to_json(QOBJECT(qkey), str, pretty, indent + 1); - qobject_unref(qkey); - - qstring_append(str, ": "); - to_json(qdict_entry_value(entry), str, pretty, indent + 1); - sep = comma; + to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry)); } - json_pretty_newline(str, pretty, indent); - qstring_append(str, "}"); + json_writer_end_object(writer); break; } case QTYPE_QLIST: { QList *val = qobject_to(QList, obj); - const char *comma = pretty ? "," : ", "; - const char *sep = ""; QListEntry *entry; - qstring_append(str, "["); + json_writer_start_array(writer, name); QLIST_FOREACH_ENTRY(val, entry) { - qstring_append(str, sep); - json_pretty_newline(str, pretty, indent + 1); - to_json(qlist_entry_obj(entry), str, pretty, indent + 1); - sep = comma; + to_json(writer, NULL, qlist_entry_obj(entry)); } - json_pretty_newline(str, pretty, indent); - qstring_append(str, "]"); + json_writer_end_array(writer); break; } case QTYPE_QBOOL: { QBool *val = qobject_to(QBool, obj); - if (qbool_get_bool(val)) { - qstring_append(str, "true"); - } else { - qstring_append(str, "false"); - } + json_writer_bool(writer, name, qbool_get_bool(val)); break; } default: @@ -294,20 +219,15 @@ static void to_json(const QObject *obj, QString *str, int pretty, int indent) } } -QString *qobject_to_json(const QObject *obj) +GString *qobject_to_json_pretty(const QObject *obj, bool pretty) { - QString *str = qstring_new(); - - to_json(obj, str, 0, 0); + JSONWriter *writer = json_writer_new(pretty); - return str; + to_json(writer, NULL, obj); + return json_writer_get_and_free(writer); } -QString *qobject_to_json_pretty(const QObject *obj) +GString *qobject_to_json(const QObject *obj) { - QString *str = qstring_new(); - - to_json(obj, str, 1, 0); - - return str; + return qobject_to_json_pretty(obj, false); } |