diff options
author | Jasper St. Pierre <jstpierre@mecheye.net> | 2011-09-01 14:52:20 -0400 |
---|---|---|
committer | Jasper St. Pierre <jstpierre@mecheye.net> | 2012-01-06 15:26:47 -0500 |
commit | 0688f72307596cd86e1f47a21a4ce73a865987f1 (patch) | |
tree | cc11624f2390f76d87e9b6817742e2e0ae91ad14 | |
parent | dc69b12d5e44f9d3b209759082f721237a8c9a06 (diff) | |
download | gjs-0688f72307596cd86e1f47a21a4ce73a865987f1.tar.gz |
Add support for flat GValue arrays
https://bugzilla.gnome.org/show_bug.cgi?id=657767
-rw-r--r-- | gi/arg.c | 128 | ||||
-rw-r--r-- | test/js/testGIMarshalling.js | 45 |
2 files changed, 161 insertions, 12 deletions
@@ -221,8 +221,10 @@ type_needs_release (GITypeInfo *type_info, break; } - if (g_type_is_a(gtype, G_TYPE_CLOSURE) || g_type_is_a(gtype, G_TYPE_VALUE)) + if (g_type_is_a(gtype, G_TYPE_CLOSURE)) needs_release = TRUE; + else if (g_type_is_a(gtype, G_TYPE_VALUE)) + needs_release = g_type_info_is_pointer(type_info); else needs_release = FALSE; @@ -729,6 +731,118 @@ gjs_array_to_ptrarray(JSContext *context, } static JSBool +gjs_array_to_flat_gvalue_array(JSContext *context, + jsval array_value, + unsigned int length, + void **arr_p) +{ + GValue *values = g_new0(GValue, length); + unsigned int i; + JSBool result = JS_TRUE; + + for (i = 0; i < length; i ++) { + jsval elem; + elem = JSVAL_VOID; + + if (!JS_GetElement(context, JSVAL_TO_OBJECT(array_value), + i, &elem)) { + g_free(values); + gjs_throw(context, + "Missing array element %u", + i); + return JS_FALSE; + } + + result = gjs_value_to_g_value(context, elem, &values[i]); + + if (!result) + break; + } + + if (result) + *arr_p = values; + + return result; +} + +static JSBool +gjs_array_from_flat_gvalue_array(JSContext *context, + gpointer array, + unsigned int length, + jsval *value) +{ + GValue *values = (GValue *)array; + unsigned int i; + jsval *elems = g_newa(jsval, length); + JSBool result = JS_TRUE; + + for (i = 0; i < length; i ++) { + GValue *value = &values[i]; + result = gjs_value_from_g_value(context, &elems[i], value); + if (!result) + break; + } + + if (result) { + JSObject *jsarray; + jsarray = JS_NewArrayObject(context, length, elems); + *value = OBJECT_TO_JSVAL(jsarray); + } + + return result; +} + +static gboolean +is_gvalue(GIBaseInfo *info, + GIInfoType info_type) +{ + gboolean result = FALSE; + + switch(info_type) { + case GI_INFO_TYPE_VALUE: + result = TRUE; + break; + case GI_INFO_TYPE_STRUCT: + case GI_INFO_TYPE_OBJECT: + case GI_INFO_TYPE_INTERFACE: + case GI_INFO_TYPE_BOXED: + { + GType gtype; + gtype = g_registered_type_info_get_g_type((GIRegisteredTypeInfo *) info); + + result = g_type_is_a(gtype, G_TYPE_VALUE); + } + break; + default: + break; + } + + return result; +} + +static gboolean +is_gvalue_flat_array(GITypeInfo *param_info, + GITypeTag element_type) +{ + GIBaseInfo *interface_info; + GIInfoType info_type; + gboolean result; + + if (element_type != GI_TYPE_TAG_INTERFACE) + return FALSE; + + interface_info = g_type_info_get_interface(param_info); + info_type = g_base_info_get_type(interface_info); + + /* Special case for GValue "flat arrays" */ + result = (is_gvalue(interface_info, info_type) && + !g_type_info_is_pointer(param_info)); + g_base_info_unref(interface_info); + + return result; +} + +static JSBool gjs_array_to_array(JSContext *context, jsval array_value, gsize length, @@ -742,6 +856,10 @@ gjs_array_to_array(JSContext *context, element_type = g_type_info_get_tag(param_info); element_type = replace_gtype(element_type); + /* Special case for GValue "flat arrays" */ + if (is_gvalue_flat_array(param_info, element_type)) + return gjs_array_to_flat_gvalue_array(context, array_value, length, arr_p); + if (element_type == GI_TYPE_TAG_INTERFACE) { GIBaseInfo *interface_info = g_type_info_get_interface(param_info); GIInfoType info_type = g_base_info_get_type(interface_info); @@ -1753,6 +1871,9 @@ gjs_array_from_carray_internal (JSContext *context, element_type = g_type_info_get_tag(param_info); element_type = replace_gtype(element_type); + if (is_gvalue_flat_array(param_info, element_type)) + return gjs_array_from_flat_gvalue_array(context, array, length, value_p); + /* Special case array(guint8) */ if (element_type == GI_TYPE_TAG_UINT8) { GByteArray gbytearray; @@ -2603,6 +2724,11 @@ gjs_g_arg_release_internal(JSContext *context, element_type = g_type_info_get_tag(param_info); element_type = replace_gtype(element_type); + if (transfer != GI_TRANSFER_CONTAINER && is_gvalue_flat_array(param_info, element_type)) { + g_free(arg->v_pointer); + return JS_TRUE; + } + switch (element_type) { case GI_TYPE_TAG_UTF8: case GI_TYPE_TAG_FILENAME: diff --git a/test/js/testGIMarshalling.js b/test/js/testGIMarshalling.js index 4a7c355f..5b10c3c6 100644 --- a/test/js/testGIMarshalling.js +++ b/test/js/testGIMarshalling.js @@ -1,4 +1,17 @@ // application/javascript;version=1.8 + +if (!('assertEquals' in this)) { /* allow running this test standalone */ + imports.lang.copyPublicProperties(imports.jsUnit, this); + gjstestRun = function() { return imports.jsUnit.gjstestRun(window); }; +} + +function assertArrayEquals(expected, got) { + assertEquals(expected.length, got.length); + for (let i = 0; i < expected.length; i ++) { + assertEquals(expected[i], got[i]); + } +} + const GIMarshallingTests = imports.gi.GIMarshallingTests; // We use Gio to have some objects that we know exist @@ -158,24 +171,34 @@ function testByteArray() { } 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()); + assertArrayEquals(refArray, GIMarshallingTests.gptrarray_utf8_none_return()); + assertArrayEquals(refArray, GIMarshallingTests.gptrarray_utf8_container_return()); + assertArrayEquals(refArray, GIMarshallingTests.gptrarray_utf8_full_return()); + + assertArrayEquals(refArray, GIMarshallingTests.gptrarray_utf8_none_out()); + assertArrayEquals(refArray, GIMarshallingTests.gptrarray_utf8_container_out()); + assertArrayEquals(refArray, GIMarshallingTests.gptrarray_utf8_full_out()); +} + +function testGValue() { + assertEquals(42, GIMarshallingTests.gvalue_return()); + assertEquals(42, GIMarshallingTests.gvalue_out()); + + GIMarshallingTests.gvalue_in(42); + GIMarshallingTests.gvalue_flat_array([42, "42", true]); + + // gjs doesn't support native enum types + // GIMarshallingTests.gvalue_in_enum(GIMarshallingTests.Enum.VALUE_3); - arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_none_out()); - arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_container_out()); - arrayEqual(refArray, GIMarshallingTests.gptrarray_utf8_full_out()); + // Test a flat GValue round-trip return + let thing = GIMarshallingTests.return_gvalue_flat_array(); + assertArrayEquals([42, "42", true], thing); } gjstestRun(); |