]>
git.proxmox.com Git - mirror_qemu.git/blob - qobject/qjson.c
2 * QObject JSON integration
4 * Copyright IBM, Corp. 2009
7 * Anthony Liguori <aliguori@us.ibm.com>
9 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 * See the COPYING.LIB file in the top-level directory.
14 #include "qemu/osdep.h"
15 #include "qapi/error.h"
16 #include "qapi/qmp/json-parser.h"
17 #include "qapi/qmp/qjson.h"
18 #include "qapi/qmp/qbool.h"
19 #include "qapi/qmp/qdict.h"
20 #include "qapi/qmp/qlist.h"
21 #include "qapi/qmp/qnum.h"
22 #include "qapi/qmp/qstring.h"
23 #include "qemu/unicode.h"
25 typedef struct JSONParsingState
27 JSONMessageParser parser
;
32 static void consume_json(void *opaque
, QObject
*json
, Error
*err
)
34 JSONParsingState
*s
= opaque
;
36 assert(!json
!= !err
);
37 assert(!s
->result
|| !s
->err
);
40 qobject_unref(s
->result
);
42 error_setg(&s
->err
, "Expecting at most one JSON value");
54 * Parse @string as JSON value.
55 * If @ap is non-null, interpolate %-escapes.
56 * Takes ownership of %p arguments.
57 * On success, return the JSON value.
58 * On failure, store an error through @errp and return NULL.
59 * Ownership of %p arguments becomes indeterminate then. To avoid
60 * leaks, callers passing %p must terminate on error, e.g. by passing
63 static QObject
*qobject_from_jsonv(const char *string
, va_list *ap
,
66 JSONParsingState state
= {};
68 json_message_parser_init(&state
.parser
, consume_json
, &state
, ap
);
69 json_message_parser_feed(&state
.parser
, string
, strlen(string
));
70 json_message_parser_flush(&state
.parser
);
71 json_message_parser_destroy(&state
.parser
);
73 if (!state
.result
&& !state
.err
) {
74 error_setg(&state
.err
, "Expecting a JSON value");
77 error_propagate(errp
, state
.err
);
81 QObject
*qobject_from_json(const char *string
, Error
**errp
)
83 return qobject_from_jsonv(string
, NULL
, errp
);
87 * Parse @string as JSON value with %-escapes interpolated.
88 * Abort on error. Do not use with untrusted @string.
89 * Return the resulting QObject. It is never null.
91 QObject
*qobject_from_vjsonf_nofail(const char *string
, va_list ap
)
96 /* va_copy() is needed when va_list is an array type */
98 obj
= qobject_from_jsonv(string
, &ap_copy
, &error_abort
);
106 * Parse @string as JSON value with %-escapes interpolated.
107 * Abort on error. Do not use with untrusted @string.
108 * Return the resulting QObject. It is never null.
110 QObject
*qobject_from_jsonf_nofail(const char *string
, ...)
115 va_start(ap
, string
);
116 obj
= qobject_from_vjsonf_nofail(string
, ap
);
123 * Parse @string as JSON object with %-escapes interpolated.
124 * Abort on error. Do not use with untrusted @string.
125 * Return the resulting QDict. It is never null.
127 QDict
*qdict_from_vjsonf_nofail(const char *string
, va_list ap
)
131 qdict
= qobject_to(QDict
, qobject_from_vjsonf_nofail(string
, ap
));
137 * Parse @string as JSON object with %-escapes interpolated.
138 * Abort on error. Do not use with untrusted @string.
139 * Return the resulting QDict. It is never null.
141 QDict
*qdict_from_jsonf_nofail(const char *string
, ...)
146 va_start(ap
, string
);
147 qdict
= qdict_from_vjsonf_nofail(string
, ap
);
152 static void json_pretty_newline(GString
*accu
, bool pretty
, int indent
)
155 g_string_append_printf(accu
, "\n%*s", indent
* 4, "");
159 static void to_json(const QObject
*obj
, GString
*accu
, bool pretty
, int indent
)
161 switch (qobject_type(obj
)) {
163 g_string_append(accu
, "null");
166 QNum
*val
= qobject_to(QNum
, obj
);
167 char *buffer
= qnum_to_string(val
);
168 g_string_append(accu
, buffer
);
172 case QTYPE_QSTRING
: {
173 QString
*val
= qobject_to(QString
, obj
);
178 ptr
= qstring_get_str(val
);
179 g_string_append_c(accu
, '"');
181 for (; *ptr
; ptr
= end
) {
182 cp
= mod_utf8_codepoint(ptr
, 6, &end
);
185 g_string_append(accu
, "\\\"");
188 g_string_append(accu
, "\\\\");
191 g_string_append(accu
, "\\b");
194 g_string_append(accu
, "\\f");
197 g_string_append(accu
, "\\n");
200 g_string_append(accu
, "\\r");
203 g_string_append(accu
, "\\t");
207 cp
= 0xFFFD; /* replacement character */
210 /* beyond BMP; need a surrogate pair */
211 g_string_append_printf(accu
, "\\u%04X\\u%04X",
212 0xD800 + ((cp
- 0x10000) >> 10),
213 0xDC00 + ((cp
- 0x10000) & 0x3FF));
214 } else if (cp
< 0x20 || cp
>= 0x7F) {
215 g_string_append_printf(accu
, "\\u%04X", cp
);
217 g_string_append_c(accu
, cp
);
222 g_string_append_c(accu
, '"');
226 QDict
*val
= qobject_to(QDict
, obj
);
227 const char *comma
= pretty
? "," : ", ";
228 const char *sep
= "";
229 const QDictEntry
*entry
;
232 g_string_append_c(accu
, '{');
234 for (entry
= qdict_first(val
);
236 entry
= qdict_next(val
, entry
)) {
237 g_string_append(accu
, sep
);
238 json_pretty_newline(accu
, pretty
, indent
+ 1);
240 qkey
= qstring_from_str(qdict_entry_key(entry
));
241 to_json(QOBJECT(qkey
), accu
, pretty
, indent
+ 1);
244 g_string_append(accu
, ": ");
245 to_json(qdict_entry_value(entry
), accu
, pretty
, indent
+ 1);
249 json_pretty_newline(accu
, pretty
, indent
);
250 g_string_append_c(accu
, '}');
254 QList
*val
= qobject_to(QList
, obj
);
255 const char *comma
= pretty
? "," : ", ";
256 const char *sep
= "";
259 g_string_append_c(accu
, '[');
261 QLIST_FOREACH_ENTRY(val
, entry
) {
262 g_string_append(accu
, sep
);
263 json_pretty_newline(accu
, pretty
, indent
+ 1);
264 to_json(qlist_entry_obj(entry
), accu
, pretty
, indent
+ 1);
268 json_pretty_newline(accu
, pretty
, indent
);
269 g_string_append_c(accu
, ']');
273 QBool
*val
= qobject_to(QBool
, obj
);
275 if (qbool_get_bool(val
)) {
276 g_string_append(accu
, "true");
278 g_string_append(accu
, "false");
287 QString
*qobject_to_json_pretty(const QObject
*obj
, bool pretty
)
289 GString
*accu
= g_string_new(NULL
);
291 to_json(obj
, accu
, pretty
, 0);
292 return qstring_from_gstring(accu
);
295 QString
*qobject_to_json(const QObject
*obj
)
297 return qobject_to_json_pretty(obj
, false);