diff options
author | Emmanuele Bassi <ebassi@gnome.org> | 2018-02-01 17:43:15 +0100 |
---|---|---|
committer | Benjamin Otte <otte@redhat.com> | 2018-02-03 16:24:13 +0100 |
commit | 2cbe094b919442471b54685a0fef0d6f83ce44b3 (patch) | |
tree | 187a9b099feed2d2da8bcc14885ab1701fc92a95 /gdk/gdkcontentformats.c | |
parent | 4fa4b8525e62c711e6a7c10f25d5015428b2fa27 (diff) | |
download | gtk+-2cbe094b919442471b54685a0fef0d6f83ce44b3.tar.gz |
Allow binding GdkContentFormatsBuilder
GdkContentFormatsBuilder is currently not introspectable, as it does not
have a GType. We can turn it into a boxed type, but we need to implement
memory management for it.
The current gdk_content_formats_builder_free() function returns a newly
constructed value, so we cannot use it as a GBoxedFreeFunc; additionally
copying a GdkContentFormatsBuilder contents would make it a bit odd, as
you could get multiple identical GdkContentFormats out of the copies.
A simple approach is to model the GdkContentFormatsBuilder API to follow
the GBytes one: use reference counting for memory management, and have
a function to release a reference, return a GdkContentFormats, and reset
the GdkContentFormatsBuilder state.
For language bindings, we can provide a get_formats() function that
returns the GdkContentFormats instance and resets the builder instance,
leaving the reference count untouched.
For C convenience we can keep gdk_content_formats_builder_free(), and
make it a wrapper around gdk_content_formats_builder_get_formats(), with
the guarantee that it'll free the builder instance regardless of its
current reference count.
https://bugzilla.gnome.org/show_bug.cgi?id=793097
https://blogs.gnome.org/otte/2018/02/03/builders/
Diffstat (limited to 'gdk/gdkcontentformats.c')
-rw-r--r-- | gdk/gdkcontentformats.c | 115 |
1 files changed, 105 insertions, 10 deletions
diff --git a/gdk/gdkcontentformats.c b/gdk/gdkcontentformats.c index 04bd0647f4..cd3293f0a3 100644 --- a/gdk/gdkcontentformats.c +++ b/gdk/gdkcontentformats.c @@ -307,7 +307,7 @@ gdk_content_formats_union (GdkContentFormats *first, gdk_content_formats_unref (first); gdk_content_formats_builder_add_formats (builder, second); - return gdk_content_formats_builder_free (builder); + return gdk_content_formats_builder_free_to_formats (builder); } static gboolean @@ -510,12 +510,22 @@ gdk_content_formats_get_mime_types (GdkContentFormats *formats, struct _GdkContentFormatsBuilder { + int ref_count; + + /* (element-type GType) */ GSList *gtypes; gsize n_gtypes; + + /* (element-type utf8) (interned) */ GSList *mime_types; gsize n_mime_types; }; +G_DEFINE_BOXED_TYPE (GdkContentFormatsBuilder, + gdk_content_formats_builder, + gdk_content_formats_builder_ref, + gdk_content_formats_builder_unref) + /** * gdk_content_formats_builder_new: * @@ -528,19 +538,106 @@ struct _GdkContentFormatsBuilder GdkContentFormatsBuilder * gdk_content_formats_builder_new (void) { - return g_slice_new0 (GdkContentFormatsBuilder); + GdkContentFormatsBuilder *builder; + + builder = g_slice_new0 (GdkContentFormatsBuilder); + builder->ref_count = 1; + + return builder; } /** - * gdk_content_formats_builder_free: + * gdk_content_formats_builder_ref: * @builder: a #GdkContentFormatsBuilder * - * Frees @builder and creates a new #GdkContentFormats from it. + * Acquires a reference on the given @builder. * - * Returns: a new #GdkContentFormats with all the formats added to @builder - **/ + * This function is intended primarily for bindings. #GdkContentFormatsBuilder objects + * should not be kept around. + * + * Returns: (transfer none): the given #GdkContentFormatsBuilder with + * its reference count increased + */ +GdkContentFormatsBuilder * +gdk_content_formats_builder_ref (GdkContentFormatsBuilder *builder) +{ + g_return_val_if_fail (builder != NULL, NULL); + g_return_val_if_fail (builder->ref_count > 0, NULL); + + builder->ref_count += 1; + + return builder; +} + +static void +gdk_content_formats_builder_clear (GdkContentFormatsBuilder *builder) +{ + g_clear_pointer (&builder->gtypes, g_slist_free); + g_clear_pointer (&builder->mime_types, g_slist_free); +} + +/** + * gdk_content_formats_builder_unref: + * @builder: a #GdkContentFormatsBuilder + * + * Releases a reference on the given @builder. + */ +void +gdk_content_formats_builder_unref (GdkContentFormatsBuilder *builder) +{ + g_return_if_fail (builder != NULL); + g_return_if_fail (builder->ref_count > 0); + + builder->ref_count -= 1; + + if (builder->ref_count > 0) + return; + + gdk_content_formats_builder_clear (builder); + g_slice_free (GdkContentFormatsBuilder, builder); +} + +/** + * gdk_content_formats_builder_free_to_formats: (skip) + * @builder: a #GdkContentFormatsBuilder + * + * Creates a new #GdkContentFormats from the current state of the + * given @builder, and frees the @builder instance. + * + * Returns: (transfer full): the newly created #GdkContentFormats + * with all the formats added to @builder + */ +GdkContentFormats * +gdk_content_formats_builder_free_to_formats (GdkContentFormatsBuilder *builder) +{ + GdkContentFormats *res; + + g_return_val_if_fail (builder != NULL, NULL); + + res = gdk_content_formats_builder_to_formats (builder); + + gdk_content_formats_builder_unref (builder); + + return res; +} + +/** + * gdk_content_formats_builder_to_formats: + * @builder: a #GdkContentFormatsBuilder + * + * Creates a new #GdkContentFormats from the given @builder. + * + * The given #GdkContentFormatsBuilder is reset once this function returns; + * you cannot call this function multiple times on the same @builder instance. + * + * This function is intended primarily for bindings. C code should use + * gdk_content_formats_builder_free_to_formats(). + * + * Returns: (transfer full): the newly created #GdkContentFormats + * with all the formats added to @builder + */ GdkContentFormats * -gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder) +gdk_content_formats_builder_to_formats (GdkContentFormatsBuilder *builder) { GdkContentFormats *result; GType *gtypes; @@ -567,9 +664,7 @@ gdk_content_formats_builder_free (GdkContentFormatsBuilder *builder) result = gdk_content_formats_new_take (gtypes, builder->n_gtypes, mime_types, builder->n_mime_types); - g_slist_free (builder->gtypes); - g_slist_free (builder->mime_types); - g_slice_free (GdkContentFormatsBuilder, builder); + gdk_content_formats_builder_clear (builder); return result; } |