g-ir-compiler: Add support for callback fields on GObjects

Use ParseState enum instead of a boolean for the ParseContexts embedded_type
flag. This allows specific tracking of the embedded type currently being
parsed which can now either be STATE_STRUCT_FIELD or STATE_CLASS_FIELD (or
allow for future expansion). Add ParseState::STATE_NONE as the default for
this field.

Fix GObject FieldBlob validation to take into account the sizeof
CallbackBlobs (copied from the struct validator).

Add static g_object_info_get_field_offset which parallels
g_struct_info_get_field_offset which is needed since callback fields may
vary in size.

https://bugzilla.gnome.org/show_bug.cgi?id=725198
This commit is contained in:
Simon Feltman 2014-02-27 02:05:54 -08:00
parent 90a99b4fcc
commit cf4fb6a0fe
3 changed files with 71 additions and 50 deletions

View File

@ -47,6 +47,40 @@
* </refsect1>
*/
/**
* g_object_info_get_field_offset:
* @info: a #GIObjectInfo
* @n: index of queried field
*
* Obtain the offset of the specified field.
*
* Returns: field offset in bytes
*/
static gint32
g_object_info_get_field_offset (GIObjectInfo *info,
gint n)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header = (Header *)rinfo->typelib->data;
ObjectBlob *blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
guint32 offset;
gint i;
FieldBlob *field_blob;
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2;
for (i = 0; i < n; i++)
{
field_blob = (FieldBlob *)&rinfo->typelib->data[offset];
offset += header->field_blob_size;
if (field_blob->has_embedded_type)
offset += header->callback_blob_size;
}
return offset;
}
/**
* g_object_info_get_parent:
* @info: a #GIObjectInfo
@ -251,18 +285,11 @@ g_object_info_get_field (GIObjectInfo *info,
{
gint offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
ObjectBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_OBJECT_INFO (info), NULL);
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ n * header->field_blob_size;
offset = g_object_info_get_field_offset(info, n);
return (GIFieldInfo *) g_info_new (GI_INFO_TYPE_FIELD, (GIBaseInfo*)info, rinfo->typelib, offset);
}
@ -313,9 +340,7 @@ g_object_info_get_property (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ n * header->property_blob_size;
return (GIPropertyInfo *) g_info_new (GI_INFO_TYPE_PROPERTY, (GIBaseInfo*)info,
@ -370,9 +395,7 @@ g_object_info_get_method (GIObjectInfo *info,
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ n * header->function_blob_size;
@ -406,9 +429,7 @@ g_object_info_find_method (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size +
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size;
return _g_base_info_find_method ((GIBaseInfo*)info, offset, blob->n_methods, name);
@ -518,9 +539,7 @@ g_object_info_get_signal (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ n * header->signal_blob_size;
@ -609,9 +628,7 @@ g_object_info_get_vfunc (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size
@ -652,9 +669,7 @@ g_object_info_find_vfunc (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size;
@ -769,9 +784,7 @@ g_object_info_get_constant (GIObjectInfo *info,
header = (Header *)rinfo->typelib->data;
blob = (ObjectBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->object_blob_size
+ (blob->n_interfaces + blob->n_interfaces % 2) * 2
+ blob->n_fields * header->field_blob_size
offset = g_object_info_get_field_offset(info, blob->n_fields)
+ blob->n_properties * header->property_blob_size
+ blob->n_methods * header->function_blob_size
+ blob->n_signals * header->signal_blob_size

View File

@ -62,37 +62,38 @@ struct _GIrParser
typedef enum
{
STATE_NONE = 0,
STATE_START,
STATE_END,
STATE_REPOSITORY,
STATE_INCLUDE,
STATE_C_INCLUDE,
STATE_PACKAGE, /* 5 */
STATE_C_INCLUDE, /* 5 */
STATE_PACKAGE,
STATE_NAMESPACE,
STATE_ENUM,
STATE_BITFIELD,
STATE_FUNCTION,
STATE_FUNCTION_RETURN, /* 10 */
STATE_FUNCTION, /* 10 */
STATE_FUNCTION_RETURN,
STATE_FUNCTION_PARAMETERS,
STATE_FUNCTION_PARAMETER,
STATE_CLASS,
STATE_CLASS_FIELD,
STATE_CLASS_PROPERTY, /* 15 */
STATE_CLASS_FIELD, /* 15 */
STATE_CLASS_PROPERTY,
STATE_INTERFACE,
STATE_INTERFACE_PROPERTY,
STATE_INTERFACE_FIELD,
STATE_IMPLEMENTS,
STATE_PREREQUISITE, /* 20 */
STATE_IMPLEMENTS, /* 20 */
STATE_PREREQUISITE,
STATE_BOXED,
STATE_BOXED_FIELD,
STATE_STRUCT,
STATE_STRUCT_FIELD,
STATE_UNION, /* 25 */
STATE_STRUCT_FIELD, /* 25 */
STATE_UNION,
STATE_UNION_FIELD,
STATE_NAMESPACE_CONSTANT,
STATE_CLASS_CONSTANT,
STATE_INTERFACE_CONSTANT,
STATE_ALIAS, /* 30 */
STATE_INTERFACE_CONSTANT, /* 30 */
STATE_ALIAS,
STATE_TYPE,
STATE_ATTRIBUTE,
STATE_PASSTHROUGH
@ -123,7 +124,7 @@ struct _ParseContext
GList *type_stack;
GList *type_parameters;
int type_depth;
gboolean in_embedded_type;
ParseState in_embedded_state;
};
#define CURRENT_NODE(ctx) ((GIrNode *)((ctx)->node_stack->data))
@ -807,7 +808,7 @@ start_function (GMarkupParseContext *context,
const gchar *throws;
GIrNodeFunction *function;
gboolean found = FALSE;
gboolean in_embedded_type;
ParseState in_embedded_state = STATE_NONE;
switch (ctx->state)
{
@ -830,8 +831,10 @@ start_function (GMarkupParseContext *context,
case STATE_ENUM:
found = strcmp (element_name, "function") == 0;
break;
case STATE_CLASS_FIELD:
case STATE_STRUCT_FIELD:
found = (found || strcmp (element_name, "callback") == 0);
in_embedded_state = ctx->state;
break;
default:
break;
@ -840,12 +843,10 @@ start_function (GMarkupParseContext *context,
if (!found)
return FALSE;
in_embedded_type = ctx->state == STATE_STRUCT_FIELD;
if (!introspectable_prelude (context, attribute_names, attribute_values, ctx, STATE_FUNCTION))
return TRUE;
ctx->in_embedded_type = in_embedded_type;
ctx->in_embedded_state = in_embedded_state;
name = find_attribute ("name", attribute_names, attribute_values);
shadows = find_attribute ("shadows", attribute_names, attribute_values);
@ -3210,10 +3211,10 @@ end_element_handler (GMarkupParseContext *context,
else
{
g_debug("case STATE_FUNCTION %d", CURRENT_NODE (ctx)->type);
if (ctx->in_embedded_type)
if (ctx->in_embedded_state != STATE_NONE)
{
ctx->in_embedded_type = FALSE;
state_switch (ctx, STATE_STRUCT_FIELD);
state_switch (ctx, ctx->in_embedded_state);
ctx->in_embedded_state = STATE_NONE;
}
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_INTERFACE)
state_switch (ctx, STATE_INTERFACE);

View File

@ -1773,10 +1773,17 @@ validate_object_blob (ValidateContext *ctx,
push_context (ctx, get_string_nofail (typelib, blob->name));
for (i = 0; i < blob->n_fields; i++, offset2 += sizeof (FieldBlob))
for (i = 0; i < blob->n_fields; i++)
{
FieldBlob *blob = (FieldBlob*) &typelib->data[offset2];
if (!validate_field_blob (ctx, offset2, error))
return FALSE;
offset2 += sizeof (FieldBlob);
/* Special case fields which are callbacks. */
if (blob->has_embedded_type)
offset2 += sizeof (CallbackBlob);
}
for (i = 0; i < blob->n_properties; i++, offset2 += sizeof (PropertyBlob))