[gjs] Add support for converting GHashTable return values/out parameters.



commit 4ed31d7d8b3f7d1a8e089d9704d0a3f68638bda5
Author: C. Scott Ananian <cscott litl com>
Date:   Thu Apr 30 15:32:41 2009 -0400

    Add support for converting GHashTable return values/out parameters.
---
 gi/arg.c                       |  108 ++++++++++++++++++++++++++++++++++++++++
 test/js/testEverythingBasic.js |   16 ++++++
 2 files changed, 124 insertions(+), 0 deletions(-)

diff --git a/gi/arg.c b/gi/arg.c
index 8418dab..4532707 100644
--- a/gi/arg.c
+++ b/gi/arg.c
@@ -969,6 +969,83 @@ gjs_array_from_g_list (JSContext  *context,
     return result;
 }
 
+static JSBool
+gjs_object_from_g_hash (JSContext  *context,
+                        jsval      *value_p,
+                        GITypeInfo *key_param_info,
+                        GITypeInfo *val_param_info,
+                        GHashTable *hash)
+{
+    GHashTableIter iter;
+    JSObject *obj;
+    JSString *keystr;
+    char     *keyutf8 = NULL;
+    jsval     keyjs,  valjs;
+    GArgument keyarg, valarg;
+    JSBool result;
+
+    // a NULL hash table becomes a null JS value
+    if (hash==NULL) {
+        *value_p = JSVAL_NULL;
+        return JS_TRUE;
+    }
+
+    obj = JS_NewObject(context, NULL, NULL, NULL);
+    if (obj == NULL)
+        return JS_FALSE;
+
+    *value_p = OBJECT_TO_JSVAL(obj);
+    JS_AddRoot(context, &obj);
+
+    keyjs = JSVAL_VOID;
+    JS_AddRoot(context, &keyjs);
+
+    valjs = JSVAL_VOID;
+    JS_AddRoot(context, &valjs);
+
+    keystr = NULL;
+    JS_AddRoot(context, &keystr);
+
+    result = JS_FALSE;
+
+    g_hash_table_iter_init(&iter, hash);
+    while (g_hash_table_iter_next
+           (&iter, &keyarg.v_pointer, &valarg.v_pointer)) {
+        if (!gjs_value_from_g_argument(context, &keyjs,
+                                       key_param_info, &keyarg))
+            goto out;
+
+        keystr = JS_ValueToString(context, keyjs);
+        if (!keystr)
+            goto out;
+
+        if (!gjs_string_to_utf8(context, STRING_TO_JSVAL(keystr), &keyutf8))
+            goto out;
+
+        if (!gjs_value_from_g_argument(context, &valjs,
+                                       val_param_info, &valarg))
+            goto out;
+
+        if (!JS_DefineProperty(context, obj, keyutf8, valjs,
+                               NULL, NULL, JSPROP_ENUMERATE))
+            goto out;
+
+        g_free(keyutf8);
+        keyutf8 = NULL;
+    }
+
+    result = JS_TRUE;
+
+ out:
+    if (keyutf8) g_free(keyutf8);
+    JS_RemoveRoot(context, &obj);
+    JS_RemoveRoot(context, &keyjs);
+    JS_RemoveRoot(context, &valjs);
+    JS_RemoveRoot(context, &keystr);
+
+    return result;
+}
+
 JSBool
 gjs_value_from_g_argument (JSContext  *context,
                            jsval      *value_p,
@@ -1193,6 +1270,29 @@ gjs_value_from_g_argument (JSContext  *context,
         }
         break;
 
+    case GI_TYPE_TAG_GHASH:
+        {
+            GITypeInfo *key_param_info, *val_param_info;
+            gboolean result;
+
+            key_param_info = g_type_info_get_param_type(type_info, 0);
+            g_assert(key_param_info != NULL);
+            val_param_info = g_type_info_get_param_type(type_info, 1);
+            g_assert(val_param_info != NULL);
+
+            result = gjs_object_from_g_hash(context,
+                                            value_p,
+                                            key_param_info,
+                                            val_param_info,
+                                            arg->v_pointer);
+
+            g_base_info_unref((GIBaseInfo*) key_param_info);
+            g_base_info_unref((GIBaseInfo*) val_param_info);
+
+            return result;
+        }
+        break;
+
     case GI_TYPE_TAG_INT:
     case GI_TYPE_TAG_UINT:
     case GI_TYPE_TAG_LONG:
@@ -1399,6 +1499,14 @@ gjs_g_arg_release_internal(JSContext  *context,
         g_slist_free(arg->v_pointer);
         break;
 
+    case GI_TYPE_TAG_GHASH:
+        // Note that we depend on the GHashTable's destroy functions to
+        // match the transfer mode.  If you don't want the keys and
+        // values freed, the GHashTable should have null key/value
+        // destroy functions.  Otherwise everything is released together.
+        g_hash_table_destroy(arg->v_pointer);
+        break;
+
     default:
         gjs_debug(GJS_DEBUG_ERROR,
                   "Unhandled type %s releasing GArgument",
diff --git a/test/js/testEverythingBasic.js b/test/js/testEverythingBasic.js
index 5f69b2f..67c396a 100644
--- a/test/js/testEverythingBasic.js
+++ b/test/js/testEverythingBasic.js
@@ -227,6 +227,22 @@ function testArrayOut() {
     // FIXME: test_array_int_full_out and test_array_int_none_out unimplemented
 }
 
+/* GHash type */
+function testGHashOut() {
+    const HASH_STR = '({foo:"bar", baz:"bat", qux:"quux"})';
+    assertEquals(null, Everything.test_ghash_null_return());
+    assertEquals(HASH_STR, Everything.test_ghash_nothing_return().toSource());
+    assertEquals(HASH_STR, Everything.test_ghash_nothing_return2().toSource());
+    assertEquals(HASH_STR, Everything.test_ghash_container_return().toSource());
+    assertEquals(HASH_STR, Everything.test_ghash_everything_return().toSource());
+}
+
+function testNestedGHashOut() {
+    const HASH_STR = '({wibble:{foo:"bar", baz:"bat", qux:"quux"}})';
+    assertEquals(HASH_STR, Everything.test_ghash_nested_everything_return().toSource());
+    assertEquals(HASH_STR, Everything.test_ghash_nested_everything_return2().toSource());
+}
+
 /* Enums */
 function testEnumParam() {
    let e = Everything.test_enum_param(Everything.TestEnum.VALUE1);



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