diff options
-rw-r--r-- | docs/reference/gobject/gobject-sections.txt | 2 | ||||
-rw-r--r-- | gobject/gobject.symbols | 2 | ||||
-rw-r--r-- | gobject/gproperty.c | 153 | ||||
-rw-r--r-- | gobject/gproperty.h | 14 | ||||
-rw-r--r-- | gobject/tests/autoproperties.c | 2 | ||||
-rw-r--r-- | gobject/tests/gproperty-example-base.c | 3 | ||||
-rw-r--r-- | gobject/tests/gproperty-example-derived.c | 9 |
7 files changed, 144 insertions, 41 deletions
diff --git a/docs/reference/gobject/gobject-sections.txt b/docs/reference/gobject/gobject-sections.txt index 2e3a93699..e71552501 100644 --- a/docs/reference/gobject/gobject-sections.txt +++ b/docs/reference/gobject/gobject-sections.txt @@ -892,6 +892,8 @@ g_property_is_writable g_property_is_redable g_property_is_deprecated g_property_is_atomic +g_property_is_copy_set +g_property_is_copy_get g_property_describe g_property_set_range_values g_property_get_range_values diff --git a/gobject/gobject.symbols b/gobject/gobject.symbols index 17229244e..fde734a8a 100644 --- a/gobject/gobject.symbols +++ b/gobject/gobject.symbols @@ -233,6 +233,8 @@ g_property_get_valist g_property_get_value g_property_get_value_type g_property_is_atomic +g_property_is_copy_get +g_property_is_copy_set g_property_is_deprecated g_property_is_readable g_property_is_writable diff --git a/gobject/gproperty.c b/gobject/gproperty.c index b94b62b3e..89ff1d5f7 100644 --- a/gobject/gproperty.c +++ b/gobject/gproperty.c @@ -156,11 +156,18 @@ * ]| * <para>Note that calling g_property_set() for a property holding a * complex type (e.g. #GObject or #GBoxed) without a specific setter - * function will result in the value being copied in the private data - * structure's field. In contrast, calling g_property_get() will return - * a pointer to the private data structure's field: it is up to the - * getter function to decide whether to return a copy of the internal - * data or the pointer itself.</para> + * function will, by default, result in the pointer to the new value + * being copied in the private data structure's field; if you need to + * copy a boxed type, or take a reference on an object type, you will + * need to set the %G_PROPERTY_COPY_SET flag when creating the + * property.</para> + * + * <para>Calling g_property_get() will return a pointer to the private + * data structure's field, unless %G_PROPERTY_COPY_GET is set when + * creating the property, in which case the returned value will either + * be a copy of the private data structure field if it is a boxed type + * or the instance with its reference count increased if it is an object + * type.</para> * </refsect3> * * <refsect3> @@ -363,7 +370,7 @@ * * |[ * test_object_property[PROP_WIDTH] = - * g_int_property_new ("width", G_PROPERTY_READWRITE, + * g_int_property_new ("width", G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, * G_STRUCT_OFFSET (TestObjectPrivate, width), * test_object_set_width, /* explicit setter */ * NULL /* implicit getter */); @@ -432,7 +439,7 @@ * |[ * G_DEFINE_PROPERTY_GET (TestObject, test_object, int, width) * G_DEFINE_PROPERTY_SET_WITH_CODE (Test_object, test_object, int, width, - * test_object_queue_resize (self)) + * test_object_queue_action (self)) * ]| * * <para>The WITH_CODE variant of the setter will define the "self" and @@ -2405,8 +2412,13 @@ g_string_property_set_value (GProperty *property, return FALSE; } - g_free (str); - (* (gpointer *) field_p) = g_strdup (value); + if (property->flags & G_PROPERTY_COPY_SET) + { + g_free (str); + (* (gpointer *) field_p) = g_strdup (value); + } + else + (* (gpointer *) field_p) = (gpointer) value; property_unlock_internal (property, gobject); @@ -2446,7 +2458,10 @@ g_string_property_get_value (GProperty *property, priv_p = get_private_pointer (gobject, property->priv_offset); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - retval = (* (gpointer *) field_p); + if (property->flags & G_PROPERTY_COPY_GET) + retval = g_strdup ((* (gpointer *) field_p)); + else + retval = (* (gpointer *) field_p); return retval; } @@ -2612,15 +2627,20 @@ g_boxed_property_set_value (GProperty *property, priv_p = get_private_pointer (gobject, property->priv_offset); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - old_value = (* (gpointer *) field_p); + if (property->flags & G_PROPERTY_COPY_SET) + { + old_value = (* (gpointer *) field_p); - if (value != NULL) - (* (gpointer *) field_p) = g_boxed_copy (((GParamSpec *) property)->value_type, value); - else - (* (gpointer *) field_p) = NULL; + if (value != NULL) + (* (gpointer *) field_p) = g_boxed_copy (((GParamSpec *) property)->value_type, value); + else + (* (gpointer *) field_p) = NULL; - if (old_value != NULL) - g_boxed_free (((GParamSpec *) property)->value_type, old_value); + if (old_value != NULL) + g_boxed_free (((GParamSpec *) property)->value_type, old_value); + } + else + (* (gpointer *) field_p) = value; property_unlock_internal (property, gobject); @@ -2659,7 +2679,11 @@ g_boxed_property_get_value (GProperty *property, priv_p = get_private_pointer (gobject, property->priv_offset); field_p = G_STRUCT_MEMBER_P (priv_p, property->field_offset); - value = (* (gpointer *) field_p); + + if (property->flags & G_PROPERTY_COPY_GET) + value = g_boxed_copy (((GParamSpec *) property)->value_type, (* (gpointer *) field_p)); + else + value = (* (gpointer *) field_p); return value; } @@ -2836,19 +2860,24 @@ g_object_property_set_value (GProperty *property, return FALSE; } - obj = (* (gpointer *) field_p); - if (obj != NULL) - g_object_unref (obj); - - (* (gpointer *) field_p) = obj = value; - - if (obj != NULL) + if (property->flags & G_PROPERTY_COPY_SET) { - if (G_IS_INITIALLY_UNOWNED (obj)) - g_object_ref_sink (obj); - else - g_object_ref (obj); + obj = (* (gpointer *) field_p); + if (obj != NULL) + g_object_unref (obj); + + (* (gpointer *) field_p) = obj = value; + + if (obj != NULL) + { + if (G_IS_INITIALLY_UNOWNED (obj)) + g_object_ref_sink (obj); + else + g_object_ref (obj); + } } + else + (* (gpointer *) field_p) = value; property_unlock_internal (property, gobject); @@ -2887,7 +2916,17 @@ g_object_property_get_value (GProperty *property, 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); + if (property->flags & G_PROPERTY_COPY_GET) + { + gpointer value = (* (gpointer *) field_p); + + if (value != NULL) + return g_object_ref (value); + else + return NULL; + } + else + return (* (gpointer *) field_p); } else { @@ -4558,8 +4597,11 @@ g_property_get_valist (GProperty *property, value = g_string_property_get_value (property, gobject); - if ((flags & G_PROPERTY_COLLECT_COPY) != 0) - (* (gchar **) ret_p) = g_strdup (value); + if (((flags & G_PROPERTY_COLLECT_COPY) != 0) && + (property->flags & G_PROPERTY_COPY_GET) == 0) + { + (* (gchar **) ret_p) = g_strdup (value); + } else (* (gconstpointer *) ret_p) = value; } @@ -4571,7 +4613,8 @@ g_property_get_valist (GProperty *property, boxed = g_boxed_property_get_value (property, gobject); - if ((flags & G_PROPERTY_COLLECT_COPY) != 0) + if (((flags & G_PROPERTY_COLLECT_COPY) != 0) && + (property->flags & G_PROPERTY_COPY_GET) == 0) { if (boxed != NULL) (* (gpointer *) ret_p) = g_boxed_copy (gtype, boxed); @@ -4587,8 +4630,12 @@ g_property_get_valist (GProperty *property, { gpointer obj = g_object_property_get_value (property, gobject); - if (((flags & G_PROPERTY_COLLECT_REF) != 0) && obj != NULL) - (* (gpointer *) ret_p) = g_object_ref (obj); + if ((((flags & G_PROPERTY_COLLECT_REF) != 0) && + (property->flags & G_PROPERTY_COPY_GET) == 0) && + (obj != NULL)) + { + (* (gpointer *) ret_p) = g_object_ref (obj); + } else (* (gpointer *) ret_p) = obj; } @@ -5349,6 +5396,42 @@ g_property_is_atomic (GProperty *property) } /** + * g_property_is_copy_set: + * @property: a #GProperty + * + * Checks whether the @property has the %G_PROPERTY_COPY_SET flag set. + * + * Return value: %TRUE if the flag is set, and %FALSE otherwise + * + * Since: 2.30 + */ +gboolean +g_property_is_copy_set (GProperty *property) +{ + g_return_val_if_fail (G_IS_PROPERTY (property), FALSE); + + return (property->flags & G_PROPERTY_COPY_SET) != 0; +} + +/** + * g_property_is_copy_get: + * @property: a #GProperty + * + * Checks whether the @property has the %G_PROPERTY_COPY_GET flag set. + * + * Return value: %TRUE if the flag is set, and %FALSE otherwise + * + * Since: 2.30 + */ +gboolean +g_property_is_copy_get (GProperty *property) +{ + g_return_val_if_fail (G_IS_PROPERTY (property), FALSE); + + return (property->flags & G_PROPERTY_COPY_GET) != 0; +} + +/** * g_property_lock: * @property: a #GProperty * @gobject: a #GObject diff --git a/gobject/gproperty.h b/gobject/gproperty.h index c1565633c..72c2c14a9 100644 --- a/gobject/gproperty.h +++ b/gobject/gproperty.h @@ -57,6 +57,13 @@ typedef struct _GProperty GProperty; * @G_PROPERTY_ATOMIC: Whether the autogenerated setter function should * be thread-safe, and acquire a lock when changing the value of the * property. + * @G_PROPERTY_COPY_SET: Whether the property will make a copy or + * take a reference when being set to a new value + * @G_PROPERTY_COPY_GET: Whether the property will make a copy or + * take a reference when the value is being retrieved + * @G_PROPERTY_COPY: Whether the property will make a copy, or take a + * reference, of the new value being set, and return a copy, or + * increase the reference count, of the value being retrieved * * Flags for properties declared using #GProperty and relative macros. * @@ -70,7 +77,10 @@ typedef enum { G_PROPERTY_READWRITE = (G_PROPERTY_READABLE | G_PROPERTY_WRITABLE), G_PROPERTY_DEPRECATED = 1 << 2, - G_PROPERTY_ATOMIC = 1 << 3 + G_PROPERTY_ATOMIC = 1 << 3, + G_PROPERTY_COPY_SET = 1 << 4, + G_PROPERTY_COPY_GET = 1 << 5, + G_PROPERTY_COPY = (G_PROPERTY_COPY_SET | G_PROPERTY_COPY_GET) } GPropertyFlags; GType g_property_get_type (void) G_GNUC_CONST; @@ -84,6 +94,8 @@ gboolean g_property_is_writable (GProperty *property) gboolean g_property_is_readable (GProperty *property); gboolean g_property_is_deprecated (GProperty *property); gboolean g_property_is_atomic (GProperty *property); +gboolean g_property_is_copy_set (GProperty *property); +gboolean g_property_is_copy_get (GProperty *property); void g_property_describe (GProperty *property, const char *nick, diff --git a/gobject/tests/autoproperties.c b/gobject/tests/autoproperties.c index 69522e8ee..8fdd948ef 100644 --- a/gobject/tests/autoproperties.c +++ b/gobject/tests/autoproperties.c @@ -333,7 +333,7 @@ test_object_class_init (TestObjectClass *klass) TEST_FLAGS_VALUE_FOO); test_object_properties[PROP_BOXED] = - g_boxed_property_new ("boxed", G_PROPERTY_READWRITE, + g_boxed_property_new ("boxed", G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, G_STRUCT_OFFSET (TestObjectPrivate, boxed), NULL, NULL); g_property_set_prerequisite (G_PROPERTY (test_object_properties[PROP_BOXED]), diff --git a/gobject/tests/gproperty-example-base.c b/gobject/tests/gproperty-example-base.c index d8b67f60b..3cb9d4b23 100644 --- a/gobject/tests/gproperty-example-base.c +++ b/gobject/tests/gproperty-example-base.c @@ -90,7 +90,8 @@ test_file_class_init (TestFileClass *klass) g_type_class_add_private (klass, sizeof (TestFilePrivate)); test_file_properties[PROP_PATH] = - g_string_property_new ("path", G_PROPERTY_READWRITE, + g_string_property_new ("path", + G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, G_STRUCT_OFFSET (TestFilePrivate, path), (GPropertyStringSet) test_file_set_path, NULL); diff --git a/gobject/tests/gproperty-example-derived.c b/gobject/tests/gproperty-example-derived.c index bdde06eaf..813c9093e 100644 --- a/gobject/tests/gproperty-example-derived.c +++ b/gobject/tests/gproperty-example-derived.c @@ -207,7 +207,8 @@ test_file_mp3_class_init (TestFileMp3Class *klass) g_type_class_add_private (klass, sizeof (TestFileMp3Private)); test_file_mp3_properties[PROP_ALBUM] = - g_string_property_new ("album", G_PROPERTY_READWRITE, + g_string_property_new ("album", + G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, G_STRUCT_OFFSET (TestFileMp3Private, album), NULL, NULL); g_property_set_default (G_PROPERTY (test_file_mp3_properties[PROP_ALBUM]), @@ -215,7 +216,8 @@ test_file_mp3_class_init (TestFileMp3Class *klass) "Unknown Album"); test_file_mp3_properties[PROP_ARTIST] = - g_string_property_new ("artist", G_PROPERTY_READWRITE, + g_string_property_new ("artist", + G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, G_STRUCT_OFFSET (TestFileMp3Private, artist), NULL, NULL); g_property_set_default (G_PROPERTY (test_file_mp3_properties[PROP_ARTIST]), @@ -223,7 +225,8 @@ test_file_mp3_class_init (TestFileMp3Class *klass) "Unknown Author"); test_file_mp3_properties[PROP_TITLE] = - g_string_property_new ("title", G_PROPERTY_READWRITE, + g_string_property_new ("title", + G_PROPERTY_READWRITE | G_PROPERTY_COPY_SET, G_STRUCT_OFFSET (TestFileMp3Private, title), NULL, NULL); g_property_set_default (G_PROPERTY (test_file_mp3_properties[PROP_TITLE]), |