+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
+Tue Dec 12 18:58:22 2000 Tim Janik <timj@gtk.org>
+
+ * ghash.c (g_hash_table_remove): return whether a value
+ got removed.
+
Tue Dec 12 15:18:10 2000 Owen Taylor <otaylor@redhat.com>
* gmain.[ch]: Revert unauthorized changes.
}
}
-void
-g_hash_table_remove (GHashTable *hash_table,
- gconstpointer key)
+gboolean
+g_hash_table_remove (GHashTable *hash_table,
+ gconstpointer key)
{
GHashNode **node, *dest;
- g_return_if_fail (hash_table != NULL);
+ g_return_val_if_fail (hash_table != NULL, FALSE);
node = g_hash_table_lookup_node (hash_table, key);
-
if (*node)
{
dest = *node;
hash_table->nnodes--;
g_hash_table_resize (hash_table);
+
+ return TRUE;
}
+
+ return FALSE;
}
gboolean
void g_hash_table_insert (GHashTable *hash_table,
gpointer key,
gpointer value);
-void g_hash_table_remove (GHashTable *hash_table,
+gboolean g_hash_table_remove (GHashTable *hash_table,
gconstpointer key);
gpointer g_hash_table_lookup (GHashTable *hash_table,
gconstpointer key);
}
}
-void
-g_hash_table_remove (GHashTable *hash_table,
- gconstpointer key)
+gboolean
+g_hash_table_remove (GHashTable *hash_table,
+ gconstpointer key)
{
GHashNode **node, *dest;
- g_return_if_fail (hash_table != NULL);
+ g_return_val_if_fail (hash_table != NULL, FALSE);
node = g_hash_table_lookup_node (hash_table, key);
-
if (*node)
{
dest = *node;
hash_table->nnodes--;
g_hash_table_resize (hash_table);
+
+ return TRUE;
}
+
+ return FALSE;
}
gboolean
void g_hash_table_insert (GHashTable *hash_table,
gpointer key,
gpointer value);
-void g_hash_table_remove (GHashTable *hash_table,
+gboolean g_hash_table_remove (GHashTable *hash_table,
gconstpointer key);
gpointer g_hash_table_lookup (GHashTable *hash_table,
gconstpointer key);
+Tue Dec 12 23:38:02 2000 Tim Janik <timj@gtk.org>
+
+ * Makefile.am: _never_ touch oldest-source-stamp.
+
+ * gobject.[hc]: construct property handling fixes/improvements.
+ fixed trailer handling in get/set property.
+
+ * gparam.[hc]: implement param spec pool, got rid of param spec
+ hashtable. the most prominent change is that e deal with type
+ prefixes here.
+
2000-12-12 Elliot Lee <sopwith@redhat.com>
* Makefile.am:
/* --- variables --- */
-static GQuark quark_notify_queue = 0;
-static GQuark quark_property_id = 0;
-static GQuark quark_closure_array = 0;
-static GHashTable *pspec_hash_table = NULL;
-static gulong gobject_signals[LAST_SIGNAL] = { 0, };
+static GQuark quark_notify_queue = 0;
+static GQuark quark_property_id = 0;
+static GQuark quark_closure_array = 0;
+static GParamSpecPool *pspec_pool = NULL;
+static gulong gobject_signals[LAST_SIGNAL] = { 0, };
/* --- functions --- */
static void
g_object_base_class_init (GObjectClass *class)
{
+ GObjectClass *pclass = g_type_class_peek_parent (class);
+
/* reset instance specific fields and methods that don't get inherited */
class->n_property_specs = 0;
class->property_specs = NULL;
+ class->construct_properties = pclass ? g_slist_copy (pclass->construct_properties) : NULL;
class->get_property = NULL;
class->set_property = NULL;
}
g_message ("finallizing base class of %s", G_OBJECT_CLASS_NAME (class));
_g_signals_destroy (G_OBJECT_CLASS_TYPE (class));
-
+
+ g_slist_free (class->construct_properties);
+ class->construct_properties = NULL;
for (i = 0; i < class->n_property_specs; i++)
{
GParamSpec *pspec = class->property_specs[i];
- g_param_spec_hash_table_remove (pspec_hash_table, pspec);
+ g_param_spec_pool_remove (pspec_pool, pspec);
g_param_spec_set_qdata (pspec, quark_property_id, NULL);
g_param_spec_unref (pspec);
}
quark_notify_queue = g_quark_from_static_string ("GObject-notify-queue");
quark_property_id = g_quark_from_static_string ("GObject-property-id");
quark_closure_array = g_quark_from_static_string ("GObject-closure-array");
- pspec_hash_table = g_param_spec_hash_table_new ();
+ pspec_pool = g_param_spec_pool_new (TRUE);
class->constructor = g_object_constructor;
class->set_property = g_object_do_set_property;
g_return_if_fail (PARAM_SPEC_PARAM_ID (pspec) == 0); /* paranoid */
if (pspec->flags & G_PARAM_CONSTRUCT)
g_return_if_fail ((pspec->flags & G_PARAM_CONSTRUCT_ONLY) == 0);
- if (pspec->flags & (G_PARAM_CONSTRUCT || G_PARAM_CONSTRUCT_ONLY))
+ if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
g_return_if_fail (pspec->flags & G_PARAM_WRITABLE);
/* expensive paranoia checks ;( */
pspec->name);
return;
}
- if (g_object_class_find_property (class, pspec->name))
+ if (g_param_spec_pool_lookup (pspec_pool, pspec->name, G_OBJECT_CLASS_TYPE (class), FALSE, NULL))
{
g_warning (G_STRLOC ": class `%s' already contains a property named `%s'",
G_OBJECT_CLASS_NAME (class),
g_param_spec_ref (pspec);
g_param_spec_sink (pspec);
g_param_spec_set_qdata (pspec, quark_property_id, GUINT_TO_POINTER (property_id));
- g_param_spec_hash_table_insert (pspec_hash_table, pspec, G_OBJECT_CLASS_TYPE (class));
+ g_param_spec_pool_insert (pspec_pool, pspec, G_OBJECT_CLASS_TYPE (class));
i = class->n_property_specs++;
class->property_specs = g_renew (GParamSpec*, class->property_specs, class->n_property_specs);
class->property_specs[i] = pspec;
+ if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+ class->construct_properties = g_slist_prepend (class->construct_properties, pspec);
+
+ /* for property overrides of construct poperties, we have to get rid
+ * of the overidden inherited construct property
+ */
+ pspec = g_param_spec_pool_lookup (pspec_pool, pspec->name, g_type_parent (G_OBJECT_CLASS_TYPE (class)), TRUE, NULL);
+ if (pspec && pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
+ class->construct_properties = g_slist_remove (class->construct_properties, pspec);
}
GParamSpec*
g_return_val_if_fail (G_IS_OBJECT_CLASS (class), NULL);
g_return_val_if_fail (property_name != NULL, NULL);
- return g_param_spec_hash_table_lookup (pspec_hash_table,
- property_name,
- G_OBJECT_CLASS_TYPE (class),
- TRUE, NULL);
+ return g_param_spec_pool_lookup (pspec_pool,
+ property_name,
+ G_OBJECT_CLASS_TYPE (class),
+ TRUE, NULL);
}
static void
gboolean swapped, after;
gpointer callback, data;
case PROP_DATA:
- g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+ g_return_if_fail (trailer != NULL);
- g_object_set_data (object, trailer + 2, g_value_get_pointer (value));
+ g_object_set_data (object, trailer, g_value_get_pointer (value));
break;
case PROP_SWAPPED_SIGNAL_AFTER:
i++;
case PROP_SIGNAL:
after = i > 2;
swapped = i & 1;
- g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+ g_return_if_fail (trailer != NULL);
g_value_get_ccallback (value, &callback, &data);
- g_signal_connect_data (object, trailer + 2,
+ g_signal_connect_data (object, trailer,
callback, data, NULL,
swapped, after);
break;
switch (property_id)
{
case PROP_DATA:
- g_return_if_fail (trailer[0] == ':' && trailer[1] == ':');
+ g_return_if_fail (trailer != NULL);
- g_value_set_pointer (value, g_object_get_data (object, trailer + 2));
+ g_value_set_pointer (value, g_object_get_data (object, trailer));
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, property_id, pspec);
g_object_notify_property_changed (GObject *object,
GParamSpec *pspec)
{
- g_message ("NOTIFICATION: %s property changed on object `%s'",
- pspec->name,
- G_OBJECT_TYPE_NAME (object));
+ if (0) /* FIXME */
+ g_message ("NOTIFICATION: property `%s' changed on object `%s'",
+ pspec->name,
+ G_OBJECT_TYPE_NAME (object));
}
void
return;
g_object_ref (object);
- pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
- property_name,
- G_OBJECT_TYPE (object),
- TRUE, NULL);
+ pspec = g_param_spec_pool_lookup (pspec_pool,
+ property_name,
+ G_OBJECT_TYPE (object),
+ TRUE, NULL);
if (!pspec)
g_warning ("%s: object class `%s' has no property named `%s'",
G_STRLOC,
const gchar *name;
GObjectConstructParam *cparams = NULL, *nparams = NULL;
guint n_cparams = 0, n_nparams = 0;
+ GSList *clist;
g_return_val_if_fail (G_TYPE_IS_OBJECT (object_type), NULL);
+ class = g_type_class_ref (object_type);
+ clist = g_slist_copy (class->construct_properties);
+
/* collect parameters, sort into construction and normal ones */
name = first_property_name;
while (name)
GValue *value;
GParamSpec *pspec;
gchar *error = NULL;
-
- pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
- name,
- object_type,
- TRUE,
- &trailer);
+
+ pspec = g_param_spec_pool_lookup (pspec_pool,
+ name,
+ object_type,
+ TRUE,
+ &trailer);
if (!pspec)
{
g_warning ("%s: object class `%s' has no property named `%s'",
}
if (pspec->flags & (G_PARAM_CONSTRUCT | G_PARAM_CONSTRUCT_ONLY))
{
+ guint i;
+
if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
- cparams = g_renew (GObjectConstructParam, cparams, n_cparams + 1);
+ cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
cparams[n_cparams].pspec = pspec;
cparams[n_cparams].value = value;
cparams[n_cparams].trailer = trailer;
+ for (i = 0; i < n_cparams; i++) /* picky, aren't we? ;) */
+ if (cparams[i].pspec == pspec)
+ g_warning (G_STRLOC ": construct property \"%s\" for object `%s' is being set twice",
+ pspec->name, g_type_name (object_type));
n_cparams++;
+ clist = g_slist_remove (clist, pspec); /* FIXME: unique */
}
else
{
if (!n_nparams || n_nparams >= PREALLOC_CPARAMS)
- nparams = g_renew (GObjectConstructParam, nparams, n_nparams + 1);
+ nparams = g_renew (GObjectConstructParam, nparams, MAX (n_nparams + 1, PREALLOC_CPARAMS));
nparams[n_nparams].pspec = pspec;
nparams[n_nparams].value = value;
nparams[n_nparams].trailer = trailer;
}
/* construct object from construction parameters */
- class = g_type_class_ref (object_type);
+ while (clist)
+ {
+ GSList *tmp = clist->next;
+ GParamSpec *pspec = clist->data;
+ GValue *value = g_new (GValue, 1);
+
+ value->g_type = 0;
+ g_value_init (value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ g_param_value_set_default (pspec, value);
+
+ if (!n_cparams || n_cparams >= PREALLOC_CPARAMS)
+ cparams = g_renew (GObjectConstructParam, cparams, MAX (n_cparams + 1, PREALLOC_CPARAMS));
+ cparams[n_cparams].pspec = pspec;
+ cparams[n_cparams].value = value;
+ cparams[n_cparams].trailer = NULL;
+ n_cparams++;
+
+ g_slist_free_1 (clist);
+ clist = tmp;
+ }
object = class->constructor (object_type, n_cparams, cparams);
- g_type_class_unref (class);
/* free construction values */
while (n_cparams--)
g_free (cparams[n_cparams].value);
}
g_free (cparams);
-
+
/* release g_object_init() notification queue freeze_count */
nqueue = object_freeze_notifies (object);
nqueue->freeze_count--;
/* set remaining properties */
+ cparams = nparams;
while (n_nparams--)
{
- GValue *value = nparams[n_nparams].value;
- GParamSpec *pspec = nparams[n_nparams].pspec;
- const gchar *trailer = nparams[n_nparams].trailer;
+ GValue *value = nparams->value;
+ GParamSpec *pspec = nparams->pspec;
+ const gchar *trailer = nparams++->trailer;
/* convert if necessary */
if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
g_value_unset (value);
g_free (value);
}
- g_free (nparams);
+ g_free (cparams);
+
+ g_type_class_unref (class);
/* release our own freeze count and handle notifications */
object_thaw_notifies (object, nqueue);
/* set construct properties */
while (n_construct_properties--)
{
- GValue *value = construct_params[n_construct_properties].value;
- GParamSpec *pspec = construct_params[n_construct_properties].pspec;
- const gchar *trailer = construct_params[n_construct_properties].trailer;
+ GValue *value = construct_params->value;
+ GParamSpec *pspec = construct_params->pspec;
+ const gchar *trailer = construct_params++->trailer;
/* convert if necessary */
if (!g_type_is_a (G_VALUE_TYPE (value), G_PARAM_SPEC_VALUE_TYPE (pspec)))
GParamSpec *pspec;
gchar *error = NULL;
- pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
- name,
- G_OBJECT_TYPE (object),
- TRUE,
- &trailer);
+ pspec = g_param_spec_pool_lookup (pspec_pool,
+ name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
if (!pspec)
{
g_warning ("%s: object class `%s' has no property named `%s'",
GParamSpec *pspec;
gchar *error;
- pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
- name,
- G_OBJECT_TYPE (object),
- TRUE,
- &trailer);
+ pspec = g_param_spec_pool_lookup (pspec_pool,
+ name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
if (!pspec)
{
g_warning ("%s: object class `%s' has no property named `%s'",
}
void
-g_object_set (GObject *object,
+g_object_set (gpointer _object,
const gchar *first_property_name,
...)
{
+ GObject *object = _object;
va_list var_args;
g_return_if_fail (G_IS_OBJECT (object));
}
void
-g_object_get (GObject *object,
+g_object_get (gpointer _object,
const gchar *first_property_name,
...)
{
+ GObject *object = _object;
va_list var_args;
g_return_if_fail (G_IS_OBJECT (object));
g_object_ref (object);
nqueue = object_freeze_notifies (object);
- pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
- property_name,
- G_OBJECT_TYPE (object),
- TRUE,
- &trailer);
+ pspec = g_param_spec_pool_lookup (pspec_pool,
+ property_name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
if (!pspec)
g_warning ("%s: object class `%s' has no property named `%s'",
G_STRLOC,
g_object_ref (object);
- pspec = g_param_spec_hash_table_lookup (pspec_hash_table,
- property_name,
- G_OBJECT_TYPE (object),
- TRUE,
- &trailer);
+ pspec = g_param_spec_pool_lookup (pspec_pool,
+ property_name,
+ G_OBJECT_TYPE (object),
+ TRUE,
+ &trailer);
if (!pspec)
g_warning ("%s: object class `%s' has no property named `%s'",
G_STRLOC,
g_object_unref (object);
}
-GObject*
-g_object_ref (GObject *object)
+gpointer
+g_object_ref (gpointer _object)
{
+ GObject *object = _object;
+
g_return_val_if_fail (G_IS_OBJECT (object), NULL);
g_return_val_if_fail (object->ref_count > 0, NULL);
}
void
-g_object_unref (GObject *object)
+g_object_unref (gpointer _object)
{
+ GObject *object = _object;
+
g_return_if_fail (G_IS_OBJECT (object));
g_return_if_fail (object->ref_count > 0);
/* private, these fields might vanish */
guint n_property_specs;
GParamSpec **property_specs;
+ GSList *construct_properties;
/* public overridable methods */
GObject* (*constructor) (GType type,
guint n_construct_properties,
- GObjectConstructParam *construct_params);
+ GObjectConstructParam *construct_properties);
void (*get_property) (GObject *object,
guint property_id,
GValue *value,
gpointer g_object_new_valist (GType object_type,
const gchar *first_property_name,
va_list var_args);
-void g_object_set (GObject *object,
+void g_object_set (gpointer object,
const gchar *first_property_name,
...);
-void g_object_get (GObject *object,
+void g_object_get (gpointer object,
const gchar *first_property_name,
...);
void g_object_set_valist (GObject *object,
void g_object_notify (GObject *object,
const gchar *property_name);
void g_object_thaw_notify (GObject *object);
-GObject* g_object_ref (GObject *object);
-void g_object_unref (GObject *object);
+gpointer g_object_ref (gpointer object);
+void g_object_unref (gpointer object);
gpointer g_object_get_qdata (GObject *object,
GQuark quark);
void g_object_set_qdata (GObject *object,
return NULL;
}
+
+/* --- param spec pool --- */
+struct _GParamSpecPool
+{
+ gboolean type_prefixing;
+ GHashTable *hash_table;
+};
+
static guint
-param_spec_hash (gconstpointer key_spec)
+param_spec_pool_hash (gconstpointer key_spec)
{
const GParamSpec *key = key_spec;
const gchar *p;
}
static gboolean
-param_spec_equals (gconstpointer key_spec_1,
- gconstpointer key_spec_2)
+param_spec_pool_equals (gconstpointer key_spec_1,
+ gconstpointer key_spec_2)
{
const GParamSpec *key1 = key_spec_1;
const GParamSpec *key2 = key_spec_2;
strcmp (key1->name, key2->name) == 0);
}
-GHashTable*
-g_param_spec_hash_table_new (void)
+GParamSpecPool*
+g_param_spec_pool_new (gboolean type_prefixing)
{
- return g_hash_table_new (param_spec_hash, param_spec_equals);
+ GParamSpecPool *pool = g_new (GParamSpecPool, 1);
+
+ pool->type_prefixing = type_prefixing != FALSE;
+ pool->hash_table = g_hash_table_new (param_spec_pool_hash, param_spec_pool_equals);
+
+ return pool;
}
void
-g_param_spec_hash_table_insert (GHashTable *hash_table,
- GParamSpec *pspec,
- GType owner_type)
+g_param_spec_pool_insert (GParamSpecPool *pool,
+ GParamSpec *pspec,
+ GType owner_type)
{
- g_return_if_fail (hash_table != NULL);
- g_return_if_fail (G_IS_PARAM_SPEC (pspec));
- g_return_if_fail (pspec->name != NULL);
- if (pspec->owner_type != owner_type)
- g_return_if_fail (pspec->owner_type == 0);
+ gchar *p;
- if (strchr (pspec->name, ':'))
- g_warning (G_STRLOC ": parameter name `%s' contains field-delimeter",
- pspec->name);
- else
+ g_return_if_fail (pool != NULL);
+ g_return_if_fail (pspec);
+ g_return_if_fail (owner_type > 0);
+ g_return_if_fail (pspec->owner_type == 0);
+
+ for (p = pspec->name; *p; p++)
{
- pspec->owner_type = owner_type;
- g_hash_table_insert (hash_table, pspec, pspec);
+ if (!strchr (G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-_", *p))
+ {
+ g_warning (G_STRLOC ": pspec name \"%s\" contains invalid characters", pspec->name);
+ return;
+ }
}
+
+ pspec->owner_type = owner_type;
+ g_param_spec_ref (pspec);
+ g_hash_table_insert (pool->hash_table, pspec, pspec);
}
void
-g_param_spec_hash_table_remove (GHashTable *hash_table,
- GParamSpec *pspec)
+g_param_spec_pool_remove (GParamSpecPool *pool,
+ GParamSpec *pspec)
{
- g_return_if_fail (hash_table != NULL);
- g_return_if_fail (G_IS_PARAM_SPEC (pspec));
+ g_return_if_fail (pool != NULL);
+ g_return_if_fail (pspec);
+
+ if (g_hash_table_remove (pool->hash_table, pspec))
+ g_param_spec_unref (pspec);
+ else
+ g_warning (G_STRLOC ": attempt to remove unknown pspec `%s' from pool", pspec->name);
+}
- g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) != NULL); /* FIXME: paranoid */
+static inline GParamSpec*
+param_spec_ht_lookup (GHashTable *hash_table,
+ const gchar *param_name,
+ GType owner_type,
+ gboolean walk_ancestors)
+{
+ GParamSpec key, *pspec;
- g_hash_table_remove (hash_table, pspec);
- g_assert (g_param_spec_hash_table_lookup (hash_table, pspec->name, pspec->owner_type, FALSE, NULL) == NULL); /* FIXME: paranoid */
- pspec->owner_type = 0;
+ key.owner_type = owner_type;
+ key.name = (gchar*) param_name;
+ if (walk_ancestors)
+ do
+ {
+ pspec = g_hash_table_lookup (hash_table, &key);
+ if (pspec)
+ return pspec;
+ key.owner_type = g_type_parent (key.owner_type);
+ }
+ while (key.owner_type);
+ else
+ pspec = g_hash_table_lookup (hash_table, &key);
+
+ if (!pspec)
+ {
+ /* sigh, try canonicalization */
+ key.name = g_strdup (param_name);
+ key.owner_type = owner_type;
+
+ g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
+ if (walk_ancestors)
+ do
+ {
+ pspec = g_hash_table_lookup (hash_table, &key);
+ if (pspec)
+ {
+ g_free (key.name);
+ return pspec;
+ }
+ key.owner_type = g_type_parent (key.owner_type);
+ }
+ while (key.owner_type);
+ else
+ pspec = g_hash_table_lookup (hash_table, &key);
+ g_free (key.name);
+ }
+
+ return pspec;
}
GParamSpec*
-g_param_spec_hash_table_lookup (GHashTable *hash_table,
- const gchar *param_name,
- GType owner_type,
- gboolean try_ancestors,
- const gchar **trailer)
+g_param_spec_pool_lookup (GParamSpecPool *pool,
+ const gchar *param_name,
+ GType owner_type,
+ gboolean walk_ancestors,
+ const gchar **trailer_p)
{
GParamSpec *pspec;
- GParamSpec key;
gchar *delim;
-
- g_return_val_if_fail (hash_table != NULL, NULL);
- g_return_val_if_fail (param_name != NULL, NULL);
-
- key.owner_type = owner_type;
+
+ g_return_val_if_fail (pool != NULL, NULL);
+ g_return_val_if_fail (param_name, NULL);
+
delim = strchr (param_name, ':');
- if (delim)
- key.name = g_strndup (param_name, delim - param_name);
- else
- key.name = g_strdup (param_name);
- g_strcanon (key.name, G_CSET_A_2_Z G_CSET_a_2_z G_CSET_DIGITS "-", '-');
- if (trailer)
- *trailer = delim;
-
- pspec = g_hash_table_lookup (hash_table, &key);
- if (!pspec && try_ancestors)
+ /* try quick and away, i.e. no prefix, no trailer */
+ if (!delim)
{
- key.owner_type = g_type_parent (key.owner_type);
- while (key.owner_type)
+ if (trailer_p)
+ *trailer_p = NULL;
+ return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+ }
+
+ /* strip type prefix */
+ if (pool->type_prefixing && delim[1] == ':')
+ {
+ guint l = delim - param_name;
+ gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
+ GType type;
+
+ strncpy (buffer, param_name, delim - param_name);
+ buffer[l] = 0;
+ type = g_type_from_name (buffer);
+ if (l >= 32)
+ g_free (buffer);
+ if (type) /* type==0 isn't a valid type pefix */
{
- pspec = g_hash_table_lookup (hash_table, &key);
- if (pspec)
- break;
- key.owner_type = g_type_parent (key.owner_type);
+ /* sanity check, these cases don't make a whole lot of sense */
+ if ((!walk_ancestors && type != owner_type) || !g_type_is_a (owner_type, type))
+ {
+ if (trailer_p)
+ *trailer_p = NULL;
+ return NULL;
+ }
+ owner_type = type;
+ param_name += l + 2;
+ delim = strchr (param_name, ':');
+ if (!delim) /* good, can still forget about trailer */
+ {
+ if (trailer_p)
+ *trailer_p = NULL;
+ return param_spec_ht_lookup (pool->hash_table, param_name, owner_type, walk_ancestors);
+ }
}
}
-
- g_free (key.name);
-
- return pspec;
+
+ /* ok, no prefix, handle trailer */
+ if (delim[1] == ':')
+ {
+ guint l = delim - param_name;
+ gchar stack_buffer[32], *buffer = l < 32 ? stack_buffer : g_new (gchar, l + 1);
+
+ strncpy (buffer, param_name, delim - param_name);
+ buffer[l] = 0;
+ pspec = param_spec_ht_lookup (pool->hash_table, buffer, owner_type, walk_ancestors);
+ if (l >= 32)
+ g_free (buffer);
+ if (trailer_p)
+ *trailer_p = pspec ? delim + 2 : NULL;
+ return pspec;
+ }
+
+ /* malformed param_name */
+ if (trailer_p)
+ *trailer_p = NULL;
+ return NULL;
}
G_PARAM_WRITABLE = 1 << 1,
G_PARAM_CONSTRUCT = 1 << 2,
G_PARAM_CONSTRUCT_ONLY = 1 << 3,
-#define G_PARAM_MASK (0x000f)
- /* bits in the range 0xfff0 are reserved for 3rd party usage */
-#define G_PARAM_USER_MASK (0xfff0)
+ G_PARAM_PRIVATE = 1 << 4,
+#define G_PARAM_MASK (0x000000ff)
+ /* bits in the range 0xffffff00 are reserved for 3rd party usage */
+#define G_PARAM_USER_MASK (0xffffff00)
} GParamFlags;
/* --- typedefs & structures --- */
typedef struct _GParamSpec GParamSpec;
typedef struct _GParamSpecClass GParamSpecClass;
+typedef struct _GParamSpecPool GParamSpecPool;
struct _GParamSpec
{
GTypeInstance g_type_instance;
const GParamSpecTypeInfo *pspec_info);
-/* --- private --- */
+/* --- protected --- */
gpointer g_param_spec_internal (GType param_type,
const gchar *name,
const gchar *nick,
const gchar *blurb,
GParamFlags flags);
-GHashTable* g_param_spec_hash_table_new (void);
-void g_param_spec_hash_table_insert (GHashTable *hash_table,
- GParamSpec *pspec,
- GType owner_type);
-void g_param_spec_hash_table_remove (GHashTable *hash_table,
- GParamSpec *pspec);
-GParamSpec* g_param_spec_hash_table_lookup (GHashTable *hash_table,
- const gchar *param_name,
- GType owner_type,
- gboolean try_ancestors,
- const gchar **trailer);
+GParamSpecPool* g_param_spec_pool_new (gboolean type_prefixing);
+void g_param_spec_pool_insert (GParamSpecPool *pool,
+ GParamSpec *pspec,
+ GType owner_type);
+void g_param_spec_pool_remove (GParamSpecPool *pool,
+ GParamSpec *pspec);
+GParamSpec* g_param_spec_pool_lookup (GParamSpecPool *pool,
+ const gchar *param_name,
+ GType owner_type,
+ gboolean walk_ancestors,
+ const gchar **trailer_p);
/* contracts:
guint n_ifaces = node->n_ifaces;
GType iface_type = NODE_TYPE (iface);
- do /* FIXME: should optimize iface lookups for <= 4 */
+ do
{
guint i;
IFaceEntry *check;