Allow enums and bitfields to have static methods

This uses the same backcompat machinery that was introduced for static
methods for non-class types, so this change does not break users of the
existing presentations.

New libgirepository API:

    g_enum_info_get_n_methods
    g_enum_info_get_method

https://bugzilla.gnome.org/show_bug.cgi?id=656499
This commit is contained in:
Torsten Schönfeld 2011-08-13 17:28:30 +02:00
parent 5167265aae
commit 322ac4f0a3
7 changed files with 115 additions and 10 deletions

View File

@ -111,6 +111,61 @@ g_enum_info_get_value (GIEnumInfo *info,
return (GIValueInfo *) g_info_new (GI_INFO_TYPE_VALUE, (GIBaseInfo*)info, rinfo->typelib, offset);
}
/**
* g_enum_info_get_n_methods:
* @info: a #GIEnumInfo
*
* Obtain the number of methods that this enum type has.
*
* Returns: number of methods
*/
gint
g_enum_info_get_n_methods (GIEnumInfo *info)
{
GIRealInfo *rinfo = (GIRealInfo *)info;
EnumBlob *blob;
g_return_val_if_fail (info != NULL, 0);
g_return_val_if_fail (GI_IS_ENUM_INFO (info), 0);
blob = (EnumBlob *)&rinfo->typelib->data[rinfo->offset];
return blob->n_methods;
}
/**
* g_enum_info_get_method:
* @info: a #GIEnumInfo
* @n: index of method to get
*
* Obtain an enum type method at index @n.
*
* Returns: (transfer full): the #GIFunctionInfo. Free the struct by calling
* g_base_info_unref() when done.
*/
GIFunctionInfo *
g_enum_info_get_method (GIEnumInfo *info,
gint n)
{
gint offset;
GIRealInfo *rinfo = (GIRealInfo *)info;
Header *header;
EnumBlob *blob;
g_return_val_if_fail (info != NULL, NULL);
g_return_val_if_fail (GI_IS_ENUM_INFO (info), NULL);
header = (Header *)rinfo->typelib->data;
blob = (EnumBlob *)&rinfo->typelib->data[rinfo->offset];
offset = rinfo->offset + header->enum_blob_size
+ blob->n_values * header->value_blob_size
+ n * header->function_blob_size;
return (GIFunctionInfo *) g_info_new (GI_INFO_TYPE_FUNCTION, (GIBaseInfo*)info,
rinfo->typelib, offset);
}
/**
* g_enum_info_get_storage_type:
* @info: a #GIEnumInfo

View File

@ -40,6 +40,9 @@ G_BEGIN_DECLS
gint g_enum_info_get_n_values (GIEnumInfo *info);
GIValueInfo * g_enum_info_get_value (GIEnumInfo *info,
gint n);
gint g_enum_info_get_n_methods (GIEnumInfo *info);
GIFunctionInfo * g_enum_info_get_method (GIEnumInfo *info,
gint n);
GITypeTag g_enum_info_get_storage_type (GIEnumInfo *info);
const gchar * g_enum_info_get_error_domain (GIEnumInfo *info);

View File

@ -333,6 +333,10 @@ _g_ir_node_free (GIrNode *node)
for (l = enum_->values; l; l = l->next)
_g_ir_node_free ((GIrNode *)l->data);
g_list_free (enum_->values);
for (l = enum_->methods; l; l = l->next)
_g_ir_node_free ((GIrNode *)l->data);
g_list_free (enum_->methods);
}
break;
@ -467,6 +471,8 @@ _g_ir_node_get_size (GIrNode *node)
size = sizeof (EnumBlob);
for (l = enum_->values; l; l = l->next)
size += _g_ir_node_get_size ((GIrNode *)l->data);
for (l = enum_->methods; l; l = l->next)
size += _g_ir_node_get_size ((GIrNode *)l->data);
}
break;
@ -718,6 +724,8 @@ _g_ir_node_get_full_size_internal (GIrNode *parent,
for (l = enum_->values; l; l = l->next)
size += _g_ir_node_get_full_size_internal (node, (GIrNode *)l->data);
for (l = enum_->methods; l; l = l->next)
size += _g_ir_node_get_full_size_internal (node, (GIrNode *)l->data);
}
break;
@ -2030,7 +2038,7 @@ _g_ir_node_build_typelib (GIrNode *node,
blob->error_domain = 0;
blob->n_values = 0;
blob->reserved2 = 0;
blob->n_methods = 0;
for (l = enum_->values; l; l = l->next)
{
@ -2039,6 +2047,14 @@ _g_ir_node_build_typelib (GIrNode *node,
blob->n_values++;
_g_ir_node_build_typelib (value, node, build, offset, offset2);
}
for (l = enum_->methods; l; l = l->next)
{
GIrNode *method = (GIrNode *)l->data;
blob->n_methods++;
_g_ir_node_build_typelib (method, node, build, offset, offset2);
}
}
break;

View File

@ -288,6 +288,7 @@ struct _GIrNodeEnum
gchar *error_domain;
GList *values;
GList *methods;
};
struct _GIrNodeBoxed

View File

@ -805,6 +805,9 @@ start_function (GMarkupParseContext *context,
strcmp (element_name, "method") == 0 ||
strcmp (element_name, "callback") == 0);
break;
case STATE_ENUM:
found = strcmp (element_name, "function") == 0;
break;
case STATE_STRUCT_FIELD:
found = (found || strcmp (element_name, "callback") == 0);
break;
@ -925,6 +928,15 @@ start_function (GMarkupParseContext *context,
union_->members = g_list_append (union_->members, function);
}
break;
case G_IR_NODE_ENUM:
case G_IR_NODE_FLAGS:
{
GIrNodeEnum *enum_;
enum_ = (GIrNodeEnum *)CURRENT_NODE (ctx);
enum_->methods = g_list_append (enum_->methods, function);
}
break;
default:
g_assert_not_reached ();
}
@ -3186,6 +3198,9 @@ end_element_handler (GMarkupParseContext *context,
state_switch (ctx, STATE_STRUCT);
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_UNION)
state_switch (ctx, STATE_UNION);
else if (CURRENT_NODE (ctx)->type == G_IR_NODE_ENUM ||
CURRENT_NODE (ctx)->type == G_IR_NODE_FLAGS)
state_switch (ctx, STATE_ENUM);
else
{
int line_number, char_number;
@ -3256,6 +3271,8 @@ end_element_handler (GMarkupParseContext *context,
case STATE_ENUM:
if (strcmp ("member", element_name) == 0)
break;
else if (strcmp ("function", element_name) == 0)
break;
else if (require_one_of_end_elements (context, ctx,
element_name, error, "enumeration",
"bitfield", NULL))

View File

@ -800,8 +800,10 @@ typedef struct {
* @gtype_init: String naming the symbol which gets the runtime #GType
* @error_domain: String naming the #GError domain this enum is
* associated with
* @n_values: The lengths of the values arrays.
* @n_values: The length of the values array.
* @n_methods: The length of the methods array.
* @values: Describes the enum values.
* @methods: Describes the enum methods.
*/
typedef struct {
guint16 blob_type;
@ -817,11 +819,14 @@ typedef struct {
guint32 gtype_init;
guint16 n_values;
guint16 reserved2;
guint16 n_methods;
guint32 error_domain;
ValueBlob values[];
#if 0
FunctionBlob methods[];
#endif
} EnumBlob;
/**

View File

@ -1428,6 +1428,7 @@ validate_enum_blob (ValidateContext *ctx,
GITypelib *typelib = ctx->typelib;
EnumBlob *blob;
gint i;
guint32 offset2;
if (typelib->len < offset + sizeof (EnumBlob))
{
@ -1473,7 +1474,8 @@ validate_enum_blob (ValidateContext *ctx,
return FALSE;
if (typelib->len < offset + sizeof (EnumBlob) +
blob->n_values * sizeof (ValueBlob))
blob->n_values * sizeof (ValueBlob) +
blob->n_methods * sizeof (FunctionBlob))
{
g_set_error (error,
G_TYPELIB_ERROR,
@ -1482,22 +1484,22 @@ validate_enum_blob (ValidateContext *ctx,
return FALSE;
}
offset2 = offset + sizeof (EnumBlob);
push_context (ctx, get_string_nofail (typelib, blob->name));
for (i = 0; i < blob->n_values; i++)
for (i = 0; i < blob->n_values; i++, offset2 += sizeof (ValueBlob))
{
if (!validate_value_blob (typelib,
offset + sizeof (EnumBlob) +
i * sizeof (ValueBlob),
offset2,
error))
return FALSE;
#if 0
v1 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
i * sizeof (ValueBlob)];
v1 = (ValueBlob *)&typelib->data[offset2];
for (j = 0; j < i; j++)
{
v2 = (ValueBlob *)&typelib->data[offset + sizeof (EnumBlob) +
v2 = (ValueBlob *)&typelib->data[offset2 +
j * sizeof (ValueBlob)];
if (v1->value == v2->value)
@ -1514,6 +1516,12 @@ validate_enum_blob (ValidateContext *ctx,
#endif
}
for (i = 0; i < blob->n_methods; i++, offset2 += sizeof (FunctionBlob))
{
if (!validate_function_blob (ctx, offset2, BLOB_TYPE_ENUM, error))
return FALSE;
}
pop_context (ctx);
return TRUE;