mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2024-12-24 22:46:15 +01:00
list, slist: Add g_clear_{s,}list()
Although not quite as often-occurring, this should help with constructs like this: if (list) { g_list_free_full (list, foo); list = NULL; } Closes https://gitlab.gnome.org/GNOME/glib/issues/1943
This commit is contained in:
parent
8555aeec8d
commit
58ba7d78fb
@ -2503,6 +2503,7 @@ g_list_delete_link
|
||||
g_list_remove_all
|
||||
g_list_free
|
||||
g_list_free_full
|
||||
g_clear_list
|
||||
|
||||
<SUBSECTION>
|
||||
g_list_alloc
|
||||
@ -2559,6 +2560,7 @@ g_slist_free
|
||||
g_slist_free_full
|
||||
g_slist_free_1
|
||||
g_slist_free1
|
||||
g_clear_slist
|
||||
|
||||
<SUBSECTION>
|
||||
g_slist_length
|
||||
|
29
glib/glist.c
29
glib/glist.c
@ -1313,3 +1313,32 @@ g_list_sort_with_data (GList *list,
|
||||
{
|
||||
return g_list_sort_real (list, (GFunc) compare_func, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_clear_list: (skip)
|
||||
* @list_ptr: (not nullable): a #GList return location
|
||||
* @destroy: (nullable): the function to pass to g_list_free_full() or %NULL to not free elements
|
||||
*
|
||||
* Clears a pointer to a #GList, freeing it and, optionally, freeing its elements using @destroy.
|
||||
*
|
||||
* @list_ptr must be a valid pointer. If @list_ptr points to a null #GList, this does nothing.
|
||||
*
|
||||
* Since: 2.64
|
||||
*/
|
||||
void
|
||||
(g_clear_list) (GList **list_ptr,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GList *list;
|
||||
|
||||
list = *list_ptr;
|
||||
if (list)
|
||||
{
|
||||
*list_ptr = NULL;
|
||||
|
||||
if (destroy)
|
||||
g_list_free_full (list, destroy);
|
||||
else
|
||||
g_list_free (list);
|
||||
}
|
||||
}
|
||||
|
21
glib/glist.h
21
glib/glist.h
@ -147,6 +147,27 @@ GLIB_AVAILABLE_IN_ALL
|
||||
gpointer g_list_nth_data (GList *list,
|
||||
guint n);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_64
|
||||
void g_clear_list (GList **list_ptr,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
#define g_clear_list(list_ptr, destroy) \
|
||||
G_STMT_START { \
|
||||
GList *_list; \
|
||||
\
|
||||
_list = *(list_ptr); \
|
||||
if (_list) \
|
||||
{ \
|
||||
*list_ptr = NULL; \
|
||||
\
|
||||
if ((destroy) != NULL) \
|
||||
g_list_free_full (_list, (destroy)); \
|
||||
else \
|
||||
g_list_free (_list); \
|
||||
} \
|
||||
} G_STMT_END \
|
||||
GLIB_AVAILABLE_MACRO_IN_2_64
|
||||
|
||||
|
||||
#define g_list_previous(list) ((list) ? (((GList *)(list))->prev) : NULL)
|
||||
#define g_list_next(list) ((list) ? (((GList *)(list))->next) : NULL)
|
||||
|
@ -1065,3 +1065,32 @@ g_slist_sort_with_data (GSList *list,
|
||||
{
|
||||
return g_slist_sort_real (list, (GFunc) compare_func, user_data);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_clear_slist: (skip)
|
||||
* @slist_ptr: (not nullable): a #GSList return location
|
||||
* @destroy: (nullable): the function to pass to g_slist_free_full() or %NULL to not free elements
|
||||
*
|
||||
* Clears a pointer to a #GSList, freeing it and, optionally, freeing its elements using @destroy.
|
||||
*
|
||||
* @slist_ptr must be a valid pointer. If @slist_ptr points to a null #GSList, this does nothing.
|
||||
*
|
||||
* Since: 2.64
|
||||
*/
|
||||
void
|
||||
(g_clear_slist) (GSList **slist_ptr,
|
||||
GDestroyNotify destroy)
|
||||
{
|
||||
GSList *slist;
|
||||
|
||||
slist = *slist_ptr;
|
||||
if (slist)
|
||||
{
|
||||
*slist_ptr = NULL;
|
||||
|
||||
if (destroy)
|
||||
g_slist_free_full (slist, destroy);
|
||||
else
|
||||
g_slist_free (slist);
|
||||
}
|
||||
}
|
||||
|
@ -136,6 +136,27 @@ GLIB_AVAILABLE_IN_ALL
|
||||
gpointer g_slist_nth_data (GSList *list,
|
||||
guint n);
|
||||
|
||||
GLIB_AVAILABLE_IN_2_64
|
||||
void g_clear_slist (GSList **slist_ptr,
|
||||
GDestroyNotify destroy);
|
||||
|
||||
#define g_clear_slist(slist_ptr, destroy) \
|
||||
G_STMT_START { \
|
||||
GSList *_slist; \
|
||||
\
|
||||
_slist = *(slist_ptr); \
|
||||
if (_slist) \
|
||||
{ \
|
||||
*slist_ptr = NULL; \
|
||||
\
|
||||
if ((destroy) != NULL) \
|
||||
g_slist_free_full (_slist, (destroy)); \
|
||||
else \
|
||||
g_slist_free (_slist); \
|
||||
} \
|
||||
} G_STMT_END \
|
||||
GLIB_AVAILABLE_MACRO_IN_2_64
|
||||
|
||||
#define g_slist_next(slist) ((slist) ? (((GSList *)(slist))->next) : NULL)
|
||||
|
||||
G_END_DECLS
|
||||
|
@ -760,6 +760,54 @@ test_int_limits (void)
|
||||
g_free (str);
|
||||
}
|
||||
|
||||
static void
|
||||
test_clear_list (void)
|
||||
{
|
||||
GList *list = NULL;
|
||||
|
||||
g_clear_list (&list, NULL);
|
||||
g_assert_null (list);
|
||||
|
||||
list = g_list_prepend (list, "test");
|
||||
g_assert_nonnull (list);
|
||||
|
||||
g_clear_list (&list, NULL);
|
||||
g_assert_null (list);
|
||||
|
||||
g_clear_list (&list, g_free);
|
||||
g_assert_null (list);
|
||||
|
||||
list = g_list_prepend (list, g_malloc (16));
|
||||
g_assert_nonnull (list);
|
||||
|
||||
g_clear_list (&list, g_free);
|
||||
g_assert_null (list);
|
||||
}
|
||||
|
||||
static void
|
||||
test_clear_slist (void)
|
||||
{
|
||||
GSList *slist = NULL;
|
||||
|
||||
g_clear_slist (&slist, NULL);
|
||||
g_assert_null (slist);
|
||||
|
||||
slist = g_slist_prepend (slist, "test");
|
||||
g_assert_nonnull (slist);
|
||||
|
||||
g_clear_slist (&slist, NULL);
|
||||
g_assert_null (slist);
|
||||
|
||||
g_clear_slist (&slist, g_free);
|
||||
g_assert_null (slist);
|
||||
|
||||
slist = g_slist_prepend (slist, g_malloc (16));
|
||||
g_assert_nonnull (slist);
|
||||
|
||||
g_clear_slist (&slist, g_free);
|
||||
g_assert_null (slist);
|
||||
}
|
||||
|
||||
int
|
||||
main (int argc,
|
||||
char *argv[])
|
||||
@ -814,6 +862,8 @@ main (int argc,
|
||||
g_test_add_func ("/utils/atexit", test_atexit);
|
||||
g_test_add_func ("/utils/check-setuid", test_check_setuid);
|
||||
g_test_add_func ("/utils/int-limits", test_int_limits);
|
||||
g_test_add_func ("/utils/clear-list", test_clear_list);
|
||||
g_test_add_func ("/utils/clear-slist", test_clear_slist);
|
||||
|
||||
return g_test_run ();
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user