Commit cb7e7311 authored by Simon Feltman's avatar Simon Feltman
Browse files

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
parent c9d86394
......@@ -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);
......
......@@ -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;
......
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment