summaryrefslogtreecommitdiff
path: root/girepository
diff options
context:
space:
mode:
authorDavid Zeuthen <davidz@redhat.com>2010-06-15 11:01:37 -0400
committerDavid Zeuthen <davidz@redhat.com>2010-06-24 11:53:18 -0400
commit11cfe386c37ced44a8e3efb5556bde3a43a11171 (patch)
treea01903a4e4596ca80c79abbc8d35c33dc665e526 /girepository
parent751ffa016e410a031028282e63f98a94cc444b7b (diff)
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.c24
-rw-r--r--girepository/gicallableinfo.c76
-rw-r--r--girepository/gicallableinfo.h6
-rw-r--r--girepository/girnode.c16
-rw-r--r--girepository/girparser.c9
-rw-r--r--girepository/girwriter.c21
-rw-r--r--girepository/gitypelib-internal.h4
7 files changed, 148 insertions, 8 deletions
diff --git a/girepository/gibaseinfo.c b/girepository/gibaseinfo.c
index c8444a5..81b936d 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 6097cb4..6b79e62 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 479baa2..54d2cac 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 fbdcdf9..576ac10 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 2713bb4..5efe7fd 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 b123a13..19862b0 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 90113ac..d4577ac 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__ */