Imported Upstream version 3.13.92
[platform/upstream/python-gobject.git] / gi / pygi-array.c
1 /* -*- Mode: C; c-basic-offset: 4 -*-
2  * vim: tabstop=4 shiftwidth=4 expandtab
3  *
4  * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
5  * Copyright (C) 2014 Simon Feltman <sfeltman@gnome.org>
6  *
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.
11  *
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.
16  *
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/>.
19  */
20
21 #include <glib.h>
22 #include <Python.h>
23 #include <pyglib-python-compat.h>
24
25 #include "pygi-array.h"
26 #include "pygi-private.h"
27 #include "pygi-marshal-cleanup.h"
28 #include "pygi-basictype.h"
29
30 /* Needed for _pygi_marshal_cleanup_from_py_interface_struct_gvalue hack */
31 #include "pygi-struct-marshal.h"
32
33 /*
34  * GArray to Python
35  */
36
37 static gboolean
38 gi_argument_from_py_ssize_t (GIArgument   *arg_out,
39                              Py_ssize_t    size_in,
40                              GITypeTag     type_tag)
41 {
42     switch (type_tag) {
43     case GI_TYPE_TAG_VOID:
44     case GI_TYPE_TAG_BOOLEAN:
45         goto unhandled_type;
46
47     case GI_TYPE_TAG_INT8:
48         if (size_in >= G_MININT8 && size_in <= G_MAXINT8) {
49             arg_out->v_int8 = size_in;
50             return TRUE;
51         } else {
52             goto overflow;
53         }
54
55     case GI_TYPE_TAG_UINT8:
56         if (size_in >= 0 && size_in <= G_MAXUINT8) {
57             arg_out->v_uint8 = size_in;
58             return TRUE;
59         } else {
60             goto overflow;
61         }
62
63     case GI_TYPE_TAG_INT16:
64         if (size_in >= G_MININT16 && size_in <= G_MAXINT16) {
65             arg_out->v_int16 = size_in;
66             return TRUE;
67         } else {
68             goto overflow;
69         }
70
71     case GI_TYPE_TAG_UINT16:
72         if (size_in >= 0 && size_in <= G_MAXUINT16) {
73             arg_out->v_uint16 = size_in;
74             return TRUE;
75         } else {
76             goto overflow;
77         }
78
79         /* Ranges assume two's complement */
80     case GI_TYPE_TAG_INT32:
81         if (size_in >= G_MININT32 && size_in <= G_MAXINT32) {
82             arg_out->v_int32 = size_in;
83             return TRUE;
84         } else {
85             goto overflow;
86         }
87
88     case GI_TYPE_TAG_UINT32:
89         if (size_in >= 0 && size_in <= G_MAXUINT32) {
90             arg_out->v_uint32 = size_in;
91             return TRUE;
92         } else {
93             goto overflow;
94         }
95
96     case GI_TYPE_TAG_INT64:
97         arg_out->v_int64 = size_in;
98         return TRUE;
99
100     case GI_TYPE_TAG_UINT64:
101         if (size_in >= 0) {
102             arg_out->v_uint64 = size_in;
103             return TRUE;
104         } else {
105             goto overflow;
106         }
107
108     case GI_TYPE_TAG_FLOAT:
109     case GI_TYPE_TAG_DOUBLE:
110     case GI_TYPE_TAG_GTYPE:
111     case GI_TYPE_TAG_UTF8:
112     case GI_TYPE_TAG_FILENAME:
113     case GI_TYPE_TAG_ARRAY:
114     case GI_TYPE_TAG_INTERFACE:
115     case GI_TYPE_TAG_GLIST:
116     case GI_TYPE_TAG_GSLIST:
117     case GI_TYPE_TAG_GHASH:
118     case GI_TYPE_TAG_ERROR:
119     case GI_TYPE_TAG_UNICHAR:
120     default:
121         goto unhandled_type;
122     }
123
124  overflow:
125     PyErr_Format (PyExc_OverflowError,
126                   "Unable to marshal C Py_ssize_t %zd to %s",
127                   size_in,
128                   g_type_tag_to_string (type_tag));
129     return FALSE;
130
131  unhandled_type:
132     PyErr_Format (PyExc_TypeError,
133                   "Unable to marshal C Py_ssize_t %zd to %s",
134                   size_in,
135                   g_type_tag_to_string (type_tag));
136     return FALSE;
137 }
138
139 static gboolean
140 gi_argument_to_gsize (GIArgument *arg_in,
141                       gsize      *gsize_out,
142                       GITypeTag   type_tag)
143 {
144     switch (type_tag) {
145       case GI_TYPE_TAG_INT8:
146           *gsize_out = arg_in->v_int8;
147           return TRUE;
148       case GI_TYPE_TAG_UINT8:
149           *gsize_out = arg_in->v_uint8;
150           return TRUE;
151       case GI_TYPE_TAG_INT16:
152           *gsize_out = arg_in->v_int16;
153           return TRUE;
154       case GI_TYPE_TAG_UINT16:
155           *gsize_out = arg_in->v_uint16;
156           return TRUE;
157       case GI_TYPE_TAG_INT32:
158           *gsize_out = arg_in->v_int32;
159           return TRUE;
160       case GI_TYPE_TAG_UINT32:
161           *gsize_out = arg_in->v_uint32;
162           return TRUE;
163       case GI_TYPE_TAG_INT64:
164           *gsize_out = arg_in->v_int64;
165           return TRUE;
166       case GI_TYPE_TAG_UINT64:
167           *gsize_out = arg_in->v_uint64;
168           return TRUE;
169       default:
170           PyErr_Format (PyExc_TypeError,
171                         "Unable to marshal %s to gsize",
172                         g_type_tag_to_string (type_tag));
173           return FALSE;
174     }
175 }
176
177 static gboolean
178 _pygi_marshal_from_py_array (PyGIInvokeState   *state,
179                              PyGICallableCache *callable_cache,
180                              PyGIArgCache      *arg_cache,
181                              PyObject          *py_arg,
182                              GIArgument        *arg,
183                              gpointer          *cleanup_data)
184 {
185     PyGIMarshalFromPyFunc from_py_marshaller;
186     int i = 0;
187     int success_count = 0;
188     Py_ssize_t length;
189     gssize item_size;
190     gboolean is_ptr_array;
191     GArray *array_ = NULL;
192     PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
193     PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
194
195
196     if (py_arg == Py_None) {
197         arg->v_pointer = NULL;
198         return TRUE;
199     }
200
201     if (!PySequence_Check (py_arg)) {
202         PyErr_Format (PyExc_TypeError, "Must be sequence, not %s",
203                       py_arg->ob_type->tp_name);
204         return FALSE;
205     }
206
207     length = PySequence_Length (py_arg);
208     if (length < 0)
209         return FALSE;
210
211     if (array_cache->fixed_size >= 0 &&
212             array_cache->fixed_size != length) {
213         PyErr_Format (PyExc_ValueError, "Must contain %zd items, not %zd",
214                       array_cache->fixed_size, length);
215
216         return FALSE;
217     }
218
219     item_size = array_cache->item_size;
220     is_ptr_array = (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY);
221     if (is_ptr_array) {
222         array_ = (GArray *)g_ptr_array_sized_new (length);
223     } else {
224         array_ = g_array_sized_new (array_cache->is_zero_terminated,
225                                     TRUE,
226                                     item_size,
227                                     length);
228     }
229
230     if (array_ == NULL) {
231         PyErr_NoMemory ();
232         return FALSE;
233     }
234
235     if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8 &&
236         PYGLIB_PyBytes_Check (py_arg)) {
237         memcpy(array_->data, PYGLIB_PyBytes_AsString (py_arg), length);
238         array_->len = length;
239         if (array_cache->is_zero_terminated) {
240             /* If array_ has been created with zero_termination, space for the
241              * terminator is properly allocated, so we're not off-by-one here. */
242             array_->data[length] = '\0';
243         }
244         goto array_success;
245     }
246
247     from_py_marshaller = sequence_cache->item_cache->from_py_marshaller;
248     for (i = 0, success_count = 0; i < length; i++) {
249         GIArgument item = {0};
250         gpointer item_cleanup_data = NULL;
251         PyObject *py_item = PySequence_GetItem (py_arg, i);
252         if (py_item == NULL)
253             goto err;
254
255         if (!from_py_marshaller ( state,
256                                   callable_cache,
257                                   sequence_cache->item_cache,
258                                   py_item,
259                                  &item,
260                                  &item_cleanup_data)) {
261             Py_DECREF (py_item);
262             goto err;
263         }
264         Py_DECREF (py_item);
265
266         if (item_cleanup_data != NULL && item_cleanup_data != item.v_pointer) {
267             /* We only support one level of data discrepancy between an items
268              * data and its cleanup data. This is because we only track a single
269              * extra cleanup data pointer per-argument and cannot track the entire
270              * array of items differing data and cleanup_data.
271              * For example, this would fail if trying to marshal an array of
272              * callback closures marked with SCOPE call type where the cleanup data
273              * is different from the items v_pointer, likewise an array of arrays.
274              */
275             PyErr_SetString(PyExc_RuntimeError, "Cannot cleanup item data for array due to "
276                                                 "the items data its cleanup data being different.");
277             goto err;
278         }
279
280         /* FIXME: it is much more efficent to have seperate marshaller
281          *        for ptr arrays than doing the evaluation
282          *        and casting each loop iteration
283          */
284         if (is_ptr_array) {
285             g_ptr_array_add((GPtrArray *)array_, item.v_pointer);
286         } else if (sequence_cache->item_cache->is_pointer) {
287             /* if the item is a pointer, simply copy the pointer */
288             g_assert (item_size == sizeof (item.v_pointer));
289             g_array_insert_val (array_, i, item);
290         } else if (sequence_cache->item_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
291             /* Special case handling of flat arrays of gvalue/boxed/struct */
292             PyGIInterfaceCache *item_iface_cache = (PyGIInterfaceCache *) sequence_cache->item_cache;
293             GIBaseInfo *base_info = (GIBaseInfo *) item_iface_cache->interface_info;
294             GIInfoType info_type = g_base_info_get_type (base_info);
295
296             switch (info_type) {
297                 case GI_INFO_TYPE_UNION:
298                 case GI_INFO_TYPE_STRUCT:
299                 {
300                     PyGIArgCache *item_arg_cache = (PyGIArgCache *)item_iface_cache;
301                     PyGIMarshalCleanupFunc from_py_cleanup = item_arg_cache->from_py_cleanup;
302
303                     if (g_type_is_a (item_iface_cache->g_type, G_TYPE_VALUE)) {
304                         /* Special case GValue flat arrays to properly init and copy the contents. */
305                         GValue* dest = (GValue*) (array_->data + (i * item_size));
306                         if (item.v_pointer != NULL) {
307                             memset (dest, 0, item_size);
308                             g_value_init (dest, G_VALUE_TYPE ((GValue*) item.v_pointer));
309                             g_value_copy ((GValue*) item.v_pointer, dest);
310                         }
311                         /* Manually increment the length because we are manually setting the memory. */
312                         array_->len++;
313
314                     } else {
315                         /* Handles flat arrays of boxed or struct types. */
316                         g_array_insert_vals (array_, i, item.v_pointer, 1);
317                     }
318
319                     /* Cleanup any memory left by the per-item marshaler because
320                      * _pygi_marshal_cleanup_from_py_array will not know about this
321                      * due to "item" being a temporarily marshaled value done on the stack.
322                      */
323                     if (from_py_cleanup)
324                         from_py_cleanup (state, item_arg_cache, py_item, item_cleanup_data, TRUE);
325
326                     break;
327                 }
328                 default:
329                     g_array_insert_val (array_, i, item);
330             }
331         } else {
332             /* default value copy of a simple type */
333             g_array_insert_val (array_, i, item);
334         }
335
336         success_count++;
337         continue;
338 err:
339         if (sequence_cache->item_cache->from_py_cleanup != NULL) {
340             gsize j;
341             PyGIMarshalCleanupFunc cleanup_func =
342                 sequence_cache->item_cache->from_py_cleanup;
343
344             /* Only attempt per item cleanup on pointer items */
345             if (sequence_cache->item_cache->is_pointer) {
346                 for(j = 0; j < success_count; j++) {
347                     PyObject *py_item = PySequence_GetItem (py_arg, j);
348                     cleanup_func (state,
349                                   sequence_cache->item_cache,
350                                   py_item,
351                                   is_ptr_array ?
352                                           g_ptr_array_index ((GPtrArray *)array_, j) :
353                                           g_array_index (array_, gpointer, j),
354                                   TRUE);
355                     Py_DECREF (py_item);
356                 }
357             }
358         }
359
360         if (is_ptr_array)
361             g_ptr_array_free ( ( GPtrArray *)array_, TRUE);
362         else
363             g_array_free (array_, TRUE);
364         _PyGI_ERROR_PREFIX ("Item %i: ", i);
365         return FALSE;
366     }
367
368 array_success:
369     if (array_cache->len_arg_index >= 0) {
370         /* we have an child arg to handle */
371         PyGIArgCache *child_cache =
372             _pygi_callable_cache_get_arg (callable_cache, array_cache->len_arg_index);
373
374         if (!gi_argument_from_py_ssize_t (&state->arg_values[child_cache->c_arg_index],
375                                           length,
376                                           child_cache->type_tag)) {
377             goto err;
378         }
379     }
380
381     if (array_cache->array_type == GI_ARRAY_TYPE_C) {
382         /* In the case of GI_ARRAY_C, we give the data directly as the argument
383          * but keep the array_ wrapper as cleanup data so we don't have to find
384          * it's length again.
385          */
386         arg->v_pointer = array_->data;
387
388         if (arg_cache->transfer == GI_TRANSFER_EVERYTHING) {
389             g_array_free (array_, FALSE);
390             *cleanup_data = NULL;
391         } else {
392             *cleanup_data = array_;
393         }
394     } else {
395         arg->v_pointer = array_;
396
397         if (arg_cache->transfer == GI_TRANSFER_NOTHING) {
398             /* Free everything in cleanup. */
399             *cleanup_data = array_;
400         } else if (arg_cache->transfer == GI_TRANSFER_CONTAINER) {
401             /* Make a shallow copy so we can free the elements later in cleanup
402              * because it is possible invoke will free the list before our cleanup. */
403             *cleanup_data = is_ptr_array ?
404                     (gpointer)g_ptr_array_ref ((GPtrArray *)array_) :
405                     (gpointer)g_array_ref (array_);
406         } else { /* GI_TRANSFER_EVERYTHING */
407             /* No cleanup, everything is given to the callee. */
408             *cleanup_data = NULL;
409         }
410     }
411
412     return TRUE;
413 }
414
415 static void
416 _pygi_marshal_cleanup_from_py_array (PyGIInvokeState *state,
417                                      PyGIArgCache    *arg_cache,
418                                      PyObject        *py_arg,
419                                      gpointer         data,
420                                      gboolean         was_processed)
421 {
422     if (was_processed) {
423         GArray *array_ = NULL;
424         GPtrArray *ptr_array_ = NULL;
425         PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
426         PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
427
428         if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
429             ptr_array_ = (GPtrArray *) data;
430         } else {
431             array_ = (GArray *) data;
432         }
433
434         /* clean up items first */
435         if (sequence_cache->item_cache->from_py_cleanup != NULL) {
436             gsize i;
437             guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
438             PyGIMarshalCleanupFunc cleanup_func =
439                 sequence_cache->item_cache->from_py_cleanup;
440
441             for (i = 0; i < len; i++) {
442                 gpointer item;
443                 PyObject *py_item = NULL;
444
445                 /* case 1: GPtrArray */
446                 if (ptr_array_ != NULL)
447                     item = g_ptr_array_index (ptr_array_, i);
448                 /* case 2: C array or GArray with object pointers */
449                 else if (sequence_cache->item_cache->is_pointer)
450                     item = g_array_index (array_, gpointer, i);
451                 /* case 3: C array or GArray with simple types or structs */
452                 else {
453                     item = array_->data + i * array_cache->item_size;
454                     /* special-case hack: GValue array items do not get slice
455                      * allocated in _pygi_marshal_from_py_array(), so we must
456                      * not try to deallocate it as a slice and thus
457                      * short-circuit cleanup_func. */
458                     if (cleanup_func == pygi_arg_gvalue_from_py_cleanup) {
459                         g_value_unset ((GValue*) item);
460                         continue;
461                     }
462                 }
463
464                 py_item = PySequence_GetItem (py_arg, i);
465                 cleanup_func (state, sequence_cache->item_cache, py_item, item, TRUE);
466                 Py_XDECREF (py_item);
467             }
468         }
469
470         /* Only free the array when we didn't transfer ownership */
471         if (array_cache->array_type == GI_ARRAY_TYPE_C) {
472             /* always free the GArray wrapper created in from_py marshaling and
473              * passed back as cleanup_data
474              */
475             g_array_free (array_, arg_cache->transfer == GI_TRANSFER_NOTHING);
476         } else {
477             if (array_ != NULL)
478                 g_array_unref (array_);
479             else
480                 g_ptr_array_unref (ptr_array_);
481         }
482     }
483 }
484
485 /*
486  * GArray from Python
487  */
488 static PyObject *
489 _pygi_marshal_to_py_array (PyGIInvokeState   *state,
490                            PyGICallableCache *callable_cache,
491                            PyGIArgCache      *arg_cache,
492                            GIArgument        *arg)
493 {
494     GArray *array_;
495     PyObject *py_obj = NULL;
496     PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
497     PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
498     gsize processed_items = 0;
499
500      /* GArrays make it easier to iterate over arrays
501       * with different element sizes but requires that
502       * we allocate a GArray if the argument was a C array
503       */
504     if (array_cache->array_type == GI_ARRAY_TYPE_C) {
505         gsize len;
506         if (array_cache->fixed_size >= 0) {
507             g_assert(arg->v_pointer != NULL);
508             len = array_cache->fixed_size;
509         } else if (array_cache->is_zero_terminated) {
510             if (arg->v_pointer == NULL) {
511                 len = 0;
512             } else if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
513                 len = strlen (arg->v_pointer);
514             } else {
515                 len = g_strv_length ((gchar **)arg->v_pointer);
516             }
517         } else {
518             GIArgument *len_arg = &state->arg_values[array_cache->len_arg_index];
519             PyGIArgCache *arg_cache = _pygi_callable_cache_get_arg (callable_cache,
520                                                                     array_cache->len_arg_index);
521
522             if (!gi_argument_to_gsize (len_arg, &len, arg_cache->type_tag)) {
523                 return NULL;
524             }
525         }
526
527         array_ = g_array_new (FALSE,
528                               FALSE,
529                               array_cache->item_size);
530         if (array_ == NULL) {
531             PyErr_NoMemory ();
532
533             if (arg_cache->transfer == GI_TRANSFER_EVERYTHING && arg->v_pointer != NULL)
534                 g_free (arg->v_pointer);
535
536             return NULL;
537         }
538
539         if (array_->data != NULL)
540             g_free (array_->data);
541         array_->data = arg->v_pointer;
542         array_->len = len;
543     } else {
544         array_ = arg->v_pointer;
545     }
546
547     if (seq_cache->item_cache->type_tag == GI_TYPE_TAG_UINT8) {
548         if (arg->v_pointer == NULL) {
549             py_obj = PYGLIB_PyBytes_FromString ("");
550         } else {
551             py_obj = PYGLIB_PyBytes_FromStringAndSize (array_->data, array_->len);
552         }
553     } else {
554         if (arg->v_pointer == NULL) {
555             py_obj = PyList_New (0);
556         } else {
557             int i;
558
559             gsize item_size;
560             PyGIMarshalToPyFunc item_to_py_marshaller;
561             PyGIArgCache *item_arg_cache;
562
563             py_obj = PyList_New (array_->len);
564             if (py_obj == NULL)
565                 goto err;
566
567
568             item_arg_cache = seq_cache->item_cache;
569             item_to_py_marshaller = item_arg_cache->to_py_marshaller;
570
571             item_size = g_array_get_element_size (array_);
572
573             for (i = 0; i < array_->len; i++) {
574                 GIArgument item_arg = {0};
575                 PyObject *py_item;
576
577                 /* If we are receiving an array of pointers, simply assign the pointer
578                  * and move on, letting the per-item marshaler deal with the
579                  * various transfer modes and ref counts (e.g. g_variant_ref_sink).
580                  */
581                 if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
582                     item_arg.v_pointer = g_ptr_array_index ( ( GPtrArray *)array_, i);
583
584                 } else if (item_arg_cache->is_pointer) {
585                     item_arg.v_pointer = g_array_index (array_, gpointer, i);
586
587                 } else if (item_arg_cache->type_tag == GI_TYPE_TAG_INTERFACE) {
588                     PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *) item_arg_cache;
589
590                     /* FIXME: This probably doesn't work with boxed types or gvalues.
591                      * See fx. _pygi_marshal_from_py_array() */
592                     switch (g_base_info_get_type (iface_cache->interface_info)) {
593                         case GI_INFO_TYPE_STRUCT:
594                             if (arg_cache->transfer == GI_TRANSFER_EVERYTHING &&
595                                        !g_type_is_a (iface_cache->g_type, G_TYPE_BOXED)) {
596                                 /* array elements are structs */
597                                 gpointer *_struct = g_malloc (item_size);
598                                 memcpy (_struct, array_->data + i * item_size,
599                                         item_size);
600                                 item_arg.v_pointer = _struct;
601                             } else {
602                                 item_arg.v_pointer = array_->data + i * item_size;
603                             }
604                             break;
605                         default:
606                             item_arg.v_pointer = g_array_index (array_, gpointer, i);
607                             break;
608                     }
609                 } else {
610                     memcpy (&item_arg, array_->data + i * item_size, item_size);
611                 }
612
613                 py_item = item_to_py_marshaller ( state,
614                                                 callable_cache,
615                                                 item_arg_cache,
616                                                 &item_arg);
617
618                 if (py_item == NULL) {
619                     Py_CLEAR (py_obj);
620
621                     if (array_cache->array_type == GI_ARRAY_TYPE_C)
622                         g_array_unref (array_);
623
624                     goto err;
625                 }
626                 PyList_SET_ITEM (py_obj, i, py_item);
627                 processed_items++;
628             }
629         }
630     }
631
632     if (array_cache->array_type == GI_ARRAY_TYPE_C)
633         g_array_free (array_, FALSE);
634
635     return py_obj;
636
637 err:
638     if (array_cache->array_type == GI_ARRAY_TYPE_C) {
639         g_array_free (array_, arg_cache->transfer == GI_TRANSFER_EVERYTHING);
640     } else {
641         /* clean up unprocessed items */
642         if (seq_cache->item_cache->to_py_cleanup != NULL) {
643             int j;
644             PyGIMarshalCleanupFunc cleanup_func = seq_cache->item_cache->to_py_cleanup;
645             for (j = processed_items; j < array_->len; j++) {
646                 cleanup_func (state,
647                               seq_cache->item_cache,
648                               NULL,
649                               g_array_index (array_, gpointer, j),
650                               FALSE);
651             }
652         }
653
654         if (arg_cache->transfer == GI_TRANSFER_EVERYTHING)
655             g_array_free (array_, TRUE);
656     }
657
658     return NULL;
659 }
660
661 static GArray*
662 _wrap_c_array (PyGIInvokeState   *state,
663                PyGIArgGArray     *array_cache,
664                gpointer           data)
665 {
666     GArray *array_;
667     gsize   len = 0;
668
669     if (array_cache->fixed_size >= 0) {
670         len = array_cache->fixed_size;
671     } else if (array_cache->is_zero_terminated) {
672         len = g_strv_length ((gchar **)data);
673     } else if (array_cache->len_arg_index >= 0) {
674         GIArgument *len_arg = &state->arg_values[array_cache->len_arg_index];
675         len = len_arg->v_long;
676     }
677
678     array_ = g_array_new (FALSE,
679                           FALSE,
680                           array_cache->item_size);
681
682     if (array_ == NULL)
683         return NULL;
684
685     g_free (array_->data);
686     array_->data = data;
687     array_->len = len;
688
689     return array_;
690 }
691
692 static void
693 _pygi_marshal_cleanup_to_py_array (PyGIInvokeState *state,
694                                    PyGIArgCache    *arg_cache,
695                                    PyObject        *dummy,
696                                    gpointer         data,
697                                    gboolean         was_processed)
698 {
699     if (arg_cache->transfer == GI_TRANSFER_EVERYTHING ||
700         arg_cache->transfer == GI_TRANSFER_CONTAINER) {
701         GArray *array_ = NULL;
702         GPtrArray *ptr_array_ = NULL;
703         PyGISequenceCache *sequence_cache = (PyGISequenceCache *)arg_cache;
704         PyGIArgGArray *array_cache = (PyGIArgGArray *)arg_cache;
705
706         /* If this isn't a garray create one to help process variable sized
707            array elements */
708         if (array_cache->array_type == GI_ARRAY_TYPE_C) {
709             array_ = _wrap_c_array (state, array_cache, data);
710
711             if (array_ == NULL)
712                 return;
713
714         } else if (array_cache->array_type == GI_ARRAY_TYPE_PTR_ARRAY) {
715             ptr_array_ = (GPtrArray *) data;
716         } else {
717             array_ = (GArray *) data;
718         }
719
720         if (sequence_cache->item_cache->to_py_cleanup != NULL) {
721             gsize i;
722             guint len = (array_ != NULL) ? array_->len : ptr_array_->len;
723
724             PyGIMarshalCleanupFunc cleanup_func = sequence_cache->item_cache->to_py_cleanup;
725             for (i = 0; i < len; i++) {
726                 cleanup_func (state,
727                               sequence_cache->item_cache,
728                               NULL,
729                               (array_ != NULL) ? g_array_index (array_, gpointer, i) : g_ptr_array_index (ptr_array_, i),
730                               was_processed);
731             }
732         }
733
734         if (array_ != NULL)
735             g_array_free (array_, TRUE);
736         else
737             g_ptr_array_free (ptr_array_, TRUE);
738     }
739 }
740
741 static void
742 _array_cache_free_func (PyGIArgGArray *cache)
743 {
744     if (cache != NULL) {
745         pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
746         g_slice_free (PyGIArgGArray, cache);
747     }
748 }
749
750 PyGIArgCache*
751 pygi_arg_garray_len_arg_setup (PyGIArgCache *arg_cache,
752                                GITypeInfo *type_info,
753                                PyGICallableCache *callable_cache,
754                                PyGIDirection direction,
755                                gssize arg_index,
756                                gssize *py_arg_index)
757 {
758     PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
759
760     /* attempt len_arg_index setup for the first time */
761     if (seq_cache->len_arg_index < 0) {
762         seq_cache->len_arg_index = g_type_info_get_array_length (type_info);
763
764         /* offset by self arg for methods and vfuncs */
765         if (seq_cache->len_arg_index >= 0 && callable_cache != NULL) {
766             seq_cache->len_arg_index += callable_cache->args_offset;
767         }
768     }
769
770     if (seq_cache->len_arg_index >= 0) {
771         PyGIArgCache *child_cache = NULL;
772
773         child_cache = _pygi_callable_cache_get_arg (callable_cache,
774                                                     seq_cache->len_arg_index);
775         if (child_cache == NULL) {
776             child_cache = pygi_arg_cache_alloc ();
777         } else {
778             /* If the "length" arg cache already exists (the length comes before
779              * the array in the argument list), remove it from the to_py_args list
780              * because it does not belong in "to python" return tuple. The length
781              * will implicitly be a part of the returned Python list.
782              */
783             if (direction & PYGI_DIRECTION_TO_PYTHON) {
784                 callable_cache->to_py_args =
785                     g_slist_remove (callable_cache->to_py_args, child_cache);
786             }
787
788             /* This is a case where the arg cache already exists and has been
789              * setup by another array argument sharing the same length argument.
790              * See: gi_marshalling_tests_multi_array_key_value_in
791              */
792             if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
793                 return child_cache;
794         }
795
796         /* There is a length argument for this array, so increment the number
797          * of "to python" child arguments when applicable.
798          */
799         if (direction & PYGI_DIRECTION_TO_PYTHON)
800              callable_cache->n_to_py_child_args++;
801
802         child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
803         child_cache->direction = direction;
804         child_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
805         child_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
806         child_cache->py_arg_index = -1;
807
808         /* ugly edge case code:
809          *
810          * When the length comes before the array parameter we need to update
811          * indexes of arguments after the index argument.
812          */
813         if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
814             gssize i;
815             (*py_arg_index) -= 1;
816             callable_cache->n_py_args -= 1;
817
818             for (i = seq_cache->len_arg_index + 1;
819                    i < _pygi_callable_cache_args_len (callable_cache); i++) {
820                 PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
821                 if (update_cache == NULL)
822                     break;
823
824                 update_cache->py_arg_index -= 1;
825             }
826         }
827
828         _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
829         return child_cache;
830     }
831
832     return NULL;
833 }
834
835 static gboolean
836 pygi_arg_garray_setup (PyGIArgGArray     *sc,
837                        GITypeInfo        *type_info,
838                        GIArgInfo         *arg_info,    /* may be NULL for return arguments */
839                        GITransfer         transfer,
840                        PyGIDirection      direction,
841                        PyGICallableCache *callable_cache)
842 {
843     GITypeInfo *item_type_info;
844     PyGIArgCache *arg_cache = (PyGIArgCache *)sc;
845
846     if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
847                                   type_info,
848                                   arg_info,
849                                   transfer,
850                                   direction,
851                                   callable_cache)) {
852         return FALSE;
853     }
854
855     ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
856     sc->array_type = g_type_info_get_array_type (type_info);
857     sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
858     sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
859     sc->len_arg_index = -1;  /* setup by pygi_arg_garray_len_arg_setup */
860
861     item_type_info = g_type_info_get_param_type (type_info, 0);
862     sc->item_size = _pygi_g_type_info_size (item_type_info);
863     g_base_info_unref ( (GIBaseInfo *)item_type_info);
864
865     if (direction & PYGI_DIRECTION_FROM_PYTHON) {
866         arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
867         arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
868     }
869
870     if (direction & PYGI_DIRECTION_TO_PYTHON) {
871         arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
872         arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
873     }
874
875     return TRUE;
876 }
877
878 PyGIArgCache *
879 pygi_arg_garray_new_from_info (GITypeInfo *type_info,
880                                GIArgInfo *arg_info,
881                                GITransfer transfer,
882                                PyGIDirection direction,
883                                PyGICallableCache *callable_cache)
884 {
885     PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
886     if (array_cache == NULL)
887         return NULL;
888
889     if (!pygi_arg_garray_setup (array_cache,
890                                 type_info,
891                                 arg_info,
892                                 transfer,
893                                 direction,
894                                 callable_cache)) {
895         pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
896         return NULL;
897     }
898
899     return (PyGIArgCache *)array_cache;
900 }