Bug 571548 - Generic attributes

We now support an extensible mechanism where arbitrary key-value
pairs may be associated with almost all items, including objects,
methods, and properties.

These attributes appear in both the .gir and the .typelib.
This commit is contained in:
Colin Walters 2009-02-19 21:48:51 -05:00
parent 86587133cd
commit cd845500a5
8 changed files with 327 additions and 74 deletions

143
ginfo.c
View File

@ -1,6 +1,7 @@
/* GObject introspection: Repository implementation /* GObject introspection: Repository implementation
* *
* Copyright (C) 2005 Matthias Clasen * Copyright (C) 2005 Matthias Clasen
* Copyright (C) 2008,2009 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -402,65 +403,131 @@ g_base_info_is_deprecated (GIBaseInfo *info)
return FALSE; return FALSE;
} }
static int /**
cmp_annotation (const void *av, * g_base_info_get_attribute:
const void *bv) * @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)
{ {
const AnnotationBlob *a = av; GIAttributeIter iter = { 0, };
const AnnotationBlob *b = bv; gchar *curname, *curvalue;
while (g_base_info_iterate_attributes (info, &iter, &curname, &curvalue))
{
if (strcmp (name, curname) == 0)
return (const gchar*) curvalue;
}
if (b->offset < a->offset) return NULL;
return -1;
if (b->offset > a->offset)
return 1;
return 0;
} }
const gchar * static int
g_base_info_get_annotation (GIBaseInfo *info, cmp_attribute (const void *av,
const gchar *name) const void *bv)
{
const AttributeBlob *a = av;
const AttributeBlob *b = bv;
if (a->offset < b->offset)
return -1;
else if (a->offset == b->offset)
return 0;
else
return 1;
}
static AttributeBlob *
find_first_attribute (GIBaseInfo *info)
{ {
GIBaseInfo *base = (GIBaseInfo *)info; GIBaseInfo *base = (GIBaseInfo *)info;
Header *header = (Header *)base->typelib->data; Header *header = (Header *)base->typelib->data;
AnnotationBlob blob, *first, *after, *res, *next; AttributeBlob blob, *first, *res, *previous;
const gchar *rname;
blob.offset = base->offset; blob.offset = base->offset;
first = (AnnotationBlob *) &base->typelib->data[header->annotations]; first = (AttributeBlob *) &base->typelib->data[header->attributes];
after = (AnnotationBlob *) &base->typelib->data[header->annotations +
header->n_annotations * header->annotation_blob_size];
res = bsearch (&blob, first, header->n_annotations, res = bsearch (&blob, first, header->n_attributes,
header->annotation_blob_size, cmp_annotation); header->attribute_blob_size, cmp_attribute);
if (res == NULL) if (res == NULL)
return NULL; return NULL;
next = res; previous = res - 1;
do while (previous >= first && previous->offset == base->offset)
{ {
res = next; res = previous;
next = res -= header->annotation_blob_size; previous = res - 1;
} }
while (next >= first && next->offset == base->offset);
next = res; return res;
do }
{
res = next;
rname = g_typelib_get_string (base->typelib, res->name); /**
if (strcmp (name, rname) == 0) * g_base_info_iterate_attributes:
return g_typelib_get_string (base->typelib, res->value); * @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;
next = res += header->annotation_blob_size; after = (AttributeBlob *) &base->typelib->data[header->attributes +
} header->n_attributes * header->attribute_blob_size];
while (next < after && next->offset == base->offset);
return NULL; 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 * GIBaseInfo *

View File

@ -1,6 +1,7 @@
/* GObject introspection: Repository /* GObject introspection: Repository
* *
* Copyright (C) 2005 Matthias Clasen * Copyright (C) 2005 Matthias Clasen
* Copyright (C) 2008,2009 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -179,14 +180,25 @@ typedef enum
/* GIBaseInfo */ /* GIBaseInfo */
typedef struct {
gpointer data;
gpointer data2;
gpointer data3;
gpointer data4;
} GIAttributeIter;
GIBaseInfo * g_base_info_ref (GIBaseInfo *info); GIBaseInfo * g_base_info_ref (GIBaseInfo *info);
void g_base_info_unref (GIBaseInfo *info); void g_base_info_unref (GIBaseInfo *info);
GIInfoType g_base_info_get_type (GIBaseInfo *info); GIInfoType g_base_info_get_type (GIBaseInfo *info);
const gchar * g_base_info_get_name (GIBaseInfo *info); const gchar * g_base_info_get_name (GIBaseInfo *info);
const gchar * g_base_info_get_namespace (GIBaseInfo *info); const gchar * g_base_info_get_namespace (GIBaseInfo *info);
gboolean g_base_info_is_deprecated (GIBaseInfo *info); gboolean g_base_info_is_deprecated (GIBaseInfo *info);
const gchar * g_base_info_get_annotation (GIBaseInfo *info, const gchar * g_base_info_get_attribute (GIBaseInfo *info,
const gchar *name); const gchar *name);
gboolean g_base_info_iterate_attributes (GIBaseInfo *info,
GIAttributeIter *iterator,
char **name,
char **value);
GIBaseInfo * g_base_info_get_container (GIBaseInfo *info); GIBaseInfo * g_base_info_get_container (GIBaseInfo *info);
GTypelib * g_base_info_get_typelib (GIBaseInfo *info); GTypelib * g_base_info_get_typelib (GIBaseInfo *info);

View File

@ -109,6 +109,53 @@ g_ir_module_add_include_module (GIrModule *module,
module); module);
} }
struct AttributeWriteData
{
guint count;
guchar *databuf;
GIrNode *node;
GHashTable *strings;
guint32 *offset;
guint32 *offset2;
};
static void
write_attribute (gpointer key, gpointer value, gpointer datap)
{
struct AttributeWriteData *data = datap;
guint32 old_offset = *(data->offset);
AttributeBlob *blob = (AttributeBlob*)&(data->databuf[old_offset]);
*(data->offset) += sizeof (AttributeBlob);
blob->offset = data->node->offset;
blob->name = write_string ((const char*) key, data->strings, data->databuf, data->offset2);
blob->value = write_string ((const char*) value, data->strings, data->databuf, data->offset2);
data->count++;
}
static guint
write_attributes (GIrModule *module,
GIrNode *node,
GHashTable *strings,
guchar *data,
guint32 *offset,
guint32 *offset2)
{
struct AttributeWriteData wdata;
wdata.count = 0;
wdata.databuf = data;
wdata.node = node;
wdata.offset = offset;
wdata.offset2 = offset2;
wdata.strings = strings;
g_hash_table_foreach (node->attributes, write_attribute, &wdata);
return wdata.count;
}
GTypelib * GTypelib *
g_ir_module_build_typelib (GIrModule *module, g_ir_module_build_typelib (GIrModule *module,
GList *modules) GList *modules)
@ -126,6 +173,7 @@ g_ir_module_build_typelib (GIrModule *module,
guint32 size, offset, offset2, old_offset; guint32 size, offset, offset2, old_offset;
GHashTable *strings; GHashTable *strings;
GHashTable *types; GHashTable *types;
GList *offset_ordered_nodes;
char *dependencies; char *dependencies;
guchar *data; guchar *data;
@ -158,6 +206,7 @@ g_ir_module_build_typelib (GIrModule *module,
_g_irnode_init_stats (); _g_irnode_init_stats ();
strings = g_hash_table_new (g_str_hash, g_str_equal); strings = g_hash_table_new (g_str_hash, g_str_equal);
types = g_hash_table_new (g_str_hash, g_str_equal); types = g_hash_table_new (g_str_hash, g_str_equal);
offset_ordered_nodes = NULL;
n_entries = g_list_length (module->entries); n_entries = g_list_length (module->entries);
g_message ("%d entries (%d local), %d dependencies\n", n_entries, n_local_entries, g_message ("%d entries (%d local), %d dependencies\n", n_entries, n_local_entries,
@ -173,6 +222,10 @@ g_ir_module_build_typelib (GIrModule *module,
GIrNode *node = e->data; GIrNode *node = e->data;
size += g_ir_node_get_full_size (node); size += g_ir_node_get_full_size (node);
size += g_ir_node_get_attribute_size (node);
/* Also reset the offset here */
node->offset = 0;
} }
/* Adjust size for strings allocated in header below specially */ /* Adjust size for strings allocated in header below specially */
@ -195,8 +248,8 @@ g_ir_module_build_typelib (GIrModule *module,
header->reserved = 0; header->reserved = 0;
header->n_entries = n_entries; header->n_entries = n_entries;
header->n_local_entries = n_local_entries; header->n_local_entries = n_local_entries;
header->n_annotations = 0; header->n_attributes = 0;
header->annotations = 0; /* filled in later */ header->attributes = 0; /* filled in later */
if (dependencies != NULL) if (dependencies != NULL)
header->dependencies = write_string (dependencies, strings, data, &header_size); header->dependencies = write_string (dependencies, strings, data, &header_size);
else else
@ -219,7 +272,7 @@ g_ir_module_build_typelib (GIrModule *module,
header->value_blob_size = sizeof (ValueBlob); header->value_blob_size = sizeof (ValueBlob);
header->constant_blob_size = sizeof (ConstantBlob); header->constant_blob_size = sizeof (ConstantBlob);
header->error_domain_blob_size = sizeof (ErrorDomainBlob); header->error_domain_blob_size = sizeof (ErrorDomainBlob);
header->annotation_blob_size = sizeof (AnnotationBlob); header->attribute_blob_size = sizeof (AttributeBlob);
header->signature_blob_size = sizeof (SignatureBlob); header->signature_blob_size = sizeof (SignatureBlob);
header->enum_blob_size = sizeof (EnumBlob); header->enum_blob_size = sizeof (EnumBlob);
header->struct_blob_size = sizeof (StructBlob); header->struct_blob_size = sizeof (StructBlob);
@ -245,10 +298,17 @@ g_ir_module_build_typelib (GIrModule *module,
/* we picked up implicit xref nodes, start over */ /* we picked up implicit xref nodes, start over */
if (i == n_entries) if (i == n_entries)
{ {
GList *link;
g_message ("Found implicit cross references, starting over"); g_message ("Found implicit cross references, starting over");
g_hash_table_destroy (strings); g_hash_table_destroy (strings);
g_hash_table_destroy (types); g_hash_table_destroy (types);
/* Reset the cached offsets */
for (link = offset_ordered_nodes; link; link = link->next)
((GIrNode *) link->data)->offset = 0;
g_list_free (offset_ordered_nodes);
strings = NULL; strings = NULL;
g_free (data); g_free (data);
@ -282,9 +342,14 @@ g_ir_module_build_typelib (GIrModule *module,
build.modules = modules; build.modules = modules;
build.strings = strings; build.strings = strings;
build.types = types; build.types = types;
build.offset_ordered_nodes = offset_ordered_nodes;
build.n_attributes = header->n_attributes;
build.data = data; build.data = data;
g_ir_node_build_typelib (node, NULL, &build, &offset, &offset2); g_ir_node_build_typelib (node, NULL, &build, &offset, &offset2);
offset_ordered_nodes = build.offset_ordered_nodes;
header->n_attributes = build.n_attributes;
if (offset2 > old_offset + g_ir_node_get_full_size (node)) if (offset2 > old_offset + g_ir_node_get_full_size (node))
g_error ("left a hole of %d bytes\n", offset2 - old_offset - g_ir_node_get_full_size (node)); g_error ("left a hole of %d bytes\n", offset2 - old_offset - g_ir_node_get_full_size (node));
} }
@ -292,9 +357,23 @@ g_ir_module_build_typelib (GIrModule *module,
entry++; entry++;
} }
offset_ordered_nodes = g_list_reverse (offset_ordered_nodes);
g_message ("header: %d entries, %d attributes", header->n_entries, header->n_attributes);
_g_irnode_dump_stats (); _g_irnode_dump_stats ();
header->annotations = offset2; /* Write attributes after the blobs */
offset = offset2;
header->attributes = offset;
offset2 = offset + header->n_attributes * header->attribute_blob_size;
for (e = offset_ordered_nodes; e; e = e->next)
{
GIrNode *node = e->data;
write_attributes (module, node, strings, data, &offset, &offset2);
}
g_message ("reallocating to %d bytes", offset2); g_message ("reallocating to %d bytes", offset2);
@ -305,6 +384,7 @@ g_ir_module_build_typelib (GIrModule *module,
g_hash_table_destroy (strings); g_hash_table_destroy (strings);
g_hash_table_destroy (types); g_hash_table_destroy (types);
g_list_free (offset_ordered_nodes);
return typelib; return typelib;
} }

View File

@ -1,6 +1,7 @@
/* GObject introspection: Typelib creation /* GObject introspection: Typelib creation
* *
* Copyright (C) 2005 Matthias Clasen * Copyright (C) 2005 Matthias Clasen
* Copyright (C) 2008,2009 Red Hat, Inc.
* *
* This library is free software; you can redistribute it and/or * This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public * modify it under the terms of the GNU Lesser General Public
@ -184,6 +185,9 @@ g_ir_node_new (GIrNodeTypeId type)
} }
node->type = type; node->type = type;
node->offset = 0;
node->attributes = g_hash_table_new_full (g_str_hash, g_str_equal,
g_free, g_free);
return node; return node;
} }
@ -400,6 +404,8 @@ g_ir_node_free (GIrNode *node)
break; break;
} }
g_hash_table_destroy (node->attributes);
g_free (node); g_free (node);
} }
@ -540,6 +546,18 @@ g_ir_node_get_size (GIrNode *node)
return size; return size;
} }
static void
add_attribute_size (gpointer key, gpointer value, gpointer data)
{
const gchar *key_str = key;
const gchar *value_str = value;
gint *size_p = data;
*size_p += sizeof (AttributeBlob);
*size_p += ALIGN_VALUE (strlen (key_str) + 1, 4);
*size_p += ALIGN_VALUE (strlen (value_str) + 1, 4);
}
/* returns the full size of the blob including variable-size parts */ /* returns the full size of the blob including variable-size parts */
static guint32 static guint32
g_ir_node_get_full_size_internal (GIrNode *parent, g_ir_node_get_full_size_internal (GIrNode *parent,
@ -851,6 +869,14 @@ g_ir_node_get_full_size (GIrNode *node)
return g_ir_node_get_full_size_internal (NULL, node); return g_ir_node_get_full_size_internal (NULL, node);
} }
guint32
g_ir_node_get_attribute_size (GIrNode *node)
{
guint32 size = 0;
g_hash_table_foreach (node->attributes, add_attribute_size, &size);
return size;
}
int int
g_ir_node_cmp (GIrNode *node, g_ir_node_cmp (GIrNode *node,
GIrNode *other) GIrNode *other)
@ -1364,6 +1390,15 @@ g_ir_node_build_typelib (GIrNode *node,
g_ir_node_compute_offsets (node, module, modules); g_ir_node_compute_offsets (node, module, modules);
/* We should only be building each node once. If we do a typelib expansion, we also
* reset the offset in girmodule.c.
*/
g_assert (node->offset == 0);
node->offset = *offset;
build->offset_ordered_nodes = g_list_prepend (build->offset_ordered_nodes, node);
build->n_attributes += g_hash_table_size (node->attributes);
switch (node->type) switch (node->type)
{ {
case G_IR_NODE_TYPE: case G_IR_NODE_TYPE:
@ -2232,7 +2267,8 @@ g_ir_node_build_typelib (GIrNode *node,
old_offset, *offset, old_offset2, *offset2); old_offset, *offset, old_offset2, *offset2);
if (*offset2 - old_offset2 + *offset - old_offset > g_ir_node_get_full_size (node)) if (*offset2 - old_offset2 + *offset - old_offset > g_ir_node_get_full_size (node))
g_error ("exceeding space reservation !!"); g_error ("exceeding space reservation; offset: %d (prev %d) offset2: %d (prev %d) nodesize: %d",
*offset, old_offset, *offset2, old_offset2, g_ir_node_get_full_size (node));
} }
/* if str is already in the pool, return previous location, otherwise write str /* if str is already in the pool, return previous location, otherwise write str

View File

@ -51,6 +51,8 @@ struct _GIrTypelibBuild {
GList *modules; GList *modules;
GHashTable *strings; GHashTable *strings;
GHashTable *types; GHashTable *types;
GList *offset_ordered_nodes;
guint32 n_attributes;
guchar *data; guchar *data;
}; };
@ -82,6 +84,10 @@ struct _GIrNode
{ {
GIrNodeTypeId type; GIrNodeTypeId type;
gchar *name; gchar *name;
guint32 offset; /* Assigned as we build the typelib */
GHashTable *attributes;
}; };
struct _GIrNodeXRef struct _GIrNodeXRef
@ -349,6 +355,7 @@ GIrNode * g_ir_node_new (GIrNodeTypeId type);
void g_ir_node_free (GIrNode *node); void g_ir_node_free (GIrNode *node);
guint32 g_ir_node_get_size (GIrNode *node); guint32 g_ir_node_get_size (GIrNode *node);
guint32 g_ir_node_get_full_size (GIrNode *node); guint32 g_ir_node_get_full_size (GIrNode *node);
guint32 g_ir_node_get_attribute_size (GIrNode *node);
void g_ir_node_build_typelib (GIrNode *node, void g_ir_node_build_typelib (GIrNode *node,
GIrNode *parent, GIrNode *parent,
GIrTypelibBuild *build, GIrTypelibBuild *build,

View File

@ -68,6 +68,7 @@ typedef enum
STATE_INTERFACE_CONSTANT, STATE_INTERFACE_CONSTANT,
STATE_ALIAS, STATE_ALIAS,
STATE_TYPE, STATE_TYPE,
STATE_ATTRIBUTE,
STATE_UNKNOWN STATE_UNKNOWN
} ParseState; } ParseState;
@ -1864,6 +1865,44 @@ end_type (ParseContext *ctx)
} }
} }
static gboolean
start_attribute (GMarkupParseContext *context,
const gchar *element_name,
const gchar **attribute_names,
const gchar **attribute_values,
ParseContext *ctx,
GError **error)
{
const gchar *name;
const gchar *value;
GIrNode *curnode;
if (strcmp (element_name, "attribute") != 0 || ctx->node_stack == NULL)
return FALSE;
name = find_attribute ("name", attribute_names, attribute_values);
value = find_attribute ("value", attribute_names, attribute_values);
if (name == NULL)
{
MISSING_ATTRIBUTE (context, error, element_name, "name");
return FALSE;
}
if (value == NULL)
{
MISSING_ATTRIBUTE (context, error, element_name, "value");
return FALSE;
}
state_switch (ctx, STATE_ATTRIBUTE);
curnode = CURRENT_NODE (ctx);
g_hash_table_insert (curnode->attributes, g_strdup (name), g_strdup (value));
return TRUE;
}
static gboolean static gboolean
start_return_value (GMarkupParseContext *context, start_return_value (GMarkupParseContext *context,
const gchar *element_name, const gchar *element_name,
@ -2383,6 +2422,10 @@ start_element_handler (GMarkupParseContext *context,
attribute_names, attribute_values, attribute_names, attribute_values,
ctx, error)) ctx, error))
goto out; goto out;
else if (start_attribute (context, element_name,
attribute_names, attribute_values,
ctx, error))
goto out;
break; break;
case 'b': case 'b':
if (start_enum (context, element_name, if (start_enum (context, element_name,
@ -2662,7 +2705,7 @@ start_element_handler (GMarkupParseContext *context,
ctx->unknown_depth += 1; ctx->unknown_depth += 1;
} }
out: ; out:
if (*error) if (*error)
{ {
g_markup_parse_context_get_position (context, &line_number, &char_number); g_markup_parse_context_get_position (context, &line_number, &char_number);
@ -3027,6 +3070,13 @@ end_element_handler (GMarkupParseContext *context,
end_type (ctx); end_type (ctx);
break; break;
} }
case STATE_ATTRIBUTE:
if (strcmp ("attribute", element_name) == 0)
{
state_switch (ctx, ctx->prev_state);
}
break;
case STATE_UNKNOWN: case STATE_UNKNOWN:
ctx->unknown_depth -= 1; ctx->unknown_depth -= 1;
if (ctx->unknown_depth == 0) if (ctx->unknown_depth == 0)

View File

@ -185,7 +185,7 @@ g_typelib_check_sanity (void)
CHECK_SIZE (ObjectBlob, 44); CHECK_SIZE (ObjectBlob, 44);
CHECK_SIZE (InterfaceBlob, 40); CHECK_SIZE (InterfaceBlob, 40);
CHECK_SIZE (ConstantBlob, 24); CHECK_SIZE (ConstantBlob, 24);
CHECK_SIZE (AnnotationBlob, 12); CHECK_SIZE (AttributeBlob, 12);
CHECK_SIZE (UnionBlob, 40); CHECK_SIZE (UnionBlob, 40);
#undef CHECK_SIZE #undef CHECK_SIZE
@ -334,7 +334,7 @@ validate_header (ValidateContext *ctx,
header->value_blob_size != sizeof (ValueBlob) || header->value_blob_size != sizeof (ValueBlob) ||
header->constant_blob_size != sizeof (ConstantBlob) || header->constant_blob_size != sizeof (ConstantBlob) ||
header->error_domain_blob_size != sizeof (ErrorDomainBlob) || header->error_domain_blob_size != sizeof (ErrorDomainBlob) ||
header->annotation_blob_size != sizeof (AnnotationBlob) || header->attribute_blob_size != sizeof (AttributeBlob) ||
header->signature_blob_size != sizeof (SignatureBlob) || header->signature_blob_size != sizeof (SignatureBlob) ||
header->enum_blob_size != sizeof (EnumBlob) || header->enum_blob_size != sizeof (EnumBlob) ||
header->struct_blob_size != sizeof (StructBlob) || header->struct_blob_size != sizeof (StructBlob) ||
@ -358,21 +358,21 @@ validate_header (ValidateContext *ctx,
return FALSE; return FALSE;
} }
if (!is_aligned (header->annotations)) if (!is_aligned (header->attributes))
{ {
g_set_error (error, g_set_error (error,
G_TYPELIB_ERROR, G_TYPELIB_ERROR,
G_TYPELIB_ERROR_INVALID_HEADER, G_TYPELIB_ERROR_INVALID_HEADER,
"Misaligned annotations"); "Misaligned attributes");
return FALSE; return FALSE;
} }
if (header->annotations == 0 && header->n_annotations > 0) if (header->attributes == 0 && header->n_attributes > 0)
{ {
g_set_error (error, g_set_error (error,
G_TYPELIB_ERROR, G_TYPELIB_ERROR,
G_TYPELIB_ERROR_INVALID_HEADER, G_TYPELIB_ERROR_INVALID_HEADER,
"Wrong number of annotations"); "Wrong number of attributes");
return FALSE; return FALSE;
} }
@ -1860,13 +1860,13 @@ validate_directory (ValidateContext *ctx,
} }
static gboolean static gboolean
validate_annotations (ValidateContext *ctx, validate_attributes (ValidateContext *ctx,
GError **error) GError **error)
{ {
GTypelib *typelib = ctx->typelib; GTypelib *typelib = ctx->typelib;
Header *header = (Header *)typelib->data; Header *header = (Header *)typelib->data;
if (header->size < header->annotations + header->n_annotations * sizeof (AnnotationBlob)) if (header->size < header->attributes + header->n_attributes * sizeof (AttributeBlob))
{ {
g_set_error (error, g_set_error (error,
G_TYPELIB_ERROR, G_TYPELIB_ERROR,
@ -1926,9 +1926,9 @@ g_typelib_validate (GTypelib *typelib,
return FALSE; return FALSE;
} }
if (!validate_annotations (&ctx, error)) if (!validate_attributes (&ctx, error))
{ {
prefix_with_context (error, "annotations", &ctx); prefix_with_context (error, "attributes", &ctx);
return FALSE; return FALSE;
} }

View File

@ -52,14 +52,15 @@ G_BEGIN_DECLS
* *
* The typelib has the following general format. * The typelib has the following general format.
* *
* typelib ::= header, directory, blobs, annotations * typelib ::= header, directory, blobs, attributes, attributedata
* *
* directory ::= list of entries * directory ::= list of entries
* *
* entry ::= blob type, name, namespace, offset * entry ::= blob type, name, namespace, offset
* blob ::= function|callback|struct|boxed|enum|flags|object|interface|constant|errordomain|union * blob ::= function|callback|struct|boxed|enum|flags|object|interface|constant|errordomain|union
* annotations ::= list of annotations, sorted by offset * attributes ::= list of attributes, sorted by offset
* annotation ::= offset, key, value * attribute ::= offset, key, value
* attributedata ::= string data for attributes
* *
* Details * Details
* *
@ -189,8 +190,8 @@ typedef enum {
* @n_local_entries: The number of entries referring to blobs in this typelib. The * @n_local_entries: The number of entries referring to blobs in this typelib. The
* local entries must occur before the unresolved entries. * local entries must occur before the unresolved entries.
* @directory: Offset of the directory in the typelib. * @directory: Offset of the directory in the typelib.
* @n_annotations: Number of annotation blocks * @n_attributes: Number of attribute blocks
* @annotations: Offset of the list of annotations in the typelib. * @attributes: Offset of the list of attributes in the typelib.
* @dependencies: Offset of a single string, which is the list of * @dependencies: Offset of a single string, which is the list of
* dependencies, separated by the '|' character. The * dependencies, separated by the '|' character. The
* dependencies are required in order to avoid having programs * dependencies are required in order to avoid having programs
@ -212,7 +213,7 @@ typedef enum {
* @property_blob_size: See above. * @property_blob_size: See above.
* @field_blob_size: See above. * @field_blob_size: See above.
* @value_blob_size: See above. * @value_blob_size: See above.
* @annotation_blob_size: See above. * @attribute_blob_size: See above.
* @constant_blob_size: See above. * @constant_blob_size: See above.
* @object_blob_size: See above. * @object_blob_size: See above.
* @union_blob_size: See above. * @union_blob_size: See above.
@ -237,8 +238,8 @@ typedef struct {
guint16 n_entries; guint16 n_entries;
guint16 n_local_entries; guint16 n_local_entries;
guint32 directory; guint32 directory;
guint32 n_annotations; guint32 n_attributes;
guint32 annotations; guint32 attributes;
guint32 dependencies; guint32 dependencies;
@ -256,7 +257,7 @@ typedef struct {
guint16 property_blob_size; guint16 property_blob_size;
guint16 field_blob_size; guint16 field_blob_size;
guint16 value_blob_size; guint16 value_blob_size;
guint16 annotation_blob_size; guint16 attribute_blob_size;
guint16 constant_blob_size; guint16 constant_blob_size;
guint16 error_domain_blob_size; guint16 error_domain_blob_size;
@ -1000,18 +1001,18 @@ typedef struct {
} ConstantBlob; } ConstantBlob;
/** /**
* AnnotationBlob: * AttributeBlob:
* @offset: The offset of the typelib entry to which this annotation refers. * @offset: The offset of the typelib entry to which this attribute refers.
* Annotations are kept sorted by offset, so that the annotations * Attributes are kept sorted by offset, so that the attributes
* of an entry can be found by a binary search. * of an entry can be found by a binary search.
* @name: The name of the annotation, a string. * @name: The name of the attribute, a string.
* @value: The value of the annotation (also a string) * @value: The value of the attribute (also a string)
*/ */
typedef struct { typedef struct {
guint32 offset; guint32 offset;
guint32 name; guint32 name;
guint32 value; guint32 value;
} AnnotationBlob; } AttributeBlob;
struct _GTypelib { struct _GTypelib {
guchar *data; guchar *data;