[pygobject] only update the arg counts once if child arg comes before parent arg



commit e30a41592baa942188574e5c9f99572963e2e387
Author: John (J5) Palmieri <johnp redhat com>
Date:   Thu Sep 15 00:02:34 2011 -0400

    only update the arg counts once if child arg comes before parent arg
    
    * if the child arg comes before the parent arg we need to update the
       argument counts and take the child arg out of the marshalling lists
       since it is handled by the parent
     * when two parents reference the same child arg as is the case with
       two arrays which have a single length argument we only want to update
       the count once
     * to do this we introduce the PYGI_META_ARG_CHILD_NEEDS_UPDATE meta type
       and only do the count update if this is set
     * APIs should keep in mind that this take extra processing so child args
       should really come after their parents
    
    https://bugzilla.gnome.org/show_bug.cgi?id=627236

 gi/pygi-cache.c |   30 ++++++++++++++++++++----------
 gi/pygi-cache.h |    9 +++++++--
 2 files changed, 27 insertions(+), 12 deletions(-)
---
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c
index 5024899..659c424 100644
--- a/gi/pygi-cache.c
+++ b/gi/pygi-cache.c
@@ -466,25 +466,30 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                 PyGICallableCache *callable_cache,
                                 GITypeInfo *type_info,
                                 GITransfer transfer,
-                                PyGIDirection direction)
+                                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;
 
-    if (seq_cache->len_arg_index >= 0 &&
-        direction == PYGI_DIRECTION_FROM_PYTHON) {
+    if (seq_cache->len_arg_index >= 0) {
         PyGIArgCache *child_cache = 
             callable_cache->args_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) {
+        } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
+                   child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
             return TRUE;
         }
 
-        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
+        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;
+
         child_cache->direction = direction;
         child_cache->to_py_marshaller = NULL;
         child_cache->from_py_marshaller = NULL;
@@ -517,11 +522,12 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
              callable_cache->n_to_py_child_args++;
 
         if (child_cache != NULL) {
-            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
-                return TRUE;
-
             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 ();
         }
@@ -1073,7 +1079,8 @@ _arg_cache_new (GITypeInfo *type_info,
                                                    callable_cache,
                                                    type_info,
                                                    transfer,
-                                                   direction);
+                                                   direction,
+                                                   c_arg_index);
 
                if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
                    _arg_cache_to_py_array_setup (arg_cache,
@@ -1089,9 +1096,12 @@ _arg_cache_new (GITypeInfo *type_info,
                 * need to update indexes if this happens
                 */ 
                if (seq_cache->len_arg_index > -1 &&
-                   seq_cache->len_arg_index < c_arg_index) {
+                   callable_cache->args_cache[seq_cache->len_arg_index]->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
                    gssize i;
+                   PyGIArgCache *child_cache =
+                       callable_cache->args_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;
 
diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h
index 162c6e2..510987b 100644
--- a/gi/pygi-cache.h
+++ b/gi/pygi-cache.h
@@ -49,13 +49,17 @@ typedef void (*PyGIMarshalCleanupFunc) (PyGIInvokeState *state,
                                         gboolean         was_processed);
 
 /* Argument meta types denote how we process the argument:
- *  - Parents (PYGI_META_ARG_TYPE_PARENT) may or may not have children
+ *  - PYGI_META_ARG_TYPE_PARENT - parents may or may not have children
  *    but are always processed via the normal marshaller for their
  *    actual GI type.  If they have children the marshaller will
  *    also handle marshalling the children.
- *  - Children without python argument (PYGI_META_ARG_TYPE_CHILD) are
+ *  - 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
@@ -63,6 +67,7 @@ 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
 } PyGIMetaArgType;
 



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