* Free Software Foundation, Inc., 59 Temple Place, Suite 330,
* Boston, MA 02111-1307, USA.
*/
+#include <config.h>
#include "gtype.h"
/*
gpointer data);
static IFaceHolder* type_iface_peek_holder_L (TypeNode *iface,
GType instance_type);
+static gboolean type_node_is_a_L (TypeNode *node,
+ TypeNode *iface_node);
/* --- structures --- */
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;
return FALSE;
}
-static inline gchar*
+static gchar*
type_descriptive_name_I (GType type)
{
if (type)
TypeNode *iface = lookup_type_node_I (iface_type);
IFaceEntry *entry;
TypeNode *tnode;
+ GType *prerequisites;
+ guint i;
+
if (!node || !node->is_instantiatable)
{
NODE_NAME (tnode));
return FALSE;
}
+ prerequisites = IFACE_NODE_PREREQUISITES (iface);
+ for (i = 0; i < IFACE_NODE_N_PREREQUISITES (iface); i++)
+ {
+ tnode = lookup_type_node_I (prerequisites[i]);
+ if (!type_node_is_a_L (node, tnode))
+ {
+ g_warning ("cannot add interface type `%s' to type `%s' which does not conform to prerequisite `%s'",
+ NODE_NAME (iface),
+ NODE_NAME (node),
+ NODE_NAME (tnode));
+ return FALSE;
+ }
+ }
return TRUE;
}
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)
}
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);
}
}
}
+/**
+ * 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)
}
instance->g_class = NULL;
- memset (instance, 0xaa, node->data->instance.instance_size); /* FIXME: debugging hack */
+#ifdef G_ENABLE_DEBUG
+ memset (instance, 0xaa, node->data->instance.instance_size); /* debugging hack */
+#endif
if (node->data->instance.n_preallocs)
{
G_WRITE_LOCK (&type_rw_lock);
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;
}
}
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,
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)
{
}
static inline gboolean
-type_node_is_a_U (TypeNode *node,
- TypeNode *iface_node,
- /* support_inheritance */
- gboolean support_interfaces,
- gboolean support_prerequisites)
+type_node_check_conformities_UorL (TypeNode *node,
+ TypeNode *iface_node,
+ /* support_inheritance */
+ gboolean support_interfaces,
+ gboolean support_prerequisites,
+ gboolean have_lock)
{
gboolean match;
match = FALSE;
if (support_interfaces || support_prerequisites)
{
- G_READ_LOCK (&type_rw_lock);
+ if (!have_lock)
+ G_READ_LOCK (&type_rw_lock);
if (support_interfaces && type_lookup_iface_entry_L (node, iface_node))
match = TRUE;
else if (support_prerequisites && type_lookup_prerequisite_L (node, NODE_TYPE (iface_node)))
match = TRUE;
- G_READ_UNLOCK (&type_rw_lock);
+ if (!have_lock)
+ G_READ_UNLOCK (&type_rw_lock);
}
return match;
}
+static gboolean
+type_node_is_a_L (TypeNode *node,
+ TypeNode *iface_node)
+{
+ return type_node_check_conformities_UorL (node, iface_node, TRUE, TRUE, TRUE);
+}
+
+static inline gboolean
+type_node_conforms_to_U (TypeNode *node,
+ TypeNode *iface_node,
+ gboolean support_interfaces,
+ gboolean support_prerequisites)
+{
+ return type_node_check_conformities_UorL (node, iface_node, support_interfaces, support_prerequisites, FALSE);
+}
+
gboolean
g_type_is_a (GType type,
GType iface_type)
node = lookup_type_node_I (type);
iface_node = lookup_type_node_I (iface_type);
- is_a = node && iface_node && type_node_is_a_U (node, iface_node, TRUE, TRUE);
+ is_a = node && iface_node && type_node_conforms_to_U (node, iface_node, TRUE, TRUE);
return is_a;
}
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)
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,
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)
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)
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;
}
node = lookup_type_node_I (type_instance->g_class->g_type);
iface = lookup_type_node_I (iface_type);
- check = node && node->is_instantiatable && iface && type_node_is_a_U (node, iface, TRUE, FALSE);
+ check = node && node->is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
return check;
}
node = lookup_type_node_I (type_class->g_type);
iface = lookup_type_node_I (is_a_type);
- check = node && node->is_classed && iface && type_node_is_a_U (node, iface, FALSE, FALSE);
+ check = node && node->is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
return check;
}
node = lookup_type_node_I (type_instance->g_class->g_type);
is_instantiatable = node && node->is_instantiatable;
iface = lookup_type_node_I (iface_type);
- check = is_instantiatable && iface && type_node_is_a_U (node, iface, TRUE, FALSE);
+ check = is_instantiatable && iface && type_node_conforms_to_U (node, iface, TRUE, FALSE);
if (check)
return 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;
}
node = lookup_type_node_I (type_class->g_type);
is_classed = node && node->is_classed;
iface = lookup_type_node_I (is_a_type);
- check = is_classed && iface && type_node_is_a_U (node, iface, FALSE, FALSE);
+ check = is_classed && iface && type_node_conforms_to_U (node, iface, FALSE, FALSE);
if (check)
return type_class;
* but we should only get called with referenced types anyway
*/
data = node ? node->data : NULL;
- if (node->mutatable_check_cache)
+ if (node && node->mutatable_check_cache)
return data->common.value_table;
G_READ_LOCK (&type_rw_lock);
return;
}
- /* setup GRuntime wide debugging flags */
+ /* setup GObject library wide debugging flags */
_g_type_debug_flags = debug_flags & G_TYPE_DEBUG_MASK;
- env_string = g_getenv ("GRUNTIME_DEBUG");
+ env_string = g_getenv ("GOBJECT_DEBUG");
if (env_string != NULL)
{
static GDebugKey debug_keys[] = {