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 "pygi-list.h"
22 #include "pygi-argument.h"
23 #include "pygi-private.h"
25 typedef PyGISequenceCache PyGIArgGList
;
28 * GList and GSList from Python
31 _pygi_marshal_from_py_glist (PyGIInvokeState
*state
,
32 PyGICallableCache
*callable_cache
,
33 PyGIArgCache
*arg_cache
,
36 gpointer
*cleanup_data
)
38 PyGIMarshalFromPyFunc from_py_marshaller
;
42 PyGISequenceCache
*sequence_cache
= (PyGISequenceCache
*)arg_cache
;
45 if (py_arg
== Py_None
) {
46 arg
->v_pointer
= NULL
;
50 if (!PySequence_Check (py_arg
)) {
51 PyErr_Format (PyExc_TypeError
, "Must be sequence, not %s",
52 py_arg
->ob_type
->tp_name
);
56 length
= PySequence_Length (py_arg
);
60 from_py_marshaller
= sequence_cache
->item_cache
->from_py_marshaller
;
61 for (i
= 0; i
< length
; i
++) {
62 GIArgument item
= {0};
63 gpointer item_cleanup_data
= NULL
;
64 PyObject
*py_item
= PySequence_GetItem (py_arg
, i
);
68 if (!from_py_marshaller ( state
,
70 sequence_cache
->item_cache
,
77 list_
= g_list_prepend (list_
, _pygi_arg_to_hash_pointer (&item
, sequence_cache
->item_cache
->type_tag
));
80 /* FIXME: clean up list
81 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
82 PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
87 _PyGI_ERROR_PREFIX ("Item %i: ", i
);
91 arg
->v_pointer
= g_list_reverse (list_
);
93 if (arg_cache
->transfer
== GI_TRANSFER_NOTHING
) {
94 /* Free everything in cleanup. */
95 *cleanup_data
= arg
->v_pointer
;
96 } else if (arg_cache
->transfer
== GI_TRANSFER_CONTAINER
) {
97 /* Make a shallow copy so we can free the elements later in cleanup
98 * because it is possible invoke will free the list before our cleanup. */
99 *cleanup_data
= g_list_copy (arg
->v_pointer
);
100 } else { /* GI_TRANSFER_EVERYTHING */
101 /* No cleanup, everything is given to the callee. */
102 *cleanup_data
= NULL
;
109 _pygi_marshal_from_py_gslist (PyGIInvokeState
*state
,
110 PyGICallableCache
*callable_cache
,
111 PyGIArgCache
*arg_cache
,
114 gpointer
*cleanup_data
)
116 PyGIMarshalFromPyFunc from_py_marshaller
;
119 GSList
*list_
= NULL
;
120 PyGISequenceCache
*sequence_cache
= (PyGISequenceCache
*)arg_cache
;
122 if (py_arg
== Py_None
) {
123 arg
->v_pointer
= NULL
;
127 if (!PySequence_Check (py_arg
)) {
128 PyErr_Format (PyExc_TypeError
, "Must be sequence, not %s",
129 py_arg
->ob_type
->tp_name
);
133 length
= PySequence_Length (py_arg
);
137 from_py_marshaller
= sequence_cache
->item_cache
->from_py_marshaller
;
138 for (i
= 0; i
< length
; i
++) {
139 GIArgument item
= {0};
140 gpointer item_cleanup_data
= NULL
;
141 PyObject
*py_item
= PySequence_GetItem (py_arg
, i
);
145 if (!from_py_marshaller ( state
,
147 sequence_cache
->item_cache
,
154 list_
= g_slist_prepend (list_
, _pygi_arg_to_hash_pointer (&item
, sequence_cache
->item_cache
->type_tag
));
157 /* FIXME: Clean up list
158 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
159 PyGIMarshalCleanupFunc cleanup = sequence_cache->item_cache->from_py_cleanup;
163 Py_XDECREF (py_item
);
164 g_slist_free (list_
);
165 _PyGI_ERROR_PREFIX ("Item %i: ", i
);
169 arg
->v_pointer
= g_slist_reverse (list_
);
171 if (arg_cache
->transfer
== GI_TRANSFER_NOTHING
) {
172 /* Free everything in cleanup. */
173 *cleanup_data
= arg
->v_pointer
;
174 } else if (arg_cache
->transfer
== GI_TRANSFER_CONTAINER
) {
175 /* Make a shallow copy so we can free the elements later in cleanup
176 * because it is possible invoke will free the list before our cleanup. */
177 *cleanup_data
= g_slist_copy (arg
->v_pointer
);
178 } else { /* GI_TRANSFER_EVERYTHING */
179 /* No cleanup, everything is given to the callee. */
180 *cleanup_data
= NULL
;
187 _pygi_marshal_cleanup_from_py_glist (PyGIInvokeState
*state
,
188 PyGIArgCache
*arg_cache
,
191 gboolean was_processed
)
195 PyGISequenceCache
*sequence_cache
= (PyGISequenceCache
*)arg_cache
;
197 list_
= (GSList
*)data
;
199 /* clean up items first */
200 if (sequence_cache
->item_cache
->from_py_cleanup
!= NULL
) {
201 PyGIMarshalCleanupFunc cleanup_func
=
202 sequence_cache
->item_cache
->from_py_cleanup
;
203 GSList
*node
= list_
;
205 while (node
!= NULL
) {
206 PyObject
*py_item
= PySequence_GetItem (py_arg
, i
);
208 sequence_cache
->item_cache
,
212 Py_XDECREF (py_item
);
218 if (arg_cache
->type_tag
== GI_TYPE_TAG_GLIST
) {
219 g_list_free ( (GList
*)list_
);
220 } else if (arg_cache
->type_tag
== GI_TYPE_TAG_GSLIST
) {
221 g_slist_free (list_
);
223 g_assert_not_reached();
230 * GList and GSList to Python
233 _pygi_marshal_to_py_glist (PyGIInvokeState
*state
,
234 PyGICallableCache
*callable_cache
,
235 PyGIArgCache
*arg_cache
,
242 PyGIMarshalToPyFunc item_to_py_marshaller
;
243 PyGIArgCache
*item_arg_cache
;
244 PyGISequenceCache
*seq_cache
= (PyGISequenceCache
*)arg_cache
;
246 PyObject
*py_obj
= NULL
;
248 list_
= arg
->v_pointer
;
249 length
= g_list_length (list_
);
251 py_obj
= PyList_New (length
);
255 item_arg_cache
= seq_cache
->item_cache
;
256 item_to_py_marshaller
= item_arg_cache
->to_py_marshaller
;
258 for (i
= 0; list_
!= NULL
; list_
= g_list_next (list_
), i
++) {
262 item_arg
.v_pointer
= list_
->data
;
263 _pygi_hash_pointer_to_arg (&item_arg
, item_arg_cache
->type_tag
);
264 py_item
= item_to_py_marshaller (state
,
269 if (py_item
== NULL
) {
271 _PyGI_ERROR_PREFIX ("Item %zu: ", i
);
275 PyList_SET_ITEM (py_obj
, i
, py_item
);
282 _pygi_marshal_to_py_gslist (PyGIInvokeState
*state
,
283 PyGICallableCache
*callable_cache
,
284 PyGIArgCache
*arg_cache
,
291 PyGIMarshalToPyFunc item_to_py_marshaller
;
292 PyGIArgCache
*item_arg_cache
;
293 PyGISequenceCache
*seq_cache
= (PyGISequenceCache
*)arg_cache
;
295 PyObject
*py_obj
= NULL
;
297 list_
= arg
->v_pointer
;
298 length
= g_slist_length (list_
);
300 py_obj
= PyList_New (length
);
304 item_arg_cache
= seq_cache
->item_cache
;
305 item_to_py_marshaller
= item_arg_cache
->to_py_marshaller
;
307 for (i
= 0; list_
!= NULL
; list_
= g_slist_next (list_
), i
++) {
311 item_arg
.v_pointer
= list_
->data
;
312 _pygi_hash_pointer_to_arg (&item_arg
, item_arg_cache
->type_tag
);
313 py_item
= item_to_py_marshaller (state
,
318 if (py_item
== NULL
) {
320 _PyGI_ERROR_PREFIX ("Item %zu: ", i
);
324 PyList_SET_ITEM (py_obj
, i
, py_item
);
331 _pygi_marshal_cleanup_to_py_glist (PyGIInvokeState
*state
,
332 PyGIArgCache
*arg_cache
,
335 gboolean was_processed
)
337 PyGISequenceCache
*sequence_cache
= (PyGISequenceCache
*)arg_cache
;
338 if (arg_cache
->transfer
== GI_TRANSFER_EVERYTHING
||
339 arg_cache
->transfer
== GI_TRANSFER_CONTAINER
) {
340 GSList
*list_
= (GSList
*)data
;
342 if (sequence_cache
->item_cache
->to_py_cleanup
!= NULL
) {
343 PyGIMarshalCleanupFunc cleanup_func
=
344 sequence_cache
->item_cache
->to_py_cleanup
;
345 GSList
*node
= list_
;
347 while (node
!= NULL
) {
349 sequence_cache
->item_cache
,
357 if (arg_cache
->type_tag
== GI_TYPE_TAG_GLIST
) {
358 g_list_free ( (GList
*)list_
);
359 } else if (arg_cache
->type_tag
== GI_TYPE_TAG_GSLIST
) {
360 g_slist_free (list_
);
362 g_assert_not_reached();
368 _arg_cache_from_py_glist_setup (PyGIArgCache
*arg_cache
,
371 arg_cache
->from_py_marshaller
= _pygi_marshal_from_py_glist
;
372 arg_cache
->from_py_cleanup
= _pygi_marshal_cleanup_from_py_glist
;
376 _arg_cache_to_py_glist_setup (PyGIArgCache
*arg_cache
,
379 arg_cache
->to_py_marshaller
= _pygi_marshal_to_py_glist
;
380 arg_cache
->to_py_cleanup
= _pygi_marshal_cleanup_to_py_glist
;
384 _arg_cache_from_py_gslist_setup (PyGIArgCache
*arg_cache
,
387 arg_cache
->from_py_marshaller
= _pygi_marshal_from_py_gslist
;
388 arg_cache
->from_py_cleanup
= _pygi_marshal_cleanup_from_py_glist
;
392 _arg_cache_to_py_gslist_setup (PyGIArgCache
*arg_cache
,
395 arg_cache
->to_py_marshaller
= _pygi_marshal_to_py_gslist
;
396 arg_cache
->to_py_cleanup
= _pygi_marshal_cleanup_to_py_glist
;
401 * GList/GSList Interface
405 pygi_arg_glist_setup_from_info (PyGIArgCache
*arg_cache
,
406 GITypeInfo
*type_info
,
409 PyGIDirection direction
,
410 PyGICallableCache
*callable_cache
)
412 GITypeTag type_tag
= g_type_info_get_tag (type_info
);
414 if (!pygi_arg_sequence_setup ((PyGISequenceCache
*)arg_cache
,
423 case GI_TYPE_TAG_GLIST
:
425 if (direction
& PYGI_DIRECTION_FROM_PYTHON
)
426 _arg_cache_from_py_glist_setup (arg_cache
, transfer
);
428 if (direction
& PYGI_DIRECTION_TO_PYTHON
)
429 _arg_cache_to_py_glist_setup (arg_cache
, transfer
);
432 case GI_TYPE_TAG_GSLIST
:
434 if (direction
& PYGI_DIRECTION_FROM_PYTHON
)
435 _arg_cache_from_py_gslist_setup (arg_cache
, transfer
);
437 if (direction
& PYGI_DIRECTION_TO_PYTHON
)
438 _arg_cache_to_py_gslist_setup (arg_cache
, transfer
);
443 g_assert_not_reached ();
450 pygi_arg_glist_new_from_info (GITypeInfo
*type_info
,
453 PyGIDirection direction
,
454 PyGICallableCache
*callable_cache
)
456 gboolean res
= FALSE
;
458 PyGIArgCache
*arg_cache
= (PyGIArgCache
*) g_slice_new0 (PyGIArgGList
);
459 if (arg_cache
== NULL
)
462 res
= pygi_arg_glist_setup_from_info (arg_cache
,
471 pygi_arg_cache_free (arg_cache
);