=== Released 2.2.0 ===
[platform/upstream/glib.git] / gobject / gtype.c
index f419af8..9742239 100644 (file)
@@ -16,6 +16,7 @@
  * Free Software Foundation, Inc., 59 Temple Place, Suite 330,
  * Boston, MA 02111-1307, USA.
  */
+#include        <config.h>
 #include       "gtype.h"
 
 /*
@@ -383,8 +384,8 @@ type_node_fundamental_new_W (GType                 ftype,
   g_assert ((ftype & TYPE_ID_MASK) == 0);
   g_assert (ftype <= G_TYPE_FUNDAMENTAL_MAX);
   
-  if (ftype == static_fundamental_next)
-    static_fundamental_next += 1 << G_TYPE_FUNDAMENTAL_SHIFT;
+  if (ftype >> G_TYPE_FUNDAMENTAL_SHIFT == static_fundamental_next)
+    static_fundamental_next++;
   
   type_flags &= TYPE_FUNDAMENTAL_FLAG_MASK;
   
@@ -473,7 +474,7 @@ type_lookup_prerequisite_L (TypeNode *iface,
   return FALSE;
 }
 
-static inline gchar*
+static gchar*
 type_descriptive_name_I (GType type)
 {
   if (type)
@@ -1145,6 +1146,17 @@ type_iface_add_prerequisite_W (TypeNode *iface,
     type_iface_add_prerequisite_W (lookup_type_node_I (dependants[i]), prerequisite_node);
 }
 
+/**
+ * g_type_interface_add_prerequisite:
+ * @interface_type: #GType value of an interface type.
+ * @prerequisite_type: #GType value of an interface or instantiatable type.
+ * 
+ * Adds @prerequisite_type to the list of prerequisites of @interface_type.
+ * This means that any type implementing @interface_type must also implement
+ * @prerequisite_type. Prerequisites can be thought of as an alternative to
+ * interface derivation (which GType doesn't support). An interface can have
+ * at most one instantiatable prerequisite type.
+ **/
 void
 g_type_interface_add_prerequisite (GType interface_type,
                                   GType prerequisite_type)
@@ -1202,13 +1214,12 @@ g_type_interface_add_prerequisite (GType interface_type,
     }
   else if (NODE_IS_IFACE (prerequisite_node))
     {
-      GType *dependants;
-      guint n_dependants, i;
+      GType *prerequisites;
+      guint i;
       
-      dependants = iface_node_get_dependants_array_L (prerequisite_node);
-      n_dependants = dependants ? dependants[0] : 0;
-      for (i = 1; i <= n_dependants; i++)
-       type_iface_add_prerequisite_W (iface, lookup_type_node_I (dependants[i]));
+      prerequisites = IFACE_NODE_PREREQUISITES (prerequisite_node);
+      for (i = 0; i < IFACE_NODE_N_PREREQUISITES (prerequisite_node); i++)
+       type_iface_add_prerequisite_W (iface, lookup_type_node_I (prerequisites[i]));
       type_iface_add_prerequisite_W (iface, prerequisite_node);
       G_WRITE_UNLOCK (&type_rw_lock);
     }
@@ -1221,6 +1232,64 @@ g_type_interface_add_prerequisite (GType interface_type,
     }
 }
 
+/**
+ * g_type_interface_prerequisites:
+ * @interface_type: an interface type
+ * @n_prerequisites: location to return the number of prerequisites, or %NULL
+ * 
+ * Returns the prerequisites of an interfaces type.
+ * 
+ * Return value: a newly-allocated zero-terminated array of #GType containing 
+ * the prerequisites of @interface_type
+ *
+ * Since: 2.2
+ **/
+GType* /* free result */
+g_type_interface_prerequisites (GType  interface_type,
+                               guint *n_prerequisites)
+{
+  TypeNode *iface;
+  
+  g_return_val_if_fail (G_TYPE_IS_INTERFACE (interface_type), NULL);
+
+  iface = lookup_type_node_I (interface_type);
+  if (iface)
+    {
+      GType *types;
+      TypeNode *inode = NULL;
+      guint i, n = 0;
+      
+      G_READ_LOCK (&type_rw_lock);
+      types = g_new0 (GType, IFACE_NODE_N_PREREQUISITES (iface) + 1);
+      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 &&
+             (!inode || type_node_is_a_L (node, inode)))
+           inode = node;
+         else
+           types[n++] = NODE_TYPE (node);
+       }
+      if (inode)
+       types[n++] = NODE_TYPE (inode);
+      
+      if (n_prerequisites)
+       *n_prerequisites = n;
+      G_READ_UNLOCK (&type_rw_lock);
+      
+      return types;
+    }
+  else
+    {
+      if (n_prerequisites)
+       *n_prerequisites = 0;
+      
+      return NULL;
+    }
+}
+
+
 static IFaceHolder*
 type_iface_peek_holder_L (TypeNode *iface,
                          GType     instance_type)
@@ -1555,34 +1624,33 @@ type_class_init_Wm (TypeNode   *node,
 static void
 type_data_finalize_class_ifaces_Wm (TypeNode *node)
 {
-  IFaceEntry *entry;
   guint i;
-  
+
   g_assert (node->is_instantiatable && node->data && node->data->class.class && node->data->common.ref_count == 0);
-  
+
   g_message ("finalizing interfaces for %sClass `%s'",
             type_descriptive_name_I (NODE_FUNDAMENTAL_TYPE (node)),
             type_descriptive_name_I (NODE_TYPE (node)));
-  
-  for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
-    if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
-       CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
-      entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
-  while (entry)
+
+ reiterate:
+  for (i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
     {
-      if (!type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
+      IFaceEntry *entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
+      if (entry->vtable)
        {
-         /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
-          * iface vtable came from parent
-          */
-         entry->vtable = NULL;
+          if (type_iface_vtable_finalize_Wm (lookup_type_node_I (entry->iface_type), node, entry->vtable))
+            {
+              /* refetch entries, IFACES_ENTRIES might be modified */
+              goto reiterate;
+            }
+          else
+            {
+              /* type_iface_vtable_finalize_Wm() doesn't modify write lock upon FALSE,
+               * iface vtable came from parent
+               */
+              entry->vtable = NULL;
+            }
        }
-      
-      /* refetch entry, IFACES_ENTRIES might be modified */
-      for (entry = NULL, i = 0; i < CLASSED_NODE_N_IFACES (node); i++)
-       if (CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable &&
-           CLASSED_NODE_IFACES_ENTRIES (node)[i].vtable->g_instance_type == NODE_TYPE (node))
-         entry = CLASSED_NODE_IFACES_ENTRIES (node) + i;
     }
 }
 
@@ -1892,6 +1960,16 @@ g_type_add_interface_static (GType                 instance_type,
   G_WRITE_UNLOCK (&type_rw_lock);
 }
 
+/**
+ * g_type_add_interface_dynamic:
+ * @instance_type: the #GType value of an instantiable type.
+ * @interface_type: the #GType value of an interface type.
+ * @plugin: the #GTypePlugin structure to retrieve the #GInterfaceInfo from.
+ * 
+ * Adds the dynamic @interface_type to @instantiable_type. The information
+ * contained in the #GTypePlugin structure pointed to by @plugin
+ * is used to manage the relationship.
+ **/
 void
 g_type_add_interface_dynamic (GType        instance_type,
                              GType        interface_type,
@@ -2082,6 +2160,19 @@ g_type_interface_peek (gpointer instance_class,
   return vtable;
 }
 
+/**
+ * g_type_interface_peek_parent:
+ * @g_iface: A #GTypeInterface structure.
+ * 
+ * Returns the corresponding #GTypeInterface structure of the parent type
+ * of the instance type to which @g_iface belongs. This is useful when 
+ * deriving the implementation of an interface from the parent type and 
+ * then possibly overriding some methods. 
+ * 
+ * Return value: The corresponding #GTypeInterface structure of the parent type
+ * of the instance type to which @g_iface belongs, or %NULL if the parent type
+ * doesn't conform to the interface.
+ **/
 gpointer
 g_type_interface_peek_parent (gpointer g_iface)
 {
@@ -2370,6 +2461,16 @@ type_get_qdata_L (TypeNode *node,
   return NULL;
 }
 
+/**
+ * g_type_get_qdata:
+ * @type: a #GType
+ * @quark: a #GQuark id to identify the data
+ * 
+ * Obtains data which has previously been attached to @type
+ * with g_type_set_qdata().
+ * 
+ * Return value: the data, or %NULL if no data was found
+ **/
 gpointer
 g_type_get_qdata (GType  type,
                  GQuark quark)
@@ -2427,6 +2528,14 @@ type_set_qdata_W (TypeNode *node,
   qdata[i].data = data;
 }
 
+/**
+ * g_type_set_qdata:
+ * @type: a #GType 
+ * @quark: a #GQuark id to identify the data
+ * @data: the data
+ * 
+ * Attaches arbitrary data to a type.
+ **/
 void
 g_type_set_qdata (GType    type,
                  GQuark   quark,
@@ -2463,6 +2572,18 @@ type_add_flags_W (TypeNode  *node,
   type_set_qdata_W (node, static_quark_type_flags, GUINT_TO_POINTER (dflags));
 }
 
+/**
+ * g_type_query:
+ * @type: the #GType value of a static, classed type.
+ * @query: A user provided structure that is filled in with constant values 
+ *         upon success.
+ * 
+ * Queries the type system for information about a specific type. 
+ * This function will fill in a user-provided structure to hold type-specific 
+ * information. If an invalid #GType is passed in, the @type member of the 
+ * #GTypeQuery is 0. All members filled into the #GTypeQuery structure should
+ * be considered constant and have to be left untouched.
+ **/
 void
 g_type_query (GType       type,
              GTypeQuery *query)
@@ -2538,6 +2659,19 @@ g_type_get_plugin (GType type)
   return node ? node->plugin : NULL;
 }
 
+/**
+ * g_type_interface_get_plugin:
+ * @instance_type: the #GType value of an instantiatable type.
+ * @interface_type: the #GType value of an interface type.
+ * 
+ * Returns the #GTypePlugin structure for the dynamic interface 
+ * @interface_type which has been added to @instance_type, or 
+ * %NULL if @interface_type has not been added to @instance_type or does 
+ * not have a #GTypePlugin structure. See g_type_add_interface_dynamic().
+ * 
+ * Return value: the #GTypePlugin for the dynamic interface @interface_type
+ * of @instance_type.
+ **/
 GTypePlugin*
 g_type_interface_get_plugin (GType instance_type,
                             GType interface_type)
@@ -2582,7 +2716,7 @@ g_type_fundamental_next (void)
   G_READ_LOCK (&type_rw_lock);
   type = static_fundamental_next;
   G_READ_UNLOCK (&type_rw_lock);
-  
+  type = G_TYPE_MAKE_FUNDAMENTAL (type);
   return type <= G_TYPE_FUNDAMENTAL_MAX ? type : 0;
 }
 
@@ -2659,9 +2793,6 @@ g_type_check_instance_cast (GTypeInstance *type_instance,
        g_warning ("invalid unclassed pointer in cast to `%s'",
                   type_descriptive_name_I (iface_type));
     }
-  else
-    g_warning ("invalid cast from (NULL) pointer to `%s'",
-              type_descriptive_name_I (iface_type));
   
   return type_instance;
 }