pygi-cache.c 46 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
#include "pygi-marshal.h"
25
#include "pygi-type.h"
26
#include <girepository.h>
27

28
PyGIArgCache * _arg_cache_new_from_type_info (GITypeInfo *type_info,
29
                                              PyGICallableCache *callable_cache,
30
31
32
33
34
35
36
                                              GIArgInfo *arg_info,
                                              GITypeTag type_tag,
                                              GITransfer transfer,
                                              GIDirection direction,
                                              gint c_arg_index,
                                              gint py_arg_index);

37
/* cleanup */
John (J5) Palmieri's avatar
John (J5) Palmieri committed
38
39
40
41
42
43
void
_pygi_arg_cache_free(PyGIArgCache *cache)
{
    if (cache == NULL)
        return;

44
45
    if (cache->type_info != NULL)
        g_base_info_unref( (GIBaseInfo *)cache->type_info);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
46
47
48
49
50
51
52
    if (cache->destroy_notify)
        cache->destroy_notify(cache);
    else
        g_slice_free(PyGIArgCache, cache);
}

static void
53
_interface_cache_free_func (PyGIInterfaceCache *cache)
54
55
56
{
    if (cache != NULL) {
        Py_XDECREF(cache->py_type);
57
58
        if (cache->type_name != NULL)
            g_free(cache->type_name);
59
60
61
        if (cache->interface_info != NULL)
            g_base_info_unref( (GIBaseInfo *)cache->interface_info);
        g_slice_free(PyGIInterfaceCache, cache);
62
63
64
    }
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
65
66
static void
_hash_cache_free_func(PyGIHashCache *cache)
67
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
68
69
70
    if (cache != NULL) {
        _pygi_arg_cache_free(cache->key_cache);
        _pygi_arg_cache_free(cache->value_cache);
71
        g_slice_free(PyGIHashCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
72
    }
73
74
}

75
static void
John (J5) Palmieri's avatar
John (J5) Palmieri committed
76
_sequence_cache_free_func(PyGISequenceCache *cache)
77
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
78
79
    if (cache != NULL) {
        _pygi_arg_cache_free(cache->item_cache);
80
        g_slice_free(PyGISequenceCache, cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
81
    }
82
83
}

84
static void
John (J5) Palmieri's avatar
John (J5) Palmieri committed
85
_callback_cache_free_func(PyGICallbackCache *cache)
86
{
87
88
89
90
    if (cache != NULL) {
        if (cache->interface_info != NULL)
            g_base_info_unref( (GIBaseInfo *)cache->interface_info);

91
        g_slice_free(PyGICallbackCache, cache);
92
    }
93
94
95
}

void
96
_pygi_callable_cache_free(PyGICallableCache *cache)
97
98
99
{
    int i;

100
101
102
    if (cache == NULL)
        return;

103
104
105
    g_slist_free(cache->out_args);
    for (i = 0; i < cache->n_args; i++) {
        PyGIArgCache *tmp = cache->args_cache[i];
106
        _pygi_arg_cache_free(tmp);
107
    }
108
109
110
    if (cache->return_cache != NULL)
        _pygi_arg_cache_free(cache->return_cache);

111
    g_slice_free1(cache->n_args * sizeof(PyGIArgCache *), cache->args_cache);
112
    g_slice_free(PyGICallableCache, cache);
113
114
115
}

/* cache generation */
116
117
static inline PyGICallableCache *
_callable_cache_new_from_callable_info(GICallableInfo *callable_info)
118
{
119
    PyGICallableCache *cache;
120

121
    cache = g_slice_new0 (PyGICallableCache);
122

123
    cache->name = g_base_info_get_name ((GIBaseInfo *)callable_info);
124

125
126
    if (g_base_info_get_type ( (GIBaseInfo *)callable_info) == GI_INFO_TYPE_FUNCTION) {
        GIFunctionInfoFlags flags;
127

128
129
130
131
132
133
134
135
136
137
138
139
140
        flags = g_function_info_get_flags ( (GIFunctionInfo *)callable_info);
        cache->is_method = flags & GI_FUNCTION_IS_METHOD;
        cache->is_constructor = flags & GI_FUNCTION_IS_CONSTRUCTOR;
    } else {
        cache->is_method = TRUE;
        cache->is_constructor = FALSE;
    }

    cache->n_args = g_callable_info_get_n_args (callable_info) + (cache->is_method ? 1: 0);
    if (cache->n_args > 0)
        cache->args_cache = g_slice_alloc0 (cache->n_args * sizeof(PyGIArgCache *));

    return cache;
141
142
}

143
144
145
146
static inline PyGIInterfaceCache *
_interface_cache_new_from_interface_info(GIInterfaceInfo *iface_info)
{
    PyGIInterfaceCache *ic;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
147

148
    ic = g_slice_new0(PyGIInterfaceCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
149
    ((PyGIArgCache *)ic)->destroy_notify = (GDestroyNotify)_interface_cache_free_func;
150
151
152
153
154
155
156
157
158
159
160
    ic->g_type = g_registered_type_info_get_g_type ( (GIRegisteredTypeInfo *)iface_info);
    if (ic->g_type != G_TYPE_NONE) {
        ic->py_type = _pygi_type_get_from_g_type (ic->g_type);
    } else {
        /* FIXME: avoid passing GI infos to noncache API */
        ic->py_type = _pygi_type_import_by_gi_info ( (GIBaseInfo *) iface_info);
    }

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

161
    ic->type_name = _pygi_g_base_info_get_fullname(iface_info);
162
163
164
    return ic;
}

165
static inline PyGISequenceCache *
166
_sequence_cache_new_from_type_info(GITypeInfo *type_info,
167
168
                                   GIDirection direction,
                                   GITransfer transfer,
169
                                   gint aux_offset)
170
171
172
{
    PyGISequenceCache *sc;
    GITypeInfo *item_type_info;
173
    GITypeTag item_type_tag;
174
    GITransfer item_transfer;
175
176

    sc = g_slice_new0(PyGISequenceCache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
177
    ((PyGIArgCache *)sc)->destroy_notify = (GDestroyNotify)_sequence_cache_free_func;
178
179
180
181

    sc->fixed_size = -1;
    sc->len_arg_index = -1;
    sc->is_zero_terminated = g_type_info_is_zero_terminated(type_info);
182
    if (!sc->is_zero_terminated) {
183
        sc->fixed_size = g_type_info_get_array_fixed_size(type_info);
184
185
186
        if (sc->fixed_size < 0)
            sc->len_arg_index = g_type_info_get_array_length (type_info) + aux_offset;
    }
187

188
    item_type_info = g_type_info_get_param_type (type_info, 0);
189
    item_type_tag = g_type_info_get_tag (item_type_info);
190

191
192
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
193

194
195
196
197
198
199
200
    sc->item_cache = _arg_cache_new_from_type_info(item_type_info,
                                                   NULL,
                                                   NULL,
                                                   item_type_tag,
                                                   item_transfer,
                                                   direction,
                                                   0, 0);
201

202
203
204
205
    if (sc->item_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)sc);
        return NULL;
    }
John (J5) Palmieri's avatar
John (J5) Palmieri committed
206

207
    sc->item_cache->type_tag = item_type_tag;
208
    sc->item_size = _pygi_g_type_info_size(item_type_info);
209
    g_base_info_unref( (GIBaseInfo *) item_type_info);
210

211
    return sc;
212
}
John (J5) Palmieri's avatar
John (J5) Palmieri committed
213
static inline PyGIHashCache *
214
215
216
_hash_cache_new_from_type_info(GITypeInfo *type_info,
                               GIDirection direction,
                               GITransfer transfer)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
217
218
219
220
221
222
{
    PyGIHashCache *hc;
    GITypeInfo *key_type_info;
    GITypeTag key_type_tag;
    GITypeInfo *value_type_info;
    GITypeTag value_type_tag;
223
    GITransfer item_transfer;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
224
225
226
227
228
229
230
231

    hc = g_slice_new0(PyGIHashCache);
    ((PyGIArgCache *)hc)->destroy_notify = (GDestroyNotify)_hash_cache_free_func;
    key_type_info = g_type_info_get_param_type (type_info, 0);
    key_type_tag = g_type_info_get_tag (key_type_info);
    value_type_info = g_type_info_get_param_type (type_info, 1);
    value_type_tag = g_type_info_get_tag (value_type_info);

232
233
    item_transfer =
        transfer == GI_TRANSFER_CONTAINER ? GI_TRANSFER_NOTHING : transfer;
234

235
236
237
238
    hc->key_cache = _arg_cache_new_from_type_info(key_type_info,
                                                  NULL,
                                                  NULL,
                                                  key_type_tag,
239
240
                                                  item_transfer,
                                                  direction,
241
                                                  0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
242
243
244
245
246
247

    if (hc->key_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)hc);
        return NULL;
    }

248
249
250
251
    hc->value_cache = _arg_cache_new_from_type_info(value_type_info,
                                                    NULL,
                                                    NULL,
                                                    value_type_tag,
252
253
                                                    item_transfer,
                                                    direction,
254
                                                    0, 0);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
255
256
257
258
259
260
261
262
263
264
265
266
267
268

    if (hc->value_cache == NULL) {
        _pygi_arg_cache_free((PyGIArgCache *)hc);
        return NULL;
    }

    hc->key_cache->type_tag = key_type_tag;
    hc->value_cache->type_tag = value_type_tag;

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

    return hc;
}
269

John (J5) Palmieri's avatar
John (J5) Palmieri committed
270
static inline PyGICallbackCache *
271
_callback_cache_new_from_arg_info(GIArgInfo *arg_info,
272
                                  GIInterfaceInfo *iface_info,
273
                                  gint aux_offset)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
274
275
276
277
{
   PyGICallbackCache *cc;

   cc = g_slice_new0(PyGICallbackCache);
278
279
280
281
282
283
   cc->user_data_index = g_arg_info_get_closure(arg_info);
   if (cc->user_data_index != -1)
       cc->user_data_index += aux_offset;
   cc->destroy_notify_index = g_arg_info_get_destroy(arg_info);
   if (cc->destroy_notify_index != -1)
       cc->destroy_notify_index += aux_offset;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
284
   cc->scope = g_arg_info_get_scope(arg_info);
285
286
   g_base_info_ref( (GIBaseInfo *)iface_info);
   cc->interface_info = iface_info;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
287
288
289
   return cc;
}

290
291
292
293
294
static inline PyGIArgCache *
_arg_cache_new(void)
{
    return g_slice_new0(PyGIArgCache);
}
295

John (J5) Palmieri's avatar
John (J5) Palmieri committed
296
static inline void
297
_arg_cache_in_void_setup(PyGIArgCache *arg_cache)
298
{
299
300
    arg_cache->in_marshaller = _pygi_marshal_in_void;
}
301

John (J5) Palmieri's avatar
John (J5) Palmieri committed
302
static inline void
303
304
305
_arg_cache_out_void_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_void;
306
307
}

308
309
static inline void
_arg_cache_in_boolean_setup(PyGIArgCache *arg_cache)
310
{
311
    arg_cache->in_marshaller = _pygi_marshal_in_boolean;
312
313
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
314
static inline void
315
316
317
318
319
320
321
_arg_cache_out_boolean_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_boolean;
}

static inline void
_arg_cache_in_int8_setup(PyGIArgCache *arg_cache)
322
{
323
    arg_cache->in_marshaller = _pygi_marshal_in_int8;
324
325
}

326
327
328
329
330
331
332
333
static inline void
_arg_cache_out_int8_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_int8;
}

static inline void
_arg_cache_in_uint8_setup(PyGIArgCache *arg_cache)
334
{
335
    arg_cache->in_marshaller = _pygi_marshal_in_uint8;
336
337
}

338
339
340
341
342
343
344
345
static inline void
_arg_cache_out_uint8_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint8;
}

static inline void
_arg_cache_in_int16_setup(PyGIArgCache *arg_cache)
346
{
347
    arg_cache->in_marshaller = _pygi_marshal_in_int16;
348
349
}

350
351
352
353
354
355
356
357
static inline void
_arg_cache_out_int16_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_int16;
}

static inline void
_arg_cache_in_uint16_setup(PyGIArgCache *arg_cache)
358
{
359
    arg_cache->in_marshaller = _pygi_marshal_in_uint16;
360
361
}

362
363
364
365
366
367
368
369
static inline void
_arg_cache_out_uint16_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint16;
}

static inline void
_arg_cache_in_int32_setup(PyGIArgCache *arg_cache)
370
{
371
    arg_cache->in_marshaller = _pygi_marshal_in_int32;
372
373
}

374
375
376
377
378
379
380
381
static inline void
_arg_cache_out_int32_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_int32;
}

static inline void
_arg_cache_in_uint32_setup(PyGIArgCache *arg_cache)
382
{
383
    arg_cache->in_marshaller = _pygi_marshal_in_uint32;
384
385
}

386
387
388
389
390
391
392
393
static inline void
_arg_cache_out_uint32_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint32;
}

static inline void
_arg_cache_in_int64_setup(PyGIArgCache *arg_cache)
394
{
395
    arg_cache->in_marshaller = _pygi_marshal_in_int64;
396
397
}

398
399
400
401
402
403
404
405
static inline void
_arg_cache_out_int64_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_int64;
}

static inline void
_arg_cache_in_uint64_setup(PyGIArgCache *arg_cache)
406
{
407
    arg_cache->in_marshaller = _pygi_marshal_in_uint64;
408
409
}

410
411
412
413
414
415
416
417
static inline void
_arg_cache_out_uint64_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_uint64;
}

static inline void
_arg_cache_in_float_setup(PyGIArgCache *arg_cache)
418
{
419
    arg_cache->in_marshaller = _pygi_marshal_in_float;
420
421
}

422
423
424
425
426
427
428
429
static inline void
_arg_cache_out_float_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_float;
}

static inline void
_arg_cache_in_double_setup(PyGIArgCache *arg_cache)
430
{
431
    arg_cache->in_marshaller = _pygi_marshal_in_double;
432
433
}

434
435
436
437
438
439
440
441
static inline void
_arg_cache_out_double_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_double;
}

static inline void
_arg_cache_in_unichar_setup(PyGIArgCache *arg_cache)
442
{
443
    arg_cache->in_marshaller = _pygi_marshal_in_unichar;
444
445
}

446
447
448
449
450
451
452
453
static inline void
_arg_cache_out_unichar_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_unichar;
}

static inline void
_arg_cache_in_gtype_setup(PyGIArgCache *arg_cache)
454
{
455
    arg_cache->in_marshaller = _pygi_marshal_in_gtype;
456
457
}

458
459
460
461
462
463
464
465
466
static inline void
_arg_cache_out_gtype_setup(PyGIArgCache *arg_cache)
{
    arg_cache->out_marshaller = _pygi_marshal_out_gtype;
}

static inline void
_arg_cache_in_utf8_setup(PyGIArgCache *arg_cache,
                         GITransfer transfer)
467
{
468
    arg_cache->in_marshaller = _pygi_marshal_in_utf8;
469
}
470

471
472
473
474
475
static inline void
_arg_cache_out_utf8_setup(PyGIArgCache *arg_cache,
                          GITransfer transfer)
{
    arg_cache->out_marshaller = _pygi_marshal_out_utf8;
476
477
}

478
479
480
static inline void
_arg_cache_in_filename_setup(PyGIArgCache *arg_cache,
                             GITransfer transfer)
481
{
482
    arg_cache->in_marshaller = _pygi_marshal_in_filename;
483
484
}

485
486
487
static inline void
_arg_cache_out_filename_setup(PyGIArgCache *arg_cache,
                              GITransfer transfer)
488
{
489
490
    arg_cache->out_marshaller = _pygi_marshal_out_filename;
}
491

492
static inline gboolean
493
494
495
496
497
_arg_cache_in_array_setup (PyGIArgCache *arg_cache,
                           PyGICallableCache *callable_cache,
                           GITypeInfo *type_info,
                           GITransfer transfer,
                           GIDirection direction)
498
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
499
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
500
    seq_cache->array_type = g_type_info_get_array_type (type_info);
501

502
    arg_cache->in_marshaller = _pygi_marshal_in_array;
503

504
505
506
    if (seq_cache->len_arg_index >= 0 &&
        direction == GI_DIRECTION_IN) {
        PyGIArgCache *aux_cache = 
507
            callable_cache->args_cache[seq_cache->len_arg_index];
508
509
510
511
512
513
514

        if (aux_cache == NULL) {
            aux_cache = _arg_cache_new();
        } else if (aux_cache->aux_type == PYGI_AUX_TYPE_IGNORE) {
            return TRUE;
        }

John (J5) Palmieri's avatar
John (J5) Palmieri committed
515
        aux_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
516
        aux_cache->direction = direction;
517
518
        aux_cache->in_marshaller = NULL;
        aux_cache->out_marshaller = NULL;
519

520
        callable_cache->args_cache[seq_cache->len_arg_index] = aux_cache;
521
522
    }

523
    /* arg_cache->cleanup = _pygi_cleanup_array; */
524
525

    return TRUE;
526
527
}

528
static inline gboolean
529
530
531
532
533
534
_arg_cache_out_array_setup (PyGIArgCache *arg_cache,
                            PyGICallableCache *callable_cache,
                            GITypeInfo *type_info,
                            GITransfer transfer,
                            GIDirection direction,
                            gssize arg_index)
535
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
536
    PyGISequenceCache *seq_cache = (PyGISequenceCache *)arg_cache;
537
538
    arg_cache->out_marshaller = _pygi_marshal_out_array;

539
    seq_cache->array_type = g_type_info_get_array_type (type_info);
540
541

    if (seq_cache->len_arg_index >= 0) {
542
        PyGIArgCache *aux_cache = callable_cache->args_cache[seq_cache->len_arg_index];
543
        if (seq_cache->len_arg_index < arg_index)
544
             callable_cache->n_out_aux_args++;
545

546
547
548
549
        if (aux_cache != NULL) {
            if (aux_cache->aux_type == PYGI_AUX_TYPE_IGNORE)
                return TRUE;

550
551
            callable_cache->out_args = 
                g_slist_remove (callable_cache->out_args, aux_cache);
552
        } else {
553
            aux_cache = _arg_cache_new();
554
        }
555
556

        aux_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
557
558
559
        aux_cache->direction = direction;
        aux_cache->in_marshaller = NULL;
        aux_cache->out_marshaller = NULL;
560

561
        callable_cache->args_cache[seq_cache->len_arg_index] = aux_cache;
562
563
564
565
566
567
568
    }

    return TRUE;
    /* arg_cache->cleanup = _pygi_cleanup_array; */
}

static inline void
569
570
_arg_cache_in_glist_setup (PyGIArgCache *arg_cache,
                           GITransfer transfer)
571
{
572
    arg_cache->in_marshaller = _pygi_marshal_in_glist;
573
    /* arg_cache->cleanup = */
574
}
575

576
static inline void
577
578
_arg_cache_out_glist_setup (PyGIArgCache *arg_cache,
                            GITransfer transfer)
579
580
581
{
    arg_cache->out_marshaller = _pygi_marshal_out_glist;
    /* arg_cache->cleanup = */
582
583
}

584
static inline void
585
586
_arg_cache_in_gslist_setup (PyGIArgCache *arg_cache,
                            GITransfer transfer)
587
{
588
    arg_cache->in_marshaller = _pygi_marshal_in_gslist;
589
    /* arg_cache->cleanup = */
590
}
591

592
static inline void
593
594
_arg_cache_out_gslist_setup (PyGIArgCache *arg_cache,
                             GITransfer transfer)
595
596
597
{
    arg_cache->out_marshaller = _pygi_marshal_out_gslist;
    /* arg_cache->cleanup = */
598
599
}

600
static inline void
601
_arg_cache_in_ghash_setup (PyGIArgCache *arg_cache)
602
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
603
    arg_cache->in_marshaller = _pygi_marshal_in_ghash;
604
605
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
606
static inline void
607
_arg_cache_out_ghash_setup (PyGIArgCache *arg_cache)
608
{
609
    arg_cache->out_marshaller = _pygi_marshal_out_ghash;
610
611
612
}

static inline void
613
_arg_cache_in_gerror_setup (PyGIArgCache *arg_cache)
614
{
615
    arg_cache->in_marshaller = _pygi_marshal_in_gerror;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
616
    arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
617
618
}

619
static inline void
620
_arg_cache_out_gerror_setup (PyGIArgCache *arg_cache)
621
622
623
624
625
626
{
    arg_cache->out_marshaller = _pygi_marshal_out_gerror;
    arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
}

static inline void
627
628
_arg_cache_in_interface_union_setup (PyGIArgCache *arg_cache,
                                     GITransfer transfer)
629
{
John (J5) Palmieri's avatar
John (J5) Palmieri committed
630
    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
631
632
633
}

static inline void
634
635
_arg_cache_out_interface_union_setup (PyGIArgCache *arg_cache,
                                      GITransfer transfer)
636
637
{
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
638
639
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
640
static void
641
_g_slice_free_gvalue_func (GValue *value) {
642
643
644
    g_slice_free(GValue, value);
}

645
static inline void
646
647
648
_arg_cache_in_interface_struct_setup (PyGIArgCache *arg_cache,
                                      GIInterfaceInfo *iface_info,
                                      GITransfer transfer)
649
{
650
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
651
652
653
654
655
656
    iface_cache->is_foreign = g_struct_info_is_foreign( (GIStructInfo*)iface_info);
    arg_cache->in_marshaller = _pygi_marshal_in_interface_struct;
    if (iface_cache->g_type == G_TYPE_VALUE)
        arg_cache->cleanup = _g_slice_free_gvalue_func;
    if (iface_cache->g_type == G_TYPE_CLOSURE)
        arg_cache->cleanup = g_closure_unref;
657
}
658

659
static inline void
660
661
662
_arg_cache_out_interface_struct_setup (PyGIArgCache *arg_cache,
                                       GIInterfaceInfo *iface_info,
                                       GITransfer transfer)
663
664
665
666
{
    PyGIInterfaceCache *iface_cache = (PyGIInterfaceCache *)arg_cache;
    iface_cache->is_foreign = g_struct_info_is_foreign( (GIStructInfo*)iface_info);
    arg_cache->out_marshaller = _pygi_marshal_out_interface_struct;
667
668
}

669
static inline void
670
671
_arg_cache_in_interface_object_setup (PyGIArgCache *arg_cache,
                                      GITransfer transfer)
672
673
674
675
676
677
{
    arg_cache->in_marshaller = _pygi_marshal_in_interface_object;
    if (transfer == GI_TRANSFER_EVERYTHING)
        arg_cache->cleanup = (GDestroyNotify)g_object_unref;
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
678
static inline void
679
680
_arg_cache_out_interface_object_setup (PyGIArgCache *arg_cache,
                                       GITransfer transfer)
681
{
682
683
684
685
    arg_cache->out_marshaller = _pygi_marshal_out_interface_object;
}

static inline void
686
687
_arg_cache_in_interface_callback_setup (PyGIArgCache *arg_cache,
                                        PyGICallableCache *callable_cache)
John (J5) Palmieri's avatar
John (J5) Palmieri committed
688
{
689
    PyGICallbackCache *callback_cache = (PyGICallbackCache *)arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
690
    if (callback_cache->user_data_index >= 0) {
691
        PyGIArgCache *user_data_arg_cache = _arg_cache_new ();
John (J5) Palmieri's avatar
John (J5) Palmieri committed
692
        user_data_arg_cache->aux_type = PYGI_AUX_TYPE_HAS_PYARG;
693
        callable_cache->args_cache[callback_cache->user_data_index] = user_data_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
694
    }
695
696

    if (callback_cache->destroy_notify_index >= 0) {
697
        PyGIArgCache *destroy_arg_cache = _arg_cache_new ();
John (J5) Palmieri's avatar
John (J5) Palmieri committed
698
        destroy_arg_cache->aux_type = PYGI_AUX_TYPE_IGNORE;
699
        callable_cache->args_cache[callback_cache->destroy_notify_index] = destroy_arg_cache;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
700
701
    }
    arg_cache->in_marshaller = _pygi_marshal_in_interface_callback;
702
703
}

John (J5) Palmieri's avatar
John (J5) Palmieri committed
704
static inline void
705
_arg_cache_out_interface_callback_setup (void)
706
{
707
708
709
    PyErr_Format(PyExc_NotImplementedError,
                 "Callback returns are not supported");
}
710

John (J5) Palmieri's avatar
John (J5) Palmieri committed
711
static inline void
712
713
_arg_cache_in_interface_enum_setup (PyGIArgCache *arg_cache,
                                    GITransfer transfer)
714
{
715
    arg_cache->in_marshaller = _pygi_marshal_in_interface_enum;
716
717
}

718
static inline void
719
720
_arg_cache_out_interface_enum_setup (PyGIArgCache *arg_cache,
                                     GITransfer transfer)
721
{
722
723
    arg_cache->out_marshaller = _pygi_marshal_out_interface_enum;
}
724

John (J5) Palmieri's avatar
John (J5) Palmieri committed
725
static inline void
726
727
_arg_cache_in_interface_flags_setup (PyGIArgCache *arg_cache,
                                     GITransfer transfer)
728
{
729
    arg_cache->in_marshaller = _pygi_marshal_in_interface_flags;
730
731
}

732
static inline void
733
734
_arg_cache_out_interface_flags_setup (PyGIArgCache *arg_cache,
                                      GITransfer transfer)
735
{
736
737
738
739
740
    arg_cache->out_marshaller = _pygi_marshal_out_interface_flags;
}

static inline PyGIArgCache *
_arg_cache_new_from_interface_info (GIInterfaceInfo *iface_info,
741
                                    PyGICallableCache *callable_cache,
742
743
744
745
746
747
748
749
                                    GIArgInfo *arg_info,
                                    GIInfoType info_type,
                                    GITransfer transfer,
                                    GIDirection direction,
                                    gint c_arg_index,
                                    gint py_arg_index)
{
    PyGIInterfaceCache *iface_cache = NULL;
750
751
    PyGIArgCache *arg_cache = NULL;

752
753
    GI_IS_INTERFACE_INFO (iface_info);

754
755
756
757
758
759
760
761
762
    /* Callbacks are special cased */
    if (info_type != GI_INFO_TYPE_CALLBACK) {
        iface_cache = _interface_cache_new_from_interface_info(iface_info);

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

763
764
    switch (info_type) {
        case GI_INFO_TYPE_UNION:
765
766
767
768
769
770
            if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_interface_union_setup(arg_cache, transfer);

            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_interface_union_setup(arg_cache, transfer);

771
772
            break;
        case GI_INFO_TYPE_STRUCT:
773
774
            if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_interface_struct_setup(arg_cache,
John (J5) Palmieri's avatar
John (J5) Palmieri committed
775
                                                    iface_info,
776
777
778
779
780
781
782
                                                    transfer);

            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_interface_struct_setup(arg_cache,
                                                     iface_info,
                                                     transfer);

783
784
785
            break;
        case GI_INFO_TYPE_OBJECT:
        case GI_INFO_TYPE_INTERFACE:
786
787
788
789
790
791
            if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_interface_object_setup(arg_cache, transfer);

            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_interface_object_setup(arg_cache, transfer);

792
793
            break;
        case GI_INFO_TYPE_BOXED:
794
            if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
795
796
797
                _arg_cache_in_interface_struct_setup (arg_cache,
                                                                                  iface_info,
                                                                                  transfer);
798
799

            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
800
801
802
                _arg_cache_out_interface_struct_setup (arg_cache,
                                                                                     iface_info,
                                                                                     transfer);
803

804
805
            break;
        case GI_INFO_TYPE_CALLBACK:
806
807
808
809
810
811
812
813
            {
                PyGICallbackCache *callback_cache;

                if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT) {
                    _arg_cache_out_interface_callback_setup();
                    return NULL;
                }

John (J5) Palmieri's avatar
John (J5) Palmieri committed
814
                callback_cache =
815
816
                    _callback_cache_new_from_arg_info(arg_info,
                                                      iface_info,
817
                                                      callable_cache->is_method ? 1: 0);
818
819
820
821
822
823

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

                if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
824
                    _arg_cache_in_interface_callback_setup(arg_cache, callable_cache);
825
826
827

                break;
            }
828
        case GI_INFO_TYPE_ENUM:
829
830
831
832
833
834
            if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_interface_enum_setup(arg_cache, transfer);

            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_interface_enum_setup(arg_cache, transfer);

835
836
            break;
        case GI_INFO_TYPE_FLAGS:
837
838
839
840
841
842
            if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_interface_flags_setup(arg_cache, transfer);

            if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_interface_flags_setup(arg_cache, transfer);

843
844
845
846
847
848
849
850
851
852
853
            break;
        default:
            g_assert_not_reached();
    }

    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;
854

855
856
857
858
        if (iface_cache != NULL) {
            g_base_info_ref( (GIBaseInfo *)iface_info);
            iface_cache->interface_info = iface_info;
        }
859
    }
860
861

    return arg_cache;
862
863
}

864
865
PyGIArgCache *
_arg_cache_new_from_type_info (GITypeInfo *type_info,
866
                               PyGICallableCache *callable_cache,
867
868
869
870
871
872
                               GIArgInfo *arg_info,
                               GITypeTag type_tag,
                               GITransfer transfer,
                               GIDirection direction,
                               gint c_arg_index,
                               gint py_arg_index)
873
{
874
    PyGIArgCache *arg_cache = NULL;
875

876
877
878
879
880
    switch (type_tag) {
       case GI_TYPE_TAG_VOID:
           arg_cache = _arg_cache_new();
           if (arg_cache == NULL)
               break;
881

882
883
           if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_void_setup(arg_cache);
884

885
886
887
888
889
890
891
           if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_void_setup(arg_cache);
           break;
       case GI_TYPE_TAG_BOOLEAN:
           arg_cache = _arg_cache_new();
           if (arg_cache == NULL)
               break;
892

893
894
           if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_boolean_setup(arg_cache);
895

896
897
           if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_boolean_setup(arg_cache);
898

899
900
901
902
903
           break;
       case GI_TYPE_TAG_INT8:
           arg_cache = _arg_cache_new();
           if (arg_cache == NULL)
               break;
904

905
906
           if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_int8_setup(arg_cache);
907

908
909
           if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_int8_setup(arg_cache);
910

911
912
913
914
915
           break;
       case GI_TYPE_TAG_UINT8:
           arg_cache = _arg_cache_new();
           if (arg_cache == NULL)
               break;
916

917
918
           if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_uint8_setup(arg_cache);
919

920
921
           if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_uint8_setup(arg_cache);
John (J5) Palmieri's avatar
John (J5) Palmieri committed
922

923
924
925
926
927
           break;
       case GI_TYPE_TAG_INT16:
           arg_cache = _arg_cache_new();
           if (arg_cache == NULL)
               break;
John (J5) Palmieri's avatar
John (J5) Palmieri committed
928

929
930
           if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_int16_setup(arg_cache);
931

932
933
           if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_int16_setup(arg_cache);
934

935
936
937
938
939
           break;
       case GI_TYPE_TAG_UINT16:
           arg_cache = _arg_cache_new();
           if (arg_cache == NULL)
               break;
940

941
942
           if (direction == GI_DIRECTION_IN || direction == GI_DIRECTION_INOUT)
               _arg_cache_in_uint16_setup(arg_cache);
943

944
945
           if (direction == GI_DIRECTION_OUT || direction == GI_DIRECTION_INOUT)
               _arg_cache_out_uint16_setup(arg_cache);
946

947