1 /* 2 * QObject JSON integration 3 * 4 * Copyright IBM, Corp. 2009 5 * 6 * Authors: 7 * Anthony Liguori <aliguori@us.ibm.com> 8 * 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. 11 * 12 */ 13 14 #include "qemu/osdep.h" 15 #include "qapi/error.h" 16 #include "qapi/qmp/json-lexer.h" 17 #include "qapi/qmp/json-parser.h" 18 #include "qapi/qmp/json-streamer.h" 19 #include "qapi/qmp/qjson.h" 20 #include "qapi/qmp/qbool.h" 21 #include "qapi/qmp/qdict.h" 22 #include "qapi/qmp/qlist.h" 23 #include "qapi/qmp/qnum.h" 24 #include "qapi/qmp/qstring.h" 25 #include "qemu/unicode.h" 26 27 typedef struct JSONParsingState 28 { 29 JSONMessageParser parser; 30 va_list *ap; 31 QObject *result; 32 Error *err; 33 } JSONParsingState; 34 35 static void parse_json(JSONMessageParser *parser, GQueue *tokens) 36 { 37 JSONParsingState *s = container_of(parser, JSONParsingState, parser); 38 39 s->result = json_parser_parse_err(tokens, s->ap, &s->err); 40 } 41 42 QObject *qobject_from_jsonv(const char *string, va_list *ap, Error **errp) 43 { 44 JSONParsingState state = {}; 45 46 state.ap = ap; 47 48 json_message_parser_init(&state.parser, parse_json); 49 json_message_parser_feed(&state.parser, string, strlen(string)); 50 json_message_parser_flush(&state.parser); 51 json_message_parser_destroy(&state.parser); 52 53 error_propagate(errp, state.err); 54 return state.result; 55 } 56 57 QObject *qobject_from_json(const char *string, Error **errp) 58 { 59 return qobject_from_jsonv(string, NULL, errp); 60 } 61 62 QObject *qobject_from_jsonf(const char *string, ...) 63 { 64 QObject *obj; 65 va_list ap; 66 67 va_start(ap, string); 68 obj = qobject_from_jsonv(string, &ap, &error_abort); 69 va_end(ap); 70 71 return obj; 72 } 73 74 /* 75 * Parse @string as JSON object with %-escapes interpolated. 76 * Abort on error. Do not use with untrusted @string. 77 * Return the resulting QDict. It is never null. 78 */ 79 QDict *qdict_from_jsonf_nofail(const char *string, ...) 80 { 81 QDict *obj; 82 va_list ap; 83 84 va_start(ap, string); 85 obj = qobject_to(QDict, qobject_from_jsonv(string, &ap, &error_abort)); 86 va_end(ap); 87 88 assert(obj); 89 return obj; 90 } 91 92 typedef struct ToJsonIterState 93 { 94 int indent; 95 int pretty; 96 int count; 97 QString *str; 98 } ToJsonIterState; 99 100 static void to_json(const QObject *obj, QString *str, int pretty, int indent); 101 102 static void to_json_dict_iter(const char *key, QObject *obj, void *opaque) 103 { 104 ToJsonIterState *s = opaque; 105 QString *qkey; 106 int j; 107 108 if (s->count) { 109 qstring_append(s->str, s->pretty ? "," : ", "); 110 } 111 112 if (s->pretty) { 113 qstring_append(s->str, "\n"); 114 for (j = 0 ; j < s->indent ; j++) 115 qstring_append(s->str, " "); 116 } 117 118 qkey = qstring_from_str(key); 119 to_json(QOBJECT(qkey), s->str, s->pretty, s->indent); 120 qobject_unref(qkey); 121 122 qstring_append(s->str, ": "); 123 to_json(obj, s->str, s->pretty, s->indent); 124 s->count++; 125 } 126 127 static void to_json_list_iter(QObject *obj, void *opaque) 128 { 129 ToJsonIterState *s = opaque; 130 int j; 131 132 if (s->count) { 133 qstring_append(s->str, s->pretty ? "," : ", "); 134 } 135 136 if (s->pretty) { 137 qstring_append(s->str, "\n"); 138 for (j = 0 ; j < s->indent ; j++) 139 qstring_append(s->str, " "); 140 } 141 142 to_json(obj, s->str, s->pretty, s->indent); 143 s->count++; 144 } 145 146 static void to_json(const QObject *obj, QString *str, int pretty, int indent) 147 { 148 switch (qobject_type(obj)) { 149 case QTYPE_QNULL: 150 qstring_append(str, "null"); 151 break; 152 case QTYPE_QNUM: { 153 QNum *val = qobject_to(QNum, obj); 154 char *buffer = qnum_to_string(val); 155 qstring_append(str, buffer); 156 g_free(buffer); 157 break; 158 } 159 case QTYPE_QSTRING: { 160 QString *val = qobject_to(QString, obj); 161 const char *ptr; 162 int cp; 163 char buf[16]; 164 char *end; 165 166 ptr = qstring_get_str(val); 167 qstring_append(str, "\""); 168 169 for (; *ptr; ptr = end) { 170 cp = mod_utf8_codepoint(ptr, 6, &end); 171 switch (cp) { 172 case '\"': 173 qstring_append(str, "\\\""); 174 break; 175 case '\\': 176 qstring_append(str, "\\\\"); 177 break; 178 case '\b': 179 qstring_append(str, "\\b"); 180 break; 181 case '\f': 182 qstring_append(str, "\\f"); 183 break; 184 case '\n': 185 qstring_append(str, "\\n"); 186 break; 187 case '\r': 188 qstring_append(str, "\\r"); 189 break; 190 case '\t': 191 qstring_append(str, "\\t"); 192 break; 193 default: 194 if (cp < 0) { 195 cp = 0xFFFD; /* replacement character */ 196 } 197 if (cp > 0xFFFF) { 198 /* beyond BMP; need a surrogate pair */ 199 snprintf(buf, sizeof(buf), "\\u%04X\\u%04X", 200 0xD800 + ((cp - 0x10000) >> 10), 201 0xDC00 + ((cp - 0x10000) & 0x3FF)); 202 } else if (cp < 0x20 || cp >= 0x7F) { 203 snprintf(buf, sizeof(buf), "\\u%04X", cp); 204 } else { 205 buf[0] = cp; 206 buf[1] = 0; 207 } 208 qstring_append(str, buf); 209 } 210 }; 211 212 qstring_append(str, "\""); 213 break; 214 } 215 case QTYPE_QDICT: { 216 ToJsonIterState s; 217 QDict *val = qobject_to(QDict, obj); 218 219 s.count = 0; 220 s.str = str; 221 s.indent = indent + 1; 222 s.pretty = pretty; 223 qstring_append(str, "{"); 224 qdict_iter(val, to_json_dict_iter, &s); 225 if (pretty) { 226 int j; 227 qstring_append(str, "\n"); 228 for (j = 0 ; j < indent ; j++) 229 qstring_append(str, " "); 230 } 231 qstring_append(str, "}"); 232 break; 233 } 234 case QTYPE_QLIST: { 235 ToJsonIterState s; 236 QList *val = qobject_to(QList, obj); 237 238 s.count = 0; 239 s.str = str; 240 s.indent = indent + 1; 241 s.pretty = pretty; 242 qstring_append(str, "["); 243 qlist_iter(val, (void *)to_json_list_iter, &s); 244 if (pretty) { 245 int j; 246 qstring_append(str, "\n"); 247 for (j = 0 ; j < indent ; j++) 248 qstring_append(str, " "); 249 } 250 qstring_append(str, "]"); 251 break; 252 } 253 case QTYPE_QBOOL: { 254 QBool *val = qobject_to(QBool, obj); 255 256 if (qbool_get_bool(val)) { 257 qstring_append(str, "true"); 258 } else { 259 qstring_append(str, "false"); 260 } 261 break; 262 } 263 default: 264 abort(); 265 } 266 } 267 268 QString *qobject_to_json(const QObject *obj) 269 { 270 QString *str = qstring_new(); 271 272 to_json(obj, str, 0, 0); 273 274 return str; 275 } 276 277 QString *qobject_to_json_pretty(const QObject *obj) 278 { 279 QString *str = qstring_new(); 280 281 to_json(obj, str, 1, 0); 282 283 return str; 284 } 285