gtype: Add g_type_interface_instantiatable_prerequisite()

This function returns the most specific instantiatable type
that is a prerequisite for a given interface.

This type is necessary in particular when dealing with GValues
because a GValue contains an instance of a type.

This commit includes tests for the new API.
This commit is contained in:
Benjamin Otte 2019-11-25 19:40:39 +01:00 committed by Philip Withnall
parent e1b5afb7c0
commit 98f0a5a7da
4 changed files with 115 additions and 0 deletions

View File

@ -65,6 +65,7 @@ g_type_default_interface_unref
g_type_children
g_type_interfaces
g_type_interface_prerequisites
g_type_interface_instantiatable_prerequisite
g_type_set_qdata
g_type_get_qdata
g_type_query

View File

@ -1689,6 +1689,54 @@ g_type_interface_prerequisites (GType interface_type,
}
}
/**
* g_type_interface_instantiatable_prerequisite:
* @interface_type: an interface type
*
* Returns the most specific instantiatable prerequisite of an
* interface type. If the interface type has no instantiatable
* prerequisite, %G_TYPE_INVALID is returned.
*
* See g_type_interface_add_prerequisite() for more information
* about prerequisites.
*
* Returns: the instantiatable prerequisite type or %G_TYPE_INVALID if none
*
* Since: 2.68
**/
GType
g_type_interface_instantiatable_prerequisite (GType interface_type)
{
TypeNode *inode = NULL;
TypeNode *iface;
guint i;
g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), G_TYPE_INVALID);
iface = lookup_type_node_I (interface_type);
if (iface == NULL)
return G_TYPE_INVALID;
G_READ_LOCK (&type_rw_lock);
for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
{
GType prerequisite = IFACE_NODE_PREREQUISITES (iface)[i];
TypeNode *node = lookup_type_node_I (prerequisite);
if (node->is_instantiatable)
{
if (!inode || type_node_is_a_L (node, inode))
inode = node;
}
}
G_READ_UNLOCK (&type_rw_lock);
if (inode)
return NODE_TYPE (inode);
else
return G_TYPE_INVALID;
}
static IFaceHolder*
type_iface_peek_holder_L (TypeNode *iface,

View File

@ -1300,6 +1300,9 @@ void g_type_interface_add_prerequisite (GType interface_type,
GLIB_AVAILABLE_IN_ALL
GType*g_type_interface_prerequisites (GType interface_type,
guint *n_prerequisites);
GLIB_AVAILABLE_IN_2_68
GType g_type_interface_instantiatable_prerequisite
(GType interface_type);
GLIB_DEPRECATED_IN_2_58
void g_type_class_add_private (gpointer g_class,
gsize private_size);

View File

@ -40,6 +40,63 @@ foo_default_init (FooInterface *iface)
{
}
typedef struct {
GTypeInterface g_iface;
} BaaInterface;
GType baa_get_type (void);
G_DEFINE_INTERFACE (Baa, baa, G_TYPE_INVALID)
static void
baa_default_init (BaaInterface *iface)
{
}
typedef struct {
GTypeInterface g_iface;
} BooInterface;
GType boo_get_type (void);
G_DEFINE_INTERFACE_WITH_CODE (Boo, boo, G_TYPE_INVALID,
g_type_interface_add_prerequisite (g_define_type_id, baa_get_type ()))
static void
boo_default_init (BooInterface *iface)
{
}
typedef struct {
GTypeInterface g_iface;
} BibiInterface;
GType bibi_get_type (void);
G_DEFINE_INTERFACE (Bibi, bibi, G_TYPE_INITIALLY_UNOWNED)
static void
bibi_default_init (BibiInterface *iface)
{
}
typedef struct {
GTypeInterface g_iface;
} BozoInterface;
GType bozo_get_type (void);
G_DEFINE_INTERFACE_WITH_CODE (Bozo, bozo, G_TYPE_INVALID,
g_type_interface_add_prerequisite (g_define_type_id, foo_get_type ());
g_type_interface_add_prerequisite (g_define_type_id, bibi_get_type ()))
static void
bozo_default_init (BozoInterface *iface)
{
}
static void
test_interface_prerequisite (void)
{
@ -52,6 +109,7 @@ test_interface_prerequisite (void)
g_assert_cmpint (n_prereqs, ==, 2);
g_assert (prereqs[0] == bar_get_type ());
g_assert (prereqs[1] == G_TYPE_OBJECT);
g_assert (g_type_interface_instantiatable_prerequisite (foo_get_type ()) == G_TYPE_OBJECT);
iface = g_type_default_interface_ref (foo_get_type ());
parent = g_type_interface_peek_parent (iface);
@ -59,6 +117,11 @@ test_interface_prerequisite (void)
g_type_default_interface_unref (iface);
g_free (prereqs);
g_assert_cmpint (g_type_interface_instantiatable_prerequisite (baa_get_type ()), ==, G_TYPE_INVALID);
g_assert_cmpint (g_type_interface_instantiatable_prerequisite (boo_get_type ()), ==, G_TYPE_INVALID);
g_assert_cmpint (g_type_interface_instantiatable_prerequisite (bozo_get_type ()), ==, G_TYPE_INITIALLY_UNOWNED);
}
typedef struct {