diff options
Diffstat (limited to 'girepository/ginfo.c')
-rw-r--r-- | girepository/ginfo.c | 143 |
1 files changed, 105 insertions, 38 deletions
diff --git a/girepository/ginfo.c b/girepository/ginfo.c index 1c34ee2..fcc5f09 100644 --- a/girepository/ginfo.c +++ b/girepository/ginfo.c @@ -1,6 +1,7 @@ /* GObject introspection: Repository implementation * * Copyright (C) 2005 Matthias Clasen + * Copyright (C) 2008,2009 Red Hat, Inc. * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -402,65 +403,131 @@ g_base_info_is_deprecated (GIBaseInfo *info) return FALSE; } +/** + * g_base_info_get_attribute: + * @info: A #GIBaseInfo + * @name: A freeform string naming an attribute + * + * Retrieve an arbitrary attribute associated with this node. + * + * Return value: The value of the attribute, or %NULL if no such attribute exists + */ +const gchar * +g_base_info_get_attribute (GIBaseInfo *info, + const gchar *name) +{ + GIAttributeIter iter = { 0, }; + gchar *curname, *curvalue; + while (g_base_info_iterate_attributes (info, &iter, &curname, &curvalue)) + { + if (strcmp (name, curname) == 0) + return (const gchar*) curvalue; + } + + return NULL; +} + static int -cmp_annotation (const void *av, - const void *bv) +cmp_attribute (const void *av, + const void *bv) { - const AnnotationBlob *a = av; - const AnnotationBlob *b = bv; + const AttributeBlob *a = av; + const AttributeBlob *b = bv; - if (b->offset < a->offset) + if (a->offset < b->offset) return -1; - - if (b->offset > a->offset) + else if (a->offset == b->offset) + return 0; + else return 1; - - return 0; } -const gchar * -g_base_info_get_annotation (GIBaseInfo *info, - const gchar *name) +static AttributeBlob * +find_first_attribute (GIBaseInfo *info) { GIBaseInfo *base = (GIBaseInfo *)info; Header *header = (Header *)base->typelib->data; - AnnotationBlob blob, *first, *after, *res, *next; - const gchar *rname; + AttributeBlob blob, *first, *res, *previous; blob.offset = base->offset; - first = (AnnotationBlob *) &base->typelib->data[header->annotations]; - after = (AnnotationBlob *) &base->typelib->data[header->annotations + - header->n_annotations * header->annotation_blob_size]; + first = (AttributeBlob *) &base->typelib->data[header->attributes]; + + res = bsearch (&blob, first, header->n_attributes, + header->attribute_blob_size, cmp_attribute); - res = bsearch (&blob, first, header->n_annotations, - header->annotation_blob_size, cmp_annotation); - if (res == NULL) return NULL; - next = res; - do + previous = res - 1; + while (previous >= first && previous->offset == base->offset) { - res = next; - next = res -= header->annotation_blob_size; + res = previous; + previous = res - 1; } - while (next >= first && next->offset == base->offset); - - next = res; - do - { - res = next; - - rname = g_typelib_get_string (base->typelib, res->name); - if (strcmp (name, rname) == 0) - return g_typelib_get_string (base->typelib, res->value); - next = res += header->annotation_blob_size; - } - while (next < after && next->offset == base->offset); + return res; +} - return NULL; +/** + * g_base_info_iterate_attributes: + * @info: A #GIBaseInfo + * @iter: 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 this node. 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. + * + * <example> + * <title>Iterating over attributes</title> + * <programlisting> + * void + * print_attributes (GIBaseInfo *info) + * { + * GIAttributeIter iter = { 0, }; + * char *name; + * char *value; + * while (g_base_info_iterate_attributes (info, &iter, &name, &value)) + * { + * g_print ("attribute name: %s value: %s", name, value); + * } + * } + * </programlisting> + * </example> + * + * Return value: %TRUE if there are more attributes, %FALSE otherwise + */ +gboolean +g_base_info_iterate_attributes (GIBaseInfo *info, + GIAttributeIter *iter, + gchar **name, + gchar **value) +{ + GIBaseInfo *base = (GIBaseInfo *)info; + Header *header = (Header *)base->typelib->data; + AttributeBlob *next, *after; + + after = (AttributeBlob *) &base->typelib->data[header->attributes + + header->n_attributes * header->attribute_blob_size]; + + if (iter->data != NULL) + next = (AttributeBlob *) iter->data; + else + next = find_first_attribute (info); + + if (next == NULL || next->offset != base->offset || next >= after) + return FALSE; + + *name = (gchar*) g_typelib_get_string (base->typelib, next->name); + *value = (gchar*) g_typelib_get_string (base->typelib, next->value); + iter->data = next + 1; + + return TRUE; } GIBaseInfo * |