diff options
author | David Zeuthen <davidz@redhat.com> | 2010-06-15 11:01:37 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2010-06-24 11:53:18 -0400 |
commit | 11cfe386c37ced44a8e3efb5556bde3a43a11171 (patch) | |
tree | a01903a4e4596ca80c79abbc8d35c33dc665e526 /girepository | |
parent | 751ffa016e410a031028282e63f98a94cc444b7b (diff) | |
download | gobject-introspection-11cfe386c37ced44a8e3efb5556bde3a43a11171.tar.gz |
Allow attributes on parameters and return values
Any annotation where the key has a dot in the name will go into the
attribute list. For example
* @arg: (foo.bar baz): some arg
the parameter @arg will get the attribute with key foo.bar and value
baz. This also works for.
* Returns: (foo.bar2 baz2): the return value
Also add tests for this new feature.
See https://bugzilla.gnome.org/show_bug.cgi?id=571548
Signed-off-by: David Zeuthen <davidz@redhat.com>
Diffstat (limited to 'girepository')
-rw-r--r-- | girepository/gibaseinfo.c | 24 | ||||
-rw-r--r-- | girepository/gicallableinfo.c | 76 | ||||
-rw-r--r-- | girepository/gicallableinfo.h | 6 | ||||
-rw-r--r-- | girepository/girnode.c | 16 | ||||
-rw-r--r-- | girepository/girparser.c | 9 | ||||
-rw-r--r-- | girepository/girwriter.c | 21 | ||||
-rw-r--r-- | girepository/gitypelib-internal.h | 4 |
7 files changed, 148 insertions, 8 deletions
diff --git a/girepository/gibaseinfo.c b/girepository/gibaseinfo.c index c8444a5e..81b936d8 100644 --- a/girepository/gibaseinfo.c +++ b/girepository/gibaseinfo.c @@ -475,7 +475,7 @@ g_base_info_get_attribute (GIBaseInfo *info, static int cmp_attribute (const void *av, - const void *bv) + const void *bv) { const AttributeBlob *a = av; const AttributeBlob *b = bv; @@ -488,13 +488,25 @@ cmp_attribute (const void *av, return 1; } -static AttributeBlob * -find_first_attribute (GIRealInfo *rinfo) +/* + * _attribute_blob_find_first: + * @GIBaseInfo: A #GIBaseInfo. + * @blob_offset: The offset for the blob to find the first attribute for. + * + * Searches for the first #AttributeBlob for @blob_offset and returns + * it if found. + * + * Returns: A pointer to #AttributeBlob or %NULL if not found. + */ +AttributeBlob * +_attribute_blob_find_first (GIBaseInfo *info, + guint32 blob_offset) { + GIRealInfo *rinfo = (GIRealInfo *) info; Header *header = (Header *)rinfo->typelib->data; AttributeBlob blob, *first, *res, *previous; - blob.offset = rinfo->offset; + blob.offset = blob_offset; first = (AttributeBlob *) &rinfo->typelib->data[header->attributes]; @@ -505,7 +517,7 @@ find_first_attribute (GIRealInfo *rinfo) return NULL; previous = res - 1; - while (previous >= first && previous->offset == rinfo->offset) + while (previous >= first && previous->offset == blob_offset) { res = previous; previous = res - 1; @@ -563,7 +575,7 @@ g_base_info_iterate_attributes (GIBaseInfo *info, if (iterator->data != NULL) next = (AttributeBlob *) iterator->data; else - next = find_first_attribute (rinfo); + next = _attribute_blob_find_first (info, rinfo->offset); if (next == NULL || next->offset != rinfo->offset || next >= after) return FALSE; diff --git a/girepository/gicallableinfo.c b/girepository/gicallableinfo.c index 6097cb48..6b79e62c 100644 --- a/girepository/gicallableinfo.c +++ b/girepository/gicallableinfo.c @@ -19,6 +19,8 @@ * Boston, MA 02111-1307, USA. */ +#include <stdlib.h> + #include <glib.h> #include <girepository.h> @@ -259,3 +261,77 @@ g_callable_info_load_arg (GICallableInfo *info, _g_info_init ((GIRealInfo*)arg, GI_INFO_TYPE_ARG, rinfo->repository, (GIBaseInfo*)info, rinfo->typelib, offset + header->signature_blob_size + n * header->arg_blob_size); } + +/** + * g_callable_info_get_return_attribute: + * @info: a #GICallableInfo + * @name: a freeform string naming an attribute + * + * Retrieve an arbitrary attribute associated with the return value. + * + * Returns: The value of the attribute, or %NULL if no such attribute exists + */ +const gchar * +g_callable_info_get_return_attribute (GICallableInfo *info, + const gchar *name) +{ + GIAttributeIter iter = { 0, }; + gchar *curname, *curvalue; + while (g_callable_info_iterate_return_attributes (info, &iter, &curname, &curvalue)) + { + if (g_strcmp0 (name, curname) == 0) + return (const gchar*) curvalue; + } + + return NULL; +} + +/** + * g_callable_info_iterate_return_attributes: + * @info: a #GICallableInfo + * @iterator: a #GIAttributeIter structure, must be initialized; see below + * @name: (out) (transfer none): Returned name, must not be freed + * @value: (out) (transfer none): Returned name, must not be freed + * + * Iterate over all attributes associated with the return value. The + * iterator structure is typically stack allocated, and must have its + * first member initialized to %NULL. + * + * Both the @name and @value should be treated as constants + * and must not be freed. + * + * See g_base_info_iterate_attributes() for an example of how to use a + * similar API. + * + * Returns: %TRUE if there are more attributes + */ +gboolean +g_callable_info_iterate_return_attributes (GICallableInfo *info, + GIAttributeIter *iterator, + char **name, + char **value) +{ + GIRealInfo *rinfo = (GIRealInfo *)info; + Header *header = (Header *)rinfo->typelib->data; + AttributeBlob *next, *after; + guint32 blob_offset; + + after = (AttributeBlob *) &rinfo->typelib->data[header->attributes + + header->n_attributes * header->attribute_blob_size]; + + blob_offset = signature_offset (info); + + if (iterator->data != NULL) + next = (AttributeBlob *) iterator->data; + else + next = _attribute_blob_find_first (info, blob_offset); + + if (next == NULL || next->offset != blob_offset || next >= after) + return FALSE; + + *name = (gchar*) g_typelib_get_string (rinfo->typelib, next->name); + *value = (gchar*) g_typelib_get_string (rinfo->typelib, next->value); + iterator->data = next + 1; + + return TRUE; +} diff --git a/girepository/gicallableinfo.h b/girepository/gicallableinfo.h index 479baa2a..54d2cacb 100644 --- a/girepository/gicallableinfo.h +++ b/girepository/gicallableinfo.h @@ -39,6 +39,12 @@ G_BEGIN_DECLS GITypeInfo * g_callable_info_get_return_type (GICallableInfo *info); void g_callable_info_load_return_type (GICallableInfo *info, GITypeInfo *type); +const gchar * g_callable_info_get_return_attribute (GICallableInfo *info, + const gchar *name); +gboolean g_callable_info_iterate_return_attributes (GICallableInfo *info, + GIAttributeIter *iterator, + char **name, + char **value); GITransfer g_callable_info_get_caller_owns (GICallableInfo *info); gboolean g_callable_info_may_return_null (GICallableInfo *info); gint g_callable_info_get_n_args (GICallableInfo *info); diff --git a/girepository/girnode.c b/girepository/girnode.c index fbdcdf96..576ac100 100644 --- a/girepository/girnode.c +++ b/girepository/girnode.c @@ -1678,6 +1678,14 @@ g_ir_node_build_typelib (GIrNode *node, blob->symbol = write_string (function->symbol, strings, data, offset2); blob->signature = signature; + /* function->result is special since it doesn't appear in the serialized format but + * we do want the attributes for it to appear + */ + build->nodes_with_attributes = g_list_prepend (build->nodes_with_attributes, function->result); + build->n_attributes += g_hash_table_size (((GIrNode *) function->result)->attributes); + g_assert (((GIrNode *) function->result)->offset == 0); + ((GIrNode *) function->result)->offset = signature; + g_debug ("building function '%s'", function->symbol); g_ir_node_build_typelib ((GIrNode *)function->result->type, @@ -1770,6 +1778,14 @@ g_ir_node_build_typelib (GIrNode *node, blob->name = write_string (node->name, strings, data, offset2); blob->signature = signature; + /* signal->result is special since it doesn't appear in the serialized format but + * we do want the attributes for it to appear + */ + build->nodes_with_attributes = g_list_prepend (build->nodes_with_attributes, signal->result); + build->n_attributes += g_hash_table_size (((GIrNode *) signal->result)->attributes); + g_assert (((GIrNode *) signal->result)->offset == 0); + ((GIrNode *) signal->result)->offset = signature; + g_ir_node_build_typelib ((GIrNode *)signal->result->type, node, build, &signature, offset2); diff --git a/girepository/girparser.c b/girepository/girparser.c index 2713bb46..5efe7fde 100644 --- a/girepository/girparser.c +++ b/girepository/girparser.c @@ -1990,7 +1990,14 @@ start_attribute (GMarkupParseContext *context, curnode = CURRENT_NODE (ctx); - g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value)); + if (ctx->current_typed && ctx->current_typed->type == G_IR_NODE_PARAM) + { + g_hash_table_insert (ctx->current_typed->attributes, g_strdup (name), g_strdup (value)); + } + else + { + g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value)); + } return TRUE; } diff --git a/girepository/girwriter.c b/girepository/girwriter.c index b123a134..19862b0d 100644 --- a/girepository/girwriter.c +++ b/girepository/girwriter.c @@ -358,7 +358,7 @@ write_type_info (const gchar *namespace, static void write_attributes (Xml *file, - GIBaseInfo *info) + GIBaseInfo *info) { GIAttributeIter iter = { 0, }; char *name, *value; @@ -372,6 +372,21 @@ write_attributes (Xml *file, } static void +write_return_value_attributes (Xml *file, + GICallableInfo *info) +{ + GIAttributeIter iter = { 0, }; + char *name, *value; + + while (g_callable_info_iterate_return_attributes (info, &iter, &name, &value)) + { + xml_start_element (file, "attribute"); + xml_printf (file, " name=\"%s\" value=\"%s\"", name, value); + xml_end_element (file, "attribute"); + } +} + +static void write_constant_value (const gchar *namespace, GITypeInfo *info, GArgument *argument, @@ -467,6 +482,8 @@ write_callable_info (const gchar *namespace, if (g_callable_info_may_return_null (info)) xml_printf (file, " allow-none=\"1\""); + write_return_value_attributes (file, info); + write_type_info (namespace, type, file); xml_end_element (file, "return-value"); @@ -528,6 +545,8 @@ write_callable_info (const gchar *namespace, if (g_arg_info_get_destroy (arg) >= 0) xml_printf (file, " destroy=\"%d\"", g_arg_info_get_destroy (arg)); + write_attributes (file, (GIBaseInfo*) arg); + type = g_arg_info_get_type (arg); write_type_info (namespace, type, file); diff --git a/girepository/gitypelib-internal.h b/girepository/gitypelib-internal.h index 90113ac2..d4577acc 100644 --- a/girepository/gitypelib-internal.h +++ b/girepository/gitypelib-internal.h @@ -1110,6 +1110,10 @@ gboolean g_typelib_validate (GTypelib *typelib, GError **error); +/* defined in gibaseinfo.c */ +AttributeBlob *_attribute_blob_find_first (GIBaseInfo *info, + guint32 blob_offset); + G_END_DECLS #endif /* __G_TYPELIB_H__ */ |