Bug 551738 - Associate classes with their structs

Inside glibtransformer, we now look at structures ending in "Class" and
see if they have an associated GlibObject (i.e. a structure of the same
name without the "Class" suffix).  If found, pair them up.

The .gir file for <class> gains an attribute denoting its associated
class struct.  Any <record> many now have a glib:is-class-struct-for
annotation which tells which (if any) <class> for which it defines the
layout.

In the .typelib, we record the association between the class and
its structure.  Generic structures however just have a boolean
saying whether they're a class struct.  (Going from a generic class
struct to its class should not be necessary).

Finally, we expose GIRepository APIs to access both bits of information
from the .typelib.

svn path=/trunk/; revision=1088
This commit is contained in:
Colin Walters 2009-02-06 18:37:13 +00:00
parent 1b22fa426f
commit ff6b28c17b
8 changed files with 100 additions and 11 deletions

37
ginfo.c
View File

@ -1178,6 +1178,24 @@ g_struct_info_get_alignment (GIStructInfo *info)
return blob->alignment;
}
/**
* g_struct_info_is_class_struct:
* @info: GIStructInfo
*
* Return true if this structure represents the "class structure" for some
* GObject. This function is mainly useful to hide this kind of structure
* from public APIs.
*
*/
gboolean
g_struct_info_is_class_struct (GIStructInfo *info)
{
GIBaseInfo *base = (GIBaseInfo *)info;
StructBlob *blob = (StructBlob *)&base->typelib->data[base->offset];
return blob->is_class_struct;
}
gint
g_enum_info_get_n_values (GIEnumInfo *info)
{
@ -1469,6 +1487,25 @@ g_object_info_get_constant (GIObjectInfo *info,
base->typelib, offset);
}
/**
* g_object_info_get_class_struct:
* @info: A #GIObjectInfo to query
*
* Every GObject has two structures; an instance structure and a class
* structure. This function returns the metadata for the class structure.
*/
GIStructInfo *
g_object_info_get_class_struct (GIObjectInfo *info)
{
GIBaseInfo *base = (GIBaseInfo *)info;
ObjectBlob *blob = (ObjectBlob *)&base->typelib->data[base->offset];
if (blob->class_struct)
return (GIStructInfo *) g_info_from_entry (base->repository,
base->typelib, blob->class_struct);
else
return NULL;
}
/* GIInterfaceInfo functions */
gint

View File

@ -412,6 +412,7 @@ GIFunctionInfo * g_struct_info_find_method (GIStructInfo *info,
const gchar *name);
gsize g_struct_info_get_size (GIStructInfo *info);
gsize g_struct_info_get_alignment (GIStructInfo *info);
gboolean g_struct_info_is_class_struct (GIStructInfo *info);
/* GIRegisteredTypeInfo */
@ -455,6 +456,7 @@ GIVFuncInfo * g_object_info_get_vfunc (GIObjectInfo *in
gint g_object_info_get_n_constants (GIObjectInfo *info);
GIConstantInfo * g_object_info_get_constant (GIObjectInfo *info,
gint n);
GIStructInfo * g_object_info_get_class_struct (GIObjectInfo *info);
/* GIInterfaceInfo */

View File

@ -223,7 +223,7 @@ g_ir_module_build_typelib (GIrModule *module,
header->signature_blob_size = 8;
header->enum_blob_size = 20;
header->struct_blob_size = 24;
header->object_blob_size = 32;
header->object_blob_size = sizeof(ObjectBlob);
header->interface_blob_size = 28;
header->union_blob_size = 32;

View File

@ -285,7 +285,8 @@ g_ir_node_free (GIrNode *node)
g_free (node->name);
g_free (iface->gtype_name);
g_free (iface->gtype_init);
g_free (iface->class_struct);
g_free (iface->parent);
for (l = iface->interfaces; l; l = l->next)
@ -431,7 +432,7 @@ g_ir_node_get_size (GIrNode *node)
GIrNodeInterface *iface = (GIrNodeInterface *)node;
n = g_list_length (iface->interfaces);
size = 32 + 2 * (n + (n % 2));
size = sizeof(ObjectBlob) + 2 * (n + (n % 2));
for (l = iface->members; l; l = l->next)
size += g_ir_node_get_size ((GIrNode *)l->data);
@ -647,9 +648,11 @@ g_ir_node_get_full_size_internal (GIrNode *parent,
GIrNodeInterface *iface = (GIrNodeInterface *)node;
n = g_list_length (iface->interfaces);
size = 32;
size = sizeof(ObjectBlob);
if (iface->parent)
size += ALIGN_VALUE (strlen (iface->parent) + 1, 4);
if (iface->class_struct)
size += ALIGN_VALUE (strlen (iface->class_struct) + 1, 4);
size += ALIGN_VALUE (strlen (node->name) + 1, 4);
size += ALIGN_VALUE (strlen (iface->gtype_name) + 1, 4);
if (iface->gtype_init)
@ -1792,6 +1795,7 @@ g_ir_node_build_typelib (GIrNode *node,
blob->blob_type = BLOB_TYPE_STRUCT;
blob->deprecated = struct_->deprecated;
blob->is_class_struct = struct_->is_gclass_struct;
blob->reserved = 0;
blob->name = write_string (node->name, strings, data, offset2);
blob->alignment = struct_->alignment;
@ -2001,6 +2005,10 @@ g_ir_node_build_typelib (GIrNode *node,
blob->parent = find_entry (module, modules, object->parent);
else
blob->parent = 0;
if (object->class_struct)
blob->class_struct = find_entry (module, modules, object->class_struct);
else
blob->class_struct = 0;
blob->n_interfaces = 0;
blob->n_fields = 0;
@ -2010,7 +2018,7 @@ g_ir_node_build_typelib (GIrNode *node,
blob->n_vfuncs = 0;
blob->n_constants = 0;
*offset += 32;
*offset += sizeof(ObjectBlob);
for (l = object->interfaces; l; l = l->next)
{
blob->n_interfaces++;

View File

@ -228,6 +228,7 @@ struct _GIrNodeInterface
gchar *gtype_init;
gchar *parent;
gchar *class_struct; /* Only applies to classes */
GList *interfaces;
GList *prerequisites;
@ -292,6 +293,7 @@ struct _GIrNodeStruct
gboolean deprecated;
gboolean disguised;
gboolean is_gclass_struct;
gchar *gtype_name;
gchar *gtype_init;

View File

@ -1530,6 +1530,7 @@ start_class (GMarkupParseContext *context,
{
const gchar *name;
const gchar *parent;
const gchar *class_struct;
const gchar *typename;
const gchar *typeinit;
const gchar *deprecated;
@ -1537,6 +1538,7 @@ start_class (GMarkupParseContext *context,
name = find_attribute ("name", attribute_names, attribute_values);
parent = find_attribute ("parent", attribute_names, attribute_values);
class_struct = find_attribute ("glib:class-struct", attribute_names, attribute_values);
typename = find_attribute ("glib:type-name", attribute_names, attribute_values);
typeinit = find_attribute ("glib:get-type", attribute_names, attribute_values);
deprecated = find_attribute ("deprecated", attribute_names, attribute_values);
@ -1557,6 +1559,7 @@ start_class (GMarkupParseContext *context,
iface->gtype_name = g_strdup (typename);
iface->gtype_init = g_strdup (typeinit);
iface->parent = g_strdup (parent);
iface->class_struct = g_strdup (class_struct);
if (deprecated)
iface->deprecated = TRUE;
else
@ -2122,6 +2125,7 @@ start_struct (GMarkupParseContext *context,
const gchar *disguised;
const gchar *gtype_name;
const gchar *gtype_init;
const gchar *gclass_struct;
GIrNodeStruct *struct_;
name = find_attribute ("name", attribute_names, attribute_values);
@ -2129,6 +2133,7 @@ start_struct (GMarkupParseContext *context,
disguised = find_attribute ("disguised", attribute_names, attribute_values);
gtype_name = find_attribute ("glib:type-name", attribute_names, attribute_values);
gtype_init = find_attribute ("glib:get-type", attribute_names, attribute_values);
gclass_struct = find_attribute ("glib:is-class-struct-for", attribute_names, attribute_values);
if (name == NULL && ctx->node_stack == NULL)
{
@ -2156,6 +2161,8 @@ start_struct (GMarkupParseContext *context,
if (disguised && strcmp (disguised, "1") == 0)
struct_->disguised = TRUE;
struct_->is_gclass_struct = gclass_struct != NULL;
struct_->gtype_name = g_strdup (gtype_name);
struct_->gtype_init = g_strdup (gtype_init);

View File

@ -181,7 +181,7 @@ g_typelib_check_sanity (void)
CHECK_SIZE (PropertyBlob, 12);
CHECK_SIZE (SignalBlob, 12);
CHECK_SIZE (VFuncBlob, 16);
CHECK_SIZE (ObjectBlob, 32);
CHECK_SIZE (ObjectBlob, 36);
CHECK_SIZE (InterfaceBlob, 28);
CHECK_SIZE (ConstantBlob, 20);
CHECK_SIZE (AnnotationBlob, 12);
@ -313,6 +313,15 @@ validate_header (ValidateContext *ctx,
"Typelib size mismatch");
return FALSE;
}
/* This is a sanity check for a specific typelib; it
* prevents us from loading an incompatible typelib. It's OK to change
* these hardcoded constants to sizeof() as you see fit.
*
* We want to keep the hardcoded checks in g_typelib_check_sanity to
* protect against inadvertent or buggy changes to the typelib format
* itself.
*/
if (header->entry_blob_size != 12 ||
header->function_blob_size != 20 ||
@ -329,7 +338,7 @@ validate_header (ValidateContext *ctx,
header->signature_blob_size != 8 ||
header->enum_blob_size != 20 ||
header->struct_blob_size != 24 ||
header->object_blob_size != 32 ||
header->object_blob_size != sizeof(ObjectBlob) ||
header->interface_blob_size != 28 ||
header->union_blob_size != 32)
{
@ -1435,7 +1444,9 @@ validate_object_blob (ValidateContext *ctx,
{
DirEntry *entry;
entry = g_typelib_get_dir_entry (typelib, blob->parent);
entry = get_dir_entry_checked (typelib, blob->parent, error);
if (!entry)
return FALSE;
if (entry->blob_type != BLOB_TYPE_OBJECT &&
(entry->local || entry->blob_type != 0))
{
@ -1447,6 +1458,23 @@ validate_object_blob (ValidateContext *ctx,
}
}
if (blob->class_struct != 0)
{
DirEntry *entry;
entry = get_dir_entry_checked (typelib, blob->class_struct, error);
if (!entry)
return FALSE;
if (entry->blob_type != BLOB_TYPE_STRUCT && entry->local)
{
g_set_error (error,
G_TYPELIB_ERROR,
G_TYPELIB_ERROR_INVALID_BLOB,
"Class struct invalid type or not local");
return FALSE;
}
}
if (typelib->len < offset + sizeof (ObjectBlob) +
(blob->n_interfaces + blob->n_interfaces % 2) * 2 +
blob->n_fields * sizeof (FieldBlob) +
@ -1481,7 +1509,9 @@ validate_object_blob (ValidateContext *ctx,
return FALSE;
}
entry = g_typelib_get_dir_entry (typelib, iface);
entry = get_dir_entry_checked (typelib, iface, error);
if (!entry)
return FALSE;
if (entry->blob_type != BLOB_TYPE_INTERFACE &&
(entry->local || entry->blob_type != 0))

View File

@ -306,8 +306,9 @@ typedef struct
guint16 deprecated : 1;
guint16 unregistered : 1;
guint16 alignment : 6;
guint16 reserved : 8;
guint16 is_class_struct : 1;
guint16 alignment : 6;
guint16 reserved : 7;
guint32 name;
@ -438,6 +439,8 @@ typedef struct
guint32 gtype_init;
guint16 parent;
guint16 class_struct;
guint16 reserved2;
guint16 n_interfaces;
guint16 n_fields;