[glib/wip/otte/interface-types: 3/6] gtype: Add g_type_interface_instantiatable_prerequisite()




commit 870461b7f121706468235bf46758debe1f03bef2
Author: Benjamin Otte <otte redhat com>
Date:   Mon Nov 25 19:40:39 2019 +0100

    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                             | 45 +++++++++++++++++++++
 gobject/gtype.h                             |  3 ++
 gobject/tests/type.c                        | 63 +++++++++++++++++++++++++++++
 4 files changed, 112 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..ff5a8b01d 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -1689,6 +1689,51 @@ 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.
+ *
+ * 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 {


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]