mirror of
https://gitlab.gnome.org/GNOME/glib.git
synced 2025-01-26 05:56:14 +01: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:
parent
030b3f25e3
commit
c602a5f887
@ -2354,6 +2354,7 @@ g_array_sort
|
||||
g_array_sort_with_data
|
||||
g_array_index
|
||||
g_array_set_size
|
||||
g_array_set_clear_func
|
||||
g_array_free
|
||||
</SECTION>
|
||||
|
||||
|
@ -110,6 +110,7 @@ struct _GRealArray
|
||||
guint zero_terminated : 1;
|
||||
guint clear : 1;
|
||||
gint ref_count;
|
||||
GDestroyNotify clear_func;
|
||||
};
|
||||
|
||||
/**
|
||||
@ -210,6 +211,34 @@ GArray* g_array_sized_new (gboolean zero_terminated,
|
||||
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:
|
||||
* @array: A #GArray.
|
||||
@ -325,6 +354,14 @@ array_free (GRealArray *array,
|
||||
|
||||
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);
|
||||
segment = NULL;
|
||||
}
|
||||
@ -514,8 +551,8 @@ g_array_set_size (GArray *farray,
|
||||
if (array->clear)
|
||||
g_array_elt_zero (array, array->len, length - array->len);
|
||||
}
|
||||
else if (G_UNLIKELY (g_mem_gc_friendly) && length < array->len)
|
||||
g_array_elt_zero (array, length, array->len - length);
|
||||
else if (length < array->len)
|
||||
g_array_remove_range (farray, 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);
|
||||
|
||||
if (array->clear_func != NULL)
|
||||
array->clear_func (g_array_elt_pos (array, index_));
|
||||
|
||||
if (index_ != array->len - 1)
|
||||
g_memmove (g_array_elt_pos (array, index_),
|
||||
g_array_elt_pos (array, index_ + 1),
|
||||
g_array_elt_len (array, array->len - index_ - 1));
|
||||
|
||||
g_array_elt_pos (array, index_ + 1),
|
||||
g_array_elt_len (array, array->len - index_ - 1));
|
||||
|
||||
array->len -= 1;
|
||||
|
||||
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);
|
||||
|
||||
if (array->clear_func != NULL)
|
||||
array->clear_func (g_array_elt_pos (array, index_));
|
||||
|
||||
if (index_ != array->len - 1)
|
||||
memcpy (g_array_elt_pos (array, index_),
|
||||
g_array_elt_pos (array, array->len - 1),
|
||||
g_array_elt_len (array, 1));
|
||||
memcpy (g_array_elt_pos (array, index_),
|
||||
g_array_elt_pos (array, array->len - 1),
|
||||
g_array_elt_len (array, 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_ + 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)
|
||||
g_memmove (g_array_elt_pos (array, index_),
|
||||
g_array_elt_pos (array, index_ + length),
|
||||
g_memmove (g_array_elt_pos (array, index_),
|
||||
g_array_elt_pos (array, index_ + length),
|
||||
(array->len - (index_ + length)) * array->elt_size);
|
||||
|
||||
array->len -= length;
|
||||
|
@ -104,6 +104,8 @@ void g_array_sort (GArray *array,
|
||||
void g_array_sort_with_data (GArray *array,
|
||||
GCompareDataFunc compare_func,
|
||||
gpointer user_data);
|
||||
void g_array_set_clear_func (GArray *array,
|
||||
GDestroyNotify clear_func);
|
||||
|
||||
/* Resizable pointer array. This interface is much less complicated
|
||||
* 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_fast
|
||||
g_array_remove_range
|
||||
g_array_set_clear_func
|
||||
g_array_set_size
|
||||
g_array_sized_new
|
||||
g_array_sort
|
||||
|
@ -304,6 +304,43 @@ array_sort_with_data (void)
|
||||
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
|
||||
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/sort", array_sort);
|
||||
g_test_add_func ("/array/sort-with-data", array_sort_with_data);
|
||||
g_test_add_func ("/array/clear-func", array_clear_func);
|
||||
|
||||
/* pointer arrays */
|
||||
g_test_add_func ("/pointerarray/add", pointer_array_add);
|
||||
|
Loading…
Reference in New Issue
Block a user