pygi-cache.c 42.4 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

#include "pygi-info.h"
23
#include "pygi-cache.h"
24 25
#include "pygi-marshal-to-py.h"
#include "pygi-marshal-from-py.h"
26
#include "pygi-marshal-cleanup.h"
27
#include "pygi-type.h"
28
#include <girepository.h>
29

30 31 32 33
PyGIArgCache * _arg_cache_new (GITypeInfo *type_info,
                               PyGICallableCache *callable_cache,
                               GIArgInfo *arg_info,
                               GITransfer transfer,
34
                               PyGIDirection direction,
35 36 37 38 39 40 41
                               gssize c_arg_index,
                               gssize py_arg_index);

PyGIArgCache * _arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                                             PyGICallableCache *callable_cache,
                                             GIArgInfo *arg_info,
                                             GITransfer transfer,
42
                                             PyGIDirection direction,
43 44
                                             gssize c_arg_index,
                                             gssize py_arg_index);
45
/* cleanup */
Martin Pitt's avatar
Martin Pitt committed
46
static void
47
_pygi_arg_cache_free (PyGIArgCache *cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
48 49 50 51
{
    if (cache == NULL)
        return;

52
    if (cache->type_info != NULL)
53
        g_base_info_unref ( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
54
    if (cache->destroy_notify)
55
        cache->destroy_notify (cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
56
    else
57
        g_slice_free (PyGIArgCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
58 59 60
}

static void
61
_interface_cache_free_func (PyGIInterfaceCache *cache)
62 63
{
    if (cache != NULL) {
64
        Py_XDECREF (cache->py_type);
65
        if (cache->type_name != NULL)
66
            g_free (cache->type_name);
67
        if (cache->interface_info != NULL)
68 69
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
        g_slice_free (PyGIInterfaceCache, cache);
70 71 72
    }
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
73
static void
74
_hash_cache_free_func (PyGIHashCache *cache)
75
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
76
    if (cache != NULL) {
77 78 79
        _pygi_arg_cache_free (cache->key_cache);
        _pygi_arg_cache_free (cache->value_cache);
        g_slice_free (PyGIHashCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
80
    }
81 82
}

83
static void
84
_sequence_cache_free_func (PyGISequenceCache *cache)
85
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
86
    if (cache != NULL) {
87 88
        _pygi_arg_cache_free (cache->item_cache);
        g_slice_free (PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
89
    }
90 91
}

92
static void
93
_callback_cache_free_func (PyGICallbackCache *cache)
94
{
95 96
    if (cache != NULL) {
        if (cache->interface_info != NULL)
97
            g_base_info_unref ( (GIBaseInfo *)cache->interface_info);
98

99
        g_slice_free (PyGICallbackCache, cache);
100
    }
101 102 103
}

void
104
_pygi_callable_cache_free (PyGICallableCache *cache)
105
{
106
    gssize i;
107

108 109 110
    if (cache == NULL)
        return;

111
    g_slist_free (cache->to_py_args);
112 113 114
    g_slist_free (cache->arg_name_list);
    g_hash_table_destroy (cache->arg_name_hash);

115 116
    for (i = 0; i < cache->n_args; i++) {
        PyGIArgCache *tmp = cache->args_cache[i];
117
        _pygi_arg_cache_free (tmp);
118
    }
119
    if (cache->return_cache != NULL)
120
        _pygi_arg_cache_free (cache->return_cache);
121

122 123
    g_slice_free1 (cache->n_args * sizeof (PyGIArgCache *), cache->args_cache);
    g_slice_free (PyGICallableCache, cache);
124 125 126 127
}

/* cache generation */

128 129
static PyGIInterfaceCache *
_interface_cache_new (GIInterfaceInfo *iface_info)
130 131
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
132

133 134
    ic = g_slice_new0 (PyGIInterfaceCache);
    ( (PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
135
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
136
    ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
137 138 139 140

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

141
    ic->type_name = _pygi_g_base_info_get_fullname (iface_info);
142 143 144
    return ic;
}

145 146 147 148 149
static PyGISequenceCache *
_sequence_cache_new (GITypeInfo *type_info,
                     GIDirection direction,
                     GITransfer transfer,
                     gssize child_offset)
150 151 152
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
153
    GITransfer item_transfer;
154

155 156
    sc = g_slice_new0 (PyGISequenceCache);
    ( (PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
157

158
    sc->is_zero_terminated = g_type_info_is_zero_terminated (type_info);
159 160 161 162
    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;
163

164 165
    item_type_info = g_type_info_get_param_type (type_info, 0);

166 167
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
168

169 170 171 172 173 174
    sc->item_cache = _arg_cache_new (item_type_info,
                                     NULL,
                                     NULL,
                                     item_transfer,
                                     direction,
                                     0, 0);
175

176
    if (sc->item_cache == NULL) {
177
        _pygi_arg_cache_free ( (PyGIArgCache *)sc);
178 179
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
180

181 182
    sc->item_size = _pygi_g_type_info_size (item_type_info);
    g_base_info_unref ( (GIBaseInfo *)item_type_info);
183

184
    return sc;
185
}
186 187 188 189
static PyGIHashCache *
_hash_cache_new (GITypeInfo *type_info,
                 GIDirection direction,
                 GITransfer transfer)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
190 191 192 193
{
    PyGIHashCache *hc;
    GITypeInfo *key_type_info;
    GITypeInfo *value_type_info;
194
    GITransfer item_transfer;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
195

196 197
    hc = g_slice_new0 (PyGIHashCache);
    ( (PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
198 199 200
    key_type_info = g_type_info_get_param_type (type_info, 0);
    value_type_info = g_type_info_get_param_type (type_info, 1);

201 202
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
203

204 205 206 207 208 209
    hc->key_cache = _arg_cache_new (key_type_info,
                                    NULL,
                                    NULL,
                                    item_transfer,
                                    direction,
                                    0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
210 211

    if (hc->key_cache == NULL) {
212
        _pygi_arg_cache_free ( (PyGIArgCache *)hc);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
213 214 215
        return NULL;
    }

216 217 218 219 220 221
    hc->value_cache = _arg_cache_new (value_type_info,
                                      NULL,
                                      NULL,
                                      item_transfer,
                                      direction,
                                      0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
222 223

    if (hc->value_cache == NULL) {
224
        _pygi_arg_cache_free ( (PyGIArgCache *)hc);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
225 226 227 228 229 230 231 232
        return NULL;
    }

    g_base_info_unref( (GIBaseInfo *)key_type_info);
    g_base_info_unref( (GIBaseInfo *)value_type_info);

    return hc;
}
233

234 235 236 237
static PyGICallbackCache *
_callback_cache_new (GIArgInfo *arg_info,
                     GIInterfaceInfo *iface_info,
                     gssize child_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
238 239 240
{
   PyGICallbackCache *cc;

241
   cc = g_slice_new0 (PyGICallbackCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
242 243
   ( (PyGIArgCache *)cc)->destroy_notify = (GDestroyNotify)_callback_cache_free_func;

244
   cc->user_data_index = g_arg_info_get_closure (arg_info);
245
   if (cc->user_data_index != -1)
246
       cc->user_data_index += child_offset;
247
   cc->destroy_notify_index = g_arg_info_get_destroy (arg_info);
248
   if (cc->destroy_notify_index != -1)
249
       cc->destroy_notify_index += child_offset;
250
   cc->scope = g_arg_info_get_scope (arg_info);
251 252
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
253 254 255
   return cc;
}

256 257
static PyGIArgCache *
_arg_cache_alloc (void)
258
{
259
    return g_slice_new0 (PyGIArgCache);
260
}
261

262 263 264 265 266 267
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;
}

268 269 270
static void
_arg_cache_to_py_basic_type_setup (PyGIArgCache *arg_cache)
{
271
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
272 273
}

274
static void
275
_arg_cache_from_py_void_setup (PyGIArgCache *arg_cache)
276
{
277
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_void;
278
}
279

280
static void
281
_arg_cache_to_py_void_setup (PyGIArgCache *arg_cache)
282
{
283
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_void;
284 285
}

286
static void
287 288
_arg_cache_from_py_utf8_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
289
{
290
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_basic_type_cache_adapter;
291
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_utf8;
292
}
293

294
static void
295 296
_arg_cache_to_py_utf8_setup (PyGIArgCache *arg_cache,
                               GITransfer transfer)
297
{
298
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_basic_type_cache_adapter;
299
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_utf8;
300 301
}

302
static gboolean
303 304 305 306
_arg_cache_from_py_array_setup (PyGIArgCache *arg_cache,
                                PyGICallableCache *callable_cache,
                                GITypeInfo *type_info,
                                GITransfer transfer,
307 308
                                PyGIDirection direction,
                                gssize arg_index)
309
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
310
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
311
    seq_cache->array_type = g_type_info_get_array_type (type_info);
312

313
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_array;
314

315
    if (seq_cache->len_arg_index >= 0) {
316
        PyGIArgCache *child_cache = 
317
            callable_cache->args_cache[seq_cache->len_arg_index];
318

319
        if (child_cache == NULL) {
320
            child_cache = _arg_cache_alloc ();
321 322
        } else if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
                   child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE) {
323
            arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
324 325 326
            return TRUE;
        }

327 328 329 330 331
        if (seq_cache->len_arg_index < arg_index)
            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE;
        else
            child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;

332
        child_cache->direction = direction;
333 334
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
335

336
        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
337 338
    }

339
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_array;
340 341

    return TRUE;
342 343
}

344
static gboolean
345 346 347 348 349 350
_arg_cache_to_py_array_setup (PyGIArgCache *arg_cache,
                              PyGICallableCache *callable_cache,
                              GITypeInfo *type_info,
                              GITransfer transfer,
                              PyGIDirection direction,
                              gssize arg_index)
351
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
352
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
353 354
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_array;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_array;
355

356
    seq_cache->array_type = g_type_info_get_array_type (type_info);
357 358

    if (seq_cache->len_arg_index >= 0) {
359
        PyGIArgCache *child_cache = callable_cache->args_cache[seq_cache->len_arg_index];
360
        if (seq_cache->len_arg_index < arg_index)
361
             callable_cache->n_to_py_child_args++;
362

363
        if (child_cache != NULL) {
364 365
            callable_cache->to_py_args =
                g_slist_remove (callable_cache->to_py_args, child_cache);
366 367 368 369

            if (child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD ||
                child_cache->meta_type == PYGI_META_ARG_TYPE_CHILD_NEEDS_UPDATE)
                return TRUE;
370
        } else {
371
            child_cache = _arg_cache_alloc ();
372
        }
373

374 375
        child_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
        child_cache->direction = direction;
376 377
        child_cache->to_py_marshaller = NULL;
        child_cache->from_py_marshaller = NULL;
378

379
        callable_cache->args_cache[seq_cache->len_arg_index] = child_cache;
380 381 382 383 384
    }

    return TRUE;
}

385
static void
386 387
_arg_cache_from_py_glist_setup (PyGIArgCache *arg_cache,
                                GITransfer transfer)
388
{
389 390
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_glist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
391
}
392

393
static void
394 395
_arg_cache_to_py_glist_setup (PyGIArgCache *arg_cache,
                              GITransfer transfer)
396
{
397 398
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_glist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
399 400
}

401
static void
402 403
_arg_cache_from_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
404
{
405 406
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gslist;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_glist;
407
}
408

409
static void
410 411
_arg_cache_to_py_gslist_setup (PyGIArgCache *arg_cache,
                                 GITransfer transfer)
412
{
413 414
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gslist;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_glist;
415 416
}

417
static void
418
_arg_cache_from_py_ghash_setup (PyGIArgCache *arg_cache)
419
{
420 421
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_ghash;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_ghash;
422 423
}

424
static void
425
_arg_cache_to_py_ghash_setup (PyGIArgCache *arg_cache)
426
{
427 428
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_ghash;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_ghash;
429 430
}

431
static void
432
_arg_cache_from_py_gerror_setup (PyGIArgCache *arg_cache)
433
{
434
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_gerror;
435
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
436 437
}

438
static void
439
_arg_cache_to_py_gerror_setup (PyGIArgCache *arg_cache)
440
{
441
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_gerror;
442
    arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
443 444
}

445
static void
446 447
_arg_cache_from_py_interface_union_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
448
{
449
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct;
450 451
}

452
static void
453 454
_arg_cache_to_py_interface_union_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
455
{
456
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct;
457 458
}

459
static void
460 461 462
_arg_cache_from_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                           GIInterfaceInfo *iface_info,
                                           GITransfer transfer)
463
{
464
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
465
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
466
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_struct;
467 468

    if (iface_cache->g_type == G_TYPE_VALUE)
469
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_gvalue;
470
    else if (iface_cache->is_foreign)
471
        arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_struct_foreign;
472
}
473

474
static void
475 476 477
_arg_cache_to_py_interface_struct_setup (PyGIArgCache *arg_cache,
                                         GIInterfaceInfo *iface_info,
                                         GITransfer transfer)
478 479
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
480
    iface_cache->is_foreign = g_struct_info_is_foreign ( (GIStructInfo*)iface_info);
481
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_struct;
482 483

    if (iface_cache->is_foreign)
484
        arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_struct_foreign;
485 486
}

487
static void
488 489
_arg_cache_from_py_interface_object_setup (PyGIArgCache *arg_cache,
                                           GITransfer transfer)
490
{
491 492
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_object;
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_object;
493 494
}

495
static void
496 497
_arg_cache_to_py_interface_object_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
498
{
499 500
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_object;
    arg_cache->to_py_cleanup = _pygi_marshal_cleanup_to_py_interface_object;
501 502
}

503
static void
504 505
_arg_cache_from_py_interface_callback_setup (PyGIArgCache *arg_cache,
                                             PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
506
{
507
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
508
    if (callback_cache->user_data_index >= 0) {
509
        PyGIArgCache *user_data_arg_cache = _arg_cache_alloc ();
510
        user_data_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD_WITH_PYARG;
511
        user_data_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
512
        callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
513
    }
514 515

    if (callback_cache->destroy_notify_index >= 0) {
516
        PyGIArgCache *destroy_arg_cache = _arg_cache_alloc ();
517
        destroy_arg_cache->meta_type = PYGI_META_ARG_TYPE_CHILD;
518
        destroy_arg_cache->direction = PYGI_DIRECTION_FROM_PYTHON;
519
        callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
520
    }
521
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_callback;
522
    arg_cache->from_py_cleanup = _pygi_marshal_cleanup_from_py_interface_callback;
523 524
}

525
static void
526
_arg_cache_to_py_interface_callback_setup (void)
527
{
528 529 530
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
531

532
static void
533 534
_arg_cache_from_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                         GITransfer transfer)
535
{
536
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_enum;
537 538
}

539
static void
540 541
_arg_cache_to_py_interface_enum_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
542
{
543
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_enum;
544
}
545

546
static void
547 548
_arg_cache_from_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                          GITransfer transfer)
549
{
550
    arg_cache->from_py_marshaller = _pygi_marshal_from_py_interface_flags;
551 552
}

553
static void
554 555
_arg_cache_to_py_interface_flags_setup (PyGIArgCache *arg_cache,
                                        GITransfer transfer)
556
{
557
    arg_cache->to_py_marshaller = _pygi_marshal_to_py_interface_flags;
558 559
}

560 561 562 563 564
PyGIArgCache *
_arg_cache_new_for_interface (GIInterfaceInfo *iface_info,
                              PyGICallableCache *callable_cache,
                              GIArgInfo *arg_info,
                              GITransfer transfer,
565
                              PyGIDirection direction,
566 567
                              gssize c_arg_index,
                              gssize py_arg_index)
568 569
{
    PyGIInterfaceCache *iface_cache = NULL;
570
    PyGIArgCache *arg_cache = NULL;
571
    gssize child_offset = 0;
572
    GIInfoType info_type;
573 574 575 576 577

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

579 580
    info_type = g_base_info_get_type ( (GIBaseInfo *)iface_info);

581 582
    /* Callbacks are special cased */
    if (info_type != GI_INFO_TYPE_CALLBACK) {
583
        iface_cache = _interface_cache_new (iface_info);
584 585 586 587 588 589

        arg_cache = (PyGIArgCache *)iface_cache;
        if (arg_cache == NULL)
            return NULL;
    }

590 591
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
592 593
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_union_setup (arg_cache, transfer);
594

595 596
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_union_setup (arg_cache, transfer);
597

598
            break;
599
        case GI_INFO_TYPE_BOXED:
600
        case GI_INFO_TYPE_STRUCT:
601 602 603 604 605 606 607 608 609
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_struct_setup (arg_cache,
                                                          iface_info,
                                                          transfer);

            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_struct_setup (arg_cache,
                                                        iface_info,
                                                        transfer);
610 611 612
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
613 614
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_object_setup (arg_cache, transfer);
615

616 617
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_object_setup (arg_cache, transfer);
618

619 620
            break;
        case GI_INFO_TYPE_CALLBACK:
621 622 623
            {
                PyGICallbackCache *callback_cache;

624 625
                if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL) {
                    _arg_cache_to_py_interface_callback_setup ();
626 627 628
                    return NULL;
                }

John (J5) Palmieri's avatar
John (J5) Palmieri committed
629
                callback_cache =
630 631 632
                    _callback_cache_new (arg_info,
                                         iface_info,
                                         child_offset);
633 634 635 636 637

                arg_cache = (PyGIArgCache *)callback_cache;
                if (arg_cache == NULL)
                    return NULL;

638 639
                if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
                    _arg_cache_from_py_interface_callback_setup (arg_cache, callable_cache);
640 641 642

                break;
            }
643
        case GI_INFO_TYPE_ENUM:
644 645
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_enum_setup (arg_cache, transfer);
646

647 648
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_enum_setup (arg_cache, transfer);
649

650 651
            break;
        case GI_INFO_TYPE_FLAGS:
652 653
            if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_interface_flags_setup (arg_cache, transfer);
654

655 656
            if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_interface_flags_setup (arg_cache, transfer);
657

658 659
            break;
        default:
660
            g_assert_not_reached ();
661 662 663 664 665 666 667 668
    }

    if (arg_cache != NULL) {
        arg_cache->direction = direction;
        arg_cache->transfer = transfer;
        arg_cache->type_tag = GI_TYPE_TAG_INTERFACE;
        arg_cache->py_arg_index = py_arg_index;
        arg_cache->c_arg_index = c_arg_index;
669

670
        if (iface_cache != NULL) {
671
            g_base_info_ref ( (GIBaseInfo *)iface_info);
672 673
            iface_cache->interface_info = iface_info;
        }
674
    }
675 676

    return arg_cache;
677 678
}

679
PyGIArgCache *
680 681 682 683
_arg_cache_new (GITypeInfo *type_info,
                PyGICallableCache *callable_cache,
                GIArgInfo *arg_info,
                GITransfer transfer,
684
                PyGIDirection direction,
685 686
                gssize c_arg_index,
                gssize py_arg_index)
687
{
688
    PyGIArgCache *arg_cache = NULL;
689
    gssize child_offset = 0;
690
    GITypeTag type_tag;
691

692 693
    type_tag = g_type_info_get_tag (type_info);

694 695 696 697
    if (callable_cache != NULL)
        child_offset =
            (callable_cache->function_type == PYGI_FUNCTION_TYPE_METHOD ||
                callable_cache->function_type == PYGI_FUNCTION_TYPE_VFUNC) ? 1: 0;
698

699 700
    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
701
           arg_cache = _arg_cache_alloc ();
702 703
           if (arg_cache == NULL)
               break;
704

705 706 707 708 709
           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_from_py_void_setup (arg_cache);

           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
               _arg_cache_to_py_void_setup (arg_cache);
710

711 712 713 714 715 716 717 718 719 720 721 722 723 724
           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:
725
           arg_cache = _arg_cache_alloc ();
726 727
           if (arg_cache == NULL)
               break;
728

729
           if (direction == PYGI_DIRECTION_FROM_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
730
               _arg_cache_from_py_basic_type_setup (arg_cache);
731

732
           if (direction == PYGI_DIRECTION_TO_PYTHON || direction == PYGI_DIRECTION_BIDIRECTIONAL)
733
               _arg_cache_to_py_basic_type_setup (arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
734

735 736
           break;
       case GI_TYPE_TAG_UTF8:
737
       case GI_TYPE_TAG_FILENAME:
738
           arg_cache = _arg_cache_alloc ();
739 740
           if (arg_cache == NULL)
               break;
John (J5) Palmieri's avatar