mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 15:36:17 +01:00
Implement callbacks as part of struct fields. Fixes #557383
gir: embed <callback> inside <field> typelib: if a field contains a callback, store it just after the FieldBlob girepository API: no additions
This commit is contained in:
parent
8ba5a13d17
commit
03dc6a590b
67
ginfo.c
67
ginfo.c
@ -134,6 +134,7 @@ struct _GIArgInfo
|
||||
struct _GITypeInfo
|
||||
{
|
||||
GIBaseInfo base;
|
||||
gboolean is_embedded;
|
||||
};
|
||||
|
||||
struct _GIUnionInfo
|
||||
@ -154,7 +155,10 @@ g_info_new_full (GIInfoType type,
|
||||
|
||||
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;
|
||||
@ -643,9 +647,13 @@ g_type_info_new (GIBaseInfo *container,
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -876,7 +884,9 @@ g_type_info_get_tag (GITypeInfo *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
|
||||
{
|
||||
@ -920,7 +930,11 @@ g_type_info_get_interface (GITypeInfo *info)
|
||||
{
|
||||
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];
|
||||
@ -1100,8 +1114,21 @@ GITypeInfo *
|
||||
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 */
|
||||
@ -1161,16 +1188,35 @@ g_struct_info_get_n_fields (GIStructInfo *info)
|
||||
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
|
||||
@ -1191,8 +1237,7 @@ g_struct_info_get_method (GIStructInfo *info,
|
||||
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);
|
||||
|
@ -162,17 +162,17 @@ typedef enum
|
||||
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,
|
||||
|
34
girnode.c
34
girnode.c
@ -279,6 +279,7 @@ g_ir_node_free (GIrNode *node)
|
||||
|
||||
g_free (node->name);
|
||||
g_ir_node_free ((GIrNode *)field->type);
|
||||
g_ir_node_free ((GIrNode *)field->callback);
|
||||
}
|
||||
break;
|
||||
|
||||
@ -508,7 +509,13 @@ g_ir_node_get_size (GIrNode *node)
|
||||
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:
|
||||
@ -797,7 +804,10 @@ g_ir_node_get_full_size_internal (GIrNode *parent,
|
||||
|
||||
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;
|
||||
|
||||
@ -1587,8 +1597,6 @@ g_ir_node_build_typelib (GIrNode *node,
|
||||
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;
|
||||
@ -1600,8 +1608,22 @@ g_ir_node_build_typelib (GIrNode *node,
|
||||
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;
|
||||
|
||||
|
@ -230,6 +230,7 @@ struct _GIrNodeField
|
||||
gboolean writable;
|
||||
gint bits;
|
||||
gint offset;
|
||||
GIrNodeFunction *callback;
|
||||
|
||||
GIrNodeType *type;
|
||||
};
|
||||
|
@ -303,7 +303,14 @@ get_field_size_alignment (GIrNodeField *field,
|
||||
|
||||
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;
|
||||
|
20
girparser.c
20
girparser.c
@ -101,6 +101,7 @@ struct _ParseContext
|
||||
GList *type_stack;
|
||||
GList *type_parameters;
|
||||
int type_depth;
|
||||
gboolean in_embedded_type;
|
||||
};
|
||||
#define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
|
||||
|
||||
@ -719,6 +720,10 @@ start_function (GMarkupParseContext *context,
|
||||
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;
|
||||
}
|
||||
@ -782,6 +787,13 @@ start_function (GMarkupParseContext *context,
|
||||
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)
|
||||
{
|
||||
@ -2902,7 +2914,13 @@ end_element_handler (GMarkupParseContext *context,
|
||||
}
|
||||
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);
|
||||
|
35
gtypelib.c
35
gtypelib.c
@ -1016,10 +1016,12 @@ validate_value_blob (GTypelib *typelib,
|
||||
}
|
||||
|
||||
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))
|
||||
@ -1035,10 +1037,15 @@ validate_field_blob (GTypelib *typelib,
|
||||
|
||||
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;
|
||||
@ -1209,6 +1216,7 @@ validate_struct_blob (ValidateContext *ctx,
|
||||
GTypelib *typelib = ctx->typelib;
|
||||
StructBlob *blob;
|
||||
gint i;
|
||||
guint32 field_offset;
|
||||
|
||||
if (typelib->len < offset + sizeof (StructBlob))
|
||||
{
|
||||
@ -1266,20 +1274,25 @@ validate_struct_blob (ValidateContext *ctx,
|
||||
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))
|
||||
@ -1532,7 +1545,7 @@ validate_object_blob (ValidateContext *ctx,
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -622,6 +622,7 @@ typedef struct {
|
||||
* @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:
|
||||
@ -634,7 +635,8 @@ typedef struct {
|
||||
|
||||
guint8 readable :1;
|
||||
guint8 writable :1;
|
||||
guint8 reserved :6;
|
||||
guint8 has_embedded_type :1;
|
||||
guint8 reserved :5;
|
||||
guint8 bits;
|
||||
|
||||
guint16 struct_offset;
|
||||
|
Loading…
Reference in New Issue
Block a user