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
142910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "json-lexer.h"
152910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "json-parser.h"
162910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "json-streamer.h"
172910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "qjson.h"
182910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "qint.h"
192910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "qlist.h"
202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "qbool.h"
212910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "qfloat.h"
222910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner#include "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;
1392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        ptr = qstring_get_str(val);
1412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, "\"");
1422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        while (*ptr) {
1432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            if ((ptr[0] & 0xE0) == 0xE0 &&
1442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                (ptr[1] & 0x80) && (ptr[2] & 0x80)) {
1452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                uint16_t wchar;
1462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                char escape[7];
1472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                wchar  = (ptr[0] & 0x0F) << 12;
1492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                wchar |= (ptr[1] & 0x3F) << 6;
1502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                wchar |= (ptr[2] & 0x3F);
1512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                ptr += 2;
1522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
1542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                qstring_append(str, escape);
1552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            } else if ((ptr[0] & 0xE0) == 0xC0 && (ptr[1] & 0x80)) {
1562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                uint16_t wchar;
1572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                char escape[7];
1582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                wchar  = (ptr[0] & 0x1F) << 6;
1602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                wchar |= (ptr[1] & 0x3F);
1612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                ptr++;
1622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
1632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
1642910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                qstring_append(str, escape);
1652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            } else switch (ptr[0]) {
1662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                case '\"':
1672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    qstring_append(str, "\\\"");
1682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
1692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                case '\\':
1702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    qstring_append(str, "\\\\");
1712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
1722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                case '\b':
1732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    qstring_append(str, "\\b");
1742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
175fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner                case '\f':
176fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner                    qstring_append(str, "\\f");
177fd4c0076b7470f5962ff462bae9cd9f208e059b7David Turner                    break;
1782910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                case '\n':
1792910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    qstring_append(str, "\\n");
1802910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
1812910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                case '\r':
1822910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    qstring_append(str, "\\r");
1832910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
1842910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                case '\t':
1852910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    qstring_append(str, "\\t");
1862910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
1872910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                default: {
1882910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    if (ptr[0] <= 0x1F) {
1892910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                        char escape[7];
1902910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                        snprintf(escape, sizeof(escape), "\\u%04X", ptr[0]);
1912910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                        qstring_append(str, escape);
1922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    } else {
1932910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                        char buf[2] = { ptr[0], 0 };
1942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                        qstring_append(str, buf);
1952910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    }
1962910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                    break;
1972910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                }
1982910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner                }
1992910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            ptr++;
2002910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
2012910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, "\"");
2022910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        break;
2032910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
2042910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QTYPE_QDICT: {
2052910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        ToJsonIterState s;
2062910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        QDict *val = qobject_to_qdict(obj);
2072910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2082910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        s.count = 0;
2092910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        s.str = str;
210f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        s.indent = indent + 1;
211f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        s.pretty = pretty;
2122910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, "{");
2132910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qdict_iter(val, to_json_dict_iter, &s);
214f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        if (pretty) {
215f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner            int j;
216f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner            qstring_append(str, "\n");
217f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner            for (j = 0 ; j < indent ; j++)
218f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner                qstring_append(str, "    ");
219f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        }
2202910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, "}");
2212910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        break;
2222910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
2232910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QTYPE_QLIST: {
2242910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        ToJsonIterState s;
2252910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        QList *val = qobject_to_qlist(obj);
2262910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2272910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        s.count = 0;
2282910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        s.str = str;
229f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        s.indent = indent + 1;
230f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        s.pretty = pretty;
2312910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, "[");
2322910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qlist_iter(val, (void *)to_json_list_iter, &s);
233f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        if (pretty) {
234f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner            int j;
235f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner            qstring_append(str, "\n");
236f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner            for (j = 0 ; j < indent ; j++)
237f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner                qstring_append(str, "    ");
238f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner        }
2392910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, "]");
2402910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        break;
2412910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
2422910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QTYPE_QFLOAT: {
2432910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        QFloat *val = qobject_to_qfloat(obj);
2442910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        char buffer[1024];
2452910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        int len;
2462910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2472910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
2482910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        while (len > 0 && buffer[len - 1] == '0') {
2492910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            len--;
2502910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
2512910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2522910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (len && buffer[len - 1] == '.') {
2532910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            buffer[len - 1] = 0;
2542910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        } else {
2552910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            buffer[len] = 0;
2562910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
2572910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2582910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        qstring_append(str, buffer);
2592910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        break;
2602910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
2612910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QTYPE_QBOOL: {
2622910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        QBool *val = qobject_to_qbool(obj);
2632910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2642910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        if (qbool_get_int(val)) {
2652910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            qstring_append(str, "true");
2662910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        } else {
2672910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner            qstring_append(str, "false");
2682910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        }
2692910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        break;
2702910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
2712910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QTYPE_QERROR:
2722910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        /* XXX: should QError be emitted? */
2732910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    case QTYPE_NONE:
2742910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner        break;
2752910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    }
2762910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
2772910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2782910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' TurnerQString *qobject_to_json(const QObject *obj)
2792910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner{
2802910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    QString *str = qstring_new();
2812910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
282f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner    to_json(obj, str, 0, 0);
283f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner
284f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner    return str;
285f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner}
286f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner
287f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' TurnerQString *qobject_to_json_pretty(const QObject *obj)
288f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner{
289f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner    QString *str = qstring_new();
290f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner
291f0753acaab4309557754ec19d3e839fe6b5e356cDavid 'Digit' Turner    to_json(obj, str, 1, 0);
2922910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner
2932910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner    return str;
2942910f183ddd5286911bc1e3499ea93cb57de8b75David 'Digit' Turner}
295