~ubuntu-branches/ubuntu/precise/libdbusmenu/precise

« back to all changes in this revision

Viewing changes to tests/json-loader.c

  • Committer: Bazaar Package Importer
  • Author(s): Ted Gould
  • Date: 2010-07-01 09:00:16 UTC
  • mto: (8.1.24 maverick)
  • mto: This revision was merged to the branch mainline in revision 11.
  • Revision ID: james.westby@ubuntu.com-20100701090016-4gz0ijjxpyn2gagm
Tags: upstream-0.3.4
ImportĀ upstreamĀ versionĀ 0.3.4

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
A loader to turn JSON into dbusmenu menuitems
 
3
 
 
4
Copyright 2010 Canonical Ltd.
 
5
 
 
6
Authors:
 
7
    Ted Gould <ted@canonical.com>
 
8
 
 
9
This program is free software: you can redistribute it and/or modify it 
 
10
under the terms of the GNU General Public License version 3, as published 
 
11
by the Free Software Foundation.
 
12
 
 
13
This program is distributed in the hope that it will be useful, but 
 
14
WITHOUT ANY WARRANTY; without even the implied warranties of 
 
15
MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR 
 
16
PURPOSE.  See the GNU General Public License for more details.
 
17
 
 
18
You should have received a copy of the GNU General Public License along 
 
19
with this program.  If not, see <http://www.gnu.org/licenses/>.
 
20
*/
 
21
 
 
22
#include "json-loader.h"
 
23
#include <dbus/dbus-gtype-specialized.h>
 
24
 
 
25
static GValue *
 
26
node2value (JsonNode * node)
 
27
{
 
28
        if (node == NULL) {
 
29
                return NULL;
 
30
        }
 
31
 
 
32
        GValue * value = g_new0(GValue, 1);
 
33
 
 
34
        if (JSON_NODE_TYPE(node) == JSON_NODE_VALUE) {
 
35
                json_node_get_value(node, value);
 
36
                return value;
 
37
        }
 
38
 
 
39
        if (JSON_NODE_TYPE(node) == JSON_NODE_ARRAY) {
 
40
                JsonArray * array = json_node_get_array(node);
 
41
                JsonNode * first = json_array_get_element(array, 0);
 
42
 
 
43
                if (JSON_NODE_TYPE(first) == JSON_NODE_VALUE) {
 
44
                        GValue subvalue = {0};
 
45
                        json_node_get_value(first, &subvalue);
 
46
 
 
47
                        if (G_VALUE_TYPE(&subvalue) == G_TYPE_STRING) {
 
48
                                GArray * garray = g_array_sized_new(TRUE, TRUE, sizeof(gchar *), json_array_get_length(array));
 
49
                                g_value_init(value, G_TYPE_STRV);
 
50
                                g_value_take_boxed(value, garray->data);
 
51
 
 
52
                                int i;
 
53
                                for (i = 0; i < json_array_get_length(array); i++) {
 
54
                                        const gchar * str = json_node_get_string(json_array_get_element(array, i));
 
55
                                        gchar * dupstr = g_strdup(str);
 
56
                                        g_array_append_val(garray, dupstr);
 
57
                                }
 
58
 
 
59
                                g_array_free(garray, FALSE);
 
60
                        } else {
 
61
                                GValueArray * varray = g_value_array_new(json_array_get_length(array));
 
62
                                g_value_init(value, G_TYPE_VALUE_ARRAY);
 
63
                                g_value_take_boxed(value, varray);
 
64
 
 
65
                                g_value_array_append(varray, &subvalue);
 
66
                                g_value_unset(&subvalue);
 
67
 
 
68
                                int i;
 
69
                                for (i = 1; i < json_array_get_length(array); i++) {
 
70
                                        json_node_get_value(first, &subvalue);
 
71
                                        g_value_array_append(varray, &subvalue);
 
72
                                        g_value_unset(&subvalue);
 
73
                                }
 
74
                        }
 
75
 
 
76
                } else {
 
77
                        GValue * subvalue = node2value(first);
 
78
                        GType type = dbus_g_type_get_collection("GPtrArray", G_VALUE_TYPE(subvalue));
 
79
                        gpointer * wrapper = dbus_g_type_specialized_construct(type);
 
80
 
 
81
                        g_value_init(value, type);
 
82
                        g_value_take_boxed(value, wrapper);
 
83
 
 
84
                        DBusGTypeSpecializedAppendContext ctx;
 
85
                        dbus_g_type_specialized_init_append(value, &ctx);
 
86
 
 
87
                        dbus_g_type_specialized_collection_append(&ctx, subvalue);
 
88
                        int i;
 
89
                        for (i = 1; i < json_array_get_length(array); i++) {
 
90
                                GValue * subvalue = node2value(node);
 
91
                                dbus_g_type_specialized_collection_append(&ctx, subvalue);
 
92
                        }
 
93
 
 
94
                        dbus_g_type_specialized_collection_end_append(&ctx);
 
95
                }
 
96
        }
 
97
 
 
98
        if (JSON_NODE_TYPE(node) == JSON_NODE_OBJECT) {
 
99
                JsonObject * obj = json_node_get_object(node);
 
100
 
 
101
                GType type = dbus_g_type_get_map("GHashTable", G_TYPE_STRING, G_TYPE_VALUE);
 
102
                GHashTable * hash = (GHashTable *)dbus_g_type_specialized_construct(type);
 
103
 
 
104
                g_value_init(value, type);
 
105
                g_value_take_boxed(value, hash);
 
106
 
 
107
                DBusGTypeSpecializedAppendContext ctx;
 
108
                dbus_g_type_specialized_init_append(value, &ctx);
 
109
                
 
110
                GList * members = NULL;
 
111
                for (members = json_object_get_members(obj); members != NULL; members = g_list_next(members)) {
 
112
                        const gchar * member = members->data;
 
113
 
 
114
                        JsonNode * lnode = json_object_get_member(obj, member);
 
115
                        GValue * value = node2value(lnode);
 
116
 
 
117
                        if (value != NULL) {
 
118
                                GValue name = {0};
 
119
                                g_value_init(&name, G_TYPE_STRING);
 
120
                                g_value_set_static_string(&name, member);
 
121
 
 
122
                                dbus_g_type_specialized_map_append(&ctx, &name, value);
 
123
                        
 
124
                                g_value_unset(&name);
 
125
                                g_value_unset(value);
 
126
                                g_free(value);
 
127
                        }
 
128
                }
 
129
        }
 
130
 
 
131
        return value;
 
132
}
 
133
 
 
134
static void
 
135
set_props (DbusmenuMenuitem * mi, JsonObject * node)
 
136
{
 
137
        if (node == NULL) return;
 
138
 
 
139
        GList * members = NULL;
 
140
        for (members = json_object_get_members(node); members != NULL; members = g_list_next(members)) {
 
141
                const gchar * member = members->data;
 
142
 
 
143
                if (!g_strcmp0(member, "id")) { continue; }
 
144
                if (!g_strcmp0(member, "submenu")) { continue; }
 
145
 
 
146
                JsonNode * lnode = json_object_get_member(node, member);
 
147
                GValue * value = node2value(lnode);
 
148
 
 
149
                if (value != NULL) {
 
150
                        dbusmenu_menuitem_property_set_value(mi, member, value);
 
151
                        g_value_unset(value);
 
152
                        g_free(value);
 
153
                }
 
154
        }
 
155
 
 
156
        return;
 
157
}
 
158
 
 
159
DbusmenuMenuitem *
 
160
dbusmenu_json_build_from_node (const JsonNode * cnode)
 
161
{
 
162
        JsonNode * node = (JsonNode *)cnode; /* To match the jsonglib API :( */
 
163
 
 
164
        if (node == NULL) return NULL;
 
165
        if (JSON_NODE_TYPE(node) != JSON_NODE_OBJECT) return NULL;
 
166
 
 
167
        JsonObject * layout = json_node_get_object(node);
 
168
 
 
169
        DbusmenuMenuitem * local = NULL;
 
170
        if (json_object_has_member(layout, "id")) {
 
171
                JsonNode * node = json_object_get_member(layout, "id");
 
172
                g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_VALUE, NULL);
 
173
                local = dbusmenu_menuitem_new_with_id(json_node_get_int(node));
 
174
        } else {
 
175
                local = dbusmenu_menuitem_new();
 
176
        }
 
177
 
 
178
        set_props(local, layout);
 
179
        
 
180
        if (json_object_has_member(layout, "submenu")) {
 
181
                JsonNode * node = json_object_get_member(layout, "submenu");
 
182
                g_return_val_if_fail(JSON_NODE_TYPE(node) == JSON_NODE_ARRAY, local);
 
183
                JsonArray * array = json_node_get_array(node);
 
184
                guint count;
 
185
                for (count = 0; count < json_array_get_length(array); count++) {
 
186
                        DbusmenuMenuitem * child = dbusmenu_json_build_from_node(json_array_get_element(array, count));
 
187
                        if (child != NULL) {
 
188
                                dbusmenu_menuitem_child_append(local, child);
 
189
                        }
 
190
                }
 
191
        }
 
192
 
 
193
        /* g_debug("Layout to menu return: 0x%X", (unsigned int)local); */
 
194
        return local;
 
195
}
 
196
 
 
197
DbusmenuMenuitem *
 
198
dbusmenu_json_build_from_file (const gchar * filename)
 
199
{
 
200
        JsonParser * parser = json_parser_new();
 
201
 
 
202
        GError * error = NULL;
 
203
        if (!json_parser_load_from_file(parser, filename, &error)) {
 
204
                g_warning("Failed parsing file %s because: %s", filename, error->message);
 
205
                g_error_free(error);
 
206
                return NULL;
 
207
        }
 
208
 
 
209
        JsonNode * root_node = json_parser_get_root(parser);
 
210
        if (JSON_NODE_TYPE(root_node) != JSON_NODE_OBJECT) {
 
211
                g_warning("Root node is not an object, fail.  It's an: %s", json_node_type_name(root_node));
 
212
                return NULL;
 
213
        }
 
214
 
 
215
        DbusmenuMenuitem * mi = dbusmenu_json_build_from_node(root_node);
 
216
 
 
217
        g_object_unref(parser);
 
218
 
 
219
        return mi;
 
220
}