[jscore] Fix compilation warning
[browser-dbus-bridge.git] / jscorebus / jscorebus-signature.c
1 /**
2  * Browser D-Bus Bridge, JavaScriptCore version
3  *
4  * Copyright © 2008 Movial Creative Technologies Inc
5  *  Contact: Movial Creative Technologies Inc, <info@movial.com>
6  *  Authors: Kalle Vahlman, <kalle.vahlman@movial.com>
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2.1 of the License, or (at your option) any later
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16  * GNU Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20  *
21  */
22
23 #include <glib.h>
24 #include <dbus/dbus.h>
25 #include <JavaScriptCore/JavaScript.h>
26
27 #include "jscorebus-classfactory.h"
28 #include "jscorebus-marshal.h"
29
30 gboolean jsvalue_typeof(JSContextRef context,
31                         JSValueRef jsvalue,
32                         const char *type)
33 {
34   const JSClassDefinition *jsclassdef;
35   JSClassRef jsclass;
36   
37   jsclassdef = jsclassdef_lookup(type);
38   if (G_UNLIKELY(jsclassdef == NULL))
39     return FALSE;
40   jsclass = jsclass_lookup(jsclassdef);
41
42   return JSValueIsObjectOfClass(context, jsvalue, jsclass);
43 }
44
45 gboolean jsvalue_instanceof(JSContextRef context,
46                             JSValueRef jsvalue,
47                             const char *constructor)
48 {
49   JSStringRef property;
50   JSObjectRef ctor;
51
52   property = JSStringCreateWithUTF8CString(constructor);
53   ctor = JSValueToObject(context,
54                          JSObjectGetProperty(context,
55                                              JSContextGetGlobalObject(context),
56                                              property,
57                                              NULL),
58                          NULL);
59   JSStringRelease(property);
60
61   return JSValueIsInstanceOfConstructor(context, jsvalue, ctor, NULL);
62 }
63
64 char *jsvalue_to_signature(JSContextRef context,
65                            JSValueRef jsvalue)
66 {
67   char *signature = NULL;
68   
69   switch (JSValueGetType(context, jsvalue))
70   {
71     case kJSTypeBoolean:
72       {
73         signature = g_strdup(DBUS_TYPE_BOOLEAN_AS_STRING);
74         break;
75       }
76     case kJSTypeNumber:
77       {
78         /* JavaScript numbers are always doubles */
79         signature = g_strdup(DBUS_TYPE_DOUBLE_AS_STRING);
80         break;
81       }
82     case kJSTypeString:
83       {
84         signature = g_strdup(DBUS_TYPE_STRING_AS_STRING);
85         break;
86       }
87     case kJSTypeObject:
88       {
89         int i;
90         char *dict_signature = NULL;
91         JSPropertyNameArrayRef propnames;
92
93         /* Check for number types */
94         for (i = 0; i < JSCOREBUS_N_NUMBER_CLASSES; i++)
95         {
96           if (jsvalue_typeof(context, jsvalue, jscorebus_number_class_names[i]))
97           {
98             switch (jscorebus_number_class_types[i])
99             {
100 #define NUMBER_SIGNATURE(t) \
101               case DBUS_TYPE_## t: \
102                 signature = g_strdup(DBUS_TYPE_## t ##_AS_STRING); \
103                 break;
104               NUMBER_SIGNATURE(UINT32)
105               NUMBER_SIGNATURE(INT32)
106               NUMBER_SIGNATURE(BYTE)
107               NUMBER_SIGNATURE(UINT64)
108               NUMBER_SIGNATURE(INT64)
109               NUMBER_SIGNATURE(UINT16)
110               NUMBER_SIGNATURE(INT16)
111
112               default:
113                 break;
114             }
115           }
116         }
117
118         /* Check for arrays */
119         if (jsvalue_instanceof(context, jsvalue, "Array"))
120         {
121           JSPropertyNameArrayRef propnames;
122           char *array_signature;
123
124           propnames = JSObjectCopyPropertyNames(context, (JSObjectRef)jsvalue);
125           if (!jsarray_get_signature(context, jsvalue, propnames, &array_signature))
126           { 
127             g_warning("Could not create array signature");
128             break;
129           }
130           signature = g_strdup_printf("a%s", array_signature);
131           g_free(array_signature);
132           break;
133         }
134
135         /* Check variants */
136         if (jsvalue_typeof(context, jsvalue, "DBusVariant"))
137         {
138           signature = g_strdup("v");
139           break;
140         }
141
142         if (jsvalue_typeof(context, jsvalue, "DBusObjectPath"))
143         {
144           signature = g_strdup(DBUS_TYPE_OBJECT_PATH_AS_STRING);
145           break;
146         }
147
148         if (jsvalue_typeof(context, jsvalue, "DBusSignature"))
149         {
150           signature = g_strdup(DBUS_TYPE_SIGNATURE_AS_STRING);
151           break;
152         }
153
154         /* Check structs */
155         if (jsvalue_typeof(context, jsvalue, "DBusStruct"))
156         {
157           JSPropertyNameArrayRef propnames;
158           JSObjectRef value = (JSObjectRef)JSObjectGetPrivate((JSObjectRef)jsvalue);
159           propnames = JSObjectCopyPropertyNames(context, value);
160           jsstruct_get_signature(context, value, propnames, &signature);
161           break;
162         }
163
164         /* Default conversion is to dict */
165         propnames = JSObjectCopyPropertyNames(context, (JSObjectRef)jsvalue);
166         jsdict_get_signature(context, jsvalue, propnames, &dict_signature);
167         if (dict_signature != NULL)
168         {
169           signature = g_strdup_printf("a%s", dict_signature);
170           g_free(dict_signature);
171         }
172
173         break;
174       }
175     case kJSTypeUndefined:
176     case kJSTypeNull:
177     default:
178       g_warning("Signature lookup failed for unsupported type %i", JSValueGetType(context, jsvalue));
179       break;
180   }
181   return signature;
182 }
183
184 gboolean
185 jsarray_get_signature(JSContextRef context,
186                       JSValueRef jsvalue,
187                       JSPropertyNameArrayRef propNames,
188                       char **signature)
189 {
190   int i, props;
191   
192   *signature = NULL;
193   props = JSPropertyNameArrayGetCount(propNames);
194   /* Arrays are restricted to single complete types so we only need to look
195    * at the first property
196    */
197   if (props > 0)
198   {
199     *signature = jsvalue_to_signature(context,
200       JSObjectGetPropertyAtIndex(context, (JSObjectRef)jsvalue, 0, NULL));
201   }
202   return *signature == NULL ? FALSE : TRUE;
203 }
204
205 gboolean
206 jsdict_get_signature(JSContextRef context,
207                      JSValueRef jsvalue,
208                      JSPropertyNameArrayRef propNames,
209                      char **signature)
210 {
211   int i, props;
212   
213   *signature = NULL;
214   props = JSPropertyNameArrayGetCount(propNames);
215   /* Dicts support only string keys currently, though numbers would be another
216    * possibility...
217    */
218   if (props > 0)
219   {
220     char **signatures = g_new0(char*, 5);
221     
222     signatures[0] = g_strdup(DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING);
223     signatures[1] = g_strdup(DBUS_TYPE_STRING_AS_STRING);
224     signatures[2] = jsvalue_to_signature(context,
225       JSObjectGetProperty(context, (JSObjectRef)jsvalue,
226         JSPropertyNameArrayGetNameAtIndex(propNames, 0), NULL));
227     signatures[3] = g_strdup(DBUS_DICT_ENTRY_END_CHAR_AS_STRING);
228
229     *signature = g_strjoinv(NULL, signatures);
230     g_strfreev(signatures);
231   }
232   return *signature == NULL ? FALSE : TRUE;
233 }
234
235 gboolean
236 jsstruct_get_signature(JSContextRef context,
237                        JSValueRef jsvalue,
238                        JSPropertyNameArrayRef propNames,
239                        char **signature)
240 {
241   int props;
242   
243   *signature = NULL;
244   props = JSPropertyNameArrayGetCount(propNames);
245   if (props > 0)
246   {
247     char **signatures = g_new0(char*, props + 2);
248     int i = 0;
249     signatures[i] = g_strdup(DBUS_STRUCT_BEGIN_CHAR_AS_STRING);
250     while (i < props)
251     {
252       signatures[i+1] = jsvalue_to_signature(context,
253         JSObjectGetProperty(context, (JSObjectRef)jsvalue,
254           JSPropertyNameArrayGetNameAtIndex(propNames, i++), NULL));
255     }
256     signatures[props + 1] = g_strdup(DBUS_STRUCT_END_CHAR_AS_STRING);
257
258     *signature = g_strjoinv(NULL, signatures);
259     g_strfreev(signatures);
260   }
261   return *signature == NULL ? FALSE : TRUE;
262 }
263