<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
- <callback name="matrix" c:type="matrix">
- <return-value transfer-ownership="none">
- <type name="int" c:type="int"/>
- </return-value>
- <parameters>
- <parameter name="obj" transfer-ownership="none">
- <type name="TestObj" c:type="TestObj*"/>
- </parameter>
- <parameter name="somestr" transfer-ownership="none">
- <type name="utf8" c:type="char*"/>
- </parameter>
- </parameters>
- </callback>
+ <field name="matrix">
+ <callback name="matrix" c:type="matrix">
+ <return-value transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </return-value>
+ <parameters>
+ <parameter name="obj" transfer-ownership="none">
+ <type name="TestObj" c:type="TestObj*"/>
+ </parameter>
+ <parameter name="somestr" transfer-ownership="none">
+ <type name="utf8" c:type="char*"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
<field name="test_signal">
<type name="uint" c:type="guint"/>
</field>
struct _GITypeInfo
{
GIBaseInfo base;
+ gboolean is_embedded;
};
struct _GIUnionInfo
g_return_val_if_fail (container != NULL || repository != NULL, NULL);
- info = g_new0 (GIBaseInfo, 1);
+ if (type == GI_INFO_TYPE_TYPE)
+ info = (GIBaseInfo *)g_new0 (GITypeInfo, 1);
+ else
+ info = g_new0 (GIBaseInfo, 1);
info->ref_count = 1;
info->type = type;
guint32 offset)
{
SimpleTypeBlob *type = (SimpleTypeBlob *)&typelib->data[offset];
+ GITypeInfo *type_info;
- return (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, typelib,
+ type_info = (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE, container, typelib,
(type->flags.reserved == 0 && type->flags.reserved2 == 0) ? offset : type->offset);
+ type_info->is_embedded = FALSE;
+
+ return type_info;
}
/**
GIBaseInfo *base = (GIBaseInfo *)info;
SimpleTypeBlob *type = (SimpleTypeBlob *)&base->typelib->data[base->offset];
- if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
+ if (info->is_embedded)
+ return GI_TYPE_TAG_INTERFACE;
+ else if (type->flags.reserved == 0 && type->flags.reserved2 == 0)
return type->flags.tag;
else
{
{
GIBaseInfo *base = (GIBaseInfo *)info;
SimpleTypeBlob *type = (SimpleTypeBlob *)&base->typelib->data[base->offset];
-
+
+ if (info->is_embedded)
+ return (GIBaseInfo *) g_info_new (type->offset, base, base->typelib,
+ base->offset);
+
if (!(type->flags.reserved == 0 && type->flags.reserved2 == 0))
{
InterfaceTypeBlob *blob = (InterfaceTypeBlob *)&base->typelib->data[base->offset];
g_field_info_get_type (GIFieldInfo *info)
{
GIBaseInfo *base = (GIBaseInfo *)info;
-
- return g_type_info_new (base, base->typelib, base->offset + G_STRUCT_OFFSET (FieldBlob, type));
+ Header *header = (Header *)base->typelib->data;
+ FieldBlob *blob = (FieldBlob *)&base->typelib->data[base->offset];
+ GITypeInfo *type_info;
+
+ if (blob->has_embedded_type)
+ {
+ type_info = (GITypeInfo *) g_info_new (GI_INFO_TYPE_TYPE,
+ (GIBaseInfo*)info, base->typelib,
+ base->offset + header->field_blob_size);
+ type_info->is_embedded = TRUE;
+ }
+ else
+ return g_type_info_new (base, base->typelib, base->offset + G_STRUCT_OFFSET (FieldBlob, type));
+
+ return type_info;
}
/* GIRegisteredTypeInfo functions */
return blob->n_fields;
}
+static gint32
+g_struct_get_field_offset (GIStructInfo *info,
+ gint n)
+{
+ GIBaseInfo *base = (GIBaseInfo *)info;
+ Header *header = (Header *)base->typelib->data;
+ guint32 offset = base->offset + header->struct_blob_size;
+ gint i;
+ FieldBlob *field_blob;
+
+ for (i = 0; i < n; i++)
+ {
+ field_blob = (FieldBlob *)&base->typelib->data[offset];
+ offset += header->field_blob_size;
+ if (field_blob->has_embedded_type)
+ offset += header->callback_blob_size;
+ }
+
+ return offset;
+}
+
GIFieldInfo *
g_struct_info_get_field (GIStructInfo *info,
gint n)
{
GIBaseInfo *base = (GIBaseInfo *)info;
- Header *header = (Header *)base->typelib->data;
return (GIFieldInfo *) g_info_new (GI_INFO_TYPE_FIELD, base, base->typelib,
- base->offset + header->struct_blob_size +
- n * header->field_blob_size);
+ g_struct_get_field_offset (info, n));
}
gint
Header *header = (Header *)base->typelib->data;
gint offset;
- offset = base->offset + header->struct_blob_size
- + blob->n_fields * header->field_blob_size
+ offset = g_struct_get_field_offset (info, blob->n_fields)
+ n * header->function_blob_size;
return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, base,
base->typelib, offset);
GI_INFO_TYPE_CALLBACK,
GI_INFO_TYPE_STRUCT,
GI_INFO_TYPE_BOXED,
- GI_INFO_TYPE_ENUM,
+ GI_INFO_TYPE_ENUM, /* 5 */
GI_INFO_TYPE_FLAGS,
GI_INFO_TYPE_OBJECT,
GI_INFO_TYPE_INTERFACE,
GI_INFO_TYPE_CONSTANT,
- GI_INFO_TYPE_ERROR_DOMAIN,
+ GI_INFO_TYPE_ERROR_DOMAIN, /* 10 */
GI_INFO_TYPE_UNION,
GI_INFO_TYPE_VALUE,
GI_INFO_TYPE_SIGNAL,
GI_INFO_TYPE_VFUNC,
- GI_INFO_TYPE_PROPERTY,
+ GI_INFO_TYPE_PROPERTY, /* 15 */
GI_INFO_TYPE_FIELD,
GI_INFO_TYPE_ARG,
GI_INFO_TYPE_TYPE,
g_free (node->name);
g_ir_node_free ((GIrNode *)field->type);
+ g_ir_node_free ((GIrNode *)field->callback);
}
break;
break;
case G_IR_NODE_FIELD:
- size = sizeof (FieldBlob);
+ {
+ GIrNodeField *field = (GIrNodeField *)node;
+
+ size = sizeof (FieldBlob);
+ if (field->callback)
+ size += g_ir_node_get_size ((GIrNode *)field->callback);
+ }
break;
case G_IR_NODE_CONSTANT:
size = sizeof (FieldBlob);
size += ALIGN_VALUE (strlen (node->name) + 1, 4);
- size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->type);
+ if (field->callback)
+ size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->callback);
+ else
+ size += g_ir_node_get_full_size_internal (node, (GIrNode *)field->type);
}
break;
FieldBlob *blob;
blob = (FieldBlob *)&data[*offset];
- /* We handle the size member specially below, so subtract it */
- *offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob);
blob->name = write_string (node->name, strings, data, offset2);
blob->readable = field->readable;
else
blob->struct_offset = 0xFFFF; /* mark as unknown */
- g_ir_node_build_typelib ((GIrNode *)field->type,
- node, build, offset, offset2);
+ if (field->callback)
+ {
+ blob->has_embedded_type = TRUE;
+ blob->type.offset = GI_INFO_TYPE_CALLBACK;
+ *offset += sizeof (FieldBlob);
+ g_ir_node_build_typelib ((GIrNode *)field->callback,
+ node, build, offset, offset2);
+ }
+ else
+ {
+ blob->has_embedded_type = FALSE;
+ /* We handle the size member specially below, so subtract it */
+ *offset += sizeof (FieldBlob) - sizeof (SimpleTypeBlob);
+ g_ir_node_build_typelib ((GIrNode *)field->type,
+ node, build, offset, offset2);
+ }
}
break;
gboolean writable;
gint bits;
gint offset;
+ GIrNodeFunction *callback;
GIrNodeType *type;
};
who = g_strdup_printf ("field %s.%s.%s", module->name, parent_node->name, ((GIrNode *)field)->name);
- success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
+ if (field->callback)
+ {
+ *size = ffi_type_pointer.size;
+ *alignment = ffi_type_pointer.alignment;
+ success = TRUE;
+ }
+ else
+ success = get_type_size_alignment (field->type, module, modules, size, alignment, who);
g_free (who);
return success;
GList *type_stack;
GList *type_parameters;
int type_depth;
+ gboolean in_embedded_type;
};
#define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
strcmp (element_name, "method") == 0 ||
strcmp (element_name, "callback") == 0);
break;
+ case STATE_STRUCT_FIELD:
+ ctx->in_embedded_type = TRUE;
+ found = (found || strcmp (element_name, "callback") == 0);
+ break;
default:
break;
}
ctx->current_module->entries =
g_list_append (ctx->current_module->entries, function);
}
+ else if (ctx->current_typed)
+ {
+ GIrNodeField *field;
+
+ field = (GIrNodeField *)ctx->current_typed;
+ field->callback = function;
+ }
else
switch (CURRENT_NODE (ctx)->type)
{
}
else
{
- if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
+ g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
+ if (ctx->in_embedded_type)
+ {
+ ctx->in_embedded_type = FALSE;
+ state_switch (ctx, STATE_STRUCT_FIELD);
+ }
+ else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
state_switch (ctx, STATE_INTERFACE);
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_OBJECT)
state_switch (ctx, STATE_CLASS);
}
static gboolean
-validate_field_blob (GTypelib *typelib,
+validate_field_blob (ValidateContext *ctx,
guint32 offset,
GError **error)
{
+ GTypelib *typelib = ctx->typelib;
+ Header *header = (Header *)typelib->data;
FieldBlob *blob;
if (typelib->len < offset + sizeof (FieldBlob))
if (!validate_name (typelib, "field", typelib->data, blob->name, error))
return FALSE;
-
- if (!validate_type_blob (typelib,
- offset + G_STRUCT_OFFSET (FieldBlob, type),
- 0, FALSE, error))
+
+ if (blob->has_embedded_type)
+ {
+ if (!validate_callback_blob (ctx, offset + header->field_blob_size, error))
+ return FALSE;
+ }
+ else if (!validate_type_blob (typelib,
+ offset + G_STRUCT_OFFSET (FieldBlob, type),
+ 0, FALSE, error))
return FALSE;
return TRUE;
GTypelib *typelib = ctx->typelib;
StructBlob *blob;
gint i;
+ guint32 field_offset;
if (typelib->len < offset + sizeof (StructBlob))
{
return FALSE;
}
+ field_offset = offset + sizeof (StructBlob);
for (i = 0; i < blob->n_fields; i++)
{
- if (!validate_field_blob (typelib,
- offset + sizeof (StructBlob) +
- i * sizeof (FieldBlob),
+ FieldBlob *blob = (FieldBlob*) &typelib->data[field_offset];
+
+ if (!validate_field_blob (ctx,
+ field_offset,
error))
return FALSE;
+
+ field_offset += sizeof (FieldBlob);
+ if (blob->has_embedded_type)
+ field_offset += sizeof (CallbackBlob);
}
for (i = 0; i < blob->n_methods; i++)
{
if (!validate_function_blob (ctx,
- offset + sizeof (StructBlob) +
- blob->n_fields * sizeof (FieldBlob) +
+ field_offset +
i * sizeof (FunctionBlob),
blob_type,
error))
for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
{
- if (!validate_field_blob (typelib, offset2, error))
+ if (!validate_field_blob (ctx, offset2, error))
return FALSE;
}
* @name: The name of the field.
* @readable:
* @writable: How the field may be accessed.
+ * @has_embedded_type: An anonymous type follows the FieldBlob.
* @bits: If this field is part of a bitfield, the number of bits which it
* uses, otherwise 0.
* @struct_offset:
guint8 readable :1;
guint8 writable :1;
- guint8 reserved :6;
+ guint8 has_embedded_type :1;
+ guint8 reserved :5;
guint8 bits;
guint16 struct_offset;
return
if isinstance(field, Callback):
- self._write_callback(field)
+ attrs = [('name', field.name)]
+ with self.tagcontext('field', attrs):
+ self._write_attributes(field)
+ self._write_callback(field)
elif isinstance(field, Struct):
self._write_record(field)
elif isinstance(field, Union):
<field name="parent_iface">
<type name="GObject.TypeInterface" c:type="GTypeInterface"/>
</field>
- <callback name="do_foo" c:type="do_foo">
- <return-value transfer-ownership="none">
- <type name="none" c:type="void"/>
- </return-value>
- <parameters>
- <parameter name="self" transfer-ownership="none">
- <type name="Interface" c:type="FooInterface*"/>
- </parameter>
- <parameter name="x" transfer-ownership="none">
- <type name="int" c:type="int"/>
- </parameter>
- </parameters>
- </callback>
+ <field name="do_foo">
+ <callback name="do_foo" c:type="do_foo">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="self" transfer-ownership="none">
+ <type name="Interface" c:type="FooInterface*"/>
+ </parameter>
+ <parameter name="x" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
</record>
<class name="Object"
c:type="FooObject"
<field name="parent_class">
<type name="GObject.ObjectClass" c:type="GObjectClass"/>
</field>
- <callback name="virtual_method" c:type="virtual_method">
- <return-value transfer-ownership="none">
- <type name="boolean" c:type="gboolean"/>
- </return-value>
- <parameters>
- <parameter name="object" transfer-ownership="none">
- <type name="Object" c:type="FooObject*"/>
- </parameter>
- <parameter name="first_param" transfer-ownership="none">
- <type name="int" c:type="int"/>
- </parameter>
- </parameters>
- </callback>
- <callback name="read_fn" c:type="read_fn">
- <return-value transfer-ownership="none">
- <type name="none" c:type="void"/>
- </return-value>
- <parameters>
- <parameter name="object" transfer-ownership="none">
- <type name="Object" c:type="FooObject*"/>
- </parameter>
- <parameter name="offset" transfer-ownership="none">
- <type name="int" c:type="int"/>
- </parameter>
- <parameter name="length" transfer-ownership="none">
- <type name="int" c:type="int"/>
- </parameter>
- </parameters>
- </callback>
+ <field name="virtual_method">
+ <callback name="virtual_method" c:type="virtual_method">
+ <return-value transfer-ownership="none">
+ <type name="boolean" c:type="gboolean"/>
+ </return-value>
+ <parameters>
+ <parameter name="object" transfer-ownership="none">
+ <type name="Object" c:type="FooObject*"/>
+ </parameter>
+ <parameter name="first_param" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
+ <field name="read_fn">
+ <callback name="read_fn" c:type="read_fn">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="object" transfer-ownership="none">
+ <type name="Object" c:type="FooObject*"/>
+ </parameter>
+ <parameter name="offset" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ <parameter name="length" transfer-ownership="none">
+ <type name="int" c:type="int"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
<field name="_reserved">
<array zero-terminated="0" c:type="GCallback" fixed-size="4">
<type name="GObject.Callback"/>
<field name="parent_iface">
<type name="GObject.TypeInterface" c:type="GTypeInterface"/>
</field>
- <callback name="destroy_event" c:type="destroy_event">
- <return-value transfer-ownership="none">
- <type name="none" c:type="void"/>
- </return-value>
- <parameters>
- <parameter name="self" transfer-ownership="none">
- <type name="SubInterface" c:type="FooSubInterface*"/>
- </parameter>
- </parameters>
- </callback>
- <callback name="do_bar" c:type="do_bar">
- <return-value transfer-ownership="none">
- <type name="none" c:type="void"/>
- </return-value>
- <parameters>
- <parameter name="self" transfer-ownership="none">
- <type name="SubInterface" c:type="FooSubInterface*"/>
- </parameter>
- </parameters>
- </callback>
+ <field name="destroy_event">
+ <callback name="destroy_event" c:type="destroy_event">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="self" transfer-ownership="none">
+ <type name="SubInterface" c:type="FooSubInterface*"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
+ <field name="do_bar">
+ <callback name="do_bar" c:type="do_bar">
+ <return-value transfer-ownership="none">
+ <type name="none" c:type="void"/>
+ </return-value>
+ <parameters>
+ <parameter name="self" transfer-ownership="none">
+ <type name="SubInterface" c:type="FooSubInterface*"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
</record>
<class name="Subobject"
c:type="FooSubobject"
<field name="parent_iface">
<type name="GObject.TypeInterface"/>
</field>
+ <field name="do_foo">
+ <callback name="do_foo">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="self" transfer-ownership="none">
+ <type name="Interface"/>
+ </parameter>
+ <parameter name="x" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
</record>
<class name="Object" parent="GObject.Object" glib:type-struct="ObjectClass" glib:type-name="FooObject" glib:get-type="foo_object_get_type">
<implements name="Interface"/>
<field name="parent_class">
<type name="GObject.ObjectClass"/>
</field>
+ <field name="virtual_method">
+ <callback name="virtual_method">
+ <return-value transfer-ownership="none">
+ <type name="boolean"/>
+ </return-value>
+ <parameters>
+ <parameter name="object" transfer-ownership="none">
+ <type name="Object"/>
+ </parameter>
+ <parameter name="first_param" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
+ <field name="read_fn">
+ <callback name="read_fn">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="object" transfer-ownership="none">
+ <type name="Object"/>
+ </parameter>
+ <parameter name="offset" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ <parameter name="length" transfer-ownership="none">
+ <type name="int"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
<field name="_reserved">
<array fixed-size="4">
<type name="GObject.Callback"/>
<field name="parent_iface">
<type name="GObject.TypeInterface"/>
</field>
+ <field name="destroy_event">
+ <callback name="destroy_event">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="self" transfer-ownership="none">
+ <type name="SubInterface"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
+ <field name="do_bar">
+ <callback name="do_bar">
+ <return-value transfer-ownership="none">
+ <type name="none"/>
+ </return-value>
+ <parameters>
+ <parameter name="self" transfer-ownership="none">
+ <type name="SubInterface"/>
+ </parameter>
+ </parameters>
+ </callback>
+ </field>
</record>
<class name="Subobject" parent="Object" glib:type-struct="SubobjectClass" abstract="1" glib:type-name="FooSubobject" glib:get-type="foo_subobject_get_type">
<implements name="Interface"/>
GArgument *argument,
Xml *file);
+static void
+write_callback_info (const gchar *namespace,
+ GICallbackInfo *info,
+ Xml *file);
+
static void
write_field_info (const gchar *namespace,
GIFieldInfo *info,
gint size;
gint offset;
GITypeInfo *type;
+ GIBaseInfo *interface;
GArgument value;
name = g_base_info_get_name ((GIBaseInfo *)info);
if (offset >= 0)
xml_printf (file, "offset=\"%d\"", offset);
}
-
- write_type_info (namespace, type, file);
+
+ interface = g_type_info_get_interface (type);
+ if (interface && g_base_info_get_type(interface) == GI_INFO_TYPE_CALLBACK)
+ write_callback_info (namespace, (GICallbackInfo *)interface, file);
+ else
+ write_type_info (namespace, type, file);
+
+ if (interface)
+ g_base_info_unref (interface);
+
g_base_info_unref ((GIBaseInfo *)type);
xml_end_element (file, "field");