[pygobject/invoke-rewrite] [gi] allow caching and marshalling of ghash out



commit 77d76df59606e470808085e977fb199cc76e8251
Author: John (J5) Palmieri <johnp redhat com>
Date:   Sun Jan 30 18:21:24 2011 -0500

    [gi] allow caching and marshalling of ghash out

 gi/pygi-argument.c |  155 ++++++++++++++++++++++++++++++++++++++++++++++++---
 gi/pygi-cache.c    |   27 ++++++---
 2 files changed, 162 insertions(+), 20 deletions(-)
---
diff --git a/gi/pygi-argument.c b/gi/pygi-argument.c
index 0dc277d..e426e63 100644
--- a/gi/pygi-argument.c
+++ b/gi/pygi-argument.c
@@ -3559,16 +3559,18 @@ _pygi_marshal_out_array (PyGIInvokeState   *state,
             item_size = g_array_get_element_size(array_);
             for (i = 0; i < array_->len; i++) {
                 GIArgument item_arg;
+                PyObject *py_item;
+
                 if (is_struct) {
                     item_arg.v_pointer = &_g_array_index(array_, GIArgument, i);
                 } else {
                     memcpy (&item_arg, &_g_array_index (array_, GIArgument, i), item_size);
                 }
 
-                PyObject *py_item = item_out_marshaller(state,
-                                                        function_cache,
-                                                        item_arg_cache,
-                                                        &item_arg);
+                py_item = item_out_marshaller(state,
+                                              function_cache,
+                                              item_arg_cache,
+                                              &item_arg);
 
                 if (py_item == NULL) {
                     Py_CLEAR(py_obj);
@@ -3595,10 +3597,45 @@ _pygi_marshal_out_glist (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
+    GList *list_;
+    gsize length;
+    gsize i;
+
+    PyGIMarshalOutFunc item_out_marshaller;
+    PyGIArgCache *item_arg_cache;
+    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+
     PyObject *py_obj = NULL;
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
+    list_ = arg->v_pointer;
+    length = g_list_length(list_);
+
+    py_obj = PyList_New(length);
+    if (py_obj == NULL)
+        return NULL;
+
+    item_arg_cache = seq_cache->item_cache;
+    item_out_marshaller = item_arg_cache->out_marshaller;
+
+    for (i = 0; list_ != NULL; list_ = g_list_next (list_), i++) {
+        GIArgument item_arg;
+        PyObject *py_item;
+
+        item_arg.v_pointer = list_->data;
+        py_item = item_out_marshaller(state,
+                                      function_cache,
+                                      item_arg_cache,
+                                      &item_arg);
+
+        if (py_item == NULL) {
+            Py_CLEAR (py_obj);
+            _PyGI_ERROR_PREFIX ("Item %zu: ", i);
+            return NULL;
+        }
+
+        PyList_SET_ITEM (py_obj, i, py_item);
+    }
+
     return py_obj;
 }
 
@@ -3608,10 +3645,45 @@ _pygi_marshal_out_gslist (PyGIInvokeState   *state,
                           PyGIArgCache      *arg_cache,
                           GIArgument        *arg)
 {
+    GSList *list_;
+    gsize length;
+    gsize i;
+
+    PyGIMarshalOutFunc item_out_marshaller;
+    PyGIArgCache *item_arg_cache;
+    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+
     PyObject *py_obj = NULL;
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
+    list_ = arg->v_pointer;
+    length = g_slist_length(list_);
+
+    py_obj = PyList_New(length);
+    if (py_obj == NULL)
+        return NULL;
+
+    item_arg_cache = seq_cache->item_cache;
+    item_out_marshaller = item_arg_cache->out_marshaller;
+
+    for (i = 0; list_ != NULL; list_ = g_slist_next (list_), i++) {
+        GIArgument item_arg;
+        PyObject *py_item;
+
+        item_arg.v_pointer = list_->data;
+        py_item = item_out_marshaller(state,
+                                      function_cache,
+                                      item_arg_cache,
+                                      &item_arg);
+
+        if (py_item == NULL) {
+            Py_CLEAR (py_obj);
+            _PyGI_ERROR_PREFIX ("Item %zu: ", i);
+            return NULL;
+        }
+
+        PyList_SET_ITEM (py_obj, i, py_item);
+    }
+
     return py_obj;
 }
 
@@ -3621,10 +3693,73 @@ _pygi_marshal_out_ghash (PyGIInvokeState   *state,
                          PyGIArgCache      *arg_cache,
                          GIArgument        *arg)
 {
+    GHashTable *hash_;
+    GHashTableIter hash_table_iter;
+
+    PyGIMarshalOutFunc key_out_marshaller;
+    PyGIMarshalOutFunc value_out_marshaller;
+
+    PyGIArgCache *key_arg_cache;
+    PyGIArgCache *value_arg_cache;
+    PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache;
+
+    GIArgument key_arg;
+    GIArgument value_arg;
+
     PyObject *py_obj = NULL;
 
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Marshalling for this type is not implemented yet");
+    hash_ = arg->v_pointer;
+
+    py_obj = PyDict_New();
+    if (py_obj == NULL)
+        return NULL;
+
+    key_arg_cache = hash_cache->key_cache;
+    key_out_marshaller = key_arg_cache->out_marshaller;
+
+    value_arg_cache = hash_cache->value_cache;
+    value_out_marshaller = value_arg_cache->out_marshaller;
+
+    g_hash_table_iter_init(&hash_table_iter, hash_);
+    while (g_hash_table_iter_next(&hash_table_iter,
+                                  &key_arg.v_pointer,
+                                  &value_arg.v_pointer)) {
+        PyObject *py_key;
+        PyObject *py_value;
+        int retval;
+
+        py_key = key_out_marshaller(state,
+                                    function_cache,
+                                    key_arg_cache,
+                                    &key_arg);
+
+        if (py_key == NULL) {
+            Py_CLEAR (py_obj);
+            return NULL;
+        }
+
+        py_value = value_out_marshaller(state,
+                                        function_cache,
+                                        value_arg_cache,
+                                        &value_arg);
+
+        if (py_value == NULL) {
+            Py_CLEAR (py_obj);
+            Py_DECREF(py_key);
+            return NULL;
+        }
+
+        retval = PyDict_SetItem (py_obj, py_key, py_value);
+
+        Py_DECREF(py_key);
+        Py_DECREF(py_value);
+
+        if (retval < 0) {
+            Py_CLEAR(py_obj);
+            return NULL;
+        }
+    }
+
     return py_obj;
 }
 
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 93dd9cd..387944a 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -207,13 +207,16 @@ _sequence_cache_new_from_type_info(GITypeInfo *type_info,
     return sc;
 }
 static inline PyGIHashCache *
-_hash_cache_new_from_type_info(GITypeInfo *type_info)
+_hash_cache_new_from_type_info(GITypeInfo *type_info,
+                               GIDirection direction,
+                               GITransfer transfer)
 {
     PyGIHashCache *hc;
     GITypeInfo *key_type_info;
     GITypeTag key_type_tag;
     GITypeInfo *value_type_info;
     GITypeTag value_type_tag;
+    GITransfer item_transfer;
 
     hc = g_slice_new0(PyGIHashCache);
     ((PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
@@ -222,12 +225,17 @@ _hash_cache_new_from_type_info(GITypeInfo *type_info)
     value_type_info = g_type_info_get_param_type (type_info, 1);
     value_type_tag = g_type_info_get_tag (value_type_info);
 
+    item_transfer = GI_TRANSFER_NOTHING;
+    if (transfer == GI_TRANSFER_EVERYTHING ||
+        transfer == GI_TRANSFER_CONTAINER)
+        item_transfer = GI_TRANSFER_EVERYTHING;
+
     hc->key_cache = _arg_cache_new_from_type_info(key_type_info,
                                                   NULL,
                                                   NULL,
                                                   key_type_tag,
-                                                  GI_TRANSFER_EVERYTHING,
-                                                  GI_DIRECTION_IN,
+                                                  item_transfer,
+                                                  direction,
                                                   FALSE,
                                                   0, 0);
 
@@ -240,8 +248,8 @@ _hash_cache_new_from_type_info(GITypeInfo *type_info)
                                                     NULL,
                                                     NULL,
                                                     value_type_tag,
-                                                    GI_TRANSFER_EVERYTHING,
-                                                    GI_DIRECTION_IN,
+                                                    item_transfer,
+                                                    direction,
                                                     FALSE,
                                                     0, 0);
 
@@ -586,8 +594,7 @@ _arg_cache_in_ghash_setup(PyGIArgCache *arg_cache)
 static inline void
 _arg_cache_out_ghash_setup(PyGIArgCache *arg_cache)
 {
-    PyErr_Format(PyExc_NotImplementedError,
-                 "Caching for Out GHash is not fully implemented yet");
+    arg_cache->out_marshaller = _pygi_marshal_out_ghash;
 }
 
 static inline void
@@ -1126,7 +1133,9 @@ _arg_cache_new_from_type_info (GITypeInfo *type_info,
             }
        case GI_TYPE_TAG_GHASH:
            arg_cache =
-               (PyGIArgCache *)_hash_cache_new_from_type_info(type_info);
+               (PyGIArgCache *)_hash_cache_new_from_type_info(type_info,
+                                                              direction,
+                                                              transfer);
 
            if (arg_cache == NULL)
                    break;
@@ -1136,8 +1145,6 @@ _arg_cache_new_from_type_info (GITypeInfo *type_info,
 
            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
                _arg_cache_out_ghash_setup(arg_cache);
-               _pygi_arg_cache_free(arg_cache);
-               arg_cache = NULL;
            }
 
            break;



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