From 169b206cbb4b347e4b17854e8f0c62a40404f803 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Torsten=20Sch=C3=B6nfeld?= Date: Sat, 13 Aug 2011 17:28:30 +0200 Subject: 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 --- girepository/gienuminfo.c | 55 +++++++++++++++++++++++++++++++++++++++ girepository/gienuminfo.h | 3 +++ girepository/girnode.c | 18 ++++++++++++- girepository/girnode.h | 1 + girepository/girparser.c | 17 ++++++++++++ girepository/gitypelib-internal.h | 9 +++++-- girepository/gitypelib.c | 22 +++++++++++----- 7 files changed, 115 insertions(+), 10 deletions(-) (limited to 'girepository') diff --git a/girepository/gienuminfo.c b/girepository/gienuminfo.c index 338a46ee..90b19a96 100644 --- a/girepository/gienuminfo.c +++ b/girepository/gienuminfo.c @@ -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 diff --git a/girepository/gienuminfo.h b/girepository/gienuminfo.h index fc0f3c84..def97f95 100644 --- a/girepository/gienuminfo.h +++ b/girepository/gienuminfo.h @@ -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); diff --git a/girepository/girnode.c b/girepository/girnode.c index 166ca30a..fcc8ce5e 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -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; diff --git a/girepository/girnode.h b/girepository/girnode.h index 6e03821b..32863455 100644 --- a/girepository/girnode.h +++ b/girepository/girnode.h @@ -288,6 +288,7 @@ struct _GIrNodeEnum gchar *error_domain; GList *values; + GList *methods; }; struct _GIrNodeBoxed diff --git a/girepository/girparser.c b/girepository/girparser.c index c9b7d629..6984e826 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -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)) diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index 1dde5163..f450a2fb 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -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; /** diff --git a/girepository/gitypelib.c b/girepository/gitypelib.c index f610d458..2e5b0e1b 100644 --- a/girepository/gitypelib.c +++ b/girepository/gitypelib.c @@ -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; -- cgit v1.2.1