Rename pyglib-python-compat.h to pygi-python-compat.h
[pygobject.git] / gi / pygi-array.c
blob9982acaf14fe9690a3365d94c1b2ce0d1275d131
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 <glib.h>
24 #include "pygi-python-compat.h"
25 #include "pygi-array.h"
26 #include "pygi-info.h"
27 #include "pygi-marshal-cleanup.h"
28 #include "pygi-basictype.h"
29 #include "pygi-util.h"
31 /* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */
32 #include "pygi-struct-marshal.h"
35 * GArray to Python
38 static gboolean
39 gi_argument_from_py_ssize_t (GIArgument *arg_out,
40 Py_ssize_t size_in,
41 GITypeTag type_tag)
43 switch (type_tag) {
44 case GI_TYPE_TAG_VOID:
45 case GI_TYPE_TAG_BOOLEAN:
46 goto unhandled_type;
48 case GI_TYPE_TAG_INT8:
49 if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
50 arg_out->v_int8 = size_in;
51 return TRUE;
52 } else {
53 goto overflow;
56 case GI_TYPE_TAG_UINT8:
57 if (size_in >= 0 && size_in <= G_MAXUINT8) {
58 arg_out->v_uint8 = size_in;
59 return TRUE;
60 } else {
61 goto overflow;
64 case GI_TYPE_TAG_INT16:
65 if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
66 arg_out->v_int16 = size_in;
67 return TRUE;
68 } else {
69 goto overflow;
72 case GI_TYPE_TAG_UINT16:
73 if (size_in >= 0 && size_in <= G_MAXUINT16) {
74 arg_out->v_uint16 = size_in;
75 return TRUE;
76 } else {
77 goto overflow;
80 /* Ranges assume two's complement */
81 case GI_TYPE_TAG_INT32:
82 if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
83 arg_out->v_int32 = size_in;
84 return TRUE;
85 } else {
86 goto overflow;
89 case GI_TYPE_TAG_UINT32:
90 if (size_in >= 0 && (gsize)size_in <= G_MAXUINT32) {
91 arg_out->v_uint32 = size_in;
92 return TRUE;
93 } else {
94 goto overflow;
97 case GI_TYPE_TAG_INT64:
98 arg_out->v_int64 = size_in;
99 return TRUE;
101 case GI_TYPE_TAG_UINT64:
102 if (size_in >= 0) {
103 arg_out->v_uint64 = size_in;
104 return TRUE;
105 } else {
106 goto overflow;
109 case GI_TYPE_TAG_FLOAT:
110 case GI_TYPE_TAG_DOUBLE:
111 case GI_TYPE_TAG_GTYPE:
112 case GI_TYPE_TAG_UTF8:
113 case GI_TYPE_TAG_FILENAME:
114 case GI_TYPE_TAG_ARRAY:
115 case GI_TYPE_TAG_INTERFACE:
116 case GI_TYPE_TAG_GLIST:
117 case GI_TYPE_TAG_GSLIST:
118 case GI_TYPE_TAG_GHASH:
119 case GI_TYPE_TAG_ERROR:
120 case GI_TYPE_TAG_UNICHAR:
121 default:
122 goto unhandled_type;
125 overflow:
126 PyErr_Format (PyExc_OverflowError,
127 "Unable to marshal C Py_ssize_t %zd to %s",
128 size_in,
129 g_type_tag_to_string (type_tag));
130 return FALSE;
132 unhandled_type:
133 PyErr_Format (PyExc_TypeError,
134 "Unable to marshal C Py_ssize_t %zd to %s",
135 size_in,
136 g_type_tag_to_string (type_tag));
137 return FALSE;
140 static gboolean
141 gi_argument_to_gsize (GIArgument *arg_in,
142 gsize *gsize_out,
143 GITypeTag type_tag)
145 switch (type_tag) {
146 case GI_TYPE_TAG_INT8:
147 *gsize_out = arg_in->v_int8;
148 return TRUE;
149 case GI_TYPE_TAG_UINT8:
150 *gsize_out = arg_in->v_uint8;
151 return TRUE;
152 case GI_TYPE_TAG_INT16:
153 *gsize_out = arg_in->v_int16;
154 return TRUE;
155 case GI_TYPE_TAG_UINT16:
156 *gsize_out = arg_in->v_uint16;
157 return TRUE;
158 case GI_TYPE_TAG_INT32:
159 *gsize_out = arg_in->v_int32;
160 return TRUE;
161 case GI_TYPE_TAG_UINT32:
162 *gsize_out = arg_in->v_uint32;
163 return TRUE;
164 case GI_TYPE_TAG_INT64:
165 *gsize_out = arg_in->v_int64;
166 return TRUE;
167 case GI_TYPE_TAG_UINT64:
168 *gsize_out = arg_in->v_uint64;
169 return TRUE;
170 default:
171 PyErr_Format (PyExc_TypeError,
172 "Unable to marshal %s to gsize",
173 g_type_tag_to_string (type_tag));
174 return FALSE;
178 static gboolean
179 _pygi_marshal_from_py_array (PyGIInvokeState *state,
180 PyGICallableCache *callable_cache,
181 PyGIArgCache *arg_cache,
182 PyObject *py_arg,
183 GIArgument *arg,
184 gpointer *cleanup_data)
186 PyGIMarshalFromPyFunc from_py_marshaller;
187 int i = 0;
188 gsize success_count = 0;
189 Py_ssize_t length;
190 gssize item_size;
191 gboolean is_ptr_array;
192 GArray *array_ = NULL;
193 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
194 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
195 GITransfer cleanup_transfer = arg_cache->transfer;
198 if (py_arg == Py_None) {
199 arg->v_pointer = NULL;
200 return TRUE;
203 if (!PySequence_Check (py_arg)) {
204 PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
205 py_arg->ob_type->tp_name);
206 return FALSE;
209 length = PySequence_Length (py_arg);
210 if (length < 0)
211 return FALSE;
213 if (array_cache->fixed_size >= 0 &&
214 array_cache->fixed_size != length) {
215 PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
216 array_cache->fixed_size, length);
218 return FALSE;
221 item_size = array_cache->item_size;
222 is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
223 if (is_ptr_array) {
224 array_ = (GArray *)g_ptr_array_sized_new (length);
225 } else {
226 array_ = g_array_sized_new (array_cache->is_zero_terminated,
227 TRUE,
228 item_size,
229 length);
232 if (array_ == NULL) {
233 PyErr_NoMemory ();
234 return FALSE;
237 if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
238 PYGLIB_PyBytes_Check (py_arg)) {
239 gchar *data = PYGLIB_PyBytes_AsString (py_arg);
241 /* Avoid making a copy if the data
242 * is not transferred to the C function
243 * and cannot not be modified by it.
245 if (array_cache->array_type == GI_ARRAY_TYPE_C &&
246 arg_cache->transfer == GI_TRANSFER_NOTHING &&
247 !array_cache->is_zero_terminated) {
248 g_free (array_->data);
249 array_->data = data;
250 cleanup_transfer = GI_TRANSFER_EVERYTHING;
251 } else {
252 memcpy (array_->data, data, length);
254 array_->len = length;
255 if (array_cache->is_zero_terminated) {
256 /* If array_ has been created with zero_termination, space for the
257 * terminator is properly allocated, so we're not off-by-one here. */
258 array_->data[length] = '\0';
260 goto array_success;
263 from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
264 for (i = 0, success_count = 0; i < length; i++) {
265 GIArgument item = {0};
266 gpointer item_cleanup_data = NULL;
267 PyObject *py_item = PySequence_GetItem (py_arg, i);
268 if (py_item == NULL)
269 goto err;
271 if (!from_py_marshaller ( state,
272 callable_cache,
273 sequence_cache->item_cache,
274 py_item,
275 &item,
276 &item_cleanup_data)) {
277 Py_DECREF (py_item);
278 goto err;
280 Py_DECREF (py_item);
282 if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
283 /* We only support one level of data discrepancy between an items
284 * data and its cleanup data. This is because we only track a single
285 * extra cleanup data pointer per-argument and cannot track the entire
286 * array of items differing data and cleanup_data.
287 * For example, this would fail if trying to marshal an array of
288 * callback closures marked with SCOPE call type where the cleanup data
289 * is different from the items v_pointer, likewise an array of arrays.
291 PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
292 "the items data its cleanup data being different.");
293 goto err;
296 /* FIXME: it is much more efficent to have seperate marshaller
297 * for ptr arrays than doing the evaluation
298 * and casting each loop iteration
300 if (is_ptr_array) {
301 g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
302 } else if (sequence_cache->item_cache->is_pointer) {
303 /* if the item is a pointer, simply copy the pointer */
304 g_assert (item_size == sizeof (item.v_pointer));
305 g_array_insert_val (array_, i, item);
306 } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
307 /* Special case handling of flat arrays of gvalue/boxed/struct */
308 PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
309 GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
310 GIInfoType info_type = g_base_info_get_type (base_info);
312 switch (info_type) {
313 case GI_INFO_TYPE_UNION:
314 case GI_INFO_TYPE_STRUCT:
316 PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
317 PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
319 if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
320 /* Special case GValue flat arrays to properly init and copy the contents. */
321 GValue* dest = (GValue*) (array_->data + (i * item_size));
322 if (item.v_pointer != NULL) {
323 memset (dest, 0, item_size);
324 g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
325 g_value_copy ((GValue*) item.v_pointer, dest);
327 /* Manually increment the length because we are manually setting the memory. */
328 array_->len++;
330 } else {
331 /* Handles flat arrays of boxed or struct types. */
332 g_array_insert_vals (array_, i, item.v_pointer, 1);
335 /* Cleanup any memory left by the per-item marshaler because
336 * _pygi_marshal_cleanup_from_py_array will not know about this
337 * due to "item" being a temporarily marshaled value done on the stack.
339 if (from_py_cleanup)
340 from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
342 break;
344 default:
345 g_array_insert_val (array_, i, item);
347 } else {
348 /* default value copy of a simple type */
349 g_array_insert_val (array_, i, item);
352 success_count++;
354 goto array_success;
356 err:
357 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
358 gsize j;
359 PyGIMarshalCleanupFunc cleanup_func =
360 sequence_cache->item_cache->from_py_cleanup;
362 /* Only attempt per item cleanup on pointer items */
363 if (sequence_cache->item_cache->is_pointer) {
364 for(j = 0; j < success_count; j++) {
365 PyObject *py_seq_item = PySequence_GetItem (py_arg, j);
366 cleanup_func (state,
367 sequence_cache->item_cache,
368 py_seq_item,
369 is_ptr_array ?
370 g_ptr_array_index ((GPtrArray *)array_, j) :
371 g_array_index (array_, gpointer, j),
372 TRUE);
373 Py_DECREF (py_seq_item);
378 if (is_ptr_array)
379 g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
380 else
381 g_array_free (array_, TRUE);
382 _PyGI_ERROR_PREFIX ("Item %i: ", i);
383 return FALSE;
385 array_success:
386 if (array_cache->len_arg_index >= 0) {
387 /* we have an child arg to handle */
388 PyGIArgCache *child_cache =
389 _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index);
391 if (!gi_argument_from_py_ssize_t (&state->args[child_cache->c_arg_index].arg_value,
392 length,
393 child_cache->type_tag)) {
394 goto err;
398 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
399 /* In the case of GI_ARRAY_C, we give the data directly as the argument
400 * but keep the array_ wrapper as cleanup data so we don't have to find
401 * it's length again.
403 arg->v_pointer = array_->data;
405 if (cleanup_transfer == GI_TRANSFER_EVERYTHING) {
406 g_array_free (array_, FALSE);
407 *cleanup_data = NULL;
408 } else {
409 *cleanup_data = array_;
411 } else {
412 arg->v_pointer = array_;
414 if (cleanup_transfer == GI_TRANSFER_NOTHING) {
415 /* Free everything in cleanup. */
416 *cleanup_data = array_;
417 } else if (cleanup_transfer == GI_TRANSFER_CONTAINER) {
418 /* Make a shallow copy so we can free the elements later in cleanup
419 * because it is possible invoke will free the list before our cleanup. */
420 *cleanup_data = is_ptr_array ?
421 (gpointer)g_ptr_array_ref ((GPtrArray *)array_) :
422 (gpointer)g_array_ref (array_);
423 } else { /* GI_TRANSFER_EVERYTHING */
424 /* No cleanup, everything is given to the callee. */
425 *cleanup_data = NULL;
429 return TRUE;
432 static void
433 _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
434 PyGIArgCache *arg_cache,
435 PyObject *py_arg,
436 gpointer data,
437 gboolean was_processed)
439 if (was_processed) {
440 GArray *array_ = NULL;
441 GPtrArray *ptr_array_ = NULL;
442 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
443 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
445 if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
446 ptr_array_ = (GPtrArray *) data;
447 } else {
448 array_ = (GArray *) data;
451 /* clean up items first */
452 if (sequence_cache->item_cache->from_py_cleanup != NULL) {
453 gsize i;
454 guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
455 PyGIMarshalCleanupFunc cleanup_func =
456 sequence_cache->item_cache->from_py_cleanup;
458 for (i = 0; i < len; i++) {
459 gpointer item;
460 PyObject *py_item = NULL;
462 /* case 1: GPtrArray */
463 if (ptr_array_ != NULL)
464 item = g_ptr_array_index (ptr_array_, i);
465 /* case 2: C array or GArray with object pointers */
466 else if (sequence_cache->item_cache->is_pointer)
467 item = g_array_index (array_, gpointer, i);
468 /* case 3: C array or GArray with simple types or structs */
469 else {
470 item = array_->data + i * array_cache->item_size;
471 /* special-case hack: GValue array items do not get slice
472 * allocated in _pygi_marshal_from_py_array(), so we must
473 * not try to deallocate it as a slice and thus
474 * short-circuit cleanup_func. */
475 if (cleanup_func == pygi_arg_gvalue_from_py_cleanup) {
476 g_value_unset ((GValue*) item);
477 continue;
481 py_item = PySequence_GetItem (py_arg, i);
482 cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE);
483 Py_XDECREF (py_item);
487 /* Only free the array when we didn't transfer ownership */
488 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
489 /* always free the GArray wrapper created in from_py marshaling and
490 * passed back as cleanup_data
492 g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
493 } else {
494 if (array_ != NULL)
495 g_array_unref (array_);
496 else
497 g_ptr_array_unref (ptr_array_);
503 * GArray from Python
505 static PyObject *
506 _pygi_marshal_to_py_array (PyGIInvokeState *state,
507 PyGICallableCache *callable_cache,
508 PyGIArgCache *arg_cache,
509 GIArgument *arg,
510 gpointer *cleanup_data)
512 GArray *array_;
513 PyObject *py_obj = NULL;
514 PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
515 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
516 gsize processed_items = 0;
518 /* GArrays make it easier to iterate over arrays
519 * with different element sizes but requires that
520 * we allocate a GArray if the argument was a C array
522 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
523 gsize len;
524 if (array_cache->fixed_size >= 0) {
525 g_assert(arg->v_pointer != NULL);
526 len = array_cache->fixed_size;
527 } else if (array_cache->is_zero_terminated) {
528 if (arg->v_pointer == NULL) {
529 len = 0;
530 } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
531 len = strlen (arg->v_pointer);
532 } else {
533 len = g_strv_length ((gchar **)arg->v_pointer);
535 } else {
536 GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
537 PyGIArgCache *sub_cache = _pygi_callable_cache_get_arg (callable_cache,
538 array_cache->len_arg_index);
540 if (!gi_argument_to_gsize (len_arg, &len, sub_cache->type_tag)) {
541 return NULL;
545 array_ = g_array_new (FALSE,
546 FALSE,
547 array_cache->item_size);
548 if (array_ == NULL) {
549 PyErr_NoMemory ();
551 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL)
552 g_free (arg->v_pointer);
554 return NULL;
557 if (array_->data != NULL)
558 g_free (array_->data);
559 array_->data = arg->v_pointer;
560 array_->len = len;
561 } else {
562 array_ = arg->v_pointer;
565 if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
566 if (arg->v_pointer == NULL) {
567 py_obj = PYGLIB_PyBytes_FromString ("");
568 } else {
569 py_obj = PYGLIB_PyBytes_FromStringAndSize (array_->data, array_->len);
571 } else {
572 if (arg->v_pointer == NULL) {
573 py_obj = PyList_New (0);
574 } else {
575 guint i;
577 gsize item_size;
578 PyGIMarshalToPyFunc item_to_py_marshaller;
579 PyGIArgCache *item_arg_cache;
580 GPtrArray *item_cleanups;
582 py_obj = PyList_New (array_->len);
583 if (py_obj == NULL)
584 goto err;
586 item_cleanups = g_ptr_array_sized_new (array_->len);
587 *cleanup_data = item_cleanups;
589 item_arg_cache = seq_cache->item_cache;
590 item_to_py_marshaller = item_arg_cache->to_py_marshaller;
592 item_size = g_array_get_element_size (array_);
594 for (i = 0; i < array_->len; i++) {
595 GIArgument item_arg = {0};
596 PyObject *py_item;
597 gpointer item_cleanup_data = NULL;
599 /* If we are receiving an array of pointers, simply assign the pointer
600 * and move on, letting the per-item marshaler deal with the
601 * various transfer modes and ref counts (e.g. g_variant_ref_sink).
603 if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
604 item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
606 } else if (item_arg_cache->is_pointer) {
607 item_arg.v_pointer = g_array_index (array_, gpointer, i);
609 } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
610 PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
612 /* FIXME: This probably doesn't work with boxed types or gvalues.
613 * See fx. _pygi_marshal_from_py_array() */
614 switch (g_base_info_get_type (iface_cache->interface_info)) {
615 case GI_INFO_TYPE_STRUCT:
616 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
617 !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
618 /* array elements are structs */
619 gpointer *_struct = g_malloc (item_size);
620 memcpy (_struct, array_->data + i * item_size,
621 item_size);
622 item_arg.v_pointer = _struct;
623 } else {
624 item_arg.v_pointer = array_->data + i * item_size;
626 break;
627 case GI_INFO_TYPE_ENUM:
628 memcpy (&item_arg, array_->data + i * item_size, item_size);
629 break;
630 default:
631 item_arg.v_pointer = g_array_index (array_, gpointer, i);
632 break;
634 } else {
635 memcpy (&item_arg, array_->data + i * item_size, item_size);
638 py_item = item_to_py_marshaller ( state,
639 callable_cache,
640 item_arg_cache,
641 &item_arg,
642 &item_cleanup_data);
644 g_ptr_array_index (item_cleanups, i) = item_cleanup_data;
646 if (py_item == NULL) {
647 Py_CLEAR (py_obj);
649 if (array_cache->array_type == GI_ARRAY_TYPE_C)
650 g_array_unref (array_);
652 g_ptr_array_unref (item_cleanups);
654 goto err;
656 PyList_SET_ITEM (py_obj, i, py_item);
657 processed_items++;
662 if (array_cache->array_type == GI_ARRAY_TYPE_C)
663 g_array_free (array_, FALSE);
665 return py_obj;
667 err:
668 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
669 g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
670 } else {
671 /* clean up unprocessed items */
672 if (seq_cache->item_cache->to_py_cleanup != NULL) {
673 guint j;
674 PyGIMarshalToPyCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
675 for (j = processed_items; j < array_->len; j++) {
676 cleanup_func (state,
677 seq_cache->item_cache,
678 NULL,
679 g_array_index (array_, gpointer, j),
680 FALSE);
684 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
685 g_array_free (array_, TRUE);
688 return NULL;
691 static GArray*
692 _wrap_c_array (PyGIInvokeState *state,
693 PyGIArgGArray *array_cache,
694 gpointer data)
696 GArray *array_;
697 gsize len = 0;
699 if (array_cache->fixed_size >= 0) {
700 len = array_cache->fixed_size;
701 } else if (array_cache->is_zero_terminated) {
702 len = g_strv_length ((gchar **)data);
703 } else if (array_cache->len_arg_index >= 0) {
704 GIArgument *len_arg = &state->args[array_cache->len_arg_index].arg_value;
705 len = len_arg->v_long;
708 array_ = g_array_new (FALSE,
709 FALSE,
710 array_cache->item_size);
712 if (array_ == NULL)
713 return NULL;
715 g_free (array_->data);
716 array_->data = data;
717 array_->len = len;
719 return array_;
722 static void
723 _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
724 PyGIArgCache *arg_cache,
725 gpointer cleanup_data,
726 gpointer data,
727 gboolean was_processed)
729 GArray *array_ = NULL;
730 GPtrArray *ptr_array_ = NULL;
731 PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
732 PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
733 gboolean free_array = FALSE;
734 gboolean free_array_full = TRUE;
736 if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
737 arg_cache->transfer == GI_TRANSFER_CONTAINER) {
738 free_array = TRUE;
741 /* If this isn't a garray create one to help process variable sized
742 array elements */
743 if (array_cache->array_type == GI_ARRAY_TYPE_C) {
744 array_ = _wrap_c_array (state, array_cache, data);
746 if (array_ == NULL)
747 return;
749 free_array = TRUE;
750 free_array_full = FALSE;
751 } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
752 ptr_array_ = (GPtrArray *) data;
753 } else {
754 array_ = (GArray *) data;
757 if (sequence_cache->item_cache->to_py_cleanup != NULL) {
758 GPtrArray *item_cleanups = (GPtrArray *) cleanup_data;
759 gsize i;
760 guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
762 PyGIMarshalToPyCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
763 for (i = 0; i < len; i++) {
764 cleanup_func (state,
765 sequence_cache->item_cache,
766 g_ptr_array_index(item_cleanups, i),
767 (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
768 was_processed);
770 g_ptr_array_unref (item_cleanups);
773 if (free_array) {
774 if (array_ != NULL)
775 g_array_free (array_, free_array_full);
776 else
777 g_ptr_array_free (ptr_array_, free_array_full);
781 static void
782 _array_cache_free_func (PyGIArgGArray *cache)
784 if (cache != NULL) {
785 pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
786 g_slice_free (PyGIArgGArray, cache);
790 PyGIArgCache*
791 pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache,
792 GITypeInfo *type_info,
793 PyGICallableCache *callable_cache,
794 PyGIDirection direction,
795 gssize arg_index,
796 gssize *py_arg_index)
798 PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
800 /* attempt len_arg_index setup for the first time */
801 if (seq_cache->len_arg_index < 0) {
802 seq_cache->len_arg_index = g_type_info_get_array_length (type_info);
804 /* offset by self arg for methods and vfuncs */
805 if (seq_cache->len_arg_index >= 0 && callable_cache != NULL) {
806 seq_cache->len_arg_index += callable_cache->args_offset;
810 if (seq_cache->len_arg_index >= 0) {
811 PyGIArgCache *child_cache = NULL;
813 child_cache = _pygi_callable_cache_get_arg (callable_cache,
814 seq_cache->len_arg_index);
815 if (child_cache == NULL) {
816 child_cache = pygi_arg_cache_alloc ();
817 } else {
818 /* If the "length" arg cache already exists (the length comes before
819 * the array in the argument list), remove it from the to_py_args list
820 * because it does not belong in "to python" return tuple. The length
821 * will implicitly be a part of the returned Python list.
823 if (direction & PYGI_DIRECTION_TO_PYTHON) {
824 callable_cache->to_py_args =
825 g_slist_remove (callable_cache->to_py_args, child_cache);
828 /* This is a case where the arg cache already exists and has been
829 * setup by another array argument sharing the same length argument.
830 * See: gi_marshalling_tests_multi_array_key_value_in
832 if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
833 return child_cache;
836 /* There is a length argument for this array, so increment the number
837 * of "to python" child arguments when applicable.
839 if (direction & PYGI_DIRECTION_TO_PYTHON)
840 callable_cache->n_to_py_child_args++;
842 child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
843 child_cache->direction = direction;
844 child_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
845 child_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
846 child_cache->py_arg_index = -1;
848 /* ugly edge case code:
850 * When the length comes before the array parameter we need to update
851 * indexes of arguments after the index argument.
853 if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
854 gssize i;
855 (*py_arg_index) -= 1;
856 callable_cache->n_py_args -= 1;
858 for (i = seq_cache->len_arg_index + 1;
859 (gsize)i < _pygi_callable_cache_args_len (callable_cache); i++) {
860 PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
861 if (update_cache == NULL)
862 break;
864 update_cache->py_arg_index -= 1;
868 _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
869 return child_cache;
872 return NULL;
875 static gboolean
876 pygi_arg_garray_setup (PyGIArgGArray *sc,
877 GITypeInfo *type_info,
878 GIArgInfo *arg_info, /* may be NULL for return arguments */
879 GITransfer transfer,
880 PyGIDirection direction,
881 PyGICallableCache *callable_cache)
883 GITypeInfo *item_type_info;
884 PyGIArgCache *arg_cache = (PyGIArgCache *)sc;
886 if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
887 type_info,
888 arg_info,
889 transfer,
890 direction,
891 callable_cache)) {
892 return FALSE;
895 ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
896 sc->array_type = g_type_info_get_array_type (type_info);
897 sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
898 sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
899 sc->len_arg_index = -1; /* setup by pygi_arg_garray_len_arg_setup */
901 item_type_info = g_type_info_get_param_type (type_info, 0);
902 sc->item_size = _pygi_g_type_info_size (item_type_info);
903 g_base_info_unref ( (GIBaseInfo *)item_type_info);
905 if (direction & PYGI_DIRECTION_FROM_PYTHON) {
906 arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
907 arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
910 if (direction & PYGI_DIRECTION_TO_PYTHON) {
911 arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
912 arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
915 return TRUE;
918 PyGIArgCache *
919 pygi_arg_garray_new_from_info (GITypeInfo *type_info,
920 GIArgInfo *arg_info,
921 GITransfer transfer,
922 PyGIDirection direction,
923 PyGICallableCache *callable_cache)
925 PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
926 if (array_cache == NULL)
927 return NULL;
929 if (!pygi_arg_garray_setup (array_cache,
930 type_info,
931 arg_info,
932 transfer,
933 direction,
934 callable_cache)) {
935 pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
936 return NULL;
939 return (PyGIArgCache *)array_cache;