[glib/wip/otte/interface-types: 437/448] gtype: Add g_type_interface_instantiable_prerequisite()




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

    gtype: Add g_type_interface_instantiable_prerequisite()
    
    There is (at most) a single GType that is instantiable and a
    prerequisite for an interface. This function returns that type.
    
    This type is necessary in particular when dealing with GValues because a
    GValue contains an instance of a type.

 docs/reference/gobject/gobject-sections.txt |  1 +
 gobject/gtype.c                             | 45 +++++++++++++++++++++++++++++
 gobject/gtype.h                             |  3 ++
 gobject/tests/type.c                        |  1 +
 4 files changed, 50 insertions(+)
---
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt
index f52d95379..065e54e8f 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_instantiable_prerequisite
 g_type_set_qdata
 g_type_get_qdata
 g_type_query
diff --git a/gobject/gtype.c b/gobject/gtype.c
index c25575800..c90cad2a8 100644
--- a/gobject/gtype.c
+++ b/gobject/gtype.c
@@ -1689,6 +1689,51 @@ g_type_interface_prerequisites (GType  interface_type,
     }
 }
 
+/**
+ * g_type_interface_instantiable_prerequisite:
+ * @interface_type: an interface type
+ *
+ * Returns the instantiable prerequisite of an interface type.
+ *
+ * If the interface type has no instantiable prerequisite, 0 is returned.
+ *
+ * Since: 2.64
+ *
+ * Returns: the instantiable prerequisite type or 0 if none
+ **/
+GType
+g_type_interface_instantiable_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 0;
+
+  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 0;
+}
 
 static IFaceHolder*
 type_iface_peek_holder_L (TypeNode *iface,
diff --git a/gobject/gtype.h b/gobject/gtype.h
index 89178411f..90a52fa18 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_64
+GType g_type_interface_instantiable_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..9ed1806e9 100644
--- a/gobject/tests/type.c
+++ b/gobject/tests/type.c
@@ -52,6 +52,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_instantiable_prerequisite (foo_get_type ()) == G_TYPE_OBJECT);
 
   iface = g_type_default_interface_ref (foo_get_type ());
   parent = g_type_interface_peek_parent (iface);


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