From 4a6bf3be49cc5aec7287c41ec02c78d60df1d44c Mon Sep 17 00:00:00 2001 From: Simon Feltman Date: Fri, 11 Oct 2013 17:39:31 -0700 Subject: cache refactoring: Move PyGIHashCache and related marshaling into new file Re-organize hash table arg cache and its marshaling by moving all related code fragments into an isolated file where most of it is made static. pygi-hashtable.h exposes a single function: pygi_arg_hash_table_new_from_info. This is all the caching system needs to produce the proper bits for handling hash table marshaling. https://bugzilla.gnome.org/show_bug.cgi?id=709700 --- gi/Makefile.am | 4 +- gi/pygi-cache.c | 103 +----------- gi/pygi-cache.h | 21 ++- gi/pygi-hashtable.c | 413 ++++++++++++++++++++++++++++++++++++++++++++++ gi/pygi-hashtable.h | 35 ++++ gi/pygi-marshal-cleanup.c | 63 ------- gi/pygi-marshal-cleanup.h | 10 -- gi/pygi-marshal-from-py.c | 125 -------------- gi/pygi-marshal-from-py.h | 6 - gi/pygi-marshal-to-py.c | 85 ---------- gi/pygi-marshal-to-py.h | 4 - 11 files changed, 471 insertions(+), 398 deletions(-) create mode 100644 gi/pygi-hashtable.c create mode 100644 gi/pygi-hashtable.h diff --git a/gi/Makefile.am b/gi/Makefile.am index fa1ce9a3..c2fcd5c9 100644 --- a/gi/Makefile.am +++ b/gi/Makefile.am @@ -102,7 +102,9 @@ _gi_la_SOURCES = \ pygi-marshal-to-py.c \ pygi-marshal-to-py.h \ pygi-marshal-cleanup.c \ - pygi-marshal-cleanup.h + pygi-marshal-cleanup.h \ + pygi-hashtable.c \ + pygi-hashtable.h _gi_la_CFLAGS = \ $(extension_cppflags) \ $(GLIB_CFLAGS) \ diff --git a/gi/pygi-cache.c b/gi/pygi-cache.c index f4765010..0c6b94c5 100644 --- a/gi/pygi-cache.c +++ b/gi/pygi-cache.c @@ -19,22 +19,16 @@ * USA */ +#include + #include "pygi-info.h" #include "pygi-cache.h" #include "pygi-marshal-to-py.h" #include "pygi-marshal-from-py.h" #include "pygi-marshal-cleanup.h" #include "pygi-type.h" -#include +#include "pygi-hashtable.h" -PyGIArgCache * _arg_cache_new (GITypeInfo *type_info, - GIArgInfo *arg_info, - GITransfer transfer, - PyGIDirection direction, - /* will be removed */ - gssize c_arg_index, - gssize py_arg_index, - PyGICallableCache *callable_cache); PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info, GITypeInfo *type_info, @@ -127,7 +121,7 @@ pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache, /* cleanup */ -static void +void _pygi_arg_cache_free (PyGIArgCache *cache) { if (cache == NULL) @@ -154,15 +148,6 @@ _interface_cache_free_func (PyGIInterfaceCache *cache) } } -static void -_hash_cache_free_func (PyGIHashCache *cache) -{ - if (cache != NULL) { - _pygi_arg_cache_free (cache->key_cache); - _pygi_arg_cache_free (cache->value_cache); - g_slice_free (PyGIHashCache, cache); - } -} static void _sequence_cache_free_func (PyGISequenceCache *cache) @@ -261,53 +246,6 @@ _sequence_cache_new (GITypeInfo *type_info, return sc; } -static PyGIHashCache * -_hash_cache_new (GITypeInfo *type_info, - GIDirection direction, - GITransfer transfer) -{ - PyGIHashCache *hc; - GITypeInfo *key_type_info; - GITypeInfo *value_type_info; - GITransfer item_transfer; - - hc = g_slice_new0 (PyGIHashCache); - ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func; - key_type_info = g_type_info_get_param_type (type_info, 0); - value_type_info = g_type_info_get_param_type (type_info, 1); - - item_transfer = - transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; - - hc->key_cache = _arg_cache_new (key_type_info, - NULL, - item_transfer, - direction, - 0, 0, - NULL); - - if (hc->key_cache == NULL) { - _pygi_arg_cache_free ( (PyGIArgCache *)hc); - return NULL; - } - - hc->value_cache = _arg_cache_new (value_type_info, - NULL, - item_transfer, - direction, - 0, 0, - NULL); - - if (hc->value_cache == NULL) { - _pygi_arg_cache_free ( (PyGIArgCache *)hc); - return NULL; - } - - g_base_info_unref( (GIBaseInfo *)key_type_info); - g_base_info_unref( (GIBaseInfo *)value_type_info); - - return hc; -} static PyGICallbackCache * _callback_cache_new (GIArgInfo *arg_info, @@ -511,20 +449,6 @@ _arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache, arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist; } -static void -_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache) -{ - arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash; - arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash; -} - -static void -_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache) -{ - arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash; - arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash; -} - static void _arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache) { @@ -920,22 +844,11 @@ _arg_cache_new (GITypeInfo *type_info, break; } case GI_TYPE_TAG_GHASH: - arg_cache = - (PyGIArgCache *)_hash_cache_new (type_info, - direction, - transfer); - - if (arg_cache == NULL) - break; + arg_cache = pygi_arg_hash_table_new_from_info (type_info, arg_info, transfer, direction); + arg_cache->py_arg_index = py_arg_index; + arg_cache->c_arg_index = c_arg_index; + return arg_cache; - if (direction & PYGI_DIRECTION_FROM_PYTHON) - _arg_cache_from_py_ghash_setup (arg_cache); - - if (direction & PYGI_DIRECTION_TO_PYTHON) { - _arg_cache_to_py_ghash_setup (arg_cache); - } - - break; case GI_TYPE_TAG_INTERFACE: { GIInterfaceInfo *interface_info = g_type_info_get_interface (type_info); diff --git a/gi/pygi-cache.h b/gi/pygi-cache.h index 7a5be37c..e1b0649e 100644 --- a/gi/pygi-cache.h +++ b/gi/pygi-cache.h @@ -150,13 +150,6 @@ typedef struct _PyGIInterfaceCache gchar *type_name; } PyGIInterfaceCache; -typedef struct _PyGIHashCache -{ - PyGIArgCache arg_cache; - PyGIArgCache *key_cache; - PyGIArgCache *value_cache; -} PyGIHashCache; - typedef struct _PyGICallbackCache { PyGIArgCache arg_cache; @@ -218,8 +211,18 @@ pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache, PyGIDirection direction, GIInterfaceInfo *iface_info); -void _pygi_arg_cache_clear (PyGIArgCache *cache); -void _pygi_callable_cache_free (PyGICallableCache *cache); +PyGIArgCache * _arg_cache_new (GITypeInfo *type_info, + GIArgInfo *arg_info, + GITransfer transfer, + PyGIDirection direction, + /* will be removed */ + gssize c_arg_index, + gssize py_arg_index, + PyGICallableCache *callable_cache); + +void _pygi_arg_cache_free (PyGIArgCache *cache); +void _pygi_arg_cache_clear (PyGIArgCache *cache); +void _pygi_callable_cache_free (PyGICallableCache *cache); PyGICallableCache *_pygi_callable_cache_new (GICallableInfo *callable_info, gboolean is_ccallback); diff --git a/gi/pygi-hashtable.c b/gi/pygi-hashtable.c new file mode 100644 index 00000000..f8864f05 --- /dev/null +++ b/gi/pygi-hashtable.c @@ -0,0 +1,413 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2011 John (J5) Palmieri + * Copyright (C) 2014 Simon Feltman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#include "pygi-hashtable.h" +#include "pygi-argument.h" +#include "pygi-private.h" + +typedef struct _PyGIHashCache +{ + PyGIArgCache arg_cache; + PyGIArgCache *key_cache; + PyGIArgCache *value_cache; +} PyGIHashCache; + + +static void +_hash_cache_free_func (PyGIHashCache *cache) +{ + if (cache != NULL) { + _pygi_arg_cache_free (cache->key_cache); + _pygi_arg_cache_free (cache->value_cache); + g_slice_free (PyGIHashCache, cache); + } +} + +static gboolean +_pygi_marshal_from_py_ghash (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + PyObject *py_arg, + GIArgument *arg, + gpointer *cleanup_data) +{ + PyGIMarshalFromPyFunc key_from_py_marshaller; + PyGIMarshalFromPyFunc value_from_py_marshaller; + + int i; + Py_ssize_t length; + PyObject *py_keys, *py_values; + + GHashFunc hash_func; + GEqualFunc equal_func; + + GHashTable *hash_ = NULL; + PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; + + if (py_arg == Py_None) { + arg->v_pointer = NULL; + return TRUE; + } + + py_keys = PyMapping_Keys (py_arg); + if (py_keys == NULL) { + PyErr_Format (PyExc_TypeError, "Must be mapping, not %s", + py_arg->ob_type->tp_name); + return FALSE; + } + + length = PyMapping_Length (py_arg); + if (length < 0) { + Py_DECREF (py_keys); + return FALSE; + } + + py_values = PyMapping_Values (py_arg); + if (py_values == NULL) { + Py_DECREF (py_keys); + return FALSE; + } + + key_from_py_marshaller = hash_cache->key_cache->from_py_marshaller; + value_from_py_marshaller = hash_cache->value_cache->from_py_marshaller; + + switch (hash_cache->key_cache->type_tag) { + case GI_TYPE_TAG_UTF8: + case GI_TYPE_TAG_FILENAME: + hash_func = g_str_hash; + equal_func = g_str_equal; + break; + default: + hash_func = NULL; + equal_func = NULL; + } + + hash_ = g_hash_table_new (hash_func, equal_func); + if (hash_ == NULL) { + PyErr_NoMemory (); + Py_DECREF (py_keys); + Py_DECREF (py_values); + return FALSE; + } + + for (i = 0; i < length; i++) { + GIArgument key, value; + gpointer key_cleanup_data = NULL; + gpointer value_cleanup_data = NULL; + PyObject *py_key = PyList_GET_ITEM (py_keys, i); + PyObject *py_value = PyList_GET_ITEM (py_values, i); + if (py_key == NULL || py_value == NULL) + goto err; + + if (!key_from_py_marshaller ( state, + callable_cache, + hash_cache->key_cache, + py_key, + &key, + &key_cleanup_data)) + goto err; + + if (!value_from_py_marshaller ( state, + callable_cache, + hash_cache->value_cache, + py_value, + &value, + &value_cleanup_data)) + goto err; + + g_hash_table_insert (hash_, + _pygi_arg_to_hash_pointer (&key, hash_cache->key_cache->type_tag), + _pygi_arg_to_hash_pointer (&value, hash_cache->value_cache->type_tag)); + continue; +err: + /* FIXME: cleanup hash keys and values */ + Py_XDECREF (py_key); + Py_XDECREF (py_value); + Py_DECREF (py_keys); + Py_DECREF (py_values); + g_hash_table_unref (hash_); + _PyGI_ERROR_PREFIX ("Item %i: ", i); + return FALSE; + } + + arg->v_pointer = hash_; + + if (arg_cache->transfer == GI_TRANSFER_NOTHING) { + /* Free everything in cleanup. */ + *cleanup_data = arg->v_pointer; + } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) { + /* Make a shallow copy so we can free the elements later in cleanup + * because it is possible invoke will free the list before our cleanup. */ + *cleanup_data = g_hash_table_ref (arg->v_pointer); + } else { /* GI_TRANSFER_EVERYTHING */ + /* No cleanup, everything is given to the callee. + * Note that the keys and values will leak for transfer everything because + * we do not use g_hash_table_new_full and set key/value_destroy_func. */ + *cleanup_data = NULL; + } + + return TRUE; +} + +static void +_pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *py_arg, + gpointer data, + gboolean was_processed) +{ + if (data == NULL) + return; + + if (was_processed) { + GHashTable *hash_; + PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; + + hash_ = (GHashTable *)data; + + /* clean up keys and values first */ + if (hash_cache->key_cache->from_py_cleanup != NULL || + hash_cache->value_cache->from_py_cleanup != NULL) { + GHashTableIter hiter; + gpointer key; + gpointer value; + + PyGIMarshalCleanupFunc key_cleanup_func = + hash_cache->key_cache->from_py_cleanup; + PyGIMarshalCleanupFunc value_cleanup_func = + hash_cache->value_cache->from_py_cleanup; + + g_hash_table_iter_init (&hiter, hash_); + while (g_hash_table_iter_next (&hiter, &key, &value)) { + if (key != NULL && key_cleanup_func != NULL) + key_cleanup_func (state, + hash_cache->key_cache, + NULL, + key, + TRUE); + if (value != NULL && value_cleanup_func != NULL) + value_cleanup_func (state, + hash_cache->value_cache, + NULL, + value, + TRUE); + } + } + + g_hash_table_unref (hash_); + } +} + +static PyObject * +_pygi_marshal_to_py_ghash (PyGIInvokeState *state, + PyGICallableCache *callable_cache, + PyGIArgCache *arg_cache, + GIArgument *arg) +{ + GHashTable *hash_; + GHashTableIter hash_table_iter; + + PyGIMarshalToPyFunc key_to_py_marshaller; + PyGIMarshalToPyFunc value_to_py_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; + + hash_ = arg->v_pointer; + + if (hash_ == NULL) { + py_obj = Py_None; + Py_INCREF (py_obj); + return py_obj; + } + + py_obj = PyDict_New (); + if (py_obj == NULL) + return NULL; + + key_arg_cache = hash_cache->key_cache; + key_to_py_marshaller = key_arg_cache->to_py_marshaller; + + value_arg_cache = hash_cache->value_cache; + value_to_py_marshaller = value_arg_cache->to_py_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; + + + _pygi_hash_pointer_to_arg (&key_arg, hash_cache->key_cache->type_tag); + py_key = key_to_py_marshaller ( state, + callable_cache, + key_arg_cache, + &key_arg); + + if (py_key == NULL) { + Py_CLEAR (py_obj); + return NULL; + } + + _pygi_hash_pointer_to_arg (&value_arg, hash_cache->value_cache->type_tag); + py_value = value_to_py_marshaller ( state, + callable_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; +} + +static void +_pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state, + PyGIArgCache *arg_cache, + PyObject *dummy, + gpointer data, + gboolean was_processed) +{ + if (data == NULL) + return; + + /* assume hashtable has boxed key and value */ + if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER) + g_hash_table_unref ( (GHashTable *)data); +} + +static void +_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache) +{ + arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash; + arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash; +} + +static void +_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache) +{ + arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash; + arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash; +} + +static gboolean +pygi_arg_hash_table_setup_from_info (PyGIHashCache *hc, + GITypeInfo *type_info, + GIArgInfo *arg_info, + GITransfer transfer, + PyGIDirection direction) +{ + GITypeInfo *key_type_info; + GITypeInfo *value_type_info; + GITransfer item_transfer; + + if (!pygi_arg_base_setup ((PyGIArgCache *)hc, type_info, arg_info, transfer, direction)) + return FALSE; + + ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func; + key_type_info = g_type_info_get_param_type (type_info, 0); + value_type_info = g_type_info_get_param_type (type_info, 1); + + item_transfer = + transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer; + + hc->key_cache = _arg_cache_new (key_type_info, + NULL, + item_transfer, + direction, + 0, 0, + NULL); + + if (hc->key_cache == NULL) { + return FALSE; + } + + hc->value_cache = _arg_cache_new (value_type_info, + NULL, + item_transfer, + direction, + 0, 0, + NULL); + + if (hc->value_cache == NULL) { + return FALSE; + } + + g_base_info_unref( (GIBaseInfo *)key_type_info); + g_base_info_unref( (GIBaseInfo *)value_type_info); + + if (direction & PYGI_DIRECTION_FROM_PYTHON) { + _arg_cache_from_py_ghash_setup ((PyGIArgCache *)hc); + } + + if (direction & PYGI_DIRECTION_TO_PYTHON) { + _arg_cache_to_py_ghash_setup ((PyGIArgCache *)hc); + } + + return TRUE; +} + +PyGIArgCache * +pygi_arg_hash_table_new_from_info (GITypeInfo *type_info, + GIArgInfo *arg_info, + GITransfer transfer, + PyGIDirection direction) +{ + gboolean res = FALSE; + PyGIHashCache *hc = NULL; + + hc = g_slice_new0 (PyGIHashCache); + if (hc == NULL) + return NULL; + + res = pygi_arg_hash_table_setup_from_info (hc, + type_info, + arg_info, + transfer, + direction); + if (res) { + return (PyGIArgCache *)hc; + } else { + _pygi_arg_cache_free ((PyGIArgCache *)hc); + return NULL; + } +} diff --git a/gi/pygi-hashtable.h b/gi/pygi-hashtable.h new file mode 100644 index 00000000..a42aaf0e --- /dev/null +++ b/gi/pygi-hashtable.h @@ -0,0 +1,35 @@ +/* -*- Mode: C; c-basic-offset: 4 -*- + * vim: tabstop=4 shiftwidth=4 expandtab + * + * Copyright (C) 2013 Simon Feltman + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2.1 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see . + */ + +#ifndef __PYGI_HASHTABLE_H__ +#define __PYGI_HASHTABLE_H__ + +#include +#include "pygi-cache.h" + +G_BEGIN_DECLS + +PyGIArgCache *pygi_arg_hash_table_new_from_info (GITypeInfo *type_info, + GIArgInfo *arg_info, /* may be null */ + GITransfer transfer, + PyGIDirection direction); + +G_END_DECLS + +#endif /*__PYGI_HASHTABLE_H__*/ diff --git a/gi/pygi-marshal-cleanup.c b/gi/pygi-marshal-cleanup.c index 33d0339f..38783d90 100644 --- a/gi/pygi-marshal-cleanup.c +++ b/gi/pygi-marshal-cleanup.c @@ -548,66 +548,3 @@ _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state, } } -void -_pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed) -{ - if (data == NULL) - return; - - if (was_processed) { - GHashTable *hash_; - PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; - - hash_ = (GHashTable *)data; - - /* clean up keys and values first */ - if (hash_cache->key_cache->from_py_cleanup != NULL || - hash_cache->value_cache->from_py_cleanup != NULL) { - GHashTableIter hiter; - gpointer key; - gpointer value; - - PyGIMarshalCleanupFunc key_cleanup_func = - hash_cache->key_cache->from_py_cleanup; - PyGIMarshalCleanupFunc value_cleanup_func = - hash_cache->value_cache->from_py_cleanup; - - g_hash_table_iter_init (&hiter, hash_); - while (g_hash_table_iter_next (&hiter, &key, &value)) { - if (key != NULL && key_cleanup_func != NULL) - key_cleanup_func (state, - hash_cache->key_cache, - NULL, - key, - TRUE); - if (value != NULL && value_cleanup_func != NULL) - value_cleanup_func (state, - hash_cache->value_cache, - NULL, - value, - TRUE); - } - } - - g_hash_table_unref (hash_); - } -} - -void -_pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *dummy, - gpointer data, - gboolean was_processed) -{ - if (data == NULL) - return; - - /* assume hashtable has boxed key and value */ - if (arg_cache->transfer == GI_TRANSFER_EVERYTHING || arg_cache->transfer == GI_TRANSFER_CONTAINER) - g_hash_table_unref ( (GHashTable *)data); -} diff --git a/gi/pygi-marshal-cleanup.h b/gi/pygi-marshal-cleanup.h index 3acfbeb0..70a91c87 100644 --- a/gi/pygi-marshal-cleanup.h +++ b/gi/pygi-marshal-cleanup.h @@ -100,16 +100,6 @@ void _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *stat PyObject *dummy, gpointer data, gboolean was_processed); -void _pygi_marshal_cleanup_from_py_ghash (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *py_arg, - gpointer data, - gboolean was_processed); -void _pygi_marshal_cleanup_to_py_ghash (PyGIInvokeState *state, - PyGIArgCache *arg_cache, - PyObject *dummy, - gpointer data, - gboolean was_processed); G_END_DECLS #endif /* __PYGI_MARSHAL_CLEANUP_H__ */ diff --git a/gi/pygi-marshal-from-py.c b/gi/pygi-marshal-from-py.c index 41dcf542..e3b8ae8e 100644 --- a/gi/pygi-marshal-from-py.c +++ b/gi/pygi-marshal-from-py.c @@ -1142,131 +1142,6 @@ err: return TRUE; } -gboolean -_pygi_marshal_from_py_ghash (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - PyObject *py_arg, - GIArgument *arg, - gpointer *cleanup_data) -{ - PyGIMarshalFromPyFunc key_from_py_marshaller; - PyGIMarshalFromPyFunc value_from_py_marshaller; - - int i; - Py_ssize_t length; - PyObject *py_keys, *py_values; - - GHashFunc hash_func; - GEqualFunc equal_func; - - GHashTable *hash_ = NULL; - PyGIHashCache *hash_cache = (PyGIHashCache *)arg_cache; - - if (py_arg == Py_None) { - arg->v_pointer = NULL; - return TRUE; - } - - py_keys = PyMapping_Keys (py_arg); - if (py_keys == NULL) { - PyErr_Format (PyExc_TypeError, "Must be mapping, not %s", - py_arg->ob_type->tp_name); - return FALSE; - } - - length = PyMapping_Length (py_arg); - if (length < 0) { - Py_DECREF (py_keys); - return FALSE; - } - - py_values = PyMapping_Values (py_arg); - if (py_values == NULL) { - Py_DECREF (py_keys); - return FALSE; - } - - key_from_py_marshaller = hash_cache->key_cache->from_py_marshaller; - value_from_py_marshaller = hash_cache->value_cache->from_py_marshaller; - - switch (hash_cache->key_cache->type_tag) { - case GI_TYPE_TAG_UTF8: - case GI_TYPE_TAG_FILENAME: - hash_func = g_str_hash; - equal_func = g_str_equal; - break; - default: - hash_func = NULL; - equal_func = NULL; - } - - hash_ = g_hash_table_new (hash_func, equal_func); - if (hash_ == NULL) { - PyErr_NoMemory (); - Py_DECREF (py_keys); - Py_DECREF (py_values); - return FALSE; - } - - for (i = 0; i < length; i++) { - GIArgument key, value; - gpointer key_cleanup_data = NULL; - gpointer value_cleanup_data = NULL; - PyObject *py_key = PyList_GET_ITEM (py_keys, i); - PyObject *py_value = PyList_GET_ITEM (py_values, i); - if (py_key == NULL || py_value == NULL) - goto err; - - if (!key_from_py_marshaller ( state, - callable_cache, - hash_cache->key_cache, - py_key, - &key, - &key_cleanup_data)) - goto err; - - if (!value_from_py_marshaller ( state, - callable_cache, - hash_cache->value_cache, - py_value, - &value, - &value_cleanup_data)) - goto err; - - g_hash_table_insert (hash_, - _pygi_arg_to_hash_pointer (&key, hash_cache->key_cache->type_tag), - _pygi_arg_to_hash_pointer (&value, hash_cache->value_cache->type_tag)); - continue; -err: - /* FIXME: cleanup hash keys and values */ - Py_XDECREF (py_key); - Py_XDECREF (py_value); - Py_DECREF (py_keys); - Py_DECREF (py_values); - g_hash_table_unref (hash_); - _PyGI_ERROR_PREFIX ("Item %i: ", i); - return FALSE; - } - - arg->v_pointer = hash_; - - if (arg_cache->transfer == GI_TRANSFER_NOTHING) { - /* Free everything in cleanup. */ - *cleanup_data = arg->v_pointer; - } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) { - /* Make a shallow copy so we can free the elements later in cleanup - * because it is possible invoke will free the list before our cleanup. */ - *cleanup_data = g_hash_table_ref (arg->v_pointer); - } else { /* GI_TRANSFER_EVERYTHING */ - /* No cleanup, everything is given to the callee. - * Note that the keys and values will leak for transfer everything because - * we do not use g_hash_table_new_full and set key/value_destroy_func. */ - *cleanup_data = NULL; - } - - return TRUE; -} gboolean _pygi_marshal_from_py_gerror (PyGIInvokeState *state, diff --git a/gi/pygi-marshal-from-py.h b/gi/pygi-marshal-from-py.h index f8e4699b..83d074a2 100644 --- a/gi/pygi-marshal-from-py.h +++ b/gi/pygi-marshal-from-py.h @@ -57,12 +57,6 @@ gboolean _pygi_marshal_from_py_gslist (PyGIInvokeState *state, PyObject *py_arg, GIArgument *arg, gpointer *cleanup_data); -gboolean _pygi_marshal_from_py_ghash (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - PyObject *py_arg, - GIArgument *arg, - gpointer *cleanup_data); gboolean _pygi_marshal_from_py_gerror (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, diff --git a/gi/pygi-marshal-to-py.c b/gi/pygi-marshal-to-py.c index 9427754a..3c7d69e6 100644 --- a/gi/pygi-marshal-to-py.c +++ b/gi/pygi-marshal-to-py.c @@ -536,91 +536,6 @@ _pygi_marshal_to_py_gslist (PyGIInvokeState *state, return py_obj; } -PyObject * -_pygi_marshal_to_py_ghash (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg) -{ - GHashTable *hash_; - GHashTableIter hash_table_iter; - - PyGIMarshalToPyFunc key_to_py_marshaller; - PyGIMarshalToPyFunc value_to_py_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; - - hash_ = arg->v_pointer; - - if (hash_ == NULL) { - py_obj = Py_None; - Py_INCREF (py_obj); - return py_obj; - } - - py_obj = PyDict_New (); - if (py_obj == NULL) - return NULL; - - key_arg_cache = hash_cache->key_cache; - key_to_py_marshaller = key_arg_cache->to_py_marshaller; - - value_arg_cache = hash_cache->value_cache; - value_to_py_marshaller = value_arg_cache->to_py_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; - - - _pygi_hash_pointer_to_arg (&key_arg, hash_cache->key_cache->type_tag); - py_key = key_to_py_marshaller ( state, - callable_cache, - key_arg_cache, - &key_arg); - - if (py_key == NULL) { - Py_CLEAR (py_obj); - return NULL; - } - - _pygi_hash_pointer_to_arg (&value_arg, hash_cache->value_cache->type_tag); - py_value = value_to_py_marshaller ( state, - callable_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; -} - PyObject * _pygi_marshal_to_py_gerror (PyGIInvokeState *state, PyGICallableCache *callable_cache, diff --git a/gi/pygi-marshal-to-py.h b/gi/pygi-marshal-to-py.h index 13786300..48f1aa26 100644 --- a/gi/pygi-marshal-to-py.h +++ b/gi/pygi-marshal-to-py.h @@ -45,10 +45,6 @@ PyObject *_pygi_marshal_to_py_gslist (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, GIArgument *arg); -PyObject *_pygi_marshal_to_py_ghash (PyGIInvokeState *state, - PyGICallableCache *callable_cache, - PyGIArgCache *arg_cache, - GIArgument *arg); PyObject *_pygi_marshal_to_py_gerror (PyGIInvokeState *state, PyGICallableCache *callable_cache, PyGIArgCache *arg_cache, -- cgit v1.2.1