[xpcom] Implement missing support for dicts inside dicts
authorKalle Vahlman <kalle.vahlman@movial.com>
Mon, 20 Apr 2009 10:04:26 +0000 (13:04 +0300)
committerKalle Vahlman <kalle.vahlman@movial.com>
Mon, 20 Apr 2009 10:04:26 +0000 (13:04 +0300)
xpcom-dbusservice/DBusMarshaling.cpp

index 84b35a4f751c782dc000f7f4eb1ffe0cd1cb5ced..d3e87039fd2c292ced646f4e222413fa356d635a 100644 (file)
@@ -48,6 +48,7 @@ void addArrayToIter(nsIVariant *aVariant, DBusMessageIter *aIter, int aDBusType)
 void addArrayDataToIter(JSContext* cx, void *data_ptr, PRUint32 start, PRUint32 count, PRUint16 type, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
 
 void addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSignatureIter *aSigIter);
+void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, jsval *v);
 already_AddRefed<nsIWritableVariant> getVariantFromIter(DBusMessageIter *aIter, int aDBusType);
 
 void addBasicTypeToIter(nsIVariant *aVariant, DBusMessageIter *aIter, int aDBusType);
@@ -890,6 +891,29 @@ addJSValueToIter(JSContext *cx, jsval *aValue, DBusMessageIter *aIter, DBusSigna
    }
 }
 
+void getDictFromArray(JSContext* cx, DBusMessageIter *arrayIter, JSObject **obj)
+{
+    *obj = JS_NewObject(cx, nsnull, nsnull, nsnull);
+
+    do
+    {
+        DBusMessageIter dict_iter;
+        char *key = nsnull;
+        dbus_message_iter_recurse(arrayIter, &dict_iter);
+        dbus_message_iter_get_basic(&dict_iter, &key);
+        BDBLOG(("    found key %s\n", key ? key : "null"));
+        dbus_message_iter_next(&dict_iter);
+        int value_type = dbus_message_iter_get_arg_type(&dict_iter);
+        BDBLOG(("    found value type %c\n", value_type));
+        jsval v;
+        getJSValueFromIter(cx, &dict_iter, value_type, &v);
+        nsAutoString ukey = NS_ConvertUTF8toUTF16(key);
+        JS_SetUCProperty(cx, *obj, ukey.get(), ukey.Length(), &v);
+
+    } while (dbus_message_iter_next(arrayIter));
+
+}
+
 void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, jsval *v)
 {
 
@@ -942,31 +966,40 @@ void getJSValueFromIter(JSContext* cx, DBusMessageIter *aIter, int aDBusType, js
         }
         case DBUS_TYPE_ARRAY:
         {
-            // FIXME: implement!
-            // FIXME: Dicts
-
-            nsTArray<jsval> elems;
-            
-            // recurse to container
             DBusMessageIter arrayIter;
             dbus_message_iter_recurse(aIter, &arrayIter);
-            
-            // iterate over array elements
-            do
+
+            if (dbus_message_iter_get_element_type(aIter) == DBUS_TYPE_DICT_ENTRY)
             {
-                jsval cv;
-                BDBLOG(("arg type: %c\n", dbus_message_iter_get_arg_type(&arrayIter)));
-                getJSValueFromIter(cx,
-                                   &arrayIter,
-                                   dbus_message_iter_get_arg_type(&arrayIter),
-                                   &cv);
-                elems.AppendElement(cv);
-                
-            } while (dbus_message_iter_next(&arrayIter));
+                BDBLOG(("    arg type ARRAY with DICT_ENTRY\n"));
+
+                JSObject *obj = nsnull;
+                getDictFromArray(cx, &arrayIter, &obj);
 
-            // Create an Array object with the elements
-            JSObject *array = JS_NewArrayObject(cx, elems.Length(), elems.Elements());
-            *v = OBJECT_TO_JSVAL(array);
+                *v = OBJECT_TO_JSVAL(obj);
+            } else {
+                nsTArray<jsval> elems;
+
+                // iterate over array elements
+                do
+                {
+                    jsval cv;
+                    BDBLOG(("arg type: %c\n",
+                            dbus_message_iter_get_arg_type(&arrayIter)));
+                    getJSValueFromIter(cx,
+                                       &arrayIter,
+                                       dbus_message_iter_get_arg_type(&arrayIter),
+                                       &cv);
+                    elems.AppendElement(cv);
+
+                } while (dbus_message_iter_next(&arrayIter));
+
+                // Create an Array object with the elements
+                JSObject *array = JS_NewArrayObject(cx,
+                                                    elems.Length(),
+                                                    elems.Elements());
+                *v = OBJECT_TO_JSVAL(array);
+            }
             break;
         }
         case DBUS_TYPE_STRUCT:
@@ -1054,30 +1087,12 @@ already_AddRefed<nsIWritableVariant> getVariantFromIter(JSContext* cx, DBusMessa
             {
                 BDBLOG(("    arg type ARRAY with DICT_ENTRY\n"));
 
-                // Construct a JS Object
-                JSObject *obj = JS_NewObject(cx, nsnull, nsnull, nsnull);
-                
-                // Set the properties
                 DBusMessageIter array_iter;
                 dbus_message_iter_recurse(aIter, &array_iter);
-                
-                do
-                {
-                    DBusMessageIter dict_iter;
-                    char *key = nsnull;
-                    dbus_message_iter_recurse(&array_iter, &dict_iter);
-                    dbus_message_iter_get_basic(&dict_iter, &key);
-                    BDBLOG(("    found key %s\n", key ? key : "null"));
-                    dbus_message_iter_next(&dict_iter);
-                    int value_type = dbus_message_iter_get_arg_type(&dict_iter);
-                    BDBLOG(("    found value type %c\n", value_type));
-                    jsval v;
-                    getJSValueFromIter(cx, &dict_iter, value_type, &v);
-                    nsAutoString ukey = NS_ConvertUTF8toUTF16(key);
-                    JS_SetUCProperty(cx, obj, ukey.get(), ukey.Length(), &v);
-                    
-                } while (dbus_message_iter_next(&array_iter));
-                
+
+                JSObject *obj = nsnull;
+                getDictFromArray(cx, &array_iter, &obj);
+
                 // get the xpconnect service
                 nsresult rv;
                 nsCOMPtr<nsIXPConnect> xpc(do_GetService(nsIXPConnect::GetCID(), &rv));