Changes to introspection generation to remove DOCTYPE and XML
[platform/core/uifw/at-spi2-atk.git] / libspi / droute.c
1 /*
2  * AT-SPI - Assistive Technology Service Provider Interface
3  * (Gnome Accessibility Project; http://developer.gnome.org/projects/gap)
4  *
5  * Copyright 2008 Novell, Inc.
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Library General Public
9  * License as published by the Free Software Foundation; either
10  * version 2 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Library General Public License for more details.
16  *
17  * You should have received a copy of the GNU Library General Public
18  * License along with this library; if not, write to the
19  * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
20  * Boston, MA 02111-1307, USA.
21  */
22
23 #include "droute.h"
24 #include <stdlib.h>
25 #include <string.h>
26
27 static DRouteInterface *
28 find_iface (DRouteData * data, const char *name)
29 {
30   GSList *l;
31
32   for (l = data->interfaces; l; l = g_slist_next (l))
33     {
34       DRouteInterface *iface = (DRouteInterface *) l->data;
35       if (iface && iface->name && !strcmp (iface->name, name))
36         return iface;
37     }
38   return NULL;
39 }
40
41 static DBusHandlerResult
42 prop_get_all (DBusConnection * bus, DBusMessage * message, DRouteData * data)
43 {
44   DRouteInterface *iface_def;
45   DRouteProperty *prop;
46   DBusError error;
47   const char *iface;
48   const char *path = dbus_message_get_path (message);
49   DBusMessage *reply;
50   DBusMessageIter iter, iter_dict, iter_dict_entry;
51
52   dbus_error_init (&error);
53   if (!dbus_message_get_args
54       (message, &error, DBUS_TYPE_STRING, &iface, DBUS_TYPE_INVALID))
55     {
56       return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
57     }
58   reply = dbus_message_new_method_return (message);
59   /* tbd: replace tbd with todo? */
60   if (!reply)
61     goto oom;
62   dbus_message_iter_init_append (reply, &iter);
63   if (!dbus_message_iter_open_container
64       (&iter, DBUS_TYPE_ARRAY, "{sv}", &iter_dict))
65     goto oom;
66   iface_def = find_iface (data, iface);
67   if (!iface_def)
68     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
69   if (iface_def->properties)
70     for (prop = iface_def->properties; prop->name; prop++)
71       {
72         if (!prop->get)
73           continue;
74         if (!dbus_message_iter_open_container
75             (&iter_dict, DBUS_TYPE_DICT_ENTRY, NULL, &iter_dict_entry))
76           goto oom;
77         dbus_message_iter_append_basic (&iter_dict_entry, DBUS_TYPE_STRING,
78                                         &prop->name);
79         (*prop->get) (path, &iter_dict_entry, data->user_data);
80         if (!dbus_message_iter_close_container (&iter_dict, &iter_dict_entry))
81           goto oom;
82       }
83   if (!dbus_message_iter_close_container (&iter, &iter_dict))
84     goto oom;
85   dbus_connection_send (bus, reply, NULL);
86   dbus_message_unref (reply);
87   return DBUS_HANDLER_RESULT_HANDLED;
88 oom:
89   /* tbd: return a standard out-of-memory error */
90   return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
91 }
92
93 static DBusHandlerResult
94 prop (DBusConnection * bus, DBusMessage * message, DRouteData * data)
95 {
96   const char *mode = dbus_message_get_member (message);
97   const char *iface, *member;
98   const char *path = dbus_message_get_path (message);
99   int set;
100   DBusMessage *reply;
101   DBusMessageIter iter;
102   DRouteInterface *iface_def;
103   DRouteProperty *prop = NULL;
104
105   if (!strcmp (mode, "Set"))
106     set = 1;
107   else if (!strcmp (mode, "Get"))
108     set = 0;
109   else
110     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
111   reply = dbus_message_new_method_return (message);
112   dbus_message_iter_init (message, &iter);
113   dbus_message_iter_get_basic (&iter, &iface);
114   dbus_message_iter_next (&iter);
115   dbus_message_iter_get_basic (&iter, &member);
116   if (!set)
117     dbus_message_iter_init_append (reply, &iter);
118   iface_def = find_iface (data, iface);
119   if (!iface_def)
120     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
121   if (iface_def->properties)
122     for (prop = iface_def->properties;
123          prop->name && strcmp (prop->name, member); prop++)
124       if (!prop || !prop->name)
125         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
126   if (set)
127     {
128       if (!prop->set)
129         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
130       (*prop->set) (path, &iter, data->user_data);
131     }
132   else
133     {
134       if (!prop->get)
135         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
136       (*prop->get) (path, &iter, data->user_data);
137     }
138   dbus_connection_send (bus, reply, NULL);
139   dbus_message_unref (reply);
140   return DBUS_HANDLER_RESULT_HANDLED;
141 }
142
143 DBusHandlerResult
144 droute_message (DBusConnection * bus, DBusMessage * message, void *user_data)
145 {
146   DRouteData *data = (DRouteData *) user_data;
147   DRouteInterface *iface_def;
148   DRouteMethod *method;
149   const char *iface = dbus_message_get_interface (message);
150   const char *member = dbus_message_get_member (message);
151   int type;
152   DBusError error;
153   DBusMessage *reply;
154
155   dbus_error_init (&error);
156   if (!member)
157     return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
158   if (iface && !strcmp (iface, "org.freedesktop.DBus.Properties"))
159     {
160       if (!strcmp (member, "GetAll"))
161         return prop_get_all (bus, message, data);
162       return prop (bus, message, data);
163     }
164   if (iface)
165     {
166       iface_def = find_iface (data, iface);
167       if (!iface_def)
168         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
169       if (iface_def->methods)
170         for (method = iface_def->methods; method->func; method++)
171           {
172             if (!strcmp (method->name, member))
173               {
174                 reply =
175                   (*method->func) (bus, message,
176                                    (method->wants_droute_data ? data : data->
177                                     user_data));
178                 if (reply)
179                   {
180                     dbus_connection_send (bus, reply, NULL);
181                     dbus_message_unref (reply);
182                   }
183                 return DBUS_HANDLER_RESULT_HANDLED;
184               }
185           }
186     }
187   else
188     {
189       GSList *l;
190       if (type == DBUS_MESSAGE_TYPE_SIGNAL)
191         return DBUS_HANDLER_RESULT_NOT_YET_HANDLED;
192       for (l = data->interfaces; l; l = g_slist_next (l))
193         {
194           iface_def = (DRouteInterface *) l->data;
195           if (iface_def->methods)
196             for (method = iface_def->methods; method->func; method++)
197               {
198                 if (!strcmp (method->name, member))
199                   {
200                     reply = (*method->func) (bus, message, data->user_data);
201                     if (reply)
202                       {
203                         dbus_connection_send (bus, reply, NULL);
204                         dbus_message_unref (reply);
205                       }
206                     return DBUS_HANDLER_RESULT_HANDLED;
207                   }
208               }
209         }
210     }
211   return DBUS_HANDLER_RESULT_HANDLED;
212 }
213
214 dbus_bool_t
215 droute_return_v_int32 (DBusMessageIter * iter, dbus_int32_t val)
216 {
217   DBusMessageIter sub;
218
219   if (!dbus_message_iter_open_container
220       (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_INT32_AS_STRING, &sub))
221     {
222       return FALSE;
223     }
224   dbus_message_iter_append_basic (&sub, DBUS_TYPE_INT32, &val);
225   dbus_message_iter_close_container (iter, &sub);
226   return TRUE;
227 }
228
229 dbus_bool_t
230 droute_return_v_double (DBusMessageIter * iter, double val)
231 {
232   DBusMessageIter sub;
233
234   if (!dbus_message_iter_open_container
235       (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_DOUBLE_AS_STRING, &sub))
236     {
237       return FALSE;
238     }
239   dbus_message_iter_append_basic (&sub, DBUS_TYPE_DOUBLE, &val);
240   dbus_message_iter_close_container (iter, &sub);
241   return TRUE;
242 }
243
244 /* Return a string in a variant
245  * will return an empty string if passed a NULL value */
246 dbus_bool_t
247 droute_return_v_string (DBusMessageIter * iter, const char *val)
248 {
249   DBusMessageIter sub;
250
251   if (!val)
252     val = "";
253   if (!dbus_message_iter_open_container
254       (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_STRING_AS_STRING, &sub))
255     {
256       return FALSE;
257     }
258   dbus_message_iter_append_basic (&sub, DBUS_TYPE_STRING, &val);
259   dbus_message_iter_close_container (iter, &sub);
260   return TRUE;
261 }
262
263 dbus_int32_t
264 droute_get_v_int32 (DBusMessageIter * iter)
265 {
266   DBusMessageIter sub;
267   dbus_int32_t rv;
268
269   // TODO- ensure we have the correct type
270   dbus_message_iter_recurse (iter, &sub);
271   dbus_message_iter_get_basic (&sub, &rv);
272   return rv;
273 }
274
275 const char *
276 droute_get_v_string (DBusMessageIter * iter)
277 {
278   DBusMessageIter sub;
279   char *rv;
280
281   // TODO- ensure we have the correct type
282   dbus_message_iter_recurse (iter, &sub);
283   dbus_message_iter_get_basic (&sub, &rv);
284   return rv;
285 }
286
287 dbus_bool_t
288 droute_return_v_object (DBusMessageIter * iter, const char *path)
289 {
290   DBusMessageIter sub;
291
292   if (!dbus_message_iter_open_container
293       (iter, DBUS_TYPE_VARIANT, DBUS_TYPE_OBJECT_PATH_AS_STRING, &sub))
294     {
295       return FALSE;
296     }
297   dbus_message_iter_append_basic (&sub, DBUS_TYPE_OBJECT_PATH, &path);
298   dbus_message_iter_close_container (iter, &sub);
299   return TRUE;
300 }
301
302 dbus_bool_t
303 droute_add_interface (DRouteData * data, const char *name,
304                       DRouteMethod * methods, DRouteProperty * properties,
305                       DRouteGetDatumFunction get_datum,
306                       DRouteFreeDatumFunction free_datum)
307 {
308   DRouteInterface *iface =
309     (DRouteInterface *) malloc (sizeof (DRouteInterface));
310   GSList *new_list;
311
312   if (!iface)
313     return FALSE;
314   iface->name = strdup (name);
315   if (!iface->name)
316     {
317       free (iface);
318       return FALSE;
319     }
320   iface->methods = methods;
321   iface->properties = properties;
322   iface->get_datum = get_datum;
323   iface->free_datum = free_datum;
324   new_list = g_slist_append (data->interfaces, iface);
325   if (!new_list)
326     {
327       free (iface->name);
328       free (iface);
329       return FALSE;
330     }
331   data->interfaces = new_list;
332   return TRUE;
333 }