[glib/g-property: 7/26] gproperty: Clean up default value implementation
- From: Emmanuele Bassi <ebassi src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib/g-property: 7/26] gproperty: Clean up default value implementation
- Date: Wed, 17 Aug 2011 13:59:19 +0000 (UTC)
commit 4f818a3cc4239107c7304e9ca3511bd147137aa7
Author: Emmanuele Bassi <ebassi linux intel com>
Date: Mon May 23 17:04:55 2011 +0100
gproperty: Clean up default value implementation
An overhaul of the default value implementation for GProperty.
Instead of using a separate GValue pointer we can use a slot inside the
GParamSpec qdata member, using a generalized lock quark as the unique
property id. The id is created on demand, so properties with no default
and no locking do not pay any penalty.
The API for setting and overriding the default required some changes:
now it is not necessary to call g_property_set_default() and pass the
class type â though overriding requires calling the newly added
g_property_override_default() and passing the GType used as the key
to retrieve the default.
These changes allow us to drop the GValue* member in the GProperty
structure; we can also reuse the GParamSpec value_type field to drop
both the gtype and prerequisite members of GProperty, thus making
GProperty smaller that 60 bytes on 32bit archs â well within the first
cacheline. This should improve memory usage and caching:
struct _GProperty {
GParamSpec parent_instance; /* 0 40 */
guint flags:15; /* 40:17 4 */
guint is_installed:1; /* 40:16 4 */
/* Bitfield combined with next fields */
guint16 type_size; /* 42 2 */
guint16 priv_offset; /* 44 2 */
guint16 field_offset; /* 46 2 */
GQuark prop_id; /* 48 4 */
GPropertyLockFunc lock_func; /* 52 4 */
GPropertyUnlockFunc unlock_func; /* 56 4 */
/* size: 60, cachelines: 1, members: 9 */
/* last cacheline: 60 bytes */
};
As a bonus, this commit adds support for generic pointer properties.
https://bugzilla.gnome.org/show_bug.cgi?id=648526
gobject/gobject.c | 6 +-
gobject/gobject.symbols | 1 +
gobject/gproperty.c | 765 ++++++++++++++++++++++++++++------------
gobject/gproperty.h | 16 +-
gobject/tests/autoproperties.c | 67 ++++-
5 files changed, 612 insertions(+), 243 deletions(-)
---
diff --git a/gobject/gobject.c b/gobject/gobject.c
index 88fe148..7360119 100644
--- a/gobject/gobject.c
+++ b/gobject/gobject.c
@@ -798,7 +798,7 @@ override_property_default_value (GObjectClass *oclass,
GProperty *property,
const GValue *value)
{
- g_property_set_default_value (property, oclass, value);
+ g_property_override_default_value (property, G_OBJECT_CLASS_TYPE (oclass), value);
}
/**
@@ -1331,9 +1331,7 @@ object_set_property (GObject *object,
{
if (G_IS_PROPERTY (pspec))
{
- GProperty *prop = G_PROPERTY (pspec);
-
- g_property_set_value (prop, object, &tmp_value);
+ g_property_set_value ((GProperty *) pspec, object, &tmp_value);
}
else
{
diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols
index 2d849b3..6098c8a 100644
--- a/gobject/gobject.symbols
+++ b/gobject/gobject.symbols
@@ -217,6 +217,7 @@ g_int8_property_new
g_int_property_new
g_long_property_new
g_object_property_new
+g_pointer_property_new
g_property_canonicalize_name
g_property_collect
g_property_get
diff --git a/gobject/gproperty.c b/gobject/gproperty.c
index 5693771..d0fa053 100644
--- a/gobject/gproperty.c
+++ b/gobject/gproperty.c
@@ -443,13 +443,8 @@ struct _GProperty
guint16 priv_offset;
guint16 field_offset;
- GType gtype;
- GType prerequisite;
-
- /* used by the default locking */
- GValue *default_value;
+ GQuark prop_id;
- GQuark lock_quark;
GPropertyLockFunc lock_func;
GPropertyUnlockFunc unlock_func;
};
@@ -570,8 +565,8 @@ g_##g_t##_property_new (const gchar *name, \
property_flags_to_param_flags (flags)); \
\
prop->flags = flags; \
- prop->gtype = G_T; \
- prop->prerequisite = G_TYPE_INVALID; \
+\
+ G_PARAM_SPEC (prop)->value_type = G_T; \
\
prop->field_offset = offset; \
\
@@ -728,11 +723,11 @@ g_property_default_lock (GProperty *property,
{
gpointer bit_lock_p;
- bit_lock_p = g_object_get_qdata (gobject, property->lock_quark);
+ bit_lock_p = g_object_get_qdata (gobject, property->prop_id);
if (bit_lock_p == NULL)
{
bit_lock_p = g_new0 (gint, 1);
- g_object_set_qdata (gobject, property->lock_quark, bit_lock_p);
+ g_object_set_qdata (gobject, property->prop_id, bit_lock_p);
}
g_bit_lock (bit_lock_p, 0);
@@ -744,11 +739,11 @@ g_property_default_unlock (GProperty *property,
{
gpointer bit_lock_p;
- bit_lock_p = g_object_get_qdata (gobject, property->lock_quark);
+ bit_lock_p = g_object_get_qdata (gobject, property->prop_id);
if (G_UNLIKELY (bit_lock_p == NULL))
return;
- g_object_set_qdata (gobject, property->lock_quark, NULL);
+ g_object_set_qdata (gobject, property->prop_id, NULL);
g_bit_unlock (bit_lock_p, 0);
g_free (bit_lock_p);
}
@@ -818,13 +813,22 @@ static const GValue *
property_get_default_for_type (GProperty *property,
GType gtype)
{
+ GParamSpec *pspec = (GParamSpec *) property;
+
if (gtype == G_TYPE_INVALID)
{
- return property->default_value;
+ if (property->prop_id == 0)
+ {
+ gchar *lock_name = g_strconcat ("__g_property_id_", pspec->name, NULL);
+
+ property->prop_id = g_quark_from_string (lock_name);
+ g_free (lock_name);
+ }
+
+ return g_param_spec_get_qdata (pspec, property->prop_id);
}
else
{
- GParamSpec *pspec = (GParamSpec *) property;
return g_param_spec_get_qdata (pspec, g_type_qname (gtype));
}
@@ -839,16 +843,42 @@ value_unset_and_free (gpointer data)
g_free (value);
}
-static void
+static inline void
property_set_default_for_type (GProperty *property,
GType gtype,
GValue *value)
{
GParamSpec *pspec = (GParamSpec *) property;
- g_param_spec_set_qdata_full (pspec, g_type_qname (gtype),
- value,
- value_unset_and_free);
+ if (gtype == G_TYPE_INVALID)
+ {
+ if (property->prop_id == 0)
+ {
+ gchar *lock_name = g_strconcat ("__g_property_id_", pspec->name, NULL);
+
+ property->prop_id = g_quark_from_string (lock_name);
+ g_free (lock_name);
+ }
+
+ if (g_param_spec_get_qdata (pspec, property->prop_id) != NULL)
+ {
+ g_critical (G_STRLOC ": The property '%s' already has a default "
+ "value. Use g_property_override_default() instead.",
+ pspec->name);
+ return;
+ }
+
+ g_param_spec_set_qdata_full (pspec, property->prop_id,
+ value,
+ value_unset_and_free);
+ }
+ else
+ {
+
+ g_param_spec_set_qdata_full (pspec, g_type_qname (gtype),
+ value,
+ value_unset_and_free);
+ }
}
/**
@@ -888,7 +918,7 @@ DEFINE_PROPERTY_INTEGER (Boolean, boolean, gboolean, G_TYPE_BOOLEAN, FALSE, FALS
*
* Since: 2.32
*/
-DEFINE_PROPERTY_INTEGER (Int, int, gint, G_TYPE_INT, 0, G_MININT, G_MAXINT)
+DEFINE_PROPERTY_INTEGER (Int, int, int, G_TYPE_INT, 0, G_MININT, G_MAXINT)
/**
* g_int8_property_new:
@@ -983,7 +1013,7 @@ DEFINE_PROPERTY_INTEGER (Int64, int64, gint64, G_TYPE_INT64, 0, G_MININT64, G_MA
*
* Since: 2.32
*/
-DEFINE_PROPERTY_INTEGER (Long, long, glong, G_TYPE_LONG, 0, G_MINLONG, G_MAXLONG)
+DEFINE_PROPERTY_INTEGER (Long, long, long, G_TYPE_LONG, 0, G_MINLONG, G_MAXLONG)
/**
* g_uint_property_new:
@@ -1226,8 +1256,8 @@ g_enum_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_ENUM;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_ENUM;
prop->field_offset = offset;
@@ -1476,8 +1506,8 @@ g_flags_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_FLAGS;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_FLAGS;
prop->field_offset = offset;
@@ -1729,8 +1759,8 @@ g_float_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_FLOAT;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_FLOAT;
prop->field_offset = offset;
@@ -2002,8 +2032,8 @@ g_double_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_DOUBLE;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_DOUBLE;
prop->field_offset = offset;
@@ -2233,8 +2263,8 @@ g_string_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_STRING;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_STRING;
prop->field_offset = offset;
@@ -2443,8 +2473,8 @@ g_boxed_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_BOXED;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_BOXED;
prop->field_offset = offset;
@@ -2511,10 +2541,10 @@ g_boxed_property_set_value (GProperty *property,
}
if ((* (gpointer *) field_p) != NULL)
- g_boxed_free (property->prerequisite, (* (gpointer *) field_p));
+ g_boxed_free (((GParamSpec *) property)->value_type, (* (gpointer *) field_p));
if (value != NULL)
- (* (gpointer *) field_p) = g_boxed_copy (property->prerequisite, value);
+ (* (gpointer *) field_p) = g_boxed_copy (((GParamSpec *) property)->value_type, value);
else
(* (gpointer *) field_p) = NULL;
@@ -2652,8 +2682,8 @@ g_object_property_new (const gchar *name,
property_flags_to_param_flags (flags));
prop->flags = flags;
- prop->gtype = G_TYPE_OBJECT;
- prop->prerequisite = G_TYPE_INVALID;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_OBJECT;
prop->field_offset = offset;
@@ -2672,14 +2702,10 @@ static inline gboolean
g_object_property_validate (GProperty *property,
gconstpointer value)
{
- GType gtype;
-
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ if (value == NULL)
+ return FALSE;
- return g_type_is_a (G_OBJECT_TYPE (value), gtype);
+ return g_type_is_a (G_OBJECT_TYPE (value), G_PARAM_SPEC (property)->value_type);
}
static inline gboolean
@@ -2792,6 +2818,208 @@ g_object_property_get_value (GProperty *property,
}
/*
+ * gpointer
+ */
+
+/* forward declaration */
+GType _g_pointer_property_get_type (void);
+
+typedef struct {
+ GProperty parent;
+
+ GPropertyPointerSet setter;
+ GPropertyPointerGet getter;
+} GPointerProperty;
+
+static void
+property_pointer_class_init (GParamSpecClass *klass)
+{
+ klass->value_type = G_TYPE_POINTER;
+}
+
+static void
+property_pointer_init (GParamSpec *pspec)
+{
+}
+
+GType
+_g_pointer_property_get_type (void)
+{
+ static volatile gsize pspec_type_id__volatile = 0;
+
+ if (g_once_init_enter (&pspec_type_id__volatile))
+ {
+ const GTypeInfo info = {
+ sizeof (GParamSpecClass),
+ NULL, NULL,
+ (GClassInitFunc) property_pointer_class_init,
+ NULL, NULL,
+ sizeof (GPointerProperty),
+ 0,
+ (GInstanceInitFunc) property_pointer_init,
+ };
+
+ GType pspec_type_id =
+ g_type_register_static (G_TYPE_PROPERTY,
+ g_intern_static_string ("GPointerProperty"),
+ &info, 0);
+
+ g_once_init_leave (&pspec_type_id__volatile, pspec_type_id);
+ }
+
+ return pspec_type_id__volatile;
+}
+
+/**
+ * g_pointer_property_new:
+ * @name: canonical name of the property
+ * @flags: flags for the property
+ * @offset: the offset in the private structure of the field
+ * that stores the property, or -1
+ * @setter: (allow-none): the setter function for the property
+ * @getter: (allow-none): the getter function for the property
+ *
+ * Creates a new #GProperty mapping to an untyped pointer.
+ *
+ * Return value: the newly created #GProperty
+ *
+ * Since: 2.32
+ */
+GParamSpec *
+g_pointer_property_new (const gchar *name,
+ GPropertyFlags flags,
+ gssize offset,
+ GPropertyObjectSet setter,
+ GPropertyObjectGet getter)
+{
+ GProperty *prop;
+ GPointerProperty *internal;
+
+ prop = g_param_spec_internal (_g_pointer_property_get_type (),
+ name, NULL, NULL,
+ property_flags_to_param_flags (flags));
+
+ prop->flags = flags;
+
+ G_PARAM_SPEC (prop)->value_type = G_TYPE_POINTER;
+
+ prop->field_offset = offset;
+
+ prop->is_installed = FALSE;
+
+ prop->type_size = sizeof (gpointer);
+
+ internal = (GPointerProperty *) prop;
+ internal->setter = setter;
+ internal->getter = getter;
+
+ return G_PARAM_SPEC (prop);
+}
+
+static inline gboolean
+g_pointer_property_validate (GProperty *property,
+ gconstpointer value)
+{
+ return TRUE;
+}
+
+static inline gboolean
+g_pointer_property_set_value (GProperty *property,
+ gpointer gobject,
+ gpointer value)
+{
+ gboolean retval = FALSE;
+
+ if ((property->flags & G_PROPERTY_WRITABLE) == 0)
+ {
+ g_critical ("The property '%s' of object '%s' is not writable",
+ G_PARAM_SPEC (property)->name,
+ G_OBJECT_TYPE_NAME (gobject));
+ return FALSE;
+ }
+
+ if (!g_pointer_property_validate (property, value))
+ {
+ g_warning ("The value for the property '%s' of object '%s' is out of the valid range",
+ G_PARAM_SPEC (property)->name,
+ G_OBJECT_TYPE_NAME (gobject));
+ return FALSE;
+ }
+
+ property_lock_internal (property, gobject);
+
+ if (((GPointerProperty *) property)->setter != NULL)
+ {
+ ((GPointerProperty *) property)->setter (gobject, value);
+
+ retval = TRUE;
+ }
+ else if (property->field_offset >= 0)
+ {
+ gpointer priv_p, field_p;
+
+ g_return_val_if_fail (value == NULL || G_IS_OBJECT (value), FALSE);
+
+ priv_p = get_private_pointer (gobject, property->priv_offset);
+ field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset);
+
+ if ((* (gpointer *) field_p) == value)
+ {
+ property_unlock_internal (property, gobject);
+ return FALSE;
+ }
+
+ (* (gpointer *) field_p) = value;
+
+ g_object_notify_by_pspec (gobject, (GParamSpec *) property);
+
+ retval = TRUE;
+ }
+ else
+ g_critical (G_STRLOC ": No setter function or field offset specified "
+ "for property '%s'",
+ G_PARAM_SPEC (property)->name);
+
+ property_unlock_internal (property, gobject);
+
+ return retval;
+}
+
+static inline gpointer
+g_pointer_property_get_value (GProperty *property,
+ gpointer gobject)
+{
+ if ((property->flags & G_PROPERTY_READABLE) == 0)
+ {
+ g_critical ("The property '%s' of object '%s' is not readable",
+ G_PARAM_SPEC (property)->name,
+ G_OBJECT_TYPE_NAME (gobject));
+ return FALSE;
+ }
+
+ if (((GPointerProperty *) property)->getter != NULL)
+ {
+ return ((GPointerProperty *) property)->getter (gobject);
+ }
+ else if (property->field_offset >= 0)
+ {
+ gpointer priv_p, field_p;
+
+ priv_p = g_type_instance_get_private (gobject, G_OBJECT_TYPE (gobject));
+ field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset);
+
+ return (* (gpointer *) field_p);
+ }
+ else
+ {
+ g_critical (G_STRLOC ": No getter function or field offset specified "
+ "for property '%s'",
+ G_PARAM_SPEC (property)->name);
+ return NULL;
+ }
+}
+
+/*
* GProperty common API
*/
@@ -2847,12 +3075,13 @@ _g_property_set_installed (GProperty *property,
* quark for the lock
*/
if ((property->flags & G_PROPERTY_ATOMIC) != 0 &&
+ property->prop_id == 0 &&
property->lock_func == NULL)
{
- gchar *lock_n = g_strconcat ("__g_property_lock_",
+ gchar *lock_n = g_strconcat ("__g_property_id_",
G_PARAM_SPEC (property)->name,
NULL);
- property->lock_quark = g_quark_from_string (lock_n);
+ property->prop_id = g_quark_from_string (lock_n);
g_free (lock_n);
}
@@ -3009,23 +3238,23 @@ g_property_set_prerequisite (GProperty *property,
{
g_return_if_fail (G_IS_PROPERTY (property));
g_return_if_fail (gtype != G_TYPE_INVALID);
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
- g_return_if_fail (g_type_is_a (gtype, property->gtype));
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
+ g_return_if_fail (g_type_is_a (gtype, G_PARAM_SPEC (property)->value_type));
- switch (property->gtype)
+ switch (G_PARAM_SPEC (property)->value_type)
{
case G_TYPE_BOXED:
case G_TYPE_OBJECT:
- property->prerequisite = gtype;
+ G_PARAM_SPEC (property)->value_type = gtype;
break;
case G_TYPE_ENUM:
- property->prerequisite = gtype;
+ G_PARAM_SPEC (property)->value_type = gtype;
((GEnumProperty *) property)->e_class = g_type_class_ref (gtype);
break;
case G_TYPE_FLAGS:
- property->prerequisite = gtype;
+ G_PARAM_SPEC (property)->value_type = gtype;
((GFlagsProperty *) property)->f_class = g_type_class_ref (gtype);
break;
@@ -3051,14 +3280,18 @@ g_property_set_range_values (GProperty *property,
const GValue *min_value,
const GValue *max_value)
{
+ GType gtype;
+
g_return_if_fail (G_IS_PROPERTY (property));
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
g_return_if_fail (!property->is_installed);
g_return_if_fail (min_value != NULL && max_value != NULL);
- g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (min_value), property->gtype));
- g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (max_value), property->gtype));
- switch (property->gtype)
+ gtype = G_PARAM_SPEC (property)->value_type;
+ g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (min_value), gtype));
+ g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (max_value), gtype));
+
+ switch (gtype)
{
case G_TYPE_BOOLEAN:
g_boolean_property_set_range (property,
@@ -3178,14 +3411,17 @@ g_property_get_range_values (GProperty *property,
GValue *max_value)
{
gboolean retval;
+ GType gtype;
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
g_return_val_if_fail (min_value != NULL, FALSE);
g_return_val_if_fail (max_value != NULL, FALSE);
- g_return_val_if_fail (g_value_type_compatible (property->gtype, G_VALUE_TYPE (min_value)), FALSE);
- g_return_val_if_fail (g_value_type_compatible (property->gtype, G_VALUE_TYPE (max_value)), FALSE);
- switch (property->gtype)
+ gtype = G_PARAM_SPEC (property)->value_type;
+ g_return_val_if_fail (g_value_type_compatible (gtype, G_VALUE_TYPE (min_value)), FALSE);
+ g_return_val_if_fail (g_value_type_compatible (gtype, G_VALUE_TYPE (max_value)), FALSE);
+
+ switch (gtype)
{
case G_TYPE_BOOLEAN:
{
@@ -3323,7 +3559,7 @@ g_property_get_range_values (GProperty *property,
break;
default:
- g_critical (G_STRLOC ": Invalid type '%s'", g_type_name (property->gtype));
+ g_critical (G_STRLOC ": Invalid type '%s'", g_type_name (gtype));
retval = FALSE;
break;
}
@@ -3346,16 +3582,19 @@ g_property_set_range (GProperty *property,
{
GValue min_value = { 0, };
GValue max_value = { 0, };
+ GType gtype;
gchar *error;
va_list var_args;
g_return_if_fail (G_IS_PROPERTY (property));
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
g_return_if_fail (!property->is_installed);
+ gtype = G_PARAM_SPEC (property)->value_type;
+ g_return_if_fail (gtype != G_TYPE_INVALID);
+
va_start (var_args, property);
- G_VALUE_COLLECT_INIT (&min_value, property->gtype, var_args, 0, &error);
+ G_VALUE_COLLECT_INIT (&min_value, gtype, var_args, 0, &error);
if (error != NULL)
{
g_warning (G_STRLOC ": %s", error);
@@ -3364,7 +3603,7 @@ g_property_set_range (GProperty *property,
return;
}
- G_VALUE_COLLECT_INIT (&max_value, property->gtype, var_args, 0, &error);
+ G_VALUE_COLLECT_INIT (&max_value, gtype, var_args, 0, &error);
if (error != NULL)
{
g_warning (G_STRLOC ": %s", error);
@@ -3403,12 +3642,9 @@ g_property_get_range (GProperty *property,
gpointer min_p, max_p;
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
- g_return_val_if_fail (property->gtype != G_TYPE_INVALID, FALSE);
+ g_return_val_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID, FALSE);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
va_start (var_args, property);
@@ -3528,58 +3764,68 @@ g_property_get_range (GProperty *property,
*/
void
g_property_set_default_value (GProperty *property,
- gpointer gobject_class,
const GValue *default_value)
{
GValue *value;
- GType gtype, class_gtype;
+ GType gtype;
g_return_if_fail (G_IS_PROPERTY (property));
- g_return_if_fail (G_IS_OBJECT_CLASS (gobject_class));
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
g_return_if_fail (default_value != NULL);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (default_value), gtype));
- /* if this is the first time g_property_set_default() has been called
- * on this property, then we special-case it, and we use a single
- * GValue, to avoid creating an hash table for the common case of a
- * property with a single default.
- */
- if (property->default_value == NULL)
+ value = g_new0 (GValue, 1);
+ g_value_init (value, gtype);
+ if (!g_value_transform (default_value, value))
{
- property->default_value = g_new0 (GValue, 1);
- g_value_init (property->default_value, gtype);
- if (!g_value_transform (default_value, property->default_value))
- {
- g_critical (G_STRLOC ": unable to set the default value for "
- "property '%s': the type %s of the value is not "
- "compatible with the type of the %s property",
- G_PARAM_SPEC (property)->name,
- g_type_name (G_VALUE_TYPE (default_value)),
- g_type_name (gtype));
-
- g_value_unset (property->default_value);
- g_free (property->default_value);
- }
+ g_critical (G_STRLOC ": unable to set the default value for "
+ "property '%s': the type %s of the value is not "
+ "compatible with the type of the %s property",
+ G_PARAM_SPEC (property)->name,
+ g_type_name (G_VALUE_TYPE (default_value)),
+ g_type_name (gtype));
+ g_value_unset (value);
+ g_free (value);
return;
}
- class_gtype = G_TYPE_FROM_CLASS (gobject_class);
- if (property_get_default_for_type (property, class_gtype) == NULL)
- {
- g_critical (G_STRLOC ": a default value of property '%s' for "
- "type '%s' has already been defined.",
- G_PARAM_SPEC (property)->name,
- g_type_name (class_gtype));
- return;
- }
+ property_set_default_for_type (property, G_TYPE_INVALID, value);
+}
+
+/**
+ * g_property_override_default_value:
+ * @property: a #GProperty
+ * @class_gtype: the type of the class overriding the value
+ * @default_value: a #GValue containing a value with the type of the
+ * property or a transformable type
+ *
+ * Overrides the default value of a @property for the given class
+ * type.
+ *
+ * This function should only be called by language bindings.
+ *
+ * Since: 2.32
+ */
+void
+g_property_override_default_value (GProperty *property,
+ GType class_gtype,
+ const GValue *default_value)
+{
+ GValue *value;
+ GType gtype;
+
+ g_return_if_fail (G_IS_PROPERTY (property));
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
+ g_return_if_fail (g_type_name (class_gtype) != 0);
+ g_return_if_fail (default_value != NULL);
+
+ gtype = G_PARAM_SPEC (property)->value_type;
+
+ g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (default_value), gtype));
value = g_new0 (GValue, 1);
g_value_init (value, gtype);
@@ -3597,6 +3843,7 @@ g_property_set_default_value (GProperty *property,
return;
}
+ /* takes ownership of value */
property_set_default_for_type (property, class_gtype, value);
}
@@ -3612,45 +3859,77 @@ g_property_set_default_value (GProperty *property,
* introspection tools; #GObject implementations should use
* g_property_get_default() instead.
*
+ * Return value: %TRUE if there is a default got the given type,
+ * and %FALSE otherwise.
+ *
* Since: 2.32
*/
-void
+gboolean
g_property_get_default_value_for_type (GProperty *property,
GType gtype,
GValue *value)
{
- const GValue *default_value;
+ const GValue *default_value = NULL;
+ GType iter;
- g_return_if_fail (G_IS_PROPERTY (property));
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
- g_return_if_fail (g_type_name (gtype) != 0);
+ g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
+ g_return_val_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID, FALSE);
+ g_return_val_if_fail (g_type_name (gtype) != 0, FALSE);
+
+ /* we need to recurse through the inheritance chain... */
+ iter = gtype;
+ while (iter != G_TYPE_INVALID && default_value == NULL)
+ {
+ default_value = property_get_default_for_type (property, iter);
+ gtype = g_type_parent (iter);
+ }
+
+ if (default_value != NULL)
+ goto out;
- if (property->default_value != NULL)
+ /* ... and eventually check the implemented interfaces */
+ if (default_value == NULL)
{
- if (!g_value_transform (property->default_value, value))
+ GType *ifaces;
+ guint n_ifaces;
+
+ ifaces = g_type_interfaces (gtype, &n_ifaces);
+ while (n_ifaces-- && default_value == NULL)
{
- g_critical (G_STRLOC ": Unable to copy the default value "
- "of property '%s' from type '%s' to type '%s'",
- G_PARAM_SPEC (property)->name,
- g_type_name (property->gtype),
- g_type_name (G_VALUE_TYPE (value)));
+ iter = ifaces[n_ifaces];
+ default_value = property_get_default_for_type (property, iter);
}
- return;
+ g_free (ifaces);
}
- default_value = property_get_default_for_type (property, gtype);
if (default_value != NULL)
+ goto out;
+
+ /* if the property hasn't been overridden then we look for the default */
+ default_value = property_get_default_for_type (property, G_TYPE_INVALID);
+
+ if (default_value == NULL)
{
- if (!g_value_transform (default_value, value))
- {
- g_critical (G_STRLOC ": Unable to copy the default value "
- "of property '%s' from type '%s' to type '%s'",
- G_PARAM_SPEC (property)->name,
- g_type_name (property->gtype),
- g_type_name (G_VALUE_TYPE (value)));
- }
+ g_critical (G_STRLOC ": No default value of property '%s' "
+ "was found for type '%s'",
+ G_PARAM_SPEC (property)->name,
+ g_type_name (gtype));
+
+ return FALSE;
}
+
+out:
+ if (!g_value_transform (default_value, value))
+ {
+ g_critical (G_STRLOC ": Unable to transform a value of type '%s' "
+ "into a value of type '%s'",
+ g_type_name (G_VALUE_TYPE (default_value)),
+ g_type_name (G_VALUE_TYPE (value)));
+ return FALSE;
+ }
+
+ return TRUE;
}
/**
@@ -3665,37 +3944,40 @@ g_property_get_default_value_for_type (GProperty *property,
* This function should only be used by language bindings and other
* introspection tools.
*
+ * Return value: %TRUE if a default value was found, and %FALSE
+ * otherwise
+ *
* Since: 2.32
*/
-void
+gboolean
g_property_get_default_value (GProperty *property,
gpointer gobject,
GValue *value)
{
- g_return_if_fail (G_IS_OBJECT (gobject));
+ g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
- g_property_get_default_value_for_type (property,
- G_OBJECT_TYPE (gobject),
- value);
+ return g_property_get_default_value_for_type (property,
+ G_OBJECT_TYPE (gobject),
+ value);
}
/**
* g_property_set_default:
* @property: a #GProperty
- * @gobject_class: a pointer to a #GObject class
* @...: the default value for the property
*
- * Sets the default value of @property for the given @gobject_class.
+ * Sets the default value of @property.
*
- * This function can only be called once for each @gobject_class.
+ * This function can only be called once for each property; derived
+ * types should call g_property_override_default() instead.
*
- * See also g_object_class_override_property_default().
+ * See also g_property_override_default() and
+ * g_object_class_override_property_default().
*
* Since: 2.32
*/
void
g_property_set_default (GProperty *property,
- gpointer gobject_class,
...)
{
GValue value = { 0, };
@@ -3704,15 +3986,11 @@ g_property_set_default (GProperty *property,
va_list var_args;
g_return_if_fail (G_IS_PROPERTY (property));
- g_return_if_fail (G_IS_OBJECT_CLASS (gobject_class));
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
- if (property->prerequisite != G_TYPE_INVALID)
- p_type = property->prerequisite;
- else
- p_type = property->gtype;
+ p_type = G_PARAM_SPEC (property)->value_type;
- va_start (var_args, gobject_class);
+ va_start (var_args, property);
G_VALUE_COLLECT_INIT (&value, p_type, var_args, 0, &error);
if (error != NULL)
@@ -3721,10 +3999,11 @@ g_property_set_default (GProperty *property,
g_free (error);
}
else
- g_property_set_default_value (property, gobject_class, &value);
+ g_property_set_default_value (property, &value);
- va_end (var_args);
g_value_unset (&value);
+
+ va_end (var_args);
}
/**
@@ -3751,22 +4030,13 @@ g_property_get_default (GProperty *property,
g_return_if_fail (G_IS_PROPERTY (property));
g_return_if_fail (G_IS_OBJECT (gobject));
- g_return_if_fail (property->gtype != G_TYPE_INVALID);
-
- gtype = G_OBJECT_TYPE (gobject);
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
- if (property->prerequisite != G_TYPE_INVALID)
- p_type = property->prerequisite;
- else
- p_type = property->gtype;
+ p_type = G_PARAM_SPEC (property)->value_type;
g_value_init (&value, p_type);
- if (property->default_value != NULL)
- {
- g_value_copy (property->default_value, &value);
- goto lcopy;
- }
+ gtype = G_OBJECT_TYPE (gobject);
/* we need to recurse through the inheritance chain... */
while (gtype != G_TYPE_INVALID && default_value == NULL)
@@ -3775,6 +4045,9 @@ g_property_get_default (GProperty *property,
gtype = g_type_parent (gtype);
}
+ if (default_value != NULL)
+ goto lcopy;
+
/* ... and eventually check the implemented interfaces */
if (default_value == NULL)
{
@@ -3785,11 +4058,21 @@ g_property_get_default (GProperty *property,
ifaces = g_type_interfaces (gtype, &n_ifaces);
while (n_ifaces-- && default_value == NULL)
- default_value = property_get_default_for_type (property, ifaces[n_ifaces]);
+ {
+ gtype = ifaces[n_ifaces];
+ default_value = property_get_default_for_type (property, gtype);
+ }
g_free (ifaces);
}
+ if (default_value != NULL)
+ goto lcopy;
+
+ /* if the property hasn't been overridden then we look for the default */
+ default_value = property_get_default_for_type (property, G_TYPE_INVALID);
+
+lcopy:
if (default_value == NULL)
{
g_critical (G_STRLOC ": No default value of property '%s' "
@@ -3800,7 +4083,6 @@ g_property_get_default (GProperty *property,
else
g_value_copy (default_value, &value);
-lcopy:
va_start (var_args, gobject);
G_VALUE_LCOPY (&value, var_args, 0, &error);
@@ -3815,6 +4097,47 @@ lcopy:
}
/**
+ * g_property_override_default:
+ * @property: a #GProperty
+ * @class_gtype: the type of the class overriding the default
+ * @...: the new default value for the property
+ *
+ * Overrides the default value of @property for the given class type.
+ *
+ * Since: 2.32
+ */
+void
+g_property_override_default (GProperty *property,
+ GType class_gtype,
+ ...)
+{
+ GValue value = { 0, };
+ GType p_type;
+ gchar *error;
+ va_list var_args;
+
+ g_return_if_fail (G_IS_PROPERTY (property));
+ g_return_if_fail (G_PARAM_SPEC (property)->value_type != G_TYPE_INVALID);
+ g_return_if_fail (g_type_name (class_gtype) != 0);
+
+ p_type = G_PARAM_SPEC (property)->value_type;
+
+ va_start (var_args, class_gtype);
+
+ G_VALUE_COLLECT_INIT (&value, p_type, var_args, 0, &error);
+ if (error != NULL)
+ {
+ g_critical (G_STRLOC ": %s", error);
+ g_free (error);
+ }
+ else
+ g_property_override_default_value (property, class_gtype, &value);
+
+ va_end (var_args);
+ g_value_unset (&value);
+}
+
+/**
* g_property_set_valist:
* @property: a #GProperty
* @gobject: a #GObject instance
@@ -3840,10 +4163,7 @@ g_property_set_valist (GProperty *property,
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
g_return_val_if_fail (property->is_installed, FALSE);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
switch (G_TYPE_FUNDAMENTAL (gtype))
{
@@ -3937,6 +4257,10 @@ g_property_set_valist (GProperty *property,
retval = g_object_property_set_value (property, gobject, va_arg (args, gpointer));
break;
+ case G_TYPE_POINTER:
+ retval = g_pointer_property_set_value (property, gobject, va_arg (args, gpointer));
+ break;
+
default:
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
retval = FALSE;
@@ -3973,10 +4297,7 @@ g_property_get_valist (GProperty *property,
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
g_return_val_if_fail (property->is_installed, FALSE);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
ret_p = va_arg (args, gpointer);
@@ -4072,8 +4393,12 @@ g_property_get_valist (GProperty *property,
(* (gpointer *) ret_p) = g_object_property_get_value (property, gobject);
break;
+ case G_TYPE_POINTER:
+ (* (gpointer *) ret_p) = g_pointer_property_get_value (property, gobject);
+ break;
+
default:
- g_critical (G_STRLOC ": Invalid type %s", g_type_name (property->gtype));
+ g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
break;
}
@@ -4146,10 +4471,7 @@ g_property_collect (GProperty *property,
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
for (i = 0; i < n_cvalues; i++)
{
@@ -4239,6 +4561,10 @@ g_property_collect (GProperty *property,
retval = g_object_property_set_value (property, gobject, _cvalue->v_pointer);
break;
+ case G_TYPE_POINTER:
+ retval = g_pointer_property_set_value (property, gobject, _cvalue->v_pointer);
+ break;
+
default:
g_critical (G_STRLOC ": Invalid value for type '%s'", g_type_name (gtype));
retval = FALSE;
@@ -4282,10 +4608,7 @@ g_property_lcopy (GProperty *property,
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
g_return_val_if_fail (G_IS_OBJECT (gobject), FALSE);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
for (i = 0; i < n_cvalues; i++)
{
@@ -4518,6 +4841,17 @@ g_property_lcopy (GProperty *property,
}
break;
+ case G_TYPE_POINTER:
+ if (_cvalue->v_pointer == NULL)
+ {
+ g_critical (G_STRLOC ": value location for gpointer passed as NULL");
+ return FALSE;
+ }
+
+ (* (gpointer *) _cvalue->v_pointer) =
+ g_pointer_property_get_value (property, gobject);
+ break;
+
default:
g_critical (G_STRLOC ": Invalid value location for type '%s'",
g_type_name (gtype));
@@ -4584,10 +4918,7 @@ g_property_set_value (GProperty *property,
g_return_if_fail (value != NULL);
g_return_if_fail (property->is_installed);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (value), gtype));
@@ -4701,6 +5032,10 @@ g_property_set_value (GProperty *property,
g_object_property_set_value (property, gobject, g_value_get_object (©));
break;
+ case G_TYPE_POINTER:
+ g_pointer_property_set_value (property, gobject, g_value_get_pointer (©));
+ break;
+
default:
g_critical (G_STRLOC ": Invalid type %s", g_type_name (G_VALUE_TYPE (©)));
break;
@@ -4735,10 +5070,7 @@ g_property_get_value (GProperty *property,
g_return_if_fail (value != NULL);
g_return_if_fail (property->is_installed);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
g_return_if_fail (g_value_type_transformable (G_VALUE_TYPE (value), gtype));
@@ -4856,6 +5188,10 @@ g_property_get_value (GProperty *property,
g_value_set_object (©, g_object_property_get_value (property, gobject));
break;
+ case G_TYPE_POINTER:
+ g_value_set_pointer (©, g_pointer_property_get_value (property, gobject));
+ break;
+
default:
g_critical (G_STRLOC ": Invalid type %s", g_type_name (gtype));
break;
@@ -4889,10 +5225,7 @@ g_property_get_value_type (GProperty *property)
{
g_return_val_if_fail (G_IS_PROPERTY (property), G_TYPE_INVALID);
- if (property->prerequisite != G_TYPE_INVALID)
- return property->prerequisite;
-
- return property->gtype;
+ return G_PARAM_SPEC (property)->value_type;
}
/**
@@ -4919,10 +5252,7 @@ g_property_validate (GProperty *property,
va_start (args, property);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
switch (G_TYPE_FUNDAMENTAL (gtype))
{
@@ -4933,15 +5263,15 @@ g_property_validate (GProperty *property,
case G_TYPE_INT:
switch (property->type_size)
{
- case 8:
+ case 1:
retval = g_int8_property_validate (property, va_arg (args, gint));
break;
- case 16:
+ case 2:
retval = g_int16_property_validate (property, va_arg (args, gint));
break;
- case 32:
+ case 4:
retval = g_int32_property_validate (property, va_arg (args, gint));
break;
@@ -4962,15 +5292,15 @@ g_property_validate (GProperty *property,
case G_TYPE_UINT:
switch (property->type_size)
{
- case 8:
+ case 1:
retval = g_uint8_property_validate (property, va_arg (args, guint));
break;
- case 16:
+ case 2:
retval = g_uint16_property_validate (property, va_arg (args, guint));
break;
- case 32:
+ case 4:
retval = g_uint32_property_validate (property, va_arg (args, guint));
break;
@@ -5050,10 +5380,7 @@ g_property_validate_value (GProperty *property,
g_return_val_if_fail (G_IS_PROPERTY (property), FALSE);
g_return_val_if_fail (value != NULL, FALSE);
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
+ gtype = G_PARAM_SPEC (property)->value_type;
g_return_val_if_fail (g_value_type_transformable (gtype, G_VALUE_TYPE (value)), FALSE);
@@ -5081,15 +5408,15 @@ g_property_validate_value (GProperty *property,
switch (property->type_size)
{
- case 8:
+ case 1:
retval = g_int8_property_validate (property, val);
break;
- case 16:
+ case 2:
retval = g_int16_property_validate (property, val);
break;
- case 32:
+ case 4:
retval = g_int32_property_validate (property, val);
break;
@@ -5114,15 +5441,15 @@ g_property_validate_value (GProperty *property,
switch (property->type_size)
{
- case 8:
+ case 1:
retval = g_uint8_property_validate (property, val);
break;
- case 16:
+ case 2:
retval = g_uint16_property_validate (property, val);
break;
- case 32:
+ case 4:
retval = g_uint32_property_validate (property, val);
break;
@@ -5324,15 +5651,8 @@ g_property_set_lock_functions (GProperty *property,
static void
property_finalize (GParamSpec *pspec)
{
- GProperty *property = G_PROPERTY (pspec);
GParamSpecClass *parent_class = g_type_class_peek (g_type_parent (G_TYPE_PROPERTY));
- if (property->default_value != NULL)
- {
- g_value_unset (property->default_value);
- g_free (property->default_value);
- }
-
parent_class->finalize (pspec);
}
@@ -5353,17 +5673,11 @@ property_validate (GParamSpec *pspec,
GValue *value)
{
GProperty *property = G_PROPERTY (pspec);
- GType gtype;
-
- if (property->prerequisite != G_TYPE_INVALID)
- gtype = property->prerequisite;
- else
- gtype = property->gtype;
- if (!g_value_type_transformable (G_VALUE_TYPE (value), gtype))
- return FALSE;
+ if (!g_value_type_transformable (G_VALUE_TYPE (value), pspec->value_type))
+ return TRUE;
- return g_property_validate_value (G_PROPERTY (pspec), value);
+ return !g_property_validate_value (property, value);
}
static gint
@@ -5391,8 +5705,7 @@ property_init (GParamSpec *pspec)
{
GProperty *property = G_PROPERTY (pspec);
- property->gtype = G_TYPE_INVALID;
- property->prerequisite = G_TYPE_INVALID;
+ pspec->value_type = G_TYPE_INVALID;
property->field_offset = -1;
property->priv_offset = -1;
diff --git a/gobject/gproperty.h b/gobject/gproperty.h
index 2e95322..41427f7 100644
--- a/gobject/gproperty.h
+++ b/gobject/gproperty.h
@@ -102,17 +102,21 @@ gboolean g_property_get_range (GProperty *property,
...);
void g_property_set_default_value (GProperty *property,
- gpointer gobject_class,
const GValue *value);
-void g_property_get_default_value_for_type (GProperty *property,
+void g_property_set_default (GProperty *property,
+ ...);
+void g_property_override_default_value (GProperty *property,
+ GType class_gtype,
+ const GValue *value);
+void g_property_override_default (GProperty *property,
+ GType class_gtype,
+ ...);
+gboolean g_property_get_default_value_for_type (GProperty *property,
GType gtype,
GValue *value);
-void g_property_get_default_value (GProperty *property,
+gboolean g_property_get_default_value (GProperty *property,
gpointer gobject,
GValue *value);
-void g_property_set_default (GProperty *property,
- gpointer gobject_class,
- ...);
void g_property_get_default (GProperty *property,
gpointer gobject,
...);
diff --git a/gobject/tests/autoproperties.c b/gobject/tests/autoproperties.c
index 2106c52..62f7a8a 100644
--- a/gobject/tests/autoproperties.c
+++ b/gobject/tests/autoproperties.c
@@ -37,6 +37,8 @@ struct _TestObjectClass
struct _TestObjectPrivate
{
+ gint dummy;
+
gint foo;
gboolean bar;
@@ -168,7 +170,7 @@ static GParamSpec *test_object_properties[LAST_PROP] = { NULL, };
G_DEFINE_TYPE (TestObject, test_object, G_TYPE_OBJECT)
-G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gint, foo)
+G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, int, foo)
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gboolean, bar)
G_DEFINE_PROPERTY_GET (TestObject, test_object, gboolean, str_set)
G_DEFINE_PROPERTY_GET_SET (TestObject, test_object, gint8, single_byte)
@@ -217,7 +219,7 @@ test_object_class_init (TestObjectClass *klass)
G_STRUCT_OFFSET (TestObjectPrivate, foo),
NULL, NULL);
g_property_set_range (G_PROPERTY (test_object_properties[PROP_FOO]), -1, 100);
- g_property_set_default (G_PROPERTY (test_object_properties[PROP_FOO]), klass, 50);
+ g_property_set_default (G_PROPERTY (test_object_properties[PROP_FOO]), 50);
test_object_properties[PROP_BAR] =
g_boolean_property_new ("bar", G_PROPERTY_READWRITE | G_PROPERTY_ATOMIC,
@@ -266,7 +268,7 @@ test_object_class_init (TestObjectClass *klass)
G_STRUCT_OFFSET (TestObjectPrivate, x_align),
NULL, NULL);
g_property_set_range (G_PROPERTY (test_object_properties[PROP_X_ALIGN]), 0.0, 1.0);
- g_property_set_default (G_PROPERTY (test_object_properties[PROP_X_ALIGN]), klass, 0.5);
+ g_property_set_default (G_PROPERTY (test_object_properties[PROP_X_ALIGN]), 0.5);
test_object_properties[PROP_ENUM_VALUE] =
g_enum_property_new ("enum-value", G_PROPERTY_READWRITE,
@@ -275,7 +277,6 @@ test_object_class_init (TestObjectClass *klass)
g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_ENUM_VALUE]),
test_enum_value_get_type ());
g_property_set_default (G_PROPERTY (test_object_properties[PROP_ENUM_VALUE]),
- klass,
TEST_ENUM_VALUE_BAR);
test_object_properties[PROP_FLAGS_VALUE] =
@@ -285,7 +286,6 @@ test_object_class_init (TestObjectClass *klass)
g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_FLAGS_VALUE]),
test_flags_value_get_type ());
g_property_set_default (G_PROPERTY (test_object_properties[PROP_FLAGS_VALUE]),
- klass,
TEST_FLAGS_VALUE_FOO);
test_object_properties[PROP_BOXED] =
@@ -330,6 +330,53 @@ autoproperties_base (void)
}
static void
+autoproperties_constructor (void)
+{
+ TestObject *t = g_object_new (test_object_get_type (),
+ "str", "Hello, World!",
+ "x-align", 1.0,
+ NULL);
+
+ g_assert (G_TYPE_CHECK_INSTANCE_TYPE (t, test_object_get_type ()));
+ g_assert_cmpstr (test_object_get_str (t), ==, "Hello, World!");
+ g_assert_cmpfloat (test_object_get_x_align (t), ==, 1.0);
+
+ g_object_unref (t);
+}
+
+typedef TestObject TestDerived;
+typedef TestObjectClass TestDerivedClass;
+
+G_DEFINE_TYPE (TestDerived, test_derived, test_object_get_type ())
+
+static void
+test_derived_class_init (TestDerivedClass *klass)
+{
+ g_object_class_override_property_default (G_OBJECT_CLASS (klass), "foo", -1);
+ g_object_class_override_property_default (G_OBJECT_CLASS (klass), "enum-value", TEST_ENUM_VALUE_BAZ);
+}
+
+static void
+test_derived_init (TestDerived *self)
+{
+ GValue value = { 0, };
+
+ g_value_init (&value, g_property_get_value_type (G_PROPERTY (test_object_properties[PROP_FOO])));
+ g_property_get_default_value_for_type (G_PROPERTY (test_object_properties[PROP_FOO]),
+ test_derived_get_type (),
+ &value);
+
+ g_assert_cmpint (g_value_get_int (&value), !=, 50);
+ g_assert_cmpint (g_value_get_int (&value), ==, -1);
+
+ test_object_set_foo ((TestObject *) self, g_value_get_int (&value));
+
+ g_value_unset (&value);
+
+ test_object_set_enum_value ((TestObject *) self, TEST_ENUM_VALUE_BAZ);
+}
+
+static void
autoproperties_default (void)
{
TestObject *t = g_object_new (test_object_get_type (), NULL);
@@ -340,6 +387,13 @@ autoproperties_default (void)
g_assert (test_object_get_flags_value (t) == TEST_FLAGS_VALUE_FOO);
g_object_unref (t);
+
+ t = g_object_new (test_derived_get_type (), NULL);
+
+ g_assert_cmpint (test_object_get_foo (t), ==, -1);
+ g_assert (test_object_get_enum_value (t) == TEST_ENUM_VALUE_BAZ);
+
+ g_object_unref (t);
}
static void
@@ -410,7 +464,6 @@ autoproperties_validate (void)
exit (0);
}
g_test_trap_assert_failed ();
-// g_test_trap_assert_stderr ("**");
if (g_test_trap_fork (0, G_TEST_TRAP_SILENCE_STDOUT|G_TEST_TRAP_SILENCE_STDERR))
{
@@ -420,7 +473,6 @@ autoproperties_validate (void)
exit (0);
}
g_test_trap_assert_failed ();
-// g_test_trap_assert_stderr ("**");
}
static void
@@ -518,6 +570,7 @@ main (int argc, char *argv[])
g_test_bug_base ("http://bugzilla.gnome.org/");
g_test_add_func ("/auto-properties/base", autoproperties_base);
+ g_test_add_func ("/auto-properties/constructor", autoproperties_constructor);
g_test_add_func ("/auto-properties/default", autoproperties_default);
g_test_add_func ("/auto-properties/range", autoproperties_range);
g_test_add_func ("/auto-properties/accessors", autoproperties_accessors);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]