From 98f0a5a7da69d5d7ed2853fb1c58ed2d4aeff809 Mon Sep 17 00:00:00 2001 From: Benjamin Otte Date: Mon, 25 Nov 2019 19:40:39 +0100 Subject: [PATCH] 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. --- docs/reference/gobject/gobject-sections.txt | 1 + gobject/gtype.c | 48 ++++++++++++++++ gobject/gtype.h | 3 + gobject/tests/type.c | 63 +++++++++++++++++++++ 4 files changed, 115 insertions(+) diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index f52d95379..36552b1b3 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -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 diff --git a/gobject/gtype.c b/gobject/gtype.c index c25575800..12ad8be28 100644 --- a/gobject/gtype.c +++ b/gobject/gtype.c @@ -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, diff --git a/gobject/gtype.h b/gobject/gtype.h index 89178411f..d839e4e3a 100644 --- a/gobject/gtype.h +++ b/gobject/gtype.h @@ -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); diff --git a/gobject/tests/type.c b/gobject/tests/type.c index c5db7e992..30e138a77 100644 --- a/gobject/tests/type.c +++ b/gobject/tests/type.c @@ -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 {