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