[pygobject/gsoc2009: 54/160] Add GHashTable support as input/output/return argument



commit d37c546c06adc4817c99acbcbdd717cff3c3f964
Author: Simon van der Linden <svdlinden src gnome org>
Date:   Wed Jul 22 17:46:37 2009 +0200

    Add GHashTable support as input/output/return argument

 gi/pygargument.c           |  217 +++++++++++++++++++++++++++++++++++++++++++-
 tests/test_girepository.py |   15 +++
 2 files changed, 231 insertions(+), 1 deletions(-)
---
diff --git a/gi/pygargument.c b/gi/pygargument.c
index 56703f6..f39476d 100644
--- a/gi/pygargument.c
+++ b/gi/pygargument.c
@@ -411,6 +411,76 @@ check_number_clean:
 
             break;
         }
+        case GI_TYPE_TAG_GHASH:
+        {
+            GITypeInfo *key_type_info;
+            GITypeInfo *value_type_info;
+            PyObject *keys;
+            PyObject *values;
+            Py_ssize_t length;
+            Py_ssize_t i;
+
+            if (!PyMapping_Check(object)) {
+                PyErr_Format(PyExc_TypeError, "Must be mapping, not %s",
+                        object->ob_type->tp_name);
+                retval = 0;
+                break;
+            }
+
+            length = PyMapping_Length(object);
+            if (length < 0) {
+                retval = -1;
+                break;
+            }
+
+            keys = PyMapping_Keys(object);
+            if (keys == NULL) {
+                retval = -1;
+                break;
+            }
+
+            values = PyMapping_Values(object);
+            if (values == NULL) {
+                retval = -1;
+                Py_DECREF(keys);
+                break;
+            }
+
+            key_type_info = g_type_info_get_param_type(type_info, 0);
+            value_type_info = g_type_info_get_param_type(type_info, 1);
+
+            for (i = 0; i < length; i++) {
+                PyObject *key;
+                PyObject *value;
+
+                key = PyList_GET_ITEM(keys, i);
+                value = PyList_GET_ITEM(values, i);
+
+                retval = pygi_gi_type_info_check_py_object(key_type_info, key);
+                if (retval < 0) {
+                    break;
+                }
+                if (!retval) {
+                    PyErr_PREFIX_FROM_FORMAT("Key %zd :", i);
+                    break;
+                }
+
+                retval = pygi_gi_type_info_check_py_object(value_type_info, value);
+                if (retval < 0) {
+                    break;
+                }
+                if (!retval) {
+                    PyErr_PREFIX_FROM_FORMAT("Value %zd :", i);
+                    break;
+                }
+            }
+
+            g_base_info_unref((GIBaseInfo *)key_type_info);
+            g_base_info_unref((GIBaseInfo *)value_type_info);
+            Py_DECREF(values);
+            Py_DECREF(keys);
+            break;
+        }
         case GI_TYPE_TAG_GTYPE:
         {
             gint is_instance;
@@ -429,7 +499,6 @@ check_number_clean:
             break;
         }
         case GI_TYPE_TAG_TIME_T:
-        case GI_TYPE_TAG_GHASH:
         case GI_TYPE_TAG_ERROR:
             /* TODO */
         default:
@@ -782,6 +851,103 @@ array_clean:
 
             break;
         }
+        case GI_TYPE_TAG_GHASH:
+        {
+            Py_ssize_t length;
+            PyObject *keys;
+            PyObject *values;
+            GITypeInfo *key_type_info;
+            GITypeInfo *value_type_info;
+            GITypeTag key_type_tag;
+            GHashFunc hash_func;
+            GEqualFunc equal_func;
+            GHashTable *hash_table;
+            Py_ssize_t i;
+
+            length = PyMapping_Length(object);
+            if (length < 0) {
+                break;
+            }
+
+            keys = PyMapping_Keys(object);
+            if (keys == NULL) {
+                break;
+            }
+
+            values = PyMapping_Values(object);
+            if (values == NULL) {
+                Py_DECREF(keys);
+                break;
+            }
+
+            key_type_info = g_type_info_get_param_type(type_info, 0);
+            value_type_info = g_type_info_get_param_type(type_info, 1);
+
+            key_type_tag = g_type_info_get_tag(key_type_info);
+
+            switch(key_type_tag) {
+                case GI_TYPE_TAG_UTF8:
+                case GI_TYPE_TAG_FILENAME:
+                    hash_func = g_str_hash;
+                    equal_func = g_str_equal;
+                    break;
+                case GI_TYPE_TAG_SHORT:
+                case GI_TYPE_TAG_USHORT:
+                case GI_TYPE_TAG_INT:
+                case GI_TYPE_TAG_INT8:
+                case GI_TYPE_TAG_UINT8:
+                case GI_TYPE_TAG_INT16:
+                case GI_TYPE_TAG_UINT16:
+                case GI_TYPE_TAG_INT32:
+                    hash_func = g_int_hash;
+                    equal_func = g_int_equal;
+                    break;
+                default:
+                    PyErr_WarnEx(NULL, "No suited hash function available; using pointers", 1);
+                    hash_func = g_direct_hash;
+                    equal_func = g_direct_equal;
+            }
+
+            hash_table = g_hash_table_new(hash_func, equal_func);
+            if (hash_table == NULL) {
+                PyErr_NoMemory();
+                Py_DECREF(keys);
+                Py_DECREF(values);
+                break;
+            }
+
+            for (i = 0; i < length; i++) {
+                PyObject *py_key;
+                PyObject *py_value;
+                GArgument key;
+                GArgument value;
+
+                py_key = PyList_GET_ITEM(keys, i);
+                py_value = PyList_GET_ITEM(values, i);
+
+                key = pygi_g_argument_from_py_object(py_key, key_type_info);
+                if (PyErr_Occurred()) {
+                    /* TODO: free the previous items */
+                    break;
+                }
+
+                value = pygi_g_argument_from_py_object(py_value, value_type_info);
+                if (PyErr_Occurred()) {
+                    /* TODO: free the previous items */
+                    break;
+                }
+
+                g_hash_table_insert(hash_table, key.v_pointer, value.v_pointer);
+            }
+
+            arg.v_pointer = hash_table;
+
+            g_base_info_unref((GIBaseInfo *)key_type_info);
+            g_base_info_unref((GIBaseInfo *)value_type_info);
+            Py_DECREF(keys);
+            Py_DECREF(values);
+            break;
+        }
         case GI_TYPE_TAG_ERROR:
             /* Allow NULL GError, otherwise fall through */
             if (object == Py_None) {
@@ -1061,6 +1227,55 @@ struct_error_clean:
             g_base_info_unref((GIBaseInfo *)item_type_info);
             break;
         }
+        case GI_TYPE_TAG_GHASH:
+        {
+            GITypeInfo *key_type_info;
+            GITypeInfo *value_type_info;
+            GHashTableIter hash_table_iter;
+            GArgument key;
+            GArgument value;
+
+            object = PyDict_New();
+            if (object == NULL) {
+                break;
+            }
+
+            key_type_info = g_type_info_get_param_type(type_info, 0);
+            value_type_info = g_type_info_get_param_type(type_info, 1);
+
+            g_hash_table_iter_init(&hash_table_iter, (GHashTable *)arg.v_pointer);
+            while (g_hash_table_iter_next(&hash_table_iter, &key.v_pointer, &value.v_pointer)) {
+                PyObject *py_key;
+                PyObject *py_value;
+                int retval;
+
+                py_key = pygi_g_argument_to_py_object(key, key_type_info);
+                if (py_key == NULL) {
+                    break;
+                }
+
+                py_value = pygi_g_argument_to_py_object(value, value_type_info);
+                if (py_value == NULL) {
+                    Py_DECREF(py_key);
+                    break;
+                }
+
+                retval = PyDict_SetItem(object, py_key, py_value);
+
+                Py_DECREF(py_key);
+                Py_DECREF(py_value);
+
+                if (retval < 0) {
+                    Py_DECREF(object);
+                    object = NULL;
+                    break;
+                }
+            }
+
+            g_base_info_unref((GIBaseInfo *)key_type_info);
+            g_base_info_unref((GIBaseInfo *)value_type_info);
+            break;
+        }
         case GI_TYPE_TAG_GTYPE:
         {
             object = pyg_type_wrapper_new(arg.v_long);
diff --git a/tests/test_girepository.py b/tests/test_girepository.py
index 97faed3..8e8c6a7 100644
--- a/tests/test_girepository.py
+++ b/tests/test_girepository.py
@@ -27,6 +27,7 @@ utf8_const = 'const \xe2\x99\xa5 utf8'
 utf8_nonconst = 'nonconst \xe2\x99\xa5 utf8'
 
 test_sequence = ('1', '2', '3')
+test_dict = {'foo': 'bar', 'baz': 'bat', 'qux': 'quux'}
 
 def createStructA():
     a = Everything.TestStructA()
@@ -409,6 +410,20 @@ class TestGIEverything(unittest.TestCase):
         self.assertRaises(TypeError, Everything.test_gslist_nothing_in, (1, 2, 3))
 
 
+# GHashTable
+
+    def testGHashTableReturn(self):
+        self.assertEqual(test_dict, Everything.test_ghash_everything_return())
+
+    def testGHashTableIn(self):
+        Everything.test_ghash_nothing_in(test_dict)
+
+        # Test type checking.
+        self.assertRaises(TypeError, Everything.test_ghash_nothing_in, 'foo')
+        self.assertRaises(TypeError, Everything.test_ghash_nothing_in, {'foo': 42})
+        self.assertRaises(TypeError, Everything.test_ghash_nothing_in, {42: 'foo'})
+
+
 # closure
 
     def testClosure(self):



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