12910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner/* 22910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * QObject JSON integration 32910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * 42910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Copyright IBM, Corp. 2009 52910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * 62910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Authors: 72910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * Anthony Liguori <aliguori@us.ibm.com> 82910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * 92910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * This work is licensed under the terms of the GNU LGPL, version 2.1 or later. 102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * See the COPYING.LIB file in the top-level directory. 112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner * 122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner */ 132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 140fdfff3cce93e16179a454fd471cd1d9126204e0David 'Digit' Turner#include "qapi/qmp/json-lexer.h" 150fdfff3cce93e16179a454fd471cd1d9126204e0David 'Digit' Turner#include "qapi/qmp/json-parser.h" 160fdfff3cce93e16179a454fd471cd1d9126204e0David 'Digit' Turner#include "qapi/qmp/json-streamer.h" 171c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qjson.h" 181c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qint.h" 191c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qlist.h" 201c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qbool.h" 211c31e3e43ce4cca85a707dfff631e5e102fdecedDavid 'Digit' Turner#include "qapi/qmp/qfloat.h" 220fdfff3cce93e16179a454fd471cd1d9126204e0David 'Digit' Turner#include "qapi/qmp/qdict.h" 232910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnertypedef struct JSONParsingState 252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner JSONMessageParser parser; 272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner va_list *ap; 282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QObject *result; 292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} JSONParsingState; 302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic void parse_json(JSONMessageParser *parser, QList *tokens) 322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner JSONParsingState *s = container_of(parser, JSONParsingState, parser); 342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s->result = json_parser_parse(tokens, s->ap); 352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQObject *qobject_from_jsonv(const char *string, va_list *ap) 382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner JSONParsingState state = {}; 402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner state.ap = ap; 422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner json_message_parser_init(&state.parser, parse_json); 442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner json_message_parser_feed(&state.parser, string, strlen(string)); 452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner json_message_parser_flush(&state.parser); 462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner json_message_parser_destroy(&state.parser); 472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner return state.result; 492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQObject *qobject_from_json(const char *string) 522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner return qobject_from_jsonv(string, NULL); 542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 569251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner/* 579251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner * IMPORTANT: This function aborts on error, thus it must not 589251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner * be used with untrusted arguments. 599251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner */ 602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQObject *qobject_from_jsonf(const char *string, ...) 612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QObject *obj; 632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner va_list ap; 642910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner va_start(ap, string); 662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner obj = qobject_from_jsonv(string, &ap); 672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner va_end(ap); 682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 699251866320b5f8329a043bb56b3a794f78d12849David 'Digit' Turner assert(obj != NULL); 702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner return obj; 712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnertypedef struct ToJsonIterState 742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 75f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner int indent; 76f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner int pretty; 772910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner int count; 782910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QString *str; 792910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} ToJsonIterState; 802910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 81f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turnerstatic void to_json(const QObject *obj, QString *str, int pretty, int indent); 822910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 832910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic void to_json_dict_iter(const char *key, QObject *obj, void *opaque) 842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 852910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner ToJsonIterState *s = opaque; 862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QString *qkey; 87f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner int j; 882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 89f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner if (s->count) 902910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(s->str, ", "); 91f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner 92f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner if (s->pretty) { 93f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(s->str, "\n"); 94f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner for (j = 0 ; j < s->indent ; j++) 95f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(s->str, " "); 962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 972910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 982910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qkey = qstring_from_str(key); 99f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner to_json(QOBJECT(qkey), s->str, s->pretty, s->indent); 1002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QDECREF(qkey); 1012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 1022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(s->str, ": "); 103f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner to_json(obj, s->str, s->pretty, s->indent); 1042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s->count++; 1052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 1062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 1072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turnerstatic void to_json_list_iter(QObject *obj, void *opaque) 1082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 1092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner ToJsonIterState *s = opaque; 110f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner int j; 1112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 112f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner if (s->count) 1132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(s->str, ", "); 114f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner 115f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner if (s->pretty) { 116f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(s->str, "\n"); 117f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner for (j = 0 ; j < s->indent ; j++) 118f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(s->str, " "); 1192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 1202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 121f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner to_json(obj, s->str, s->pretty, s->indent); 1222910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s->count++; 1232910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 1242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 125f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turnerstatic void to_json(const QObject *obj, QString *str, int pretty, int indent) 1262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 1272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner switch (qobject_type(obj)) { 1282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QINT: { 1292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QInt *val = qobject_to_qint(obj); 1302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner char buffer[1024]; 1312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 1322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val)); 1332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, buffer); 1342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 1352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 1362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QSTRING: { 1372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QString *val = qobject_to_qstring(obj); 1382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner const char *ptr; 139910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner int cp; 140910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner char buf[16]; 141910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner char *end; 1422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 1432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner ptr = qstring_get_str(val); 1442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "\""); 145910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 146910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner for (; *ptr; ptr = end) { 147910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner cp = mod_utf8_codepoint(ptr, 6, &end); 148910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner switch (cp) { 149910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\"': 150910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\\""); 151910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 152910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\\': 153910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\\\"); 154910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 155910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\b': 156910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\b"); 157910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 158910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\f': 159910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\f"); 160910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 161910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\n': 162910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\n"); 163910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 164910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\r': 165910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\r"); 166910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 167910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case '\t': 168910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, "\\t"); 169910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner break; 170910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner default: 171910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (cp < 0) { 172910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner cp = 0xFFFD; /* replacement character */ 1732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 174910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner if (cp > 0xFFFF) { 175910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner /* beyond BMP; need a surrogate pair */ 176910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner snprintf(buf, sizeof(buf), "\\u%04X\\u%04X", 177910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 0xD800 + ((cp - 0x10000) >> 10), 178910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 0xDC00 + ((cp - 0x10000) & 0x3FF)); 179910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } else if (cp < 0x20 || cp >= 0x7F) { 180910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner snprintf(buf, sizeof(buf), "\\u%04X", cp); 181910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } else { 182910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner buf[0] = cp; 183910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner buf[1] = 0; 1842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 185910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner qstring_append(str, buf); 186910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner } 187910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner }; 188910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner 1892910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "\""); 1902910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 1912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 1922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QDICT: { 1932910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner ToJsonIterState s; 1942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QDict *val = qobject_to_qdict(obj); 1952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 1962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s.count = 0; 1972910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s.str = str; 198f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner s.indent = indent + 1; 199f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner s.pretty = pretty; 2002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "{"); 2012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qdict_iter(val, to_json_dict_iter, &s); 202f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner if (pretty) { 203f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner int j; 204f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(str, "\n"); 205f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner for (j = 0 ; j < indent ; j++) 206f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(str, " "); 207f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner } 2082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "}"); 2092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 2102910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2112910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QLIST: { 2122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner ToJsonIterState s; 2132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QList *val = qobject_to_qlist(obj); 2142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 2152910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s.count = 0; 2162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner s.str = str; 217f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner s.indent = indent + 1; 218f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner s.pretty = pretty; 2192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "["); 2202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qlist_iter(val, (void *)to_json_list_iter, &s); 221f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner if (pretty) { 222f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner int j; 223f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(str, "\n"); 224f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner for (j = 0 ; j < indent ; j++) 225f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner qstring_append(str, " "); 226f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner } 2272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "]"); 2282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 2292910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2302910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QFLOAT: { 2312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QFloat *val = qobject_to_qfloat(obj); 2322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner char buffer[1024]; 2332910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner int len; 2342910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 2352910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val)); 2362910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner while (len > 0 && buffer[len - 1] == '0') { 2372910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner len--; 2382910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 2402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner if (len && buffer[len - 1] == '.') { 2412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner buffer[len - 1] = 0; 2422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } else { 2432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner buffer[len] = 0; 2442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 245c005246ed03de874fdc432073ba8e5e8ebfed922David 'Digit' Turner 2462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, buffer); 2472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 2482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QBOOL: { 2502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QBool *val = qobject_to_qbool(obj); 2512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 2522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner if (qbool_get_int(val)) { 2532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "true"); 2542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } else { 2552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner qstring_append(str, "false"); 2562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 2582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_QERROR: 2602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner /* XXX: should QError be emitted? */ 2612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner case QTYPE_NONE: 2622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner break; 263910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner case QTYPE_MAX: 264910aea96b67d7f0357f586c47f20848ec435aa1bDavid 'Digit' Turner abort(); 2652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner } 2662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 2672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 2682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQString *qobject_to_json(const QObject *obj) 2692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{ 2702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner QString *str = qstring_new(); 2712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 272f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner to_json(obj, str, 0, 0); 273f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner 274f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner return str; 275f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner} 276f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner 277f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' TurnerQString *qobject_to_json_pretty(const QObject *obj) 278f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner{ 279f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner QString *str = qstring_new(); 280f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner 281f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner to_json(obj, str, 1, 0); 2822910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner 2832910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner return str; 2842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner} 285