123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232 |
- /*
- * QObject JSON integration
- *
- * Copyright IBM, Corp. 2009
- *
- * Authors:
- * Anthony Liguori <aliguori@us.ibm.com>
- *
- * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
- * See the COPYING.LIB file in the top-level directory.
- *
- */
- #include "qemu/osdep.h"
- #include "qapi/error.h"
- #include "qobject/json-parser.h"
- #include "qobject/json-writer.h"
- #include "qobject/qjson.h"
- #include "qobject/qbool.h"
- #include "qobject/qdict.h"
- #include "qobject/qlist.h"
- #include "qobject/qnum.h"
- #include "qobject/qstring.h"
- typedef struct JSONParsingState {
- JSONMessageParser parser;
- QObject *result;
- Error *err;
- } JSONParsingState;
- static void consume_json(void *opaque, QObject *json, Error *err)
- {
- JSONParsingState *s = opaque;
- assert(!json != !err);
- assert(!s->result || !s->err);
- if (s->result) {
- qobject_unref(s->result);
- s->result = NULL;
- error_setg(&s->err, "Expecting at most one JSON value");
- }
- if (s->err) {
- qobject_unref(json);
- error_free(err);
- return;
- }
- s->result = json;
- s->err = err;
- }
- /*
- * Parse @string as JSON value.
- * If @ap is non-null, interpolate %-escapes.
- * Takes ownership of %p arguments.
- * On success, return the JSON value.
- * On failure, store an error through @errp and return NULL.
- * Ownership of %p arguments becomes indeterminate then. To avoid
- * leaks, callers passing %p must terminate on error, e.g. by passing
- * &error_abort.
- */
- static QObject *qobject_from_jsonv(const char *string, va_list *ap,
- Error **errp)
- {
- JSONParsingState state = {};
- json_message_parser_init(&state.parser, consume_json, &state, ap);
- json_message_parser_feed(&state.parser, string, strlen(string));
- json_message_parser_flush(&state.parser);
- json_message_parser_destroy(&state.parser);
- if (!state.result && !state.err) {
- error_setg(&state.err, "Expecting a JSON value");
- }
- error_propagate(errp, state.err);
- return state.result;
- }
- QObject *qobject_from_json(const char *string, Error **errp)
- {
- return qobject_from_jsonv(string, NULL, errp);
- }
- /*
- * Parse @string as JSON value with %-escapes interpolated.
- * Abort on error. Do not use with untrusted @string.
- * Return the resulting QObject. It is never null.
- */
- QObject *qobject_from_vjsonf_nofail(const char *string, va_list ap)
- {
- va_list ap_copy;
- QObject *obj;
- /* va_copy() is needed when va_list is an array type */
- va_copy(ap_copy, ap);
- obj = qobject_from_jsonv(string, &ap_copy, &error_abort);
- va_end(ap_copy);
- assert(obj);
- return obj;
- }
- /*
- * Parse @string as JSON value with %-escapes interpolated.
- * Abort on error. Do not use with untrusted @string.
- * Return the resulting QObject. It is never null.
- */
- QObject *qobject_from_jsonf_nofail(const char *string, ...)
- {
- QObject *obj;
- va_list ap;
- va_start(ap, string);
- obj = qobject_from_vjsonf_nofail(string, ap);
- va_end(ap);
- return obj;
- }
- /*
- * Parse @string as JSON object with %-escapes interpolated.
- * Abort on error. Do not use with untrusted @string.
- * Return the resulting QDict. It is never null.
- */
- QDict *qdict_from_vjsonf_nofail(const char *string, va_list ap)
- {
- QDict *qdict;
- qdict = qobject_to(QDict, qobject_from_vjsonf_nofail(string, ap));
- assert(qdict);
- return qdict;
- }
- /*
- * Parse @string as JSON object with %-escapes interpolated.
- * Abort on error. Do not use with untrusted @string.
- * Return the resulting QDict. It is never null.
- */
- QDict *qdict_from_jsonf_nofail(const char *string, ...)
- {
- QDict *qdict;
- va_list ap;
- va_start(ap, string);
- qdict = qdict_from_vjsonf_nofail(string, ap);
- va_end(ap);
- return qdict;
- }
- static void to_json(JSONWriter *writer, const char *name,
- const QObject *obj)
- {
- switch (qobject_type(obj)) {
- case QTYPE_QNULL:
- json_writer_null(writer, name);
- break;
- case QTYPE_QNUM: {
- QNum *val = qobject_to(QNum, obj);
- 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);
- json_writer_str(writer, name, qstring_get_str(val));
- break;
- }
- case QTYPE_QDICT: {
- QDict *val = qobject_to(QDict, obj);
- const QDictEntry *entry;
- json_writer_start_object(writer, name);
- for (entry = qdict_first(val);
- entry;
- entry = qdict_next(val, entry)) {
- to_json(writer, qdict_entry_key(entry), qdict_entry_value(entry));
- }
- json_writer_end_object(writer);
- break;
- }
- case QTYPE_QLIST: {
- QList *val = qobject_to(QList, obj);
- QListEntry *entry;
- json_writer_start_array(writer, name);
- QLIST_FOREACH_ENTRY(val, entry) {
- to_json(writer, NULL, qlist_entry_obj(entry));
- }
- json_writer_end_array(writer);
- break;
- }
- case QTYPE_QBOOL: {
- QBool *val = qobject_to(QBool, obj);
- json_writer_bool(writer, name, qbool_get_bool(val));
- break;
- }
- default:
- abort();
- }
- }
- GString *qobject_to_json_pretty(const QObject *obj, bool pretty)
- {
- JSONWriter *writer = json_writer_new(pretty);
- to_json(writer, NULL, obj);
- return json_writer_get_and_free(writer);
- }
- GString *qobject_to_json(const QObject *obj)
- {
- return qobject_to_json_pretty(obj, false);
- }
|