[gjs] Add support for GPtrArrays



commit 1149483f2f738a18dad447359e269f84bcb6ab1a
Author: Giovanni Campagna <gcampagna src gnome org>
Date:   Sun Jun 19 22:33:21 2011 +0200

    Add support for GPtrArrays
    
    Using code that already exists for GArray, implement marshalling
    for GPtrArrays. Includes some general cleanup of array code.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=652753

 gi/arg.c                     |  199 +++++++++++++++++-------------------------
 test/js/testGIMarshalling.js |   43 +++++++--
 2 files changed, 113 insertions(+), 129 deletions(-)
---
diff --git a/gi/arg.c b/gi/arg.c
index d73e3dd..0170845 100644
--- a/gi/arg.c
+++ b/gi/arg.c
@@ -481,7 +481,7 @@ gjs_array_to_strv(JSContext   *context,
 static JSBool
 gjs_string_to_intarray(JSContext   *context,
                        jsval        string_val,
-                       GITypeTag    param_tag,
+                       GITypeInfo  *param_info,
                        void       **arr_p,
                        gsize       *length)
 {
@@ -489,7 +489,8 @@ gjs_string_to_intarray(JSContext   *context,
     char *result;
     guint16 *result16;
 
-    element_type = replace_gtype(param_tag);
+    element_type = g_type_info_get_tag(param_info);
+    element_type = replace_gtype(element_type);
 
     switch (element_type) {
     case GI_TYPE_TAG_INT8:
@@ -680,21 +681,21 @@ gjs_array_to_ptrarray(JSContext   *context,
 
     *arr_p = array;
     return JS_TRUE;
-} 
+}
 
 static JSBool
 gjs_array_to_array(JSContext   *context,
                    jsval        array_value,
                    gsize        length,
                    GITransfer   transfer,
-                   GITypeTag    param_tag,
                    GITypeInfo  *param_info,
                    void       **arr_p)
 {
     enum { UNSIGNED=FALSE, SIGNED=TRUE };
     GITypeTag element_type;
 
-    element_type = replace_gtype(param_tag);
+    element_type = g_type_info_get_tag(param_info);
+    element_type = replace_gtype(element_type);
 
     if (element_type == GI_TYPE_TAG_INTERFACE) {
         GIBaseInfo *interface_info = g_type_info_get_interface(param_info);
@@ -849,24 +850,15 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
                                      gsize           *length_p)
 {
     JSBool ret = JS_TRUE;
-    GIArrayType array_type = g_type_info_get_array_type(type_info);
     GITypeInfo *param_info;
-    GITypeTag param_tag;
 
     param_info = g_type_info_get_param_type(type_info, 0);
-    param_tag = g_type_info_get_tag(param_info);
-
-    if (array_type == GI_ARRAY_TYPE_BYTE_ARRAY) {
-        /* HACK: ByteArrays are reported as having a param of gpointer (GI_TYPE_TAG_VOID),
-           which is obviously wrong. Override it here */
-        param_tag = GI_TYPE_TAG_UINT8;
-    }
 
     if ((JSVAL_IS_NULL(value) && !may_be_null) ||
         (!JSVAL_IS_STRING(value) && !JSVAL_IS_OBJECT(value) && !JSVAL_IS_NULL(value))) {
         gchar *display_name = get_argument_display_name(arg_name, arg_type);
         gjs_throw(context, "Expected type %s for %s but got type '%s' %p",
-                  g_type_tag_to_string(param_tag),
+                  g_type_tag_to_string(g_type_info_get_tag(param_info)),
                   display_name,
                   JS_GetTypeName(context,
                                  JS_TypeOfValue(context, value)),
@@ -880,7 +872,7 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
         *length_p = 0;
     } else if (JSVAL_IS_STRING(value)) {
         /* Allow strings as int8/uint8/int16/uint16 arrays */
-        if (!gjs_string_to_intarray(context, value, param_tag,
+        if (!gjs_string_to_intarray(context, value, param_info,
                                     contents, length_p))
             ret = JS_FALSE;
     } else if (gjs_object_has_property(context,
@@ -900,7 +892,6 @@ gjs_array_to_explicit_array_internal(JSContext       *context,
                                     value,
                                     length,
                                     transfer,
-                                    param_tag,
                                     param_info,
                                     contents))
                 ret = JS_FALSE;
@@ -1376,9 +1367,7 @@ gjs_value_to_g_argument(JSContext      *context,
 
             byte_array = gjs_byte_array_get_byte_array(context, JSVAL_TO_OBJECT(value));
             if (byte_array) {
-                /* extra reference will be removed gjs_g_argument_release
-                   (and actually has no effect given that finalizer invokes
-                   g_byte_array_free without caring of refcount) */
+                /* extra reference will be removed by gjs_g_argument_release */
                 arg->v_pointer = g_byte_array_ref(byte_array);
                 break;
             }
@@ -1421,6 +1410,14 @@ gjs_value_to_g_argument(JSContext      *context,
             arg->v_pointer = byte_array;
 
             g_free(data);
+        } else if (array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+            GPtrArray *array = g_ptr_array_sized_new(length);
+
+            g_ptr_array_set_size(array, length);
+            memcpy(array->pdata, data, sizeof(gpointer) * length);
+            arg->v_pointer = array;
+
+            g_free(data);
         }
         break;
     }
@@ -1800,10 +1797,10 @@ finally:
 }
 
 static JSBool
-gjs_array_from_carray (JSContext  *context,
-                       jsval      *value_p,
-                       GITypeInfo *type_info,
-                       gpointer    array)
+gjs_array_from_fixed_size_array (JSContext  *context,
+                                 jsval      *value_p,
+                                 GITypeInfo *type_info,
+                                 gpointer    array)
 {
     gint length;
     GITypeInfo *param_info;
@@ -1811,10 +1808,7 @@ gjs_array_from_carray (JSContext  *context,
 
     length = g_type_info_get_array_fixed_size(type_info);
 
-    if (length == -1) {
-        gjs_throw(context, "FIXME: Only supporting fixed size ARRAYs");
-        return JS_FALSE;
-    }
+    g_assert (length != -1);
 
     param_info = g_type_info_get_param_type(type_info, 0);
 
@@ -1845,92 +1839,35 @@ gjs_value_from_explicit_array(JSContext  *context,
 }
 
 static JSBool
-gjs_array_from_g_array (JSContext  *context,
-                        jsval      *value_p,
-                        GITypeInfo *param_info,
-                        GArray     *array)
+gjs_array_from_boxed_array (JSContext   *context,
+                            jsval       *value_p,
+                            GIArrayType  array_type,
+                            GITypeInfo  *param_info,
+                            GArgument   *arg)
 {
-    JSObject *obj;
-    jsval elem;
-    GArgument arg;
-    JSBool result;
-    GITypeTag element_type;
-    guint i;
-
-    element_type = g_type_info_get_tag(param_info);
-    element_type = replace_gtype(element_type);
-
-    obj = JS_NewArrayObject(context, 0, NULL);
-    if (obj == NULL)
-      return JS_FALSE;
-
-    *value_p = OBJECT_TO_JSVAL(obj);
-
-    elem = JSVAL_VOID;
-
-#define ITERATE(type) \
-    for (i = 0; i < array->len; i++) { \
-        arg.v_##type = g_array_index(array, g##type, i); \
-        if (!gjs_value_from_g_argument(context, &elem, param_info, &arg)) \
-          goto finally; \
-        if (!JS_DefineElement(context, obj, i, elem, NULL, NULL, \
-              JSPROP_ENUMERATE)) \
-          goto finally; \
-    }
-
-    switch (element_type) {
-        case GI_TYPE_TAG_UINT8:
-          ITERATE(uint8);
-          break;
-        case GI_TYPE_TAG_INT8:
-          ITERATE(int8);
-          break;
-        case GI_TYPE_TAG_UINT16:
-          ITERATE(uint16);
-          break;
-        case GI_TYPE_TAG_INT16:
-          ITERATE(int16);
-          break;
-        case GI_TYPE_TAG_UINT32:
-          ITERATE(uint32);
-          break;
-        case GI_TYPE_TAG_INT32:
-          ITERATE(int32);
-          break;
-        case GI_TYPE_TAG_UINT64:
-          ITERATE(uint64);
-          break;
-        case GI_TYPE_TAG_INT64:
-          ITERATE(int64);
-          break;
-        case GI_TYPE_TAG_FLOAT:
-          ITERATE(float);
-          break;
-        case GI_TYPE_TAG_DOUBLE:
-          ITERATE(double);
-          break;
-        case GI_TYPE_TAG_UTF8:
-        case GI_TYPE_TAG_FILENAME:
-        case GI_TYPE_TAG_ARRAY:
-        case GI_TYPE_TAG_INTERFACE:
-        case GI_TYPE_TAG_GLIST:
-        case GI_TYPE_TAG_GSLIST:
-        case GI_TYPE_TAG_GHASH:
-          ITERATE(pointer);
-          break;
-        default:
-          gjs_throw(context, "Unknown GArray element-type %d", element_type);
-          goto finally;
+    GArray *array;
+    GPtrArray *ptr_array;
+    gpointer data = NULL;
+    gsize length = 0;
+
+    switch(array_type) {
+    case GI_ARRAY_TYPE_BYTE_ARRAY:
+        /* GByteArray is just a typedef for GArray internally */
+    case GI_ARRAY_TYPE_ARRAY:
+        array = (GArray*)(arg->v_pointer);
+        data = array->data;
+        length = array->len;
+        break;
+    case GI_ARRAY_TYPE_PTR_ARRAY:
+        ptr_array = (GPtrArray*)(arg->v_pointer);
+        data = ptr_array->pdata;
+        length = ptr_array->len;
+        break;
+    default:
+        g_assert_not_reached();
     }
 
-#undef ITERATE
-
-    result = JS_TRUE;
-
-finally:
-    JS_RemoveValueRoot(context, &elem);
-
-    return result;
+    return gjs_array_from_carray_internal(context, value_p, param_info, length, data);
 }
 
 static JSBool
@@ -2348,7 +2285,8 @@ gjs_value_from_g_argument (JSContext  *context,
 
                 return result;
             } else {
-                return gjs_array_from_carray(context, value_p, type_info, arg->v_pointer);
+                /* arrays with length are handled outside of this function */
+                return gjs_array_from_fixed_size_array(context, value_p, type_info, arg->v_pointer);
             }
         } else if (g_type_info_get_array_type(type_info) == GI_ARRAY_TYPE_BYTE_ARRAY) {
             JSObject *array = gjs_byte_array_from_byte_array(context,
@@ -2367,10 +2305,11 @@ gjs_value_from_g_argument (JSContext  *context,
             param_info = g_type_info_get_param_type(type_info, 0);
             g_assert(param_info != NULL);
 
-            result = gjs_array_from_g_array(context,
-                                            value_p,
-                                            param_info,
-                                            arg->v_pointer);
+            result = gjs_array_from_boxed_array(context,
+                                                value_p,
+                                                g_type_info_get_array_type(type_info),
+                                                param_info,
+                                                arg);
 
             g_base_info_unref((GIBaseInfo*) param_info);
 
@@ -2721,11 +2660,31 @@ gjs_g_arg_release_internal(JSContext  *context,
 
             g_base_info_unref((GIBaseInfo*) param_info);
         } else if (array_type == GI_ARRAY_TYPE_BYTE_ARRAY) {
-            if (transfer == GI_TRANSFER_CONTAINER) {
-                g_byte_array_free ((GByteArray*)arg->v_pointer, FALSE);
-            } else if (transfer == GI_TRANSFER_EVERYTHING) {
-                g_byte_array_free ((GByteArray*)arg->v_pointer, TRUE);
+            g_byte_array_unref ((GByteArray*)arg->v_pointer);
+        } else if (array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
+            GITypeInfo *param_info;
+            GPtrArray *array;
+
+            param_info = g_type_info_get_param_type(type_info, 0);
+            array = arg->v_pointer;
+
+            if (transfer != GI_TRANSFER_CONTAINER) {
+                guint i;
+
+                for (i = 0; i < array->len; i++) {
+                    GArgument arg;
+
+                    arg.v_pointer = g_ptr_array_index (array, i);
+                    gjs_g_argument_release(context,
+                                           transfer,
+                                           param_info,
+                                           &arg);
+                }
             }
+
+            g_ptr_array_free(array, TRUE);
+
+            g_base_info_unref((GIBaseInfo*) param_info);
         } else {
             g_assert_not_reached();
         }
diff --git a/test/js/testGIMarshalling.js b/test/js/testGIMarshalling.js
index 4ca9e15..4a7c355 100644
--- a/test/js/testGIMarshalling.js
+++ b/test/js/testGIMarshalling.js
@@ -102,13 +102,11 @@ function testCArray() {
 
 function testGArray() {
     var array;
-    // Tests disabled due to do g-i typelib compilation bug
-    // https://bugzilla.gnome.org/show_bug.cgi?id=622335
-    //array = GIMarshallingTests.garray_int_none_return();
-    //assertEquals(-1, array[0]);
-    //assertEquals(0, array[1]);
-    //assertEquals(1, array[2]);
-    //assertEquals(2, array[3]);
+    array = GIMarshallingTests.garray_int_none_return();
+    assertEquals(-1, array[0]);
+    assertEquals(0, array[1]);
+    assertEquals(1, array[2]);
+    assertEquals(2, array[3]);
     array = GIMarshallingTests.garray_utf8_none_return()
     assertEquals("0", array[0]);
     assertEquals("1", array[1]);
@@ -122,8 +120,8 @@ function testGArray() {
     assertEquals("1", array[1]);
     assertEquals("2", array[2]);
 
-    // GIMarshallingTests.garray_int_none_in([-1, 0, 1, 2])
-    // GIMarshallingTests.garray_utf8_none_in(["0", "1", "2"])
+    GIMarshallingTests.garray_int_none_in([-1, 0, 1, 2])
+    GIMarshallingTests.garray_utf8_none_in(["0", "1", "2"])
 
     array = GIMarshallingTests.garray_utf8_none_out()
     assertEquals("0", array[0]);
@@ -151,6 +149,33 @@ function testByteArray() {
     for (i = 0; i < refByteArray.length; i++)
 	assertEquals(refByteArray[i], byteArray[i]);
     GIMarshallingTests.bytearray_none_in(refByteArray);
+
+    // Another test, with a normal array, to test conversion
+    GIMarshallingTests.bytearray_none_in([0, 49, 0xFF, 51]);
+
+    // Another test, with a string, to test conversion
+    GIMarshallingTests.bytearray_none_in("\x00\x31\xFF\x33");
+}
+
+function testPtrArray() {
+    function arrayEqual(ref, val) {
+	assertEquals(ref.length, val.length);
+	for (i = 0; i < ref.length; i++)
+	    assertEquals(ref[i], val[i]);
+    }
+    var array;
+
+    GIMarshallingTests.gptrarray_utf8_none_in(["0", "1", "2"]);
+
+    var refArray = ["0", "1", "2"];
+
+    arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_none_return());
+    arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_container_return());
+    arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_full_return());
+
+    arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_none_out());
+    arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_container_out());
+    arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_full_out());
 }
 
 gjstestRun();



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]