From 43df97ab86187a56495c8c00abb6130b7e379c8c Mon Sep 17 00:00:00 2001 From: Bastien Nocera Date: Thu, 22 Jan 2015 14:44:47 +0100 Subject: [PATCH] goption: Add boxed type for GOptionGroup This would allow bindings to use _get_option_group() functions, which would then allow them to use GOption parsing. This also adds introspection annotations to g_option_context_add_group(), g_option_context_set_main_group() and g_option_context_get_main_group(). https://bugzilla.gnome.org/show_bug.cgi?id=743349 --- glib/goption.c | 85 ++++++++++++++++++++++++++++++++++++++-------------- glib/goption.h | 6 +++- gobject/gboxed.c | 2 ++ gobject/glib-types.h | 11 +++++++ 4 files changed, 81 insertions(+), 23 deletions(-) diff --git a/glib/goption.c b/glib/goption.c index 10bbafd..7d59eee 100644 --- a/glib/goption.c +++ b/glib/goption.c @@ -267,6 +267,8 @@ struct _GOptionGroup gchar *description; gchar *help_description; + gint ref_count; + GDestroyNotify destroy_notify; gpointer user_data; @@ -382,10 +384,10 @@ void g_option_context_free (GOptionContext *context) { g_return_if_fail (context != NULL); - g_list_free_full (context->groups, (GDestroyNotify) g_option_group_free); + g_list_free_full (context->groups, (GDestroyNotify) g_option_group_unref); if (context->main_group) - g_option_group_free (context->main_group); + g_option_group_unref (context->main_group); free_changes_list (context, FALSE); free_pending_nulls (context, FALSE); @@ -549,13 +551,11 @@ g_option_context_get_strict_posix (GOptionContext *context) /** * g_option_context_add_group: * @context: a #GOptionContext - * @group: the group to add + * @group: (transfer full): the group to add * * Adds a #GOptionGroup to the @context, so that parsing with @context - * will recognize the options in the group. Note that the group will - * be freed together with the context when g_option_context_free() is - * called, so you must not free the group yourself after adding it - * to a context. + * will recognize the options in the group. Note that this will take + * ownership of the @group and thus the @group should not be freed. * * Since: 2.6 **/ @@ -587,7 +587,7 @@ g_option_context_add_group (GOptionContext *context, /** * g_option_context_set_main_group: * @context: a #GOptionContext - * @group: the group to set as main group + * @group: (transfer full): the group to set as main group * * Sets a #GOptionGroup as main group of the @context. * This has the same effect as calling g_option_context_add_group(), @@ -619,9 +619,9 @@ g_option_context_set_main_group (GOptionContext *context, * * Returns a pointer to the main group of @context. * - * Returns: the main group of @context, or %NULL if @context doesn't - * have a main group. Note that group belongs to @context and should - * not be modified or freed. + * Returns: (transfer none): the main group of @context, or %NULL if + * @context doesn't have a main group. Note that group belongs to + * @context and should not be modified or freed. * * Since: 2.6 **/ @@ -2232,7 +2232,7 @@ g_option_context_parse (GOptionContext *context, * Creates a new #GOptionGroup. * * Returns: a newly created option group. It should be added - * to a #GOptionContext or freed with g_option_group_free(). + * to a #GOptionContext or freed with g_option_group_unref(). * * Since: 2.6 **/ @@ -2247,6 +2247,7 @@ g_option_group_new (const gchar *name, GOptionGroup *group; group = g_new0 (GOptionGroup, 1); + group->ref_count = 1; group->name = g_strdup (name); group->description = g_strdup (description); group->help_description = g_strdup (help_description); @@ -2265,28 +2266,68 @@ g_option_group_new (const gchar *name, * which have been added to a #GOptionContext. * * Since: 2.6 + * + * Deprecated: 2.44: Use g_option_group_unref() instead. */ void g_option_group_free (GOptionGroup *group) { + g_option_group_unref (group); +} + +/** + * g_option_group_ref: + * @group: a #GOptionGroup + * + * Increments the reference count of @group by one. + * + * Returns: a #GoptionGroup + * + * Since: 2.44 + */ +GOptionGroup * +g_option_group_ref (GOptionGroup *group) +{ + g_return_val_if_fail (group != NULL, NULL); + + group->ref_count++; + + return group; +} + +/** + * g_option_group_unref: + * @group: a #GOptionGroup + * + * Decrements the reference count of @group by one. + * If the reference count drops to 0, the @group will be freed. + * and all memory allocated by the @group is released. + * + * Since: 2.44 + */ +void +g_option_group_unref (GOptionGroup *group) +{ g_return_if_fail (group != NULL); - g_free (group->name); - g_free (group->description); - g_free (group->help_description); + if (--group->ref_count == 0) + { + g_free (group->name); + g_free (group->description); + g_free (group->help_description); - g_free (group->entries); + g_free (group->entries); - if (group->destroy_notify) - (* group->destroy_notify) (group->user_data); + if (group->destroy_notify) + (* group->destroy_notify) (group->user_data); - if (group->translate_notify) - (* group->translate_notify) (group->translate_data); + if (group->translate_notify) + (* group->translate_notify) (group->translate_data); - g_free (group); + g_free (group); + } } - /** * g_option_group_add_entries: * @group: a #GOptionGroup diff --git a/glib/goption.h b/glib/goption.h index 205a484..8f3a92c 100644 --- a/glib/goption.h +++ b/glib/goption.h @@ -364,8 +364,12 @@ void g_option_group_set_parse_hooks (GOptionGroup *group, GLIB_AVAILABLE_IN_ALL void g_option_group_set_error_hook (GOptionGroup *group, GOptionErrorFunc error_func); -GLIB_AVAILABLE_IN_ALL +GLIB_DEPRECATED_IN_2_44 void g_option_group_free (GOptionGroup *group); +GLIB_AVAILABLE_IN_2_44 +GOptionGroup *g_option_group_ref (GOptionGroup *group); +GLIB_AVAILABLE_IN_2_44 +void g_option_group_unref (GOptionGroup *group); GLIB_AVAILABLE_IN_ALL void g_option_group_add_entries (GOptionGroup *group, const GOptionEntry *entries); diff --git a/gobject/gboxed.c b/gobject/gboxed.c index ca7f66c..54f658e 100644 --- a/gobject/gboxed.c +++ b/gobject/gboxed.c @@ -165,6 +165,8 @@ G_DEFINE_BOXED_TYPE (GMarkupParseContext, g_markup_parse_context, g_markup_parse G_DEFINE_BOXED_TYPE (GThread, g_thread, g_thread_ref, g_thread_unref) G_DEFINE_BOXED_TYPE (GChecksum, g_checksum, g_checksum_copy, g_checksum_free) +G_DEFINE_BOXED_TYPE (GOptionGroup, g_option_group, g_option_group_ref, g_option_group_unref) + /* This one can't use G_DEFINE_BOXED_TYPE (GStrv, g_strv, g_strdupv, g_strfreev) */ GType g_strv_get_type (void) diff --git a/gobject/glib-types.h b/gobject/glib-types.h index e9f6472..ac222b8 100644 --- a/gobject/glib-types.h +++ b/gobject/glib-types.h @@ -288,6 +288,15 @@ typedef gsize GType; */ #define G_TYPE_CHECKSUM (g_checksum_get_type ()) +/** + * G_TYPE_OPTION_GROUP: + * + * The #GType for a boxed type holding a #GOptionGroup. + * + * Since: 2.44 + */ +#define G_TYPE_OPTION_GROUP (g_option_group_get_type ()) + GLIB_AVAILABLE_IN_ALL GType g_date_get_type (void) G_GNUC_CONST; GLIB_AVAILABLE_IN_ALL @@ -342,6 +351,8 @@ GLIB_AVAILABLE_IN_2_36 GType g_markup_parse_context_get_type (void) G_GNUC_CONST; GLIB_AVAILABLE_IN_2_40 GType g_mapped_file_get_type (void) G_GNUC_CONST; +GLIB_AVAILABLE_IN_2_44 +GType g_option_group_get_type (void) G_GNUC_CONST; GLIB_DEPRECATED_FOR('G_TYPE_VARIANT') GType g_variant_get_gtype (void) G_GNUC_CONST; -- 2.7.4