pygi-cache.c 43 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
#include "pygi-basictype.h"
32

33 34

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
35
                                             GITypeInfo *type_info,
36 37
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
38
                                             PyGIDirection direction,
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 122
                                             /* 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;
}

123

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

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

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


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

162 163 164 165 166 167 168 169 170
static void
_array_cache_free_func (PyGIArgGArray *cache)
{
    if (cache != NULL) {
        _pygi_arg_cache_free (((PyGISequenceCache *)cache)->item_cache);
        g_slice_free (PyGIArgGArray, cache);
    }
}

171
static void
172
_callback_cache_free_func (PyGICallbackCache *cache)
173
{
174 175
    if (cache != NULL) {
        if (cache->interface_info != NULL)
176
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
177

178
        g_slice_free (PyGICallbackCache, cache);
179
    }
180 181 182
}

void
183
_pygi_callable_cache_free (PyGICallableCache *cache)
184
{
185 186 187
    if (cache == NULL)
        return;

188
    g_slist_free (cache->to_py_args);
189 190
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);
191
    g_ptr_array_unref (cache->args_cache);
192

193
    if (cache->return_cache != NULL)
194
        _pygi_arg_cache_free (cache->return_cache);
195

196
    g_slice_free (PyGICallableCache, cache);
197 198 199 200
}

/* cache generation */

201 202
static PyGIInterfaceCache *
_interface_cache_new (GIInterfaceInfo *iface_info)
203 204
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
205

206 207
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
208
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
209
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
210 211 212 213

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

214
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
215 216 217
    return ic;
}

218 219 220 221 222 223
gboolean
pygi_arg_sequence_setup (PyGISequenceCache  *sc,
                         GITypeInfo         *type_info,
                         GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                         GITransfer          transfer,
                         PyGIDirection       direction)
224 225
{
    GITypeInfo *item_type_info;
226
    GITransfer item_transfer;
227

228 229 230 231 232 233 234
    if (!pygi_arg_base_setup ((PyGIArgCache *)sc,
                              type_info,
                              arg_info,
                              transfer,
                              direction)) {
        return FALSE;
    }
235

236
    sc->arg_cache.destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
237
    item_type_info = g_type_info_get_param_type (type_info, 0);
238 239
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
240

241 242 243 244
    sc->item_cache = _arg_cache_new (item_type_info,
                                     NULL,
                                     item_transfer,
                                     direction,
245 246
                                     0, 0,
                                     NULL);
247

248 249
    g_base_info_unref ( (GIBaseInfo *)item_type_info);

250
    if (sc->item_cache == NULL) {
251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
        return FALSE;
    }

    return TRUE;
}

static gboolean
pygi_arg_garray_setup (PyGIArgGArray      *sc,
                       GITypeInfo         *type_info,
                       GIArgInfo          *arg_info,    /* may be NULL for return arguments */
                       GITransfer          transfer,
                       PyGIDirection       direction,
                       gssize              child_offset)
{
    GITypeInfo *item_type_info;

    if (!pygi_arg_sequence_setup ((PyGISequenceCache *)sc,
                                  type_info,
                                  arg_info,
                                  transfer,
                                  direction)) {
        return FALSE;
273
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
274

275 276 277 278 279 280 281 282
    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_array_cache_free_func;
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
    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;

    item_type_info = g_type_info_get_param_type (type_info, 0);
283 284
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
285

286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303
    return TRUE;
}

static PyGISequenceCache *
pygi_arg_sequence_new (GITypeInfo *type_info,
                       GIArgInfo *arg_info,
                       GITransfer transfer,
                       PyGIDirection direction)
{
    PyGISequenceCache *sc = g_slice_new0 (PyGISequenceCache);
    if (sc == NULL)
        return NULL;

    if (!pygi_arg_sequence_setup (sc, type_info, arg_info, transfer, direction)) {
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
        return NULL;
    }

304
    return sc;
305 306
}

307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330
static PyGIArgGArray *
_arg_array_cache_new (GITypeInfo *type_info,
                      GIArgInfo *arg_info,
                      GITransfer transfer,
                      PyGIDirection direction,
                      gssize child_offset)
{
    PyGIArgGArray *array_cache = g_slice_new0 (PyGIArgGArray);
    if (array_cache == NULL)
        return NULL;

    if (!pygi_arg_garray_setup (array_cache,
                                type_info,
                                arg_info,
                                transfer,
                                direction,
                                child_offset)) {
        _pygi_arg_cache_free ( (PyGIArgCache *)array_cache);
        return NULL;
    }

    return array_cache;
}

331 332 333 334
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
                     GIInterfaceInfo *iface_info,
                     gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
335 336 337
{
   PyGICallbackCache *cc;

338
   cc = g_slice_new0 (PyGICallbackCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
339 340
   ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

341
   cc->user_data_index = g_arg_info_get_closure (arg_info);
342
   if (cc->user_data_index != -1)
343
       cc->user_data_index += child_offset;
344
   cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
345
   if (cc->destroy_notify_index != -1)
346
       cc->destroy_notify_index += child_offset;
347
   cc->scope = g_arg_info_get_scope (arg_info);
348 349
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
350 351 352
   return cc;
}

353
PyGIArgCache *
354
_arg_cache_alloc (void)
355
{
356
    return g_slice_new0 (PyGIArgCache);
357
}
358 359


360 361
static PyGIArgCache*
_arg_cache_array_len_arg_setup (PyGIArgCache *arg_cache,
362
                                PyGICallableCache *callable_cache,
363
                                PyGIDirection direction,
364 365
                                gssize arg_index,
                                gssize *py_arg_index)
366
{
367
    PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
368
    if (seq_cache->len_arg_index >= 0) {
369
        PyGIArgCache *child_cache = NULL;
370

371 372
        child_cache = _pygi_callable_cache_get_arg (callable_cache,
                                                    seq_cache->len_arg_index);
373
        if (child_cache == NULL) {
374
            child_cache = _arg_cache_alloc ();
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
        } 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;
392 393
        }

394 395 396 397 398
        /* 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++;
399

400
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
401
        child_cache->direction = direction;
402 403
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
404

405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
        /* 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;
            }
        }

425
        _pygi_callable_cache_set_arg (callable_cache, seq_cache->len_arg_index, child_cache);
426
        return child_cache;
427 428
    }

429 430
    return NULL;
}
431

432 433 434 435 436 437 438 439
static gboolean
_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                PyGICallableCache *callable_cache,
                                GITypeInfo *type_info,
                                GITransfer transfer,
                                PyGIDirection direction,
                                gssize arg_index)
{
440
    PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
441 442 443
    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;
444
    return TRUE;
445 446
}

447
static gboolean
448 449 450 451 452 453
_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                              PyGICallableCache *callable_cache,
                              GITypeInfo *type_info,
                              GITransfer transfer,
                              PyGIDirection direction,
                              gssize arg_index)
454
{
455
    PyGIArgGArray *seq_cache = (PyGIArgGArray *)arg_cache;
456
    seq_cache->array_type = g_type_info_get_array_type (type_info);
457 458
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
459 460 461
    return TRUE;
}

462
static void
463 464
_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
                                GITransfer transfer)
465
{
466 467
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
468
}
469

470
static void
471 472
_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
                              GITransfer transfer)
473
{
474 475
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
476 477
}

478
static void
479 480
_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
481
{
482 483
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
484
}
485

486
static void
487 488
_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
489
{
490 491
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
492 493
}

494
static void
495
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
496
{
497
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
498
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
499 500
}

501
static void
502
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
503
{
504
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
505
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
506 507
}

508
static void
509 510
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
511
{
512
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
513 514
}

515
static void
516 517
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
518
{
519
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
520 521
}

522
static void
523 524 525
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
526
{
527
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
528
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
529
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct_cache_adapter;
530 531

    if (iface_cache->g_type == G_TYPE_VALUE)
532
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
533
    else if (iface_cache->is_foreign)
534
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
535
}
536

537
static void
538 539 540
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
541 542
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
543
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
544
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct_cache_adapter;
545 546

    if (iface_cache->is_foreign)
547
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
548 549
}

550
static void
551 552
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
553
{
554 555
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
556 557
}

558
static void
559 560
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
561
{
562
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object_cache_adapter;
563
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
564 565
}

566
static void
567 568
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
569
{
570
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
571
    if (callback_cache->user_data_index >= 0) {
572
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
573
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
574
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
575
        user_data_arg_cache->has_default = TRUE; /* always allow user data with a NULL default. */
576 577
        _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
578
    }
579 580

    if (callback_cache->destroy_notify_index >= 0) {
581
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
582
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
583
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
584 585
        _pygi_callable_cache_set_arg (callable_cache, callback_cache->destroy_notify_index,
                                      destroy_arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
586
    }
587
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
588
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
589 590
}

591
static void
592
_arg_cache_to_py_interface_callback_setup (void)
593
{
594 595 596
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
597

598
static void
599 600
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
601
{
602
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
603 604
}

605
static void
606 607
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
608
{
609
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
610
}
611

612
static void
613 614
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
615
{
616
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
617 618
}

619
static void
620 621
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
622
{
623
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
624 625
}

626

627
PyGIArgCache *
628 629 630 631 632 633
_arg_cache_new_for_interface (GIInterfaceInfo   *iface_info,
                              GITypeInfo        *type_info,
                              GIArgInfo         *arg_info,
                              GITransfer         transfer,
                              PyGIDirection      direction,
                              PyGICallableCache *callable_cache)
634
{
635
    PyGIArgCache *arg_cache = NULL;
636
    gssize child_offset = 0;
637
    GIInfoType info_type;
638 639 640 641 642

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

644 645
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

646
    /* Callbacks are special cased */
647 648
    if (info_type == GI_INFO_TYPE_CALLBACK) {
        PyGICallbackCache *callback_cache;
649

650 651 652 653 654 655 656 657 658 659 660
        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;
661 662
        if (arg_cache == NULL)
            return NULL;
663 664 665 666 667 668 669 670 671 672 673 674

        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;

675 676
    }

677 678 679 680
    arg_cache = (PyGIArgCache *)_interface_cache_new (iface_info);
    if (arg_cache == NULL)
        return NULL;

681 682
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
683
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
684
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
685

686
            if (direction & PYGI_DIRECTION_TO_PYTHON)
687
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
688

689
            break;
690
        case GI_INFO_TYPE_BOXED:
691
        case GI_INFO_TYPE_STRUCT:
692
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
693 694 695 696
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

697
            if (direction & PYGI_DIRECTION_TO_PYTHON)
698 699 700
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
701 702 703
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
704
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
705
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
706

707
            if (direction & PYGI_DIRECTION_TO_PYTHON)
708
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
709

710 711
            break;
        case GI_INFO_TYPE_ENUM:
712
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
713
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
714

715
            if (direction & PYGI_DIRECTION_TO_PYTHON)
716
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
717

718 719
            break;
        case GI_INFO_TYPE_FLAGS:
720
            if (direction & PYGI_DIRECTION_FROM_PYTHON)
721
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
722

723
            if (direction & PYGI_DIRECTION_TO_PYTHON)
724
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
725

726 727
            break;
        default:
728
            g_assert_not_reached ();
729 730
    }

731 732 733 734 735 736
    pygi_arg_interface_setup ((PyGIInterfaceCache *)arg_cache,
                              type_info,
                              arg_info,
                              transfer,
                              direction,
                              iface_info);
737 738

    return arg_cache;
739 740
}

741
PyGIArgCache *
742
_arg_cache_new (GITypeInfo *type_info,
743
                GIArgInfo *arg_info,     /* may be null */
744
                GITransfer transfer,
745
                PyGIDirection direction,
746
                gssize c_arg_index,
747 748
                gssize py_arg_index,
                PyGICallableCache *callable_cache)
749
{
750
    PyGIArgCache *arg_cache = NULL;
751
    gssize child_offset = 0;
752
    GITypeTag type_tag;
753

754 755
    type_tag = g_type_info_get_tag (type_info);

756 757 758 759
    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
760

761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776
    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
       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:
       case GI_TYPE_TAG_UTF8:
777
       case GI_TYPE_TAG_FILENAME:
778 779 780 781 782 783 784 785
           arg_cache = pygi_arg_basic_type_new_from_info (type_info, arg_info, transfer, direction);
           if (arg_cache) {
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
           } else {
               return NULL;
           }
786

787 788
       case GI_TYPE_TAG_ARRAY:
           {
789 790 791 792 793 794
               PyGIArgGArray *seq_cache =
                   _arg_array_cache_new (type_info,
                                         arg_info,
                                         transfer,
                                         direction,
                                         child_offset);
795 796 797 798 799

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

800
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
801 802 803 804
                   _arg_cache_from_py_array_setup (arg_cache,
                                                   callable_cache,
                                                   type_info,
                                                   transfer,
805 806
                                                   direction,
                                                   c_arg_index);
807

808
               if (direction & PYGI_DIRECTION_TO_PYTHON)
809 810 811 812 813 814
                   _arg_cache_to_py_array_setup (arg_cache,
                                                 callable_cache,
                                                 type_info,
                                                 transfer,
                                                 direction,
                                                 c_arg_index);
815

816 817 818 819 820
               _arg_cache_array_len_arg_setup (arg_cache,
                                               callable_cache,
                                               direction,
                                               c_arg_index,
                                               &py_arg_index);
821

822 823 824
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
825 826 827
           }
       case GI_TYPE_TAG_GLIST:
           {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
828
               PyGISequenceCache *seq_cache =
829 830 831 832
                   pygi_arg_sequence_new (type_info,
                                          arg_info,
                                          transfer,
                                          direction);
833

834 835 836
               arg_cache = (PyGIArgCache *)seq_cache;
               if (arg_cache == NULL)
                   break;
837

838
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
839
                   _arg_cache_from_py_glist_setup (arg_cache, transfer);
840

841
               if (direction & PYGI_DIRECTION_TO_PYTHON)
842
                   _arg_cache_to_py_glist_setup (arg_cache, transfer);
843

844 845 846
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
847 848
           }
       case GI_TYPE_TAG_GSLIST:
849
           {
John (J5) Palmieri's avatar
John (J5) Palmieri committed
850
               PyGISequenceCache *seq_cache =
851 852 853 854
                   pygi_arg_sequence_new (type_info,
                                          arg_info,
                                          transfer,
                                          direction);
855 856 857 858 859

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

860
               if (direction & PYGI_DIRECTION_FROM_PYTHON)
861
                   _arg_cache_from_py_gslist_setup (arg_cache, transfer);
862

863
               if (direction & PYGI_DIRECTION_TO_PYTHON)
864
                   _arg_cache_to_py_gslist_setup (arg_cache, transfer);
865

866 867 868
               arg_cache->py_arg_index = py_arg_index;
               arg_cache->c_arg_index = c_arg_index;
               return arg_cache;
869
            }
870
       case GI_TYPE_TAG_GHASH:
Simon Feltman's avatar