[pygobject] cache refactoring: Cleanup array length argument marshaling



commit cb7e7311bff57eb4c79c7772b6db4d00084656bb
Author: Simon Feltman <sfeltman src gnome org>
Date:   Fri Aug 2 20:27:02 2013 -0700

    cache refactoring: Cleanup array length argument marshaling
    
    Add shared function: _arg_cache_array_len_arg_setup for use
    with both to and from array marshaling setup. This function
    consolidates all of the edge cases regarding array length setup
    and removes the need for flagging arguments with
    PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE.
    
    https://bugzilla.gnome.org/show_bug.cgi?id=640812

 gi/pygi-cache.c |  145 +++++++++++++++++++++++++++----------------------------
 gi/pygi-cache.h |    5 --
 2 files changed, 71 insertions(+), 79 deletions(-)
---
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 5b160fe..e60471c 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -294,45 +294,90 @@ _arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
     arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
 }
 
-static gboolean
-_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
+static PyGIArgCache*
+_arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
                                 PyGICallableCache *callable_cache,
-                                GITypeInfo *type_info,
-                                GITransfer transfer,
                                 PyGIDirection direction,
-                                gssize arg_index)
+                                gssize arg_index,
+                                gssize *py_arg_index)
 {
     PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
-    seq_cache->array_type = g_type_info_get_array_type (type_info);
-
-    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
-
     if (seq_cache->len_arg_index >= 0) {
-        PyGIArgCache *child_cache = 
-            _pygi_callable_cache_get_arg (callable_cache, seq_cache->len_arg_index);
+        PyGIArgCache *child_cache = NULL;
 
+        child_cache = _pygi_callable_cache_get_arg (callable_cache,
+                                                    seq_cache->len_arg_index);
         if (child_cache == NULL) {
             child_cache = _arg_cache_alloc ();
-        } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
-                   child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
-            arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
-            return TRUE;
+        } else {
+            /* If the "length" arg cache already exists (the length comes before
+             * the array in the argument list), remove it from the to_py_args list
+             * because it does not belong in "to python" return tuple. The length
+             * will implicitly be a part of the returned Python list.
+             */
+            if (direction & PYGI_DIRECTION_TO_PYTHON) {
+                callable_cache->to_py_args =
+                    g_slist_remove (callable_cache->to_py_args, child_cache);
+            }
+
+            /* This is a case where the arg cache already exists and has been
+             * setup by another array argument sharing the same length argument.
+             * See: gi_marshalling_tests_multi_array_key_value_in
+             */
+            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
+                return child_cache;
         }
 
-        if (seq_cache->len_arg_index < arg_index)
-            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE;
-        else
-            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+        /* There is a length argument for this array, so increment the number
+         * of "to python" child arguments when applicable.
+         */
+        if (direction & PYGI_DIRECTION_TO_PYTHON)
+             callable_cache->n_to_py_child_args++;
 
+        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
         child_cache->direction = direction;
         child_cache->to_py_marshaller = NULL;
         child_cache->from_py_marshaller = NULL;
 
+        /* ugly edge case code:
+         *
+         * When the length comes before the array parameter we need to update
+         * indexes of arguments after the index argument.
+         */
+        if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
+            gssize i;
+            (*py_arg_index) -= 1;
+            callable_cache->n_py_args -= 1;
+
+            for (i = seq_cache->len_arg_index + 1;
+                   i < _pygi_callable_cache_args_len (callable_cache); i++) {
+                PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
+                if (update_cache == NULL)
+                    break;
+
+                update_cache->py_arg_index -= 1;
+            }
+        }
+
         _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
+        return child_cache;
     }
 
-    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
+    return NULL;
+}
 
+static gboolean
+_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
+                                PyGICallableCache *callable_cache,
+                                GITypeInfo *type_info,
+                                GITransfer transfer,
+                                PyGIDirection direction,
+                                gssize arg_index)
+{
+    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+    seq_cache->array_type = g_type_info_get_array_type (type_info);
+    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
+    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
     return TRUE;
 }
 
@@ -345,36 +390,9 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                               gssize arg_index)
 {
     PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
+    seq_cache->array_type = g_type_info_get_array_type (type_info);
     arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
     arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
-
-    seq_cache->array_type = g_type_info_get_array_type (type_info);
-
-    if (seq_cache->len_arg_index >= 0) {
-        PyGIArgCache *child_cache = _pygi_callable_cache_get_arg (callable_cache,
-                                                                  seq_cache->len_arg_index);
-        if (seq_cache->len_arg_index < arg_index)
-             callable_cache->n_to_py_child_args++;
-
-        if (child_cache != NULL) {
-            callable_cache->to_py_args =
-                g_slist_remove (callable_cache->to_py_args, child_cache);
-
-            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
-                child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE)
-                return TRUE;
-        } else {
-            child_cache = _arg_cache_alloc ();
-        }
-
-        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
-        child_cache->direction = direction;
-        child_cache->to_py_marshaller = NULL;
-        child_cache->from_py_marshaller = NULL;
-
-        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
-    }
-
     return TRUE;
 }
 
@@ -772,31 +790,11 @@ _arg_cache_new (GITypeInfo *type_info,
                                                  direction,
                                                  c_arg_index);
 
-               /* ugly edge case code:
-                *  
-                * length can come before the array parameter which means we
-                * need to update indexes if this happens
-                */ 
-               if (seq_cache->len_arg_index > -1 &&
-                   _pygi_callable_cache_get_arg (callable_cache,
-                                                 seq_cache->len_arg_index)->meta_type == 
PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
-                   gssize i;
-                   PyGIArgCache *child_cache = _pygi_callable_cache_get_arg (callable_cache,
-                                                                             seq_cache->len_arg_index);
-                   child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
-                   py_arg_index -= 1;
-                   callable_cache->n_py_args -= 1;
-
-                   for (i = seq_cache->len_arg_index + 1; 
-                          i < _pygi_callable_cache_args_len (callable_cache);
-                            i++) {
-                       PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
-                       if (update_cache == NULL)
-                           break;
-
-                       update_cache->py_arg_index -= 1;
-                   }
-               }
+               _arg_cache_array_len_arg_setup (arg_cache,
+                                               callable_cache,
+                                               direction,
+                                               c_arg_index,
+                                               &py_arg_index);
 
                break;
            }
@@ -1065,7 +1063,6 @@ _args_cache_generate (GICallableInfo *callable_info,
 
                 if (direction & PYGI_DIRECTION_TO_PYTHON) {
                     callable_cache->n_to_py_args++;
-                    callable_cache->n_to_py_child_args++;
                 }
 
                 arg_cache->type_tag = g_type_info_get_tag (type_info);
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 404015c..e0ef5d3 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -56,10 +56,6 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
  *  - PYGI_META_ARG_TYPE_CHILD - Children without python argument are
  *    ignored by the marshallers and handled directly by their parents
  *    marshaller.
- *  - PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE -Sometimes children arguments
- *    come before the parent.  In these cases they need to be flagged
- *    so that the argument list counts must be updated for the cache to
- *    be valid
  *  - Children with pyargs (PYGI_META_ARG_TYPE_CHILD_WITH_PYARG) are processed
  *    the same as other child args but also have an index into the 
  *    python parameters passed to the invoker
@@ -67,7 +63,6 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
 typedef enum {
     PYGI_META_ARG_TYPE_PARENT,
     PYGI_META_ARG_TYPE_CHILD,
-    PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE,
     PYGI_META_ARG_TYPE_CHILD_WITH_PYARG,
     PYGI_META_ARG_TYPE_CLOSURE,
 } PyGIMetaArgType;


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