pygi-cache.c 41.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/* -*- Mode: C; c-basic-offset: 4 -*-
 * vim: tabstop=4 shiftwidth=4 expandtab
 *
 * Copyright (C) 2011 John (J5) Palmieri <johnp@redhat.com>
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301
 * USA
 */
21

22 23
#include <girepository.h>

24
#include "pygi-info.h"
25
#include "pygi-cache.h"
26 27
#include "pygi-marshal-to-py.h"
#include "pygi-marshal-from-py.h"
28
#include "pygi-marshal-cleanup.h"
29
#include "pygi-type.h"
30
#include "pygi-hashtable.h"
31

32 33

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
34
                                             GITypeInfo *type_info,
35 36
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
37
                                             PyGIDirection direction,
38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121
                                             /* will be removed */
                                             PyGICallableCache *callable_cache);


/* _arg_info_default_value
 * info:
 * arg: (out): GIArgument to fill in with default value.
 *
 * This is currently a place holder API which only supports "allow-none" pointer args.
 * Once defaults are part of the GI API, we can replace this with: g_arg_info_default_value
 * https://bugzilla.gnome.org/show_bug.cgi?id=558620
 *
 * Returns: TRUE if the given argument supports a default value and was filled in.
 */
static gboolean
_arg_info_default_value (GIArgInfo *info, GIArgument *arg)
{
    if (g_arg_info_may_be_null (info)) {
        arg->v_pointer = NULL;
        return TRUE;
    }
    return FALSE;
}

gboolean
pygi_arg_base_setup (PyGIArgCache *arg_cache,
                     GITypeInfo   *type_info,
                     GIArgInfo    *arg_info,  /* may be NULL for return arguments */
                     GITransfer    transfer,
                     PyGIDirection direction)
{
    arg_cache->direction = direction;
    arg_cache->transfer = transfer;
    arg_cache->py_arg_index = -1;
    arg_cache->c_arg_index = -1;

    if (type_info != NULL) {
        arg_cache->is_pointer = g_type_info_is_pointer (type_info);
        arg_cache->type_tag = g_type_info_get_tag (type_info);
        g_base_info_ref ( (GIBaseInfo *) type_info);
        arg_cache->type_info = type_info;
    }

    if (arg_info != NULL) {
        if (!arg_cache->has_default) {
            /* It is possible has_default was set somewhere else */
            arg_cache->has_default = _arg_info_default_value (arg_info,
                                                              &arg_cache->default_value);
        }
        arg_cache->arg_name = g_base_info_get_name ((GIBaseInfo *) arg_info);
        arg_cache->allow_none = g_arg_info_may_be_null (arg_info);

        if (arg_cache->type_tag == GI_TYPE_TAG_INTERFACE || arg_cache->type_tag == GI_TYPE_TAG_ARRAY)
            arg_cache->is_caller_allocates = g_arg_info_is_caller_allocates (arg_info);
        else
            arg_cache->is_caller_allocates = FALSE;
    }
    return TRUE;
}


gboolean
pygi_arg_interface_setup (PyGIInterfaceCache *iface_cache,
                          GITypeInfo         *type_info,
                          GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                          GITransfer          transfer,
                          PyGIDirection       direction,
                          GIInterfaceInfo    *iface_info)
{
    if (!pygi_arg_base_setup ((PyGIArgCache *)iface_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }

    g_base_info_ref ( (GIBaseInfo *)iface_info);
    iface_cache->interface_info = iface_info;
    iface_cache->arg_cache.type_tag = GI_TYPE_TAG_INTERFACE;

    return TRUE;
}

122

123
/* cleanup */
124
void
125
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
126 127 128 129
{
    if (cache == NULL)
        return;

130
    if (cache->type_info != NULL)
131
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
132
    if (cache->destroy_notify)
133
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
134
    else
135
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
136 137 138
}

static void
139
_interface_cache_free_func (PyGIInterfaceCache *cache)
140 141
{
    if (cache != NULL) {
142
        Py_XDECREF (cache->py_type);
143
        if (cache->type_name != NULL)
144
            g_free (cache->type_name);
145
        if (cache->interface_info != NULL)
146 147
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
148 149 150 151
    }
}


152
static void
153
_sequence_cache_free_func (PyGISequenceCache *cache)
154
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
155
    if (cache != NULL) {
156 157
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
158
    }
159 160
}

161
static void
162
_callback_cache_free_func (PyGICallbackCache *cache)
163
{
164 165
    if (cache != NULL) {
        if (cache->interface_info != NULL)
166
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
167

168
        g_slice_free (PyGICallbackCache, cache);
169
    }
170 171 172
}

void
173
_pygi_callable_cache_free (PyGICallableCache *cache)
174
{
175 176 177
    if (cache == NULL)
        return;

178
    g_slist_free (cache->to_py_args);
179 180
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);
181
    g_ptr_array_unref (cache->args_cache);
182

183
    if (cache->return_cache != NULL)
184
        _pygi_arg_cache_free (cache->return_cache);
185

186
    g_slice_free (PyGICallableCache, cache);
187 188 189 190
}

/* cache generation */

191 192
static PyGIInterfaceCache *
_interface_cache_new (GIInterfaceInfo *iface_info)
193 194
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
195

196 197
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
198
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
199
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
200 201 202 203

    if (ic->py_type == NULL)
        return NULL;

204
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
205 206 207
    return ic;
}

208 209 210 211 212
static PyGISequenceCache *
_sequence_cache_new (GITypeInfo *type_info,
                     GIDirection direction,
                     GITransfer transfer,
                     gssize child_offset)
213 214 215
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
216
    GITransfer item_transfer;
217

218 219
    sc = g_slice_new0 (PyGISequenceCache);
    ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
220

221
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
222 223 224 225
    sc->fixed_size = g_type_info_get_array_fixed_size (type_info);
    sc->len_arg_index = g_type_info_get_array_length (type_info);
    if (sc->len_arg_index >= 0)
        sc->len_arg_index += child_offset;
226

227 228
    item_type_info = g_type_info_get_param_type (type_info, 0);

229 230
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
231

232 233 234 235
    sc->item_cache = _arg_cache_new (item_type_info,
                                     NULL,
                                     item_transfer,
                                     direction,
236 237
                                     0, 0,
                                     NULL);
238

239
    if (sc->item_cache == NULL) {
240
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
241 242
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
243

244 245
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
246

247
    return sc;
248 249
}

250 251 252 253
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
                     GIInterfaceInfo *iface_info,
                     gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
254 255 256
{
   PyGICallbackCache *cc;

257
   cc = g_slice_new0 (PyGICallbackCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
258 259
   ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

260
   cc->user_data_index = g_arg_info_get_closure (arg_info);
261
   if (cc->user_data_index != -1)
262
       cc->user_data_index += child_offset;
263
   cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
264
   if (cc->destroy_notify_index != -1)
265
       cc->destroy_notify_index += child_offset;
266
   cc->scope = g_arg_info_get_scope (arg_info);
267 268
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
269 270 271
   return cc;
}

272 273
static PyGIArgCache *
_arg_cache_alloc (void)
274
{
275
    return g_slice_new0 (PyGIArgCache);
276
}
277

278 279 280 281 282 283
static void
_arg_cache_from_py_basic_type_setup (PyGIArgCache *arg_cache)
{
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
}

284 285 286
static void
_arg_cache_to_py_basic_type_setup (PyGIArgCache *arg_cache)
{
287
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
288 289
}

290
static void
291
_arg_cache_from_py_void_setup (PyGIArgCache *arg_cache)
292
{
293
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_void;
294
}
295

296
static void
297
_arg_cache_to_py_void_setup (PyGIArgCache *arg_cache)
298
{
299
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_void;
300 301
}

302
static void
303 304
_arg_cache_from_py_utf8_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
305
{
306
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
307
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
308
}
309

310
static void
311 312
_arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
313
{
314
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
315
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
316 317
}

318 319
static PyGIArgCache*
_arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
320
                                PyGICallableCache *callable_cache,
321
                                PyGIDirection direction,
322 323
                                gssize arg_index,
                                gssize *py_arg_index)
324
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
325
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
326
    if (seq_cache->len_arg_index >= 0) {
327
        PyGIArgCache *child_cache = NULL;
328

329 330
        child_cache = _pygi_callable_cache_get_arg (callable_cache,
                                                    seq_cache->len_arg_index);
331
        if (child_cache == NULL) {
332
            child_cache = _arg_cache_alloc ();
333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349
        } else {
            /* If the "length" arg cache already exists (the length comes before
             * the array in the argument list), remove it from the to_py_args list
             * because it does not belong in "to python" return tuple. The length
             * will implicitly be a part of the returned Python list.
             */
            if (direction & PYGI_DIRECTION_TO_PYTHON) {
                callable_cache->to_py_args =
                    g_slist_remove (callable_cache->to_py_args, child_cache);
            }

            /* This is a case where the arg cache already exists and has been
             * setup by another array argument sharing the same length argument.
             * See: gi_marshalling_tests_multi_array_key_value_in
             */
            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD)
                return child_cache;
350 351
        }

352 353 354 355 356
        /* There is a length argument for this array, so increment the number
         * of "to python" child arguments when applicable.
         */
        if (direction & PYGI_DIRECTION_TO_PYTHON)
             callable_cache->n_to_py_child_args++;
357

358
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
359
        child_cache->direction = direction;
360 361
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
362

363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382
        /* ugly edge case code:
         *
         * When the length comes before the array parameter we need to update
         * indexes of arguments after the index argument.
         */
        if (seq_cache->len_arg_index < arg_index && direction & PYGI_DIRECTION_FROM_PYTHON) {
            gssize i;
            (*py_arg_index) -= 1;
            callable_cache->n_py_args -= 1;

            for (i = seq_cache->len_arg_index + 1;
                   i < _pygi_callable_cache_args_len (callable_cache); i++) {
                PyGIArgCache *update_cache = _pygi_callable_cache_get_arg (callable_cache, i);
                if (update_cache == NULL)
                    break;

                update_cache->py_arg_index -= 1;
            }
        }

383
        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
384
        return child_cache;
385 386
    }

387 388
    return NULL;
}
389

390 391 392 393 394 395 396 397 398 399 400 401
static gboolean
_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                PyGICallableCache *callable_cache,
                                GITypeInfo *type_info,
                                GITransfer transfer,
                                PyGIDirection direction,
                                gssize arg_index)
{
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
    seq_cache->array_type = g_type_info_get_array_type (type_info);
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
402
    return TRUE;
403 404
}

405
static gboolean
406 407 408 409 410 411
_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                              PyGICallableCache *callable_cache,
                              GITypeInfo *type_info,
                              GITransfer transfer,
                              PyGIDirection direction,
                              gssize arg_index)
412
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
413
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
414
    seq_cache->array_type = g_type_info_get_array_type (type_info);
415 416
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
417 418 419
    return TRUE;
}

420
static void
421 422
_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
                                GITransfer transfer)
423
{
424 425
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
426
}
427

428
static void
429 430
_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
                              GITransfer transfer)
431
{
432 433
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
434 435
}

436
static void
437 438
_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
439
{
440 441
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
442
}
443

444
static void
445 446
_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
447
{
448 449
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
450 451
}

452
static void
453
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
454
{
455
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
456
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
457 458
}

459
static void
460
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
461
{
462
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
463
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
464 465
}

466
static void
467 468
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
469
{
470
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
471 472
}

473
static void
474 475
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
476
{
477
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
478 479
}

480
static void
481 482 483
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
484
{
485
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
486
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
487
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
488 489

    if (iface_cache->g_type == G_TYPE_VALUE)
490
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
491
    else if (iface_cache->is_foreign)
492
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
493
}
494

495
static void
496 497 498
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
499 500
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
501
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
502
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
503 504

    if (iface_cache->is_foreign)
505
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
506 507
}

508
static void
509 510
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
511
{
512 513
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
514 515
}

516
static void
517 518
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
519
{
520
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object_cache_adapter;
521
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
522 523
}

524
static void
525 526
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
527
{
528
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
529
    if (callback_cache->user_data_index >= 0) {
530
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
531
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
532
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
533
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
534 535
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->user_data_index,
                                      user_data_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
536
    }
537 538

    if (callback_cache->destroy_notify_index >= 0) {
539
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
540
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
541
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
542 543
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
                                      destroy_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
544
    }
545
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
546
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
547 548
}

549
static void
550
_arg_cache_to_py_interface_callback_setup (void)
551
{
552 553 554
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
555

556
static void
557 558
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
559
{
560
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
561 562
}

563
static void
564 565
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
566
{
567
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
568
}
569

570
static void
571 572
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
573
{
574
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
575 576
}

577
static void
578 579
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
580
{
581
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
582 583
}

584

585
PyGIArgCache *
586 587 588 589 590 591
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
592
{
593
    PyGIArgCache *arg_cache = NULL;
594
    gssize child_offset = 0;
595
    GIInfoType info_type;
596 597 598 599 600

    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                 callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
601

602 603
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

604
    /* Callbacks are special cased */
605 606
    if (info_type == GI_INFO_TYPE_CALLBACK) {
        PyGICallbackCache *callback_cache;
607

608 609 610 611 612 613 614 615 616 617 618
        if (direction & PYGI_DIRECTION_TO_PYTHON) {
            _arg_cache_to_py_interface_callback_setup ();
            return NULL;
        }

        callback_cache =
            _callback_cache_new (arg_info,
                                 iface_info,
                                 child_offset);

        arg_cache = (PyGIArgCache *)callback_cache;
619 620
        if (arg_cache == NULL)
            return NULL;
621 622 623 624 625 626 627 628 629 630 631 632

        pygi_arg_base_setup (arg_cache,
                             type_info,
                             arg_info,
                             transfer,
                             direction);

        if (direction & PYGI_DIRECTION_FROM_PYTHON)
            _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);

        return arg_cache;

633 634
    }

635 636 637 638
    arg_cache = (PyGIArgCache *)_interface_cache_new (iface_info);
    if (arg_cache == NULL)
        return NULL;

639 640
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
641
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
642
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
643

644
            if (direction & PYGI_DIRECTION_TO_PYTHON)
645
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
646

647
            break;
648
        case GI_INFO_TYPE_BOXED:
649
        case GI_INFO_TYPE_STRUCT:
650
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
651 652 653 654
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

655
            if (direction & PYGI_DIRECTION_TO_PYTHON)
656 657 658
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
659 660 661
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
662
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
663
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
664

665
            if (direction & PYGI_DIRECTION_TO_PYTHON)
666
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
667

668 669
            break;
        case GI_INFO_TYPE_ENUM:
670
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
671
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
672

673
            if (direction & PYGI_DIRECTION_TO_PYTHON)
674
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
675

676 677
            break;
        case GI_INFO_TYPE_FLAGS:
678
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
679
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
680

681
            if (direction & PYGI_DIRECTION_TO_PYTHON)
682
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
683

684 685
            break;
        default:
686
            g_assert_not_reached ();
687 688
    }

689 690 691 692 693 694
    pygi_arg_interface_setup ((PyGIInterfaceCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction,
                              iface_info);
695 696

    return arg_cache;
697 698
}

699
PyGIArgCache *
700
_arg_cache_new (GITypeInfo *type_info,
701
                GIArgInfo *arg_info,     /* may be null */
702
                GITransfer transfer,
703
                PyGIDirection direction,
704
                gssize c_arg_index,
705 706
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
707
{
708
    PyGIArgCache *arg_cache = NULL;
709
    gssize child_offset = 0;
710
    GITypeTag type_tag;
711

712 713
    type_tag = g_type_info_get_tag (type_info);

714 715 716 717
    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
718

719 720
    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
721
           arg_cache = _arg_cache_alloc ();
722 723
           if (arg_cache == NULL)
               break;
724

725
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
726 727
               _arg_cache_from_py_void_setup (arg_cache);

728
           if (direction & PYGI_DIRECTION_TO_PYTHON)
729
               _arg_cache_to_py_void_setup (arg_cache);
730

731 732 733 734 735 736 737 738 739 740 741 742 743 744
           break;
       case GI_TYPE_TAG_BOOLEAN:
       case GI_TYPE_TAG_INT8:
       case GI_TYPE_TAG_UINT8:
       case GI_TYPE_TAG_INT16:
       case GI_TYPE_TAG_UINT16:
       case GI_TYPE_TAG_INT32:
       case GI_TYPE_TAG_UINT32:
       case GI_TYPE_TAG_INT64:
       case GI_TYPE_TAG_UINT64:
       case GI_TYPE_TAG_FLOAT:
       case GI_TYPE_TAG_DOUBLE:
       case GI_TYPE_TAG_UNICHAR:
       case GI_TYPE_TAG_GTYPE:
745
           arg_cache = _arg_cache_alloc ();
746 747
           if (arg_cache == NULL)
               break;
748

749
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
750
               _arg_cache_from_py_basic_type_setup (arg_cache);
751

752
           if (direction & PYGI_DIRECTION_TO_PYTHON)
753
               _arg_cache_to_py_basic_type_setup (arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
754

755 756
           break;
       case GI_TYPE_TAG_UTF8:
757
       case GI_TYPE_TAG_FILENAME:
758
           arg_cache = _arg_cache_alloc ();
759 760
           if (arg_cache == NULL)
               break;
761

762
           if (direction & PYGI_DIRECTION_FROM_PYTHON)
763
               _arg_cache_from_py_utf8_setup (arg_cache, transfer);
764

765
           if (direction & PYGI_DIRECTION_TO_PYTHON)
766
               _arg_cache_to_py_utf8_setup (arg_cache, transfer);
767

768 769 770
           break;
       case GI_TYPE_TAG_ARRAY:
           {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
771
               PyGISequenceCache *seq_cache =
772 773 774 775
                   _sequence_cache_new (type_info,
                                        direction,
                                        transfer,
                                        child_offset);
776 777 778 779 780

               arg_cache = (PyGIArgCache *)seq_cache;
               if (arg_cache == NULL)
                   break;

781
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
782 783 784 785
                   _arg_cache_from_py_array_setup (arg_cache,
                                                   callable_cache,
                                                   type_info,
                                                   transfer,
786 787
                                                   direction,
                                                   c_arg_index);
788

789
               if (direction & PYGI_DIRECTION_TO_PYTHON)
790 791 792 793 794 795
                   _arg_cache_to_py_array_setup (arg_cache,
                                                 callable_cache,
                                                 type_info,
                                                 transfer,
                                                 direction,
                                                 c_arg_index);
796

797 798 799 800 801
               _arg_cache_array_len_arg_setup (arg_cache,
                                               callable_cache,
                                               direction,
                                               c_arg_index,
                                               &py_arg_index);
802