mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-11-10 03:16:17 +01:00
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:
parent
1b22fa426f
commit
ff6b28c17b
37
ginfo.c
37
ginfo.c
@ -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
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
|
||||
|
16
girnode.c
16
girnode.c
@ -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++;
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
38
gtypelib.c
38
gtypelib.c
@ -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))
|
||||
|
@ -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;
|
||||
|
Loading…
Reference in New Issue
Block a user