mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-12 07:26:15 +01:00
Adds g_list_copy_deep and g_slist_copy_deep
They make a full (deep) copy of a list. In contrast with g_[s]list_copy(), these functions take a function as a argument to make a copy of each list element, in addition to copying the list container itself. The functions g_[s]list_copy() were reimplemented to just call the new functions with NULL as the function argument, which will behave like current implementation. https://bugzilla.gnome.org/show_bug.cgi?id=675024
This commit is contained in:
parent
e0f4b2b03b
commit
2fd6eb7e1c
@ -2051,6 +2051,7 @@ g_list_free1
|
||||
<SUBSECTION>
|
||||
g_list_length
|
||||
g_list_copy
|
||||
g_list_copy_deep
|
||||
g_list_reverse
|
||||
g_list_sort
|
||||
GCompareFunc
|
||||
@ -2101,6 +2102,7 @@ g_slist_free1
|
||||
<SUBSECTION>
|
||||
g_slist_length
|
||||
g_slist_copy
|
||||
g_slist_copy_deep
|
||||
g_slist_reverse
|
||||
g_slist_insert_sorted_with_data
|
||||
g_slist_sort
|
||||
|
@ -551,6 +551,7 @@ g_list_alloc
|
||||
g_list_append
|
||||
g_list_concat
|
||||
g_list_copy
|
||||
g_list_copy_deep
|
||||
g_list_delete_link
|
||||
g_list_find
|
||||
g_list_find_custom
|
||||
@ -942,6 +943,7 @@ g_slist_alloc
|
||||
g_slist_append
|
||||
g_slist_concat
|
||||
g_slist_copy
|
||||
g_slist_copy_deep
|
||||
g_slist_delete_link
|
||||
g_slist_find
|
||||
g_slist_find_custom
|
||||
|
48
glib/glist.c
48
glib/glist.c
@ -566,13 +566,49 @@ g_list_delete_link (GList *list,
|
||||
* <note><para>
|
||||
* Note that this is a "shallow" copy. If the list elements
|
||||
* consist of pointers to data, the pointers are copied but
|
||||
* the actual data is not.
|
||||
* the actual data is not. See g_list_copy_deep() if you need
|
||||
* to copy the data as well.
|
||||
* </para></note>
|
||||
*
|
||||
* Returns: a copy of @list
|
||||
*/
|
||||
GList*
|
||||
g_list_copy (GList *list)
|
||||
{
|
||||
return g_list_copy_deep (list, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_list_copy_deep:
|
||||
* @list: a #GList
|
||||
* @func: a copy function used to copy every element in the list
|
||||
* @user_data: user data passed to the copy function @func, or #NULL
|
||||
*
|
||||
* Makes a full (deep) copy of a #GList.
|
||||
*
|
||||
* In contrast with g_list_copy(), this function uses @func to make a copy of
|
||||
* each list element, in addition to copying the list container itself.
|
||||
*
|
||||
* @func, as a #GCopyFunc, takes two arguments, the data to be copied and a user
|
||||
* pointer. It's safe to pass #NULL as user_data, if the copy function takes only
|
||||
* one argument.
|
||||
*
|
||||
* For instance, if @list holds a list of GObjects, you can do:
|
||||
* |[
|
||||
* another_list = g_list_copy_deep (list, (GCopyFunc) g_object_ref, NULL);
|
||||
* ]|
|
||||
*
|
||||
* And, to entirely free the new list, you could do:
|
||||
* |[
|
||||
* g_list_free_full (another_list, g_object_unref);
|
||||
* ]|
|
||||
*
|
||||
* Returns: a full copy of @list, use #g_list_free_full to free it
|
||||
*
|
||||
* Since: 2.34
|
||||
*/
|
||||
GList*
|
||||
g_list_copy_deep (GList *list, GCopyFunc func, gpointer user_data)
|
||||
{
|
||||
GList *new_list = NULL;
|
||||
|
||||
@ -581,7 +617,10 @@ g_list_copy (GList *list)
|
||||
GList *last;
|
||||
|
||||
new_list = _g_list_alloc ();
|
||||
new_list->data = list->data;
|
||||
if (func)
|
||||
new_list->data = func (list->data, user_data);
|
||||
else
|
||||
new_list->data = list->data;
|
||||
new_list->prev = NULL;
|
||||
last = new_list;
|
||||
list = list->next;
|
||||
@ -590,7 +629,10 @@ g_list_copy (GList *list)
|
||||
last->next = _g_list_alloc ();
|
||||
last->next->prev = last;
|
||||
last = last->next;
|
||||
last->data = list->data;
|
||||
if (func)
|
||||
last->data = func (list->data, user_data);
|
||||
else
|
||||
last->data = list->data;
|
||||
list = list->next;
|
||||
}
|
||||
last->next = NULL;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define __G_LIST_H__
|
||||
|
||||
#include <glib/gmem.h>
|
||||
#include <glib/gnode.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -81,6 +82,12 @@ GList* g_list_delete_link (GList *list,
|
||||
GList *link_) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GList* g_list_reverse (GList *list) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GList* g_list_copy (GList *list) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
GList* g_list_copy_deep (GList *list,
|
||||
GCopyFunc func,
|
||||
gpointer user_data) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GList* g_list_nth (GList *list,
|
||||
guint n);
|
||||
GList* g_list_nth_prev (GList *list,
|
||||
|
@ -554,13 +554,49 @@ g_slist_delete_link (GSList *list,
|
||||
* <note><para>
|
||||
* Note that this is a "shallow" copy. If the list elements
|
||||
* consist of pointers to data, the pointers are copied but
|
||||
* the actual data isn't.
|
||||
* the actual data isn't. See g_slist_copy_deep() if you need
|
||||
* to copy the data as well.
|
||||
* </para></note>
|
||||
*
|
||||
* Returns: a copy of @list
|
||||
*/
|
||||
GSList*
|
||||
g_slist_copy (GSList *list)
|
||||
{
|
||||
return g_slist_copy_deep (list, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* g_slist_copy_deep:
|
||||
* @list: a #GSList
|
||||
* @func: a copy function used to copy every element in the list
|
||||
* @user_data: user data passed to the copy function @func, or #NULL
|
||||
*
|
||||
* Makes a full (deep) copy of a #GSList.
|
||||
*
|
||||
* In contrast with g_slist_copy(), this function uses @func to make a copy of
|
||||
* each list element, in addition to copying the list container itself.
|
||||
*
|
||||
* @func, as a #GCopyFunc, takes two arguments, the data to be copied and a user
|
||||
* pointer. It's safe to pass #NULL as user_data, if the copy function takes only
|
||||
* one argument.
|
||||
*
|
||||
* For instance, if @list holds a list of GObjects, you can do:
|
||||
* |[
|
||||
* another_list = g_slist_copy_deep (list, (GCopyFunc) g_object_ref, NULL);
|
||||
* ]|
|
||||
*
|
||||
* And, to entirely free the new list, you could do:
|
||||
* |[
|
||||
* g_slist_free_full (another_list, g_object_unref);
|
||||
* ]|
|
||||
*
|
||||
* Returns: a full copy of @list, use #g_slist_free_full to free it
|
||||
*
|
||||
* Since: 2.34
|
||||
*/
|
||||
GSList*
|
||||
g_slist_copy_deep (GSList *list, GCopyFunc func, gpointer user_data)
|
||||
{
|
||||
GSList *new_list = NULL;
|
||||
|
||||
@ -569,14 +605,20 @@ g_slist_copy (GSList *list)
|
||||
GSList *last;
|
||||
|
||||
new_list = _g_slist_alloc ();
|
||||
new_list->data = list->data;
|
||||
if (func)
|
||||
new_list->data = func (list->data, user_data);
|
||||
else
|
||||
new_list->data = list->data;
|
||||
last = new_list;
|
||||
list = list->next;
|
||||
while (list)
|
||||
{
|
||||
last->next = _g_slist_alloc ();
|
||||
last = last->next;
|
||||
last->data = list->data;
|
||||
if (func)
|
||||
last->data = func (list->data, user_data);
|
||||
else
|
||||
last->data = list->data;
|
||||
list = list->next;
|
||||
}
|
||||
last->next = NULL;
|
||||
|
@ -32,6 +32,7 @@
|
||||
#define __G_SLIST_H__
|
||||
|
||||
#include <glib/gmem.h>
|
||||
#include <glib/gnode.h>
|
||||
|
||||
G_BEGIN_DECLS
|
||||
|
||||
@ -80,6 +81,11 @@ GSList* g_slist_delete_link (GSList *list,
|
||||
GSList *link_) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GSList* g_slist_reverse (GSList *list) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GSList* g_slist_copy (GSList *list) G_GNUC_WARN_UNUSED_RESULT;
|
||||
|
||||
GLIB_AVAILABLE_IN_2_34
|
||||
GSList* g_slist_copy_deep (GSList *list,
|
||||
GCopyFunc func,
|
||||
gpointer user_data) G_GNUC_WARN_UNUSED_RESULT;
|
||||
GSList* g_slist_nth (GSList *list,
|
||||
guint n);
|
||||
GSList* g_slist_find (GSList *list,
|
||||
|
@ -388,6 +388,34 @@ test_list_copy (void)
|
||||
g_list_free (l2);
|
||||
}
|
||||
|
||||
static gpointer
|
||||
multiply_value (gconstpointer value, gpointer data)
|
||||
{
|
||||
return GINT_TO_POINTER (GPOINTER_TO_INT (value) * GPOINTER_TO_INT (data));
|
||||
}
|
||||
|
||||
static void
|
||||
test_list_copy_deep (void)
|
||||
{
|
||||
GList *l, *l2;
|
||||
GList *u, *v;
|
||||
|
||||
l = NULL;
|
||||
l = g_list_append (l, GINT_TO_POINTER (1));
|
||||
l = g_list_append (l, GINT_TO_POINTER (2));
|
||||
l = g_list_append (l, GINT_TO_POINTER (3));
|
||||
|
||||
l2 = g_list_copy_deep (l, multiply_value, GINT_TO_POINTER (2));
|
||||
|
||||
for (u = l, v = l2; u && v; u = u->next, v = v->next)
|
||||
{
|
||||
g_assert_cmpint (GPOINTER_TO_INT (u->data) * 2, ==, GPOINTER_TO_INT (v->data));
|
||||
}
|
||||
|
||||
g_list_free (l);
|
||||
g_list_free (l2);
|
||||
}
|
||||
|
||||
static void
|
||||
test_delete_link (void)
|
||||
{
|
||||
@ -484,6 +512,7 @@ main (int argc, char *argv[])
|
||||
g_test_add_func ("/list/insert", test_list_insert);
|
||||
g_test_add_func ("/list/free-full", test_free_full);
|
||||
g_test_add_func ("/list/copy", test_list_copy);
|
||||
g_test_add_func ("/list/copy-deep", test_list_copy_deep);
|
||||
g_test_add_func ("/list/delete-link", test_delete_link);
|
||||
g_test_add_func ("/list/prepend", test_prepend);
|
||||
g_test_add_func ("/list/position", test_position);
|
||||
|
Loading…
Reference in New Issue
Block a user