1 /* -*- Mode: C; c-basic-offset: 4 -*-
2 * vim: tabstop=4 shiftwidth=4 expandtab
4 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5 * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
22 #include "pygi-list.h"
23 #include "pygi-argument.h"
24 #include "pygi-util.h"
26 typedef PyGISequenceCache PyGIArgGList;
29 * GList and GSList from Python
32 _pygi_marshal_from_py_glist (PyGIInvokeState *state,
33 PyGICallableCache *callable_cache,
34 PyGIArgCache *arg_cache,
37 gpointer *cleanup_data)
39 PyGIMarshalFromPyFunc from_py_marshaller;
43 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
46 if (py_arg == Py_None) {
47 arg->v_pointer = NULL;
51 if (!PySequence_Check (py_arg)) {
52 PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
53 py_arg->ob_type->tp_name);
57 length = PySequence_Length (py_arg);
61 from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
62 for (i = 0; i < length; i++) {
63 GIArgument item = {0};
64 gpointer item_cleanup_data = NULL;
65 PyObject *py_item = PySequence_GetItem (py_arg, i);
69 if (!from_py_marshaller ( state,
71 sequence_cache->item_cache,
78 list_ = g_list_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_info));
81 /* FIXME: clean up list
82 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
83 PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
88 _PyGI_ERROR_PREFIX ("Item %i: ", i);
92 arg->v_pointer = g_list_reverse (list_);
94 if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
95 /* Free everything in cleanup. */
96 *cleanup_data = arg->v_pointer;
97 } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
98 /* Make a shallow copy so we can free the elements later in cleanup
99 * because it is possible invoke will free the list before our cleanup. */
100 *cleanup_data = g_list_copy (arg->v_pointer);
101 } else { /* GI_TRANSFER_EVERYTHING */
102 /* No cleanup, everything is given to the callee. */
103 *cleanup_data = NULL;
110 _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
111 PyGICallableCache *callable_cache,
112 PyGIArgCache *arg_cache,
115 gpointer *cleanup_data)
117 PyGIMarshalFromPyFunc from_py_marshaller;
120 GSList *list_ = NULL;
121 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
123 if (py_arg == Py_None) {
124 arg->v_pointer = NULL;
128 if (!PySequence_Check (py_arg)) {
129 PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
130 py_arg->ob_type->tp_name);
134 length = PySequence_Length (py_arg);
138 from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
139 for (i = 0; i < length; i++) {
140 GIArgument item = {0};
141 gpointer item_cleanup_data = NULL;
142 PyObject *py_item = PySequence_GetItem (py_arg, i);
146 if (!from_py_marshaller ( state,
148 sequence_cache->item_cache,
155 list_ = g_slist_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_info));
158 /* FIXME: Clean up list
159 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
160 PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
164 Py_XDECREF (py_item);
165 g_slist_free (list_);
166 _PyGI_ERROR_PREFIX ("Item %i: ", i);
170 arg->v_pointer = g_slist_reverse (list_);
172 if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
173 /* Free everything in cleanup. */
174 *cleanup_data = arg->v_pointer;
175 } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
176 /* Make a shallow copy so we can free the elements later in cleanup
177 * because it is possible invoke will free the list before our cleanup. */
178 *cleanup_data = g_slist_copy (arg->v_pointer);
179 } else { /* GI_TRANSFER_EVERYTHING */
180 /* No cleanup, everything is given to the callee. */
181 *cleanup_data = NULL;
188 _pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state,
189 PyGIArgCache *arg_cache,
192 gboolean was_processed)
196 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
198 list_ = (GSList *)data;
200 /* clean up items first */
201 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
202 PyGIMarshalCleanupFunc cleanup_func =
203 sequence_cache->item_cache->from_py_cleanup;
204 GSList *node = list_;
206 while (node != NULL) {
207 PyObject *py_item = PySequence_GetItem (py_arg, i);
209 sequence_cache->item_cache,
213 Py_XDECREF (py_item);
219 if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
220 g_list_free ( (GList *)list_);
221 } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
222 g_slist_free (list_);
224 g_assert_not_reached();
231 * GList and GSList to Python
234 _pygi_marshal_to_py_glist (PyGIInvokeState *state,
235 PyGICallableCache *callable_cache,
236 PyGIArgCache *arg_cache,
243 PyGIMarshalToPyFunc item_to_py_marshaller;
244 PyGIArgCache *item_arg_cache;
245 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
247 PyObject *py_obj = NULL;
249 list_ = arg->v_pointer;
250 length = g_list_length (list_);
252 py_obj = PyList_New (length);
256 item_arg_cache = seq_cache->item_cache;
257 item_to_py_marshaller = item_arg_cache->to_py_marshaller;
259 for (i = 0; list_ != NULL; list_ = g_list_next (list_), i++) {
263 item_arg.v_pointer = list_->data;
264 _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info);
265 py_item = item_to_py_marshaller (state,
270 if (py_item == NULL) {
272 _PyGI_ERROR_PREFIX ("Item %zu: ", i);
276 PyList_SET_ITEM (py_obj, i, py_item);
283 _pygi_marshal_to_py_gslist (PyGIInvokeState *state,
284 PyGICallableCache *callable_cache,
285 PyGIArgCache *arg_cache,
292 PyGIMarshalToPyFunc item_to_py_marshaller;
293 PyGIArgCache *item_arg_cache;
294 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
296 PyObject *py_obj = NULL;
298 list_ = arg->v_pointer;
299 length = g_slist_length (list_);
301 py_obj = PyList_New (length);
305 item_arg_cache = seq_cache->item_cache;
306 item_to_py_marshaller = item_arg_cache->to_py_marshaller;
308 for (i = 0; list_ != NULL; list_ = g_slist_next (list_), i++) {
312 item_arg.v_pointer = list_->data;
313 _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info);
314 py_item = item_to_py_marshaller (state,
319 if (py_item == NULL) {
321 _PyGI_ERROR_PREFIX ("Item %zu: ", i);
325 PyList_SET_ITEM (py_obj, i, py_item);
332 _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
333 PyGIArgCache *arg_cache,
336 gboolean was_processed)
338 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
339 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
340 arg_cache->transfer == GI_TRANSFER_CONTAINER) {
341 GSList *list_ = (GSList *)data;
343 if (sequence_cache->item_cache->to_py_cleanup != NULL) {
344 PyGIMarshalCleanupFunc cleanup_func =
345 sequence_cache->item_cache->to_py_cleanup;
346 GSList *node = list_;
348 while (node != NULL) {
350 sequence_cache->item_cache,
358 if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
359 g_list_free ( (GList *)list_);
360 } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
361 g_slist_free (list_);
363 g_assert_not_reached();
369 _arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
372 arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
373 arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
377 _arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
380 arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
381 arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
385 _arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
388 arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
389 arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
393 _arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
396 arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
397 arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
402 * GList/GSList Interface
406 pygi_arg_glist_setup_from_info (PyGIArgCache *arg_cache,
407 GITypeInfo *type_info,
410 PyGIDirection direction,
411 PyGICallableCache *callable_cache)
413 GITypeTag type_tag = g_type_info_get_tag (type_info);
415 if (!pygi_arg_sequence_setup ((PyGISequenceCache *)arg_cache,
424 case GI_TYPE_TAG_GLIST:
426 if (direction & PYGI_DIRECTION_FROM_PYTHON)
427 _arg_cache_from_py_glist_setup (arg_cache, transfer);
429 if (direction & PYGI_DIRECTION_TO_PYTHON)
430 _arg_cache_to_py_glist_setup (arg_cache, transfer);
433 case GI_TYPE_TAG_GSLIST:
435 if (direction & PYGI_DIRECTION_FROM_PYTHON)
436 _arg_cache_from_py_gslist_setup (arg_cache, transfer);
438 if (direction & PYGI_DIRECTION_TO_PYTHON)
439 _arg_cache_to_py_gslist_setup (arg_cache, transfer);
444 g_assert_not_reached ();
451 pygi_arg_glist_new_from_info (GITypeInfo *type_info,
454 PyGIDirection direction,
455 PyGICallableCache *callable_cache)
457 gboolean res = FALSE;
459 PyGIArgCache *arg_cache = (PyGIArgCache *) g_slice_new0 (PyGIArgGList);
460 if (arg_cache == NULL)
463 res = pygi_arg_glist_setup_from_info (arg_cache,
472 pygi_arg_cache_free (arg_cache);