tests: don't test for specific device labels
[pygobject.git] / gi / pygi-list.c
blob712c372cd3e47f93ccfd963cc86888a867a19967
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/>.
21 #include <Python.h>
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
31 static gboolean
32 _pygi_marshal_from_py_glist (PyGIInvokeState *state,
33 PyGICallableCache *callable_cache,
34 PyGIArgCache *arg_cache,
35 PyObject *py_arg,
36 GIArgument *arg,
37 gpointer *cleanup_data)
39 PyGIMarshalFromPyFunc from_py_marshaller;
40 int i;
41 Py_ssize_t length;
42 GList *list_ = NULL;
43 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
46 if (py_arg == Py_None) {
47 arg->v_pointer = NULL;
48 return TRUE;
51 if (!PySequence_Check (py_arg)) {
52 PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
53 Py_TYPE (py_arg)->tp_name);
54 return FALSE;
57 length = PySequence_Length (py_arg);
58 if (length < 0)
59 return FALSE;
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);
66 if (py_item == NULL)
67 goto err;
69 if (!from_py_marshaller ( state,
70 callable_cache,
71 sequence_cache->item_cache,
72 py_item,
73 &item,
74 &item_cleanup_data))
75 goto err;
77 Py_DECREF (py_item);
78 list_ = g_list_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_info));
79 continue;
80 err:
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;
86 Py_XDECREF (py_item);
87 g_list_free (list_);
88 _PyGI_ERROR_PREFIX ("Item %i: ", i);
89 return FALSE;
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;
105 return TRUE;
109 static gboolean
110 _pygi_marshal_from_py_gslist (PyGIInvokeState *state,
111 PyGICallableCache *callable_cache,
112 PyGIArgCache *arg_cache,
113 PyObject *py_arg,
114 GIArgument *arg,
115 gpointer *cleanup_data)
117 PyGIMarshalFromPyFunc from_py_marshaller;
118 int i;
119 Py_ssize_t length;
120 GSList *list_ = NULL;
121 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
123 if (py_arg == Py_None) {
124 arg->v_pointer = NULL;
125 return TRUE;
128 if (!PySequence_Check (py_arg)) {
129 PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
130 Py_TYPE (py_arg)->tp_name);
131 return FALSE;
134 length = PySequence_Length (py_arg);
135 if (length < 0)
136 return FALSE;
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);
143 if (py_item == NULL)
144 goto err;
146 if (!from_py_marshaller ( state,
147 callable_cache,
148 sequence_cache->item_cache,
149 py_item,
150 &item,
151 &item_cleanup_data))
152 goto err;
154 Py_DECREF (py_item);
155 list_ = g_slist_prepend (list_, _pygi_arg_to_hash_pointer (&item, sequence_cache->item_cache->type_info));
156 continue;
157 err:
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);
167 return FALSE;
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;
184 return TRUE;
187 static void
188 _pygi_marshal_cleanup_from_py_glist (PyGIInvokeState *state,
189 PyGIArgCache *arg_cache,
190 PyObject *py_arg,
191 gpointer data,
192 gboolean was_processed)
194 if (was_processed) {
195 GSList *list_;
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_;
205 gsize i = 0;
206 while (node != NULL) {
207 PyObject *py_item = PySequence_GetItem (py_arg, i);
208 cleanup_func (state,
209 sequence_cache->item_cache,
210 py_item,
211 node->data,
212 TRUE);
213 Py_XDECREF (py_item);
214 node = node->next;
215 i++;
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_);
223 } else {
224 g_assert_not_reached();
231 * GList and GSList to Python
233 static PyObject *
234 _pygi_marshal_to_py_glist (PyGIInvokeState *state,
235 PyGICallableCache *callable_cache,
236 PyGIArgCache *arg_cache,
237 GIArgument *arg,
238 gpointer *cleanup_data)
240 GList *list_;
241 guint length;
242 guint i;
243 GPtrArray *item_cleanups;
245 PyGIMarshalToPyFunc item_to_py_marshaller;
246 PyGIArgCache *item_arg_cache;
247 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
249 PyObject *py_obj = NULL;
251 list_ = arg->v_pointer;
252 length = g_list_length (list_);
254 py_obj = PyList_New (length);
255 if (py_obj == NULL)
256 return NULL;
258 item_cleanups = g_ptr_array_sized_new (length);
259 *cleanup_data = item_cleanups;
261 item_arg_cache = seq_cache->item_cache;
262 item_to_py_marshaller = item_arg_cache->to_py_marshaller;
264 for (i = 0; list_ != NULL; list_ = g_list_next (list_), i++) {
265 GIArgument item_arg;
266 PyObject *py_item;
267 gpointer item_cleanup_data = NULL;
269 item_arg.v_pointer = list_->data;
270 _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info);
271 py_item = item_to_py_marshaller (state,
272 callable_cache,
273 item_arg_cache,
274 &item_arg,
275 &item_cleanup_data);
277 g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
279 if (py_item == NULL) {
280 Py_CLEAR (py_obj);
281 _PyGI_ERROR_PREFIX ("Item %u: ", i);
282 g_ptr_array_unref (item_cleanups);
283 return NULL;
286 PyList_SET_ITEM (py_obj, i, py_item);
289 return py_obj;
292 static PyObject *
293 _pygi_marshal_to_py_gslist (PyGIInvokeState *state,
294 PyGICallableCache *callable_cache,
295 PyGIArgCache *arg_cache,
296 GIArgument *arg,
297 gpointer *cleanup_data)
299 GSList *list_;
300 guint length;
301 guint i;
302 GPtrArray *item_cleanups;
304 PyGIMarshalToPyFunc item_to_py_marshaller;
305 PyGIArgCache *item_arg_cache;
306 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
308 PyObject *py_obj = NULL;
310 list_ = arg->v_pointer;
311 length = g_slist_length (list_);
313 py_obj = PyList_New (length);
314 if (py_obj == NULL)
315 return NULL;
317 item_cleanups = g_ptr_array_sized_new (length);
318 *cleanup_data = item_cleanups;
320 item_arg_cache = seq_cache->item_cache;
321 item_to_py_marshaller = item_arg_cache->to_py_marshaller;
323 for (i = 0; list_ != NULL; list_ = g_slist_next (list_), i++) {
324 GIArgument item_arg;
325 PyObject *py_item;
326 gpointer item_cleanup_data = NULL;
328 item_arg.v_pointer = list_->data;
329 _pygi_hash_pointer_to_arg (&item_arg, item_arg_cache->type_info);
330 py_item = item_to_py_marshaller (state,
331 callable_cache,
332 item_arg_cache,
333 &item_arg,
334 &item_cleanup_data);
336 g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
337 if (py_item == NULL) {
338 Py_CLEAR (py_obj);
339 _PyGI_ERROR_PREFIX ("Item %u: ", i);
340 g_ptr_array_unref (item_cleanups);
341 return NULL;
344 PyList_SET_ITEM (py_obj, i, py_item);
347 return py_obj;
350 static void
351 _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState *state,
352 PyGIArgCache *arg_cache,
353 gpointer cleanup_data,
354 gpointer data,
355 gboolean was_processed)
357 GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
358 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
359 GSList *list_ = (GSList *)data;
361 if (sequence_cache->item_cache->to_py_cleanup != NULL) {
362 PyGIMarshalToPyCleanupFunc cleanup_func =
363 sequence_cache->item_cache->to_py_cleanup;
364 GSList *node = list_;
365 guint i = 0;
367 while (node != NULL) {
368 cleanup_func (state,
369 sequence_cache->item_cache,
370 g_ptr_array_index(item_cleanups, i),
371 node->data,
372 was_processed);
373 node = node->next;
374 i++;
378 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
379 arg_cache->transfer == GI_TRANSFER_CONTAINER) {
381 if (arg_cache->type_tag == GI_TYPE_TAG_GLIST) {
382 g_list_free ( (GList *)list_);
383 } else if (arg_cache->type_tag == GI_TYPE_TAG_GSLIST) {
384 g_slist_free (list_);
385 } else {
386 g_assert_not_reached();
390 g_ptr_array_unref (item_cleanups);
393 static void
394 _arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
395 GITransfer transfer)
397 arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
398 arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
401 static void
402 _arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
403 GITransfer transfer)
405 arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
406 arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
409 static void
410 _arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
411 GITransfer transfer)
413 arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
414 arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
417 static void
418 _arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
419 GITransfer transfer)
421 arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
422 arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
427 * GList/GSList Interface
430 static gboolean
431 pygi_arg_glist_setup_from_info (PyGIArgCache *arg_cache,
432 GITypeInfo *type_info,
433 GIArgInfo *arg_info,
434 GITransfer transfer,
435 PyGIDirection direction,
436 PyGICallableCache *callable_cache)
438 GITypeTag type_tag = g_type_info_get_tag (type_info);
440 if (!pygi_arg_sequence_setup ((PyGISequenceCache *)arg_cache,
441 type_info,
442 arg_info,
443 transfer,
444 direction,
445 callable_cache))
446 return FALSE;
448 switch (type_tag) {
449 case GI_TYPE_TAG_GLIST:
451 if (direction & PYGI_DIRECTION_FROM_PYTHON)
452 _arg_cache_from_py_glist_setup (arg_cache, transfer);
454 if (direction & PYGI_DIRECTION_TO_PYTHON)
455 _arg_cache_to_py_glist_setup (arg_cache, transfer);
456 break;
458 case GI_TYPE_TAG_GSLIST:
460 if (direction & PYGI_DIRECTION_FROM_PYTHON)
461 _arg_cache_from_py_gslist_setup (arg_cache, transfer);
463 if (direction & PYGI_DIRECTION_TO_PYTHON)
464 _arg_cache_to_py_gslist_setup (arg_cache, transfer);
466 break;
468 default:
469 g_assert_not_reached ();
472 return TRUE;
475 PyGIArgCache *
476 pygi_arg_glist_new_from_info (GITypeInfo *type_info,
477 GIArgInfo *arg_info,
478 GITransfer transfer,
479 PyGIDirection direction,
480 PyGICallableCache *callable_cache)
482 gboolean res = FALSE;
484 PyGIArgCache *arg_cache = (PyGIArgCache *) g_slice_new0 (PyGIArgGList);
485 if (arg_cache == NULL)
486 return NULL;
488 res = pygi_arg_glist_setup_from_info (arg_cache,
489 type_info,
490 arg_info,
491 transfer,
492 direction,
493 callable_cache);
494 if (res) {
495 return arg_cache;
496 } else {
497 pygi_arg_cache_free (arg_cache);
498 return NULL;