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_TYPE (py_arg
)->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_TYPE (py_arg
)->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
,
238 gpointer
*cleanup_data
)
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
);
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
++) {
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
,
277 g_ptr_array_index (item_cleanups
, i
) = item_cleanup_data
;
279 if (py_item
== NULL
) {
281 _PyGI_ERROR_PREFIX ("Item %u: ", i
);
282 g_ptr_array_unref (item_cleanups
);
286 PyList_SET_ITEM (py_obj
, i
, py_item
);
293 _pygi_marshal_to_py_gslist (PyGIInvokeState
*state
,
294 PyGICallableCache
*callable_cache
,
295 PyGIArgCache
*arg_cache
,
297 gpointer
*cleanup_data
)
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
);
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
++) {
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
,
336 g_ptr_array_index (item_cleanups
, i
) = item_cleanup_data
;
337 if (py_item
== NULL
) {
339 _PyGI_ERROR_PREFIX ("Item %u: ", i
);
340 g_ptr_array_unref (item_cleanups
);
344 PyList_SET_ITEM (py_obj
, i
, py_item
);
351 _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState
*state
,
352 PyGIArgCache
*arg_cache
,
353 gpointer cleanup_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_
;
367 while (node
!= NULL
) {
369 sequence_cache
->item_cache
,
370 g_ptr_array_index(item_cleanups
, 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_
);
386 g_assert_not_reached();
390 g_ptr_array_unref (item_cleanups
);
394 _arg_cache_from_py_glist_setup (PyGIArgCache
*arg_cache
,
397 arg_cache
->from_py_marshaller
= _pygi_marshal_from_py_glist
;
398 arg_cache
->from_py_cleanup
= _pygi_marshal_cleanup_from_py_glist
;
402 _arg_cache_to_py_glist_setup (PyGIArgCache
*arg_cache
,
405 arg_cache
->to_py_marshaller
= _pygi_marshal_to_py_glist
;
406 arg_cache
->to_py_cleanup
= _pygi_marshal_cleanup_to_py_glist
;
410 _arg_cache_from_py_gslist_setup (PyGIArgCache
*arg_cache
,
413 arg_cache
->from_py_marshaller
= _pygi_marshal_from_py_gslist
;
414 arg_cache
->from_py_cleanup
= _pygi_marshal_cleanup_from_py_glist
;
418 _arg_cache_to_py_gslist_setup (PyGIArgCache
*arg_cache
,
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
431 pygi_arg_glist_setup_from_info (PyGIArgCache
*arg_cache
,
432 GITypeInfo
*type_info
,
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
,
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
);
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
);
469 g_assert_not_reached ();
476 pygi_arg_glist_new_from_info (GITypeInfo
*type_info
,
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
)
488 res
= pygi_arg_glist_setup_from_info (arg_cache
,
497 pygi_arg_cache_free (arg_cache
);