1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
|
/* -*- mode: c; indent-tabs-mode: t; c-basic-offset: 8; -*- */
static void
store_fields (HV *fields, GIBaseInfo *info, GIInfoType info_type)
{
const gchar *namespace;
AV *av;
gint i;
namespace = g_base_info_get_name (info);
av = newAV ();
switch (info_type) {
case GI_INFO_TYPE_BOXED:
case GI_INFO_TYPE_STRUCT:
{
gint n_fields = g_struct_info_get_n_fields (
(GIStructInfo *) info);
for (i = 0; i < n_fields; i++) {
GIFieldInfo *field_info;
const gchar *field_name;
field_info = g_struct_info_get_field ((GIStructInfo *) info, i);
field_name = g_base_info_get_name ((GIBaseInfo *) field_info);
av_push (av, newSVpv (field_name, PL_na));
g_base_info_unref ((GIBaseInfo *) field_info);
}
break;
}
case GI_INFO_TYPE_UNION:
{
gint n_fields = g_union_info_get_n_fields ((GIUnionInfo *) info);
for (i = 0; i < n_fields; i++) {
GIFieldInfo *field_info;
const gchar *field_name;
field_info = g_union_info_get_field ((GIUnionInfo *) info, i);
field_name = g_base_info_get_name ((GIBaseInfo *) field_info);
av_push (av, newSVpv (field_name, PL_na));
g_base_info_unref ((GIBaseInfo *) field_info);
}
break;
}
default:
ccroak ("store_fields: unsupported info type %d", info_type);
}
gperl_hv_take_sv (fields, namespace, strlen (namespace),
newRV_noinc ((SV *) av));
}
/* This may call Perl code (via arg_to_sv), so it needs to be wrapped with
* PUTBACK/SPAGAIN by the caller. */
static SV *
get_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer)
{
GITypeInfo *field_type;
GIBaseInfo *interface_info;
GIArgument value;
SV *sv = NULL;
field_type = g_field_info_get_type (field_info);
interface_info = g_type_info_get_interface (field_type);
/* This case is not handled by g_field_info_set_field. */
if (!g_type_info_is_pointer (field_type) &&
g_type_info_get_tag (field_type) == GI_TYPE_TAG_INTERFACE &&
g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT)
{
gsize offset;
offset = g_field_info_get_offset (field_info);
value.v_pointer = mem + offset;
sv = arg_to_sv (&value,
field_type,
GI_TRANSFER_NOTHING,
NULL);
} else if (g_field_info_get_field (field_info, mem, &value)) {
sv = arg_to_sv (&value,
field_type,
transfer,
NULL);
} else {
ccroak ("Could not get field '%s'",
g_base_info_get_name (field_info));
}
if (interface_info)
g_base_info_unref (interface_info);
g_base_info_unref ((GIBaseInfo *) field_type);
return sv;
}
static void
set_field (GIFieldInfo *field_info, gpointer mem, GITransfer transfer, SV *value)
{
GITypeInfo *field_type;
GIBaseInfo *interface_info;
GIArgument arg;
field_type = g_field_info_get_type (field_info);
interface_info = g_type_info_get_interface (field_type);
/* FIXME: No GIArgInfo and no
* GPerlI11nInvocationInfo here. What if the
* struct contains an object pointer, or a
* callback field? And is it OK to always
* allow undef? */
/* This case is not handled by g_field_info_set_field. */
if (!g_type_info_is_pointer (field_type) &&
g_type_info_get_tag (field_type) == GI_TYPE_TAG_INTERFACE &&
g_base_info_get_type (interface_info) == GI_INFO_TYPE_STRUCT)
{
gsize offset;
gssize size;
/* Enforce GI_TRANSFER_NOTHING since we will copy into the
* memory that has already been allocated inside 'mem' */
sv_to_arg (value, &arg, NULL, field_type,
GI_TRANSFER_NOTHING, TRUE, NULL);
offset = g_field_info_get_offset (field_info);
size = g_struct_info_get_size (interface_info);
g_memmove (mem + offset, arg.v_pointer, size);
} else {
sv_to_arg (value, &arg, NULL, field_type,
transfer, TRUE, NULL);
if (!g_field_info_set_field (field_info, mem, &arg))
ccroak ("Could not set field '%s'",
g_base_info_get_name (field_info));
}
if (interface_info)
g_base_info_unref (interface_info);
g_base_info_unref (field_type);
}
|