mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-08-10 03:04:05 +02:00
array: Add a clear function
Like GPtrArray has a "free function" that can be used to free memory associated to each pointer in the array, GArray would benefit from having a "clear function" that can be used to clear the content of each element of the array when it's removed, or when the entire array is freed. https://bugzilla.gnome.org/show_bug.cgi?id=667243
This commit is contained in:
committed by
Matthias Clasen
parent
030b3f25e3
commit
c602a5f887
@@ -2354,6 +2354,7 @@ g_array_sort
|
|||||||
g_array_sort_with_data
|
g_array_sort_with_data
|
||||||
g_array_index
|
g_array_index
|
||||||
g_array_set_size
|
g_array_set_size
|
||||||
|
g_array_set_clear_func
|
||||||
g_array_free
|
g_array_free
|
||||||
</SECTION>
|
</SECTION>
|
||||||
|
|
||||||
|
@@ -110,6 +110,7 @@ struct _GRealArray
|
|||||||
guint zero_terminated : 1;
|
guint zero_terminated : 1;
|
||||||
guint clear : 1;
|
guint clear : 1;
|
||||||
gint ref_count;
|
gint ref_count;
|
||||||
|
GDestroyNotify clear_func;
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -210,6 +211,34 @@ GArray* g_array_sized_new (gboolean zero_terminated,
|
|||||||
return (GArray*) array;
|
return (GArray*) array;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* g_array_set_clear_func:
|
||||||
|
* @array: A #GArray
|
||||||
|
* @clear_func: a function to clear an element of @array
|
||||||
|
*
|
||||||
|
* Sets a function to clear an element of @array.
|
||||||
|
*
|
||||||
|
* The @clear_func will be called when an element in the array
|
||||||
|
* data segment is removed and when the array is freed and data
|
||||||
|
* segment is deallocated as well.
|
||||||
|
*
|
||||||
|
* Note that in contrast with other uses of #GDestroyNotify
|
||||||
|
* functions, @clear_func is expected to clear the contents of
|
||||||
|
* the array element it is given, but not free the element itself.
|
||||||
|
*
|
||||||
|
* Since: 2.32
|
||||||
|
*/
|
||||||
|
void
|
||||||
|
g_array_set_clear_func (GArray *array,
|
||||||
|
GDestroyNotify clear_func)
|
||||||
|
{
|
||||||
|
GRealArray *rarray = (GRealArray *) array;
|
||||||
|
|
||||||
|
g_return_if_fail (array != NULL);
|
||||||
|
|
||||||
|
rarray->clear_func = clear_func;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* g_array_ref:
|
* g_array_ref:
|
||||||
* @array: A #GArray.
|
* @array: A #GArray.
|
||||||
@@ -325,6 +354,14 @@ array_free (GRealArray *array,
|
|||||||
|
|
||||||
if (flags & FREE_SEGMENT)
|
if (flags & FREE_SEGMENT)
|
||||||
{
|
{
|
||||||
|
if (array->clear_func != NULL)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < array->len; i++)
|
||||||
|
array->clear_func (g_array_elt_pos (array, i));
|
||||||
|
}
|
||||||
|
|
||||||
g_free (array->data);
|
g_free (array->data);
|
||||||
segment = NULL;
|
segment = NULL;
|
||||||
}
|
}
|
||||||
@@ -514,8 +551,8 @@ g_array_set_size (GArray *farray,
|
|||||||
if (array->clear)
|
if (array->clear)
|
||||||
g_array_elt_zero (array, array->len, length - array->len);
|
g_array_elt_zero (array, array->len, length - array->len);
|
||||||
}
|
}
|
||||||
else if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
|
else if (length < array->len)
|
||||||
g_array_elt_zero (array, length, array->len - length);
|
g_array_remove_range (farray, length, array->len - length);
|
||||||
|
|
||||||
array->len = length;
|
array->len = length;
|
||||||
|
|
||||||
@@ -543,11 +580,14 @@ g_array_remove_index (GArray *farray,
|
|||||||
|
|
||||||
g_return_val_if_fail (index_ < array->len, NULL);
|
g_return_val_if_fail (index_ < array->len, NULL);
|
||||||
|
|
||||||
|
if (array->clear_func != NULL)
|
||||||
|
array->clear_func (g_array_elt_pos (array, index_));
|
||||||
|
|
||||||
if (index_ != array->len - 1)
|
if (index_ != array->len - 1)
|
||||||
g_memmove (g_array_elt_pos (array, index_),
|
g_memmove (g_array_elt_pos (array, index_),
|
||||||
g_array_elt_pos (array, index_ + 1),
|
g_array_elt_pos (array, index_ + 1),
|
||||||
g_array_elt_len (array, array->len - index_ - 1));
|
g_array_elt_len (array, array->len - index_ - 1));
|
||||||
|
|
||||||
array->len -= 1;
|
array->len -= 1;
|
||||||
|
|
||||||
if (G_UNLIKELY (g_mem_gc_friendly))
|
if (G_UNLIKELY (g_mem_gc_friendly))
|
||||||
@@ -579,10 +619,13 @@ g_array_remove_index_fast (GArray *farray,
|
|||||||
|
|
||||||
g_return_val_if_fail (index_ < array->len, NULL);
|
g_return_val_if_fail (index_ < array->len, NULL);
|
||||||
|
|
||||||
|
if (array->clear_func != NULL)
|
||||||
|
array->clear_func (g_array_elt_pos (array, index_));
|
||||||
|
|
||||||
if (index_ != array->len - 1)
|
if (index_ != array->len - 1)
|
||||||
memcpy (g_array_elt_pos (array, index_),
|
memcpy (g_array_elt_pos (array, index_),
|
||||||
g_array_elt_pos (array, array->len - 1),
|
g_array_elt_pos (array, array->len - 1),
|
||||||
g_array_elt_len (array, 1));
|
g_array_elt_len (array, 1));
|
||||||
|
|
||||||
array->len -= 1;
|
array->len -= 1;
|
||||||
|
|
||||||
@@ -617,9 +660,17 @@ g_array_remove_range (GArray *farray,
|
|||||||
g_return_val_if_fail (index_ < array->len, NULL);
|
g_return_val_if_fail (index_ < array->len, NULL);
|
||||||
g_return_val_if_fail (index_ + length <= array->len, NULL);
|
g_return_val_if_fail (index_ + length <= array->len, NULL);
|
||||||
|
|
||||||
|
if (array->clear_func != NULL)
|
||||||
|
{
|
||||||
|
guint i;
|
||||||
|
|
||||||
|
for (i = 0; i < length; i++)
|
||||||
|
array->clear_func (g_array_elt_pos (array, index_ + i));
|
||||||
|
}
|
||||||
|
|
||||||
if (index_ + length != array->len)
|
if (index_ + length != array->len)
|
||||||
g_memmove (g_array_elt_pos (array, index_),
|
g_memmove (g_array_elt_pos (array, index_),
|
||||||
g_array_elt_pos (array, index_ + length),
|
g_array_elt_pos (array, index_ + length),
|
||||||
(array->len - (index_ + length)) * array->elt_size);
|
(array->len - (index_ + length)) * array->elt_size);
|
||||||
|
|
||||||
array->len -= length;
|
array->len -= length;
|
||||||
|
@@ -104,6 +104,8 @@ void g_array_sort (GArray *array,
|
|||||||
void g_array_sort_with_data (GArray *array,
|
void g_array_sort_with_data (GArray *array,
|
||||||
GCompareDataFunc compare_func,
|
GCompareDataFunc compare_func,
|
||||||
gpointer user_data);
|
gpointer user_data);
|
||||||
|
void g_array_set_clear_func (GArray *array,
|
||||||
|
GDestroyNotify clear_func);
|
||||||
|
|
||||||
/* Resizable pointer array. This interface is much less complicated
|
/* Resizable pointer array. This interface is much less complicated
|
||||||
* than the above. Add appends a pointer. Remove fills any cleared
|
* than the above. Add appends a pointer. Remove fills any cleared
|
||||||
|
@@ -12,6 +12,7 @@ g_array_prepend_vals
|
|||||||
g_array_remove_index
|
g_array_remove_index
|
||||||
g_array_remove_index_fast
|
g_array_remove_index_fast
|
||||||
g_array_remove_range
|
g_array_remove_range
|
||||||
|
g_array_set_clear_func
|
||||||
g_array_set_size
|
g_array_set_size
|
||||||
g_array_sized_new
|
g_array_sized_new
|
||||||
g_array_sort
|
g_array_sort
|
||||||
|
@@ -304,6 +304,43 @@ array_sort_with_data (void)
|
|||||||
g_array_free (garray, TRUE);
|
g_array_free (garray, TRUE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static gint num_clear_func_invocations = 0;
|
||||||
|
|
||||||
|
static void
|
||||||
|
my_clear_func (gpointer data)
|
||||||
|
{
|
||||||
|
num_clear_func_invocations += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
array_clear_func (void)
|
||||||
|
{
|
||||||
|
GArray *garray;
|
||||||
|
gint i;
|
||||||
|
gint cur;
|
||||||
|
|
||||||
|
garray = g_array_new (FALSE, FALSE, sizeof (gint));
|
||||||
|
g_array_set_clear_func (garray, my_clear_func);
|
||||||
|
|
||||||
|
for (i = 0; i < 10; i++)
|
||||||
|
{
|
||||||
|
cur = g_random_int_range (0, 100);
|
||||||
|
g_array_append_val (garray, cur);
|
||||||
|
}
|
||||||
|
|
||||||
|
g_array_remove_index (garray, 9);
|
||||||
|
g_assert_cmpint (num_clear_func_invocations, ==, 1);
|
||||||
|
|
||||||
|
g_array_remove_range (garray, 5, 3);
|
||||||
|
g_assert_cmpint (num_clear_func_invocations, ==, 4);
|
||||||
|
|
||||||
|
g_array_remove_index_fast (garray, 4);
|
||||||
|
g_assert_cmpint (num_clear_func_invocations, ==, 5);
|
||||||
|
|
||||||
|
g_array_free (garray, TRUE);
|
||||||
|
g_assert_cmpint (num_clear_func_invocations, ==, 10);
|
||||||
|
}
|
||||||
|
|
||||||
static void
|
static void
|
||||||
pointer_array_add (void)
|
pointer_array_add (void)
|
||||||
{
|
{
|
||||||
@@ -812,6 +849,7 @@ main (int argc, char *argv[])
|
|||||||
g_test_add_func ("/array/large-size", array_large_size);
|
g_test_add_func ("/array/large-size", array_large_size);
|
||||||
g_test_add_func ("/array/sort", array_sort);
|
g_test_add_func ("/array/sort", array_sort);
|
||||||
g_test_add_func ("/array/sort-with-data", array_sort_with_data);
|
g_test_add_func ("/array/sort-with-data", array_sort_with_data);
|
||||||
|
g_test_add_func ("/array/clear-func", array_clear_func);
|
||||||
|
|
||||||
/* pointer arrays */
|
/* pointer arrays */
|
||||||
g_test_add_func ("/pointerarray/add", pointer_array_add);
|
g_test_add_func ("/pointerarray/add", pointer_array_add);
|
||||||
|
Reference in New Issue
Block a user