Statistics
| Branch: | Revision:

root / qjson.c @ 96560cb3

History | View | Annotate | Download (5.7 kB)

1 b4748b9b Anthony Liguori
/*
2 b4748b9b Anthony Liguori
 * QObject JSON integration
3 b4748b9b Anthony Liguori
 *
4 b4748b9b Anthony Liguori
 * Copyright IBM, Corp. 2009
5 b4748b9b Anthony Liguori
 *
6 b4748b9b Anthony Liguori
 * Authors:
7 b4748b9b Anthony Liguori
 *  Anthony Liguori   <aliguori@us.ibm.com>
8 b4748b9b Anthony Liguori
 *
9 b4748b9b Anthony Liguori
 * This work is licensed under the terms of the GNU LGPL, version 2.1 or later.
10 b4748b9b Anthony Liguori
 * See the COPYING.LIB file in the top-level directory.
11 b4748b9b Anthony Liguori
 *
12 b4748b9b Anthony Liguori
 */
13 b4748b9b Anthony Liguori
14 b4748b9b Anthony Liguori
#include "json-lexer.h"
15 b4748b9b Anthony Liguori
#include "json-parser.h"
16 b4748b9b Anthony Liguori
#include "json-streamer.h"
17 b4748b9b Anthony Liguori
#include "qjson.h"
18 1fd825f7 Anthony Liguori
#include "qint.h"
19 1fd825f7 Anthony Liguori
#include "qlist.h"
20 1fd825f7 Anthony Liguori
#include "qbool.h"
21 1fd825f7 Anthony Liguori
#include "qfloat.h"
22 1fd825f7 Anthony Liguori
#include "qdict.h"
23 b4748b9b Anthony Liguori
24 b4748b9b Anthony Liguori
typedef struct JSONParsingState
25 b4748b9b Anthony Liguori
{
26 b4748b9b Anthony Liguori
    JSONMessageParser parser;
27 b4748b9b Anthony Liguori
    va_list *ap;
28 b4748b9b Anthony Liguori
    QObject *result;
29 b4748b9b Anthony Liguori
} JSONParsingState;
30 b4748b9b Anthony Liguori
31 b4748b9b Anthony Liguori
static void parse_json(JSONMessageParser *parser, QList *tokens)
32 b4748b9b Anthony Liguori
{
33 b4748b9b Anthony Liguori
    JSONParsingState *s = container_of(parser, JSONParsingState, parser);
34 b4748b9b Anthony Liguori
    s->result = json_parser_parse(tokens, s->ap);
35 b4748b9b Anthony Liguori
}
36 b4748b9b Anthony Liguori
37 8ff5a7d3 Luiz Capitulino
QObject *qobject_from_jsonv(const char *string, va_list *ap)
38 b4748b9b Anthony Liguori
{
39 b4748b9b Anthony Liguori
    JSONParsingState state = {};
40 b4748b9b Anthony Liguori
41 8ff5a7d3 Luiz Capitulino
    state.ap = ap;
42 8ff5a7d3 Luiz Capitulino
43 b4748b9b Anthony Liguori
    json_message_parser_init(&state.parser, parse_json);
44 b4748b9b Anthony Liguori
    json_message_parser_feed(&state.parser, string, strlen(string));
45 b4748b9b Anthony Liguori
    json_message_parser_flush(&state.parser);
46 b4748b9b Anthony Liguori
    json_message_parser_destroy(&state.parser);
47 b4748b9b Anthony Liguori
48 b4748b9b Anthony Liguori
    return state.result;
49 b4748b9b Anthony Liguori
}
50 b4748b9b Anthony Liguori
51 8ff5a7d3 Luiz Capitulino
QObject *qobject_from_json(const char *string)
52 8ff5a7d3 Luiz Capitulino
{
53 8ff5a7d3 Luiz Capitulino
    return qobject_from_jsonv(string, NULL);
54 8ff5a7d3 Luiz Capitulino
}
55 8ff5a7d3 Luiz Capitulino
56 b4748b9b Anthony Liguori
QObject *qobject_from_jsonf(const char *string, ...)
57 b4748b9b Anthony Liguori
{
58 8ff5a7d3 Luiz Capitulino
    QObject *obj;
59 b4748b9b Anthony Liguori
    va_list ap;
60 b4748b9b Anthony Liguori
61 b4748b9b Anthony Liguori
    va_start(ap, string);
62 8ff5a7d3 Luiz Capitulino
    obj = qobject_from_jsonv(string, &ap);
63 b4748b9b Anthony Liguori
    va_end(ap);
64 b4748b9b Anthony Liguori
65 8ff5a7d3 Luiz Capitulino
    return obj;
66 b4748b9b Anthony Liguori
}
67 1fd825f7 Anthony Liguori
68 1fd825f7 Anthony Liguori
typedef struct ToJsonIterState
69 1fd825f7 Anthony Liguori
{
70 1fd825f7 Anthony Liguori
    int count;
71 1fd825f7 Anthony Liguori
    QString *str;
72 1fd825f7 Anthony Liguori
} ToJsonIterState;
73 1fd825f7 Anthony Liguori
74 1fd825f7 Anthony Liguori
static void to_json(const QObject *obj, QString *str);
75 1fd825f7 Anthony Liguori
76 1fd825f7 Anthony Liguori
static void to_json_dict_iter(const char *key, QObject *obj, void *opaque)
77 1fd825f7 Anthony Liguori
{
78 1fd825f7 Anthony Liguori
    ToJsonIterState *s = opaque;
79 1fd825f7 Anthony Liguori
    QString *qkey;
80 1fd825f7 Anthony Liguori
81 1fd825f7 Anthony Liguori
    if (s->count) {
82 1fd825f7 Anthony Liguori
        qstring_append(s->str, ", ");
83 1fd825f7 Anthony Liguori
    }
84 1fd825f7 Anthony Liguori
85 1fd825f7 Anthony Liguori
    qkey = qstring_from_str(key);
86 1fd825f7 Anthony Liguori
    to_json(QOBJECT(qkey), s->str);
87 1fd825f7 Anthony Liguori
    QDECREF(qkey);
88 1fd825f7 Anthony Liguori
89 1fd825f7 Anthony Liguori
    qstring_append(s->str, ": ");
90 1fd825f7 Anthony Liguori
    to_json(obj, s->str);
91 1fd825f7 Anthony Liguori
    s->count++;
92 1fd825f7 Anthony Liguori
}
93 1fd825f7 Anthony Liguori
94 1fd825f7 Anthony Liguori
static void to_json_list_iter(QObject *obj, void *opaque)
95 1fd825f7 Anthony Liguori
{
96 1fd825f7 Anthony Liguori
    ToJsonIterState *s = opaque;
97 1fd825f7 Anthony Liguori
98 1fd825f7 Anthony Liguori
    if (s->count) {
99 1fd825f7 Anthony Liguori
        qstring_append(s->str, ", ");
100 1fd825f7 Anthony Liguori
    }
101 1fd825f7 Anthony Liguori
102 1fd825f7 Anthony Liguori
    to_json(obj, s->str);
103 1fd825f7 Anthony Liguori
    s->count++;
104 1fd825f7 Anthony Liguori
}
105 1fd825f7 Anthony Liguori
106 1fd825f7 Anthony Liguori
static void to_json(const QObject *obj, QString *str)
107 1fd825f7 Anthony Liguori
{
108 1fd825f7 Anthony Liguori
    switch (qobject_type(obj)) {
109 1fd825f7 Anthony Liguori
    case QTYPE_QINT: {
110 1fd825f7 Anthony Liguori
        QInt *val = qobject_to_qint(obj);
111 1fd825f7 Anthony Liguori
        char buffer[1024];
112 1fd825f7 Anthony Liguori
113 1fd825f7 Anthony Liguori
        snprintf(buffer, sizeof(buffer), "%" PRId64, qint_get_int(val));
114 1fd825f7 Anthony Liguori
        qstring_append(str, buffer);
115 1fd825f7 Anthony Liguori
        break;
116 1fd825f7 Anthony Liguori
    }
117 1fd825f7 Anthony Liguori
    case QTYPE_QSTRING: {
118 1fd825f7 Anthony Liguori
        QString *val = qobject_to_qstring(obj);
119 1fd825f7 Anthony Liguori
        const char *ptr;
120 1fd825f7 Anthony Liguori
121 1fd825f7 Anthony Liguori
        ptr = qstring_get_str(val);
122 1fd825f7 Anthony Liguori
        qstring_append(str, "\"");
123 1fd825f7 Anthony Liguori
        while (*ptr) {
124 1fd825f7 Anthony Liguori
            if ((ptr[0] & 0xE0) == 0xE0 &&
125 1fd825f7 Anthony Liguori
                (ptr[1] & 0x80) && (ptr[2] & 0x80)) {
126 1fd825f7 Anthony Liguori
                uint16_t wchar;
127 1fd825f7 Anthony Liguori
                char escape[7];
128 1fd825f7 Anthony Liguori
129 1fd825f7 Anthony Liguori
                wchar  = (ptr[0] & 0x0F) << 12;
130 1fd825f7 Anthony Liguori
                wchar |= (ptr[1] & 0x3F) << 6;
131 1fd825f7 Anthony Liguori
                wchar |= (ptr[2] & 0x3F);
132 1fd825f7 Anthony Liguori
                ptr += 2;
133 1fd825f7 Anthony Liguori
134 1fd825f7 Anthony Liguori
                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
135 1fd825f7 Anthony Liguori
                qstring_append(str, escape);
136 1fd825f7 Anthony Liguori
            } else if ((ptr[0] & 0xE0) == 0xC0 && (ptr[1] & 0x80)) {
137 1fd825f7 Anthony Liguori
                uint16_t wchar;
138 1fd825f7 Anthony Liguori
                char escape[7];
139 1fd825f7 Anthony Liguori
140 1fd825f7 Anthony Liguori
                wchar  = (ptr[0] & 0x1F) << 6;
141 1fd825f7 Anthony Liguori
                wchar |= (ptr[1] & 0x3F);
142 1fd825f7 Anthony Liguori
                ptr++;
143 1fd825f7 Anthony Liguori
144 1fd825f7 Anthony Liguori
                snprintf(escape, sizeof(escape), "\\u%04X", wchar);
145 1fd825f7 Anthony Liguori
                qstring_append(str, escape);
146 1fd825f7 Anthony Liguori
            } else switch (ptr[0]) {
147 1fd825f7 Anthony Liguori
                case '\"':
148 1fd825f7 Anthony Liguori
                    qstring_append(str, "\\\"");
149 1fd825f7 Anthony Liguori
                    break;
150 1fd825f7 Anthony Liguori
                case '\\':
151 1fd825f7 Anthony Liguori
                    qstring_append(str, "\\\\");
152 1fd825f7 Anthony Liguori
                    break;
153 1fd825f7 Anthony Liguori
                case '\b':
154 1fd825f7 Anthony Liguori
                    qstring_append(str, "\\b");
155 1fd825f7 Anthony Liguori
                    break;
156 1fd825f7 Anthony Liguori
                case '\n':
157 1fd825f7 Anthony Liguori
                    qstring_append(str, "\\n");
158 1fd825f7 Anthony Liguori
                    break;
159 1fd825f7 Anthony Liguori
                case '\r':
160 1fd825f7 Anthony Liguori
                    qstring_append(str, "\\r");
161 1fd825f7 Anthony Liguori
                    break;
162 1fd825f7 Anthony Liguori
                case '\t':
163 1fd825f7 Anthony Liguori
                    qstring_append(str, "\\t");
164 1fd825f7 Anthony Liguori
                    break;
165 1fd825f7 Anthony Liguori
                default: {
166 1fd825f7 Anthony Liguori
                    char buf[2] = { ptr[0], 0 };
167 1fd825f7 Anthony Liguori
                    qstring_append(str, buf);
168 1fd825f7 Anthony Liguori
                    break;
169 1fd825f7 Anthony Liguori
                }
170 1fd825f7 Anthony Liguori
                }
171 1fd825f7 Anthony Liguori
            ptr++;
172 1fd825f7 Anthony Liguori
        }
173 1fd825f7 Anthony Liguori
        qstring_append(str, "\"");
174 1fd825f7 Anthony Liguori
        break;
175 1fd825f7 Anthony Liguori
    }
176 1fd825f7 Anthony Liguori
    case QTYPE_QDICT: {
177 1fd825f7 Anthony Liguori
        ToJsonIterState s;
178 1fd825f7 Anthony Liguori
        QDict *val = qobject_to_qdict(obj);
179 1fd825f7 Anthony Liguori
180 1fd825f7 Anthony Liguori
        s.count = 0;
181 1fd825f7 Anthony Liguori
        s.str = str;
182 1fd825f7 Anthony Liguori
        qstring_append(str, "{");
183 1fd825f7 Anthony Liguori
        qdict_iter(val, to_json_dict_iter, &s);
184 1fd825f7 Anthony Liguori
        qstring_append(str, "}");
185 1fd825f7 Anthony Liguori
        break;
186 1fd825f7 Anthony Liguori
    }
187 1fd825f7 Anthony Liguori
    case QTYPE_QLIST: {
188 1fd825f7 Anthony Liguori
        ToJsonIterState s;
189 1fd825f7 Anthony Liguori
        QList *val = qobject_to_qlist(obj);
190 1fd825f7 Anthony Liguori
191 1fd825f7 Anthony Liguori
        s.count = 0;
192 1fd825f7 Anthony Liguori
        s.str = str;
193 1fd825f7 Anthony Liguori
        qstring_append(str, "[");
194 1fd825f7 Anthony Liguori
        qlist_iter(val, (void *)to_json_list_iter, &s);
195 1fd825f7 Anthony Liguori
        qstring_append(str, "]");
196 1fd825f7 Anthony Liguori
        break;
197 1fd825f7 Anthony Liguori
    }
198 1fd825f7 Anthony Liguori
    case QTYPE_QFLOAT: {
199 1fd825f7 Anthony Liguori
        QFloat *val = qobject_to_qfloat(obj);
200 1fd825f7 Anthony Liguori
        char buffer[1024];
201 1fd825f7 Anthony Liguori
        int len;
202 1fd825f7 Anthony Liguori
203 1fd825f7 Anthony Liguori
        len = snprintf(buffer, sizeof(buffer), "%f", qfloat_get_double(val));
204 1fd825f7 Anthony Liguori
        while (len > 0 && buffer[len - 1] == '0') {
205 1fd825f7 Anthony Liguori
            len--;
206 1fd825f7 Anthony Liguori
        }
207 1fd825f7 Anthony Liguori
208 1fd825f7 Anthony Liguori
        if (len && buffer[len - 1] == '.') {
209 1fd825f7 Anthony Liguori
            buffer[len - 1] = 0;
210 1fd825f7 Anthony Liguori
        } else {
211 1fd825f7 Anthony Liguori
            buffer[len] = 0;
212 1fd825f7 Anthony Liguori
        }
213 1fd825f7 Anthony Liguori
        
214 1fd825f7 Anthony Liguori
        qstring_append(str, buffer);
215 1fd825f7 Anthony Liguori
        break;
216 1fd825f7 Anthony Liguori
    }
217 1fd825f7 Anthony Liguori
    case QTYPE_QBOOL: {
218 1fd825f7 Anthony Liguori
        QBool *val = qobject_to_qbool(obj);
219 1fd825f7 Anthony Liguori
220 1fd825f7 Anthony Liguori
        if (qbool_get_int(val)) {
221 1fd825f7 Anthony Liguori
            qstring_append(str, "true");
222 1fd825f7 Anthony Liguori
        } else {
223 1fd825f7 Anthony Liguori
            qstring_append(str, "false");
224 1fd825f7 Anthony Liguori
        }
225 1fd825f7 Anthony Liguori
        break;
226 1fd825f7 Anthony Liguori
    }
227 9f9daf9a Luiz Capitulino
    case QTYPE_QERROR:
228 9f9daf9a Luiz Capitulino
        /* XXX: should QError be emitted? */
229 1fd825f7 Anthony Liguori
    case QTYPE_NONE:
230 1fd825f7 Anthony Liguori
        break;
231 1fd825f7 Anthony Liguori
    }
232 1fd825f7 Anthony Liguori
}
233 1fd825f7 Anthony Liguori
234 1fd825f7 Anthony Liguori
QString *qobject_to_json(const QObject *obj)
235 1fd825f7 Anthony Liguori
{
236 1fd825f7 Anthony Liguori
    QString *str = qstring_new();
237 1fd825f7 Anthony Liguori
238 1fd825f7 Anthony Liguori
    to_json(obj, str);
239 1fd825f7 Anthony Liguori
240 1fd825f7 Anthony Liguori
    return str;
241 1fd825f7 Anthony Liguori
}