diff options
-rw-r--r-- | gi/pygi-cache.c | 160 | ||||
-rw-r--r-- | gi/pygi-cache.h | 16 | ||||
-rw-r--r-- | gi/pygi-invoke.c | 4 | ||||
-rw-r--r-- | gi/pygi-marshal-cleanup.c | 28 | ||||
-rw-r--r-- | gi/pygi-marshal-from-py.c | 37 | ||||
-rw-r--r-- | gi/pygi-marshal-to-py.c | 23 |
6 files changed, 177 insertions, 91 deletions
diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index 9793ffee..a8468cce 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -160,6 +160,15 @@ _sequence_cache_free_func (PyGISequenceCache *cache) } static void +_array_cache_free_func (PyGIArgGArray *cache) +{ + if (cache != NULL) { + _pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache); + g_slice_free (PyGIArgGArray, cache); + } +} + +static void _callback_cache_free_func (PyGICallbackCache *cache) { if (cache != NULL) { @@ -206,27 +215,26 @@ _interface_cache_new (GIInterfaceInfo *iface_info) return ic; } -static PyGISequenceCache * -_sequence_cache_new (GITypeInfo *type_info, - GIDirection direction, - GITransfer transfer, - gssize child_offset) +gboolean +pygi_arg_sequence_setup (PyGISequenceCache *sc, + GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be NULL for return arguments */ + GITransfer transfer, + PyGIDirection direction) { - PyGISequenceCache *sc; GITypeInfo *item_type_info; GITransfer item_transfer; - sc = g_slice_new0 (PyGISequenceCache); - ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func; - - sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info); - sc->fixed_size = g_type_info_get_array_fixed_size (type_info); - sc->len_arg_index = g_type_info_get_array_length (type_info); - if (sc->len_arg_index >= 0) - sc->len_arg_index += child_offset; + if (!pygi_arg_base_setup ((PyGIArgCache *)sc, + type_info, + arg_info, + transfer, + direction)) { + return FALSE; + } + sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func; item_type_info = g_type_info_get_param_type (type_info, 0); - item_transfer = transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; @@ -237,17 +245,89 @@ _sequence_cache_new (GITypeInfo *type_info, 0, 0, NULL); + g_base_info_unref ( (GIBaseInfo *)item_type_info); + if (sc->item_cache == NULL) { - _pygi_arg_cache_free ( (PyGIArgCache *)sc); - return NULL; + return FALSE; } + return TRUE; +} + +static gboolean +pygi_arg_garray_setup (PyGIArgGArray *sc, + GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be NULL for return arguments */ + GITransfer transfer, + PyGIDirection direction, + gssize child_offset) +{ + GITypeInfo *item_type_info; + + if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc, + type_info, + arg_info, + transfer, + direction)) { + return FALSE; + } + + ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func; + sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info); + sc->fixed_size = g_type_info_get_array_fixed_size (type_info); + sc->len_arg_index = g_type_info_get_array_length (type_info); + if (sc->len_arg_index >= 0) + sc->len_arg_index += child_offset; + + item_type_info = g_type_info_get_param_type (type_info, 0); sc->item_size = _pygi_g_type_info_size (item_type_info); g_base_info_unref ( (GIBaseInfo *)item_type_info); + return TRUE; +} + +static PyGISequenceCache * +pygi_arg_sequence_new (GITypeInfo *type_info, + GIArgInfo *arg_info, + GITransfer transfer, + PyGIDirection direction) +{ + PyGISequenceCache *sc = g_slice_new0 (PyGISequenceCache); + if (sc == NULL) + return NULL; + + if (!pygi_arg_sequence_setup (sc, type_info, arg_info, transfer, direction)) { + _pygi_arg_cache_free ( (PyGIArgCache *)sc); + return NULL; + } + return sc; } +static PyGIArgGArray * +_arg_array_cache_new (GITypeInfo *type_info, + GIArgInfo *arg_info, + GITransfer transfer, + PyGIDirection direction, + gssize child_offset) +{ + PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray); + if (array_cache == NULL) + return NULL; + + if (!pygi_arg_garray_setup (array_cache, + type_info, + arg_info, + transfer, + direction, + child_offset)) { + _pygi_arg_cache_free ( (PyGIArgCache *)array_cache); + return NULL; + } + + return array_cache; +} + static PyGICallbackCache * _callback_cache_new (GIArgInfo *arg_info, GIInterfaceInfo *iface_info, @@ -284,7 +364,7 @@ _arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache, gssize arg_index, gssize *py_arg_index) { - PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache; if (seq_cache->len_arg_index >= 0) { PyGIArgCache *child_cache = NULL; @@ -357,7 +437,7 @@ _arg_cache_from_py_array_setup (PyGIArgCache *arg_cache, PyGIDirection direction, gssize arg_index) { - PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *seq_cache = (PyGIArgGArray *)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; @@ -372,7 +452,7 @@ _arg_cache_to_py_array_setup (PyGIArgCache *arg_cache, PyGIDirection direction, gssize arg_index) { - PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *seq_cache = (PyGIArgGArray *)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; @@ -706,11 +786,12 @@ _arg_cache_new (GITypeInfo *type_info, case GI_TYPE_TAG_ARRAY: { - PyGISequenceCache *seq_cache = - _sequence_cache_new (type_info, - direction, - transfer, - child_offset); + PyGIArgGArray *seq_cache = + _arg_array_cache_new (type_info, + arg_info, + transfer, + direction, + child_offset); arg_cache = (PyGIArgCache *)seq_cache; if (arg_cache == NULL) @@ -738,15 +819,17 @@ _arg_cache_new (GITypeInfo *type_info, c_arg_index, &py_arg_index); - break; + arg_cache->py_arg_index = py_arg_index; + arg_cache->c_arg_index = c_arg_index; + return arg_cache; } case GI_TYPE_TAG_GLIST: { PyGISequenceCache *seq_cache = - _sequence_cache_new (type_info, - direction, - transfer, - child_offset); + pygi_arg_sequence_new (type_info, + arg_info, + transfer, + direction); arg_cache = (PyGIArgCache *)seq_cache; if (arg_cache == NULL) @@ -758,16 +841,17 @@ _arg_cache_new (GITypeInfo *type_info, if (direction & PYGI_DIRECTION_TO_PYTHON) _arg_cache_to_py_glist_setup (arg_cache, transfer); - - break; + arg_cache->py_arg_index = py_arg_index; + arg_cache->c_arg_index = c_arg_index; + return arg_cache; } case GI_TYPE_TAG_GSLIST: { PyGISequenceCache *seq_cache = - _sequence_cache_new (type_info, - direction, - transfer, - child_offset); + pygi_arg_sequence_new (type_info, + arg_info, + transfer, + direction); arg_cache = (PyGIArgCache *)seq_cache; if (arg_cache == NULL) @@ -779,7 +863,9 @@ _arg_cache_new (GITypeInfo *type_info, if (direction & PYGI_DIRECTION_TO_PYTHON) _arg_cache_to_py_gslist_setup (arg_cache, transfer); - break; + arg_cache->py_arg_index = py_arg_index; + arg_cache->c_arg_index = c_arg_index; + return arg_cache; } case GI_TYPE_TAG_GHASH: arg_cache = pygi_arg_hash_table_new_from_info (type_info, arg_info, transfer, direction); diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h index 82e25197..0629646a 100644 --- a/gi/pygi-cache.h +++ b/gi/pygi-cache.h @@ -132,13 +132,18 @@ struct _PyGIArgCache typedef struct _PyGISequenceCache { PyGIArgCache arg_cache; + PyGIArgCache *item_cache; +} PyGISequenceCache; + +typedef struct _PyGIArgGArray +{ + PyGISequenceCache seq_cache; gssize fixed_size; gssize len_arg_index; gboolean is_zero_terminated; gsize item_size; GIArrayType array_type; - PyGIArgCache *item_cache; -} PyGISequenceCache; +} PyGIArgGArray; typedef struct _PyGIInterfaceCache { @@ -211,6 +216,13 @@ pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache, PyGIDirection direction, GIInterfaceInfo *iface_info); +gboolean +pygi_arg_sequence_setup (PyGISequenceCache *sc, + GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be NULL for return arguments */ + GITransfer transfer, + PyGIDirection direction); + PyGIArgCache * _arg_cache_alloc (void); PyGIArgCache * _arg_cache_new (GITypeInfo *type_info, GIArgInfo *arg_info, diff --git a/gi/pygi-invoke.c b/gi/pygi-invoke.c index 675b0ef3..151c9e5e 100644 --- a/gi/pygi-invoke.c +++ b/gi/pygi-invoke.c @@ -422,9 +422,9 @@ static gboolean _caller_alloc (PyGIInvokeState *state, state->args[arg_count]->v_pointer = g_malloc0 (size); } } else if (arg_cache->type_tag == GI_TYPE_TAG_ARRAY) { - PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; - state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, seq_cache->item_size); + state->out_args[out_count].v_pointer = g_array_new (TRUE, TRUE, array_cache->item_size); state->args[arg_count] = &state->out_args[out_count]; } else { return FALSE; diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c index 0bf08a9c..52d7bb38 100644 --- a/gi/pygi-marshal-cleanup.c +++ b/gi/pygi-marshal-cleanup.c @@ -297,24 +297,24 @@ _pygi_marshal_cleanup_to_py_interface_struct_foreign (PyGIInvokeState *state, static GArray* _wrap_c_array (PyGIInvokeState *state, - PyGISequenceCache *sequence_cache, + PyGIArgGArray *array_cache, gpointer data) { GArray *array_; gsize len = 0; - if (sequence_cache->fixed_size >= 0) { - len = sequence_cache->fixed_size; - } else if (sequence_cache->is_zero_terminated) { + if (array_cache->fixed_size >= 0) { + len = array_cache->fixed_size; + } else if (array_cache->is_zero_terminated) { len = g_strv_length ((gchar **)data); - } else if (sequence_cache->len_arg_index >= 0) { - GIArgument *len_arg = state->args[sequence_cache->len_arg_index]; + } else if (array_cache->len_arg_index >= 0) { + GIArgument *len_arg = state->args[array_cache->len_arg_index]; len = len_arg->v_long; } array_ = g_array_new (FALSE, FALSE, - sequence_cache->item_size); + array_cache->item_size); if (array_ == NULL) return NULL; @@ -337,8 +337,9 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, GArray *array_ = NULL; GPtrArray *ptr_array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; - if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { + if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { ptr_array_ = (GPtrArray *) data; } else { array_ = (GArray *) data; @@ -363,7 +364,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, item = g_array_index (array_, gpointer, i); /* case 3: C array or GArray with simple types or structs */ else { - item = array_->data + i * sequence_cache->item_size; + item = array_->data + i * array_cache->item_size; /* special-case hack: GValue array items do not get slice * allocated in _pygi_marshal_from_py_array(), so we must * not try to deallocate it as a slice and thus @@ -381,7 +382,7 @@ _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state, } /* Only free the array when we didn't transfer ownership */ - if (sequence_cache->array_type == GI_ARRAY_TYPE_C) { + if (array_cache->array_type == GI_ARRAY_TYPE_C) { /* always free the GArray wrapper created in from_py marshaling and * passed back as cleanup_data */ @@ -407,16 +408,17 @@ _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state, GArray *array_ = NULL; GPtrArray *ptr_array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; /* If this isn't a garray create one to help process variable sized array elements */ - if (sequence_cache->array_type == GI_ARRAY_TYPE_C) { - array_ = _wrap_c_array (state, sequence_cache, data); + if (array_cache->array_type == GI_ARRAY_TYPE_C) { + array_ = _wrap_c_array (state, array_cache, data); if (array_ == NULL) return; - } else if (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { + } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { ptr_array_ = (GPtrArray *) data; } else { array_ = (GArray *) data; diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index b143727c..3867c233 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -258,6 +258,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state, gboolean is_ptr_array; GArray *array_ = NULL; PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; if (py_arg == Py_None) { @@ -275,20 +276,20 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state, if (length < 0) return FALSE; - if (sequence_cache->fixed_size >= 0 && - sequence_cache->fixed_size != length) { + if (array_cache->fixed_size >= 0 && + array_cache->fixed_size != length) { PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd", - sequence_cache->fixed_size, length); + array_cache->fixed_size, length); return FALSE; } - item_size = sequence_cache->item_size; - is_ptr_array = (sequence_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY); + item_size = array_cache->item_size; + is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY); if (is_ptr_array) { array_ = (GArray *)g_ptr_array_sized_new (length); } else { - array_ = g_array_sized_new (sequence_cache->is_zero_terminated, + array_ = g_array_sized_new (array_cache->is_zero_terminated, TRUE, item_size, length); @@ -303,7 +304,7 @@ _pygi_marshal_from_py_array (PyGIInvokeState *state, PYGLIB_PyBytes_Check (py_arg)) { memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length); array_->len = length; - if (sequence_cache->is_zero_terminated) { + if (array_cache->is_zero_terminated) { /* If array_ has been created with zero_termination, space for the * terminator is properly allocated, so we're not off-by-one here. */ array_->data[length] = '\0'; @@ -433,10 +434,10 @@ err: } array_success: - if (sequence_cache->len_arg_index >= 0) { + if (array_cache->len_arg_index >= 0) { /* we have an child arg to handle */ PyGIArgCache *child_cache = - _pygi_callable_cache_get_arg (callable_cache, sequence_cache->len_arg_index); + _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index); if (child_cache->direction == PYGI_DIRECTION_BIDIRECTIONAL) { gint *len_arg = (gint *)state->in_args[child_cache->c_arg_index].v_pointer; @@ -459,7 +460,7 @@ array_success: } } - if (sequence_cache->array_type == GI_ARRAY_TYPE_C) { + if (array_cache->array_type == GI_ARRAY_TYPE_C) { /* In the case of GI_ARRAY_C, we give the data directly as the argument * but keep the array_ wrapper as cleanup data so we don't have to find * it's length again. @@ -523,14 +524,6 @@ _pygi_marshal_from_py_glist (PyGIInvokeState *state, if (length < 0) return FALSE; - if (sequence_cache->fixed_size >= 0 && - sequence_cache->fixed_size != length) { - PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd", - sequence_cache->fixed_size, length); - - return FALSE; - } - from_py_marshaller = sequence_cache->item_cache->from_py_marshaller; for (i = 0; i < length; i++) { GIArgument item = {0}; @@ -607,14 +600,6 @@ _pygi_marshal_from_py_gslist (PyGIInvokeState *state, if (length < 0) return FALSE; - if (sequence_cache->fixed_size >= 0 && - sequence_cache->fixed_size != length) { - PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd", - sequence_cache->fixed_size, length); - - return FALSE; - } - from_py_marshaller = sequence_cache->item_cache->from_py_marshaller; for (i = 0; i < length; i++) { GIArgument item = {0}; diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index 292f9628..e3d5475d 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -121,18 +121,19 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, GArray *array_; PyObject *py_obj = NULL; PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache; + PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache; gsize processed_items = 0; /* GArrays make it easier to iterate over arrays * with different element sizes but requires that * we allocate a GArray if the argument was a C array */ - if (seq_cache->array_type == GI_ARRAY_TYPE_C) { + if (array_cache->array_type == GI_ARRAY_TYPE_C) { gsize len; - if (seq_cache->fixed_size >= 0) { + if (array_cache->fixed_size >= 0) { g_assert(arg->v_pointer != NULL); - len = seq_cache->fixed_size; - } else if (seq_cache->is_zero_terminated) { + len = array_cache->fixed_size; + } else if (array_cache->is_zero_terminated) { if (arg->v_pointer == NULL) { len = 0; } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) { @@ -141,9 +142,9 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, len = g_strv_length ((gchar **)arg->v_pointer); } } else { - GIArgument *len_arg = state->args[seq_cache->len_arg_index]; + GIArgument *len_arg = state->args[array_cache->len_arg_index]; PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache, - seq_cache->len_arg_index); + array_cache->len_arg_index); if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) { return NULL; @@ -152,7 +153,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, array_ = g_array_new (FALSE, FALSE, - seq_cache->item_size); + array_cache->item_size); if (array_ == NULL) { PyErr_NoMemory (); @@ -204,7 +205,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, * and move on, letting the per-item marshaler deal with the * various transfer modes and ref counts (e.g. g_variant_ref_sink). */ - if (seq_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { + if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) { item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i); } else if (item_arg_cache->is_pointer) { @@ -243,7 +244,7 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, if (py_item == NULL) { Py_CLEAR (py_obj); - if (seq_cache->array_type == GI_ARRAY_TYPE_C) + if (array_cache->array_type == GI_ARRAY_TYPE_C) g_array_unref (array_); goto err; @@ -254,13 +255,13 @@ _pygi_marshal_to_py_array (PyGIInvokeState *state, } } - if (seq_cache->array_type == GI_ARRAY_TYPE_C) + if (array_cache->array_type == GI_ARRAY_TYPE_C) g_array_free (array_, FALSE); return py_obj; err: - if (seq_cache->array_type == GI_ARRAY_TYPE_C) { + if (array_cache->array_type == GI_ARRAY_TYPE_C) { g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING); } else { /* clean up unprocessed items */ |