[glib] array: Add a clear function
- From: Matthias Clasen <matthiasc src gnome org>
- To: commits-list gnome org
- Cc:
- Subject: [glib] array: Add a clear function
- Date: Wed, 25 Jan 2012 04:27:24 +0000 (UTC)
commit c602a5f887233bdd75544a290023d10029ca4fda
Author: Emmanuele Bassi <ebassi gnome org>
Date: Wed Jan 4 07:41:47 2012 +0000
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
docs/reference/glib/glib-sections.txt | 1 +
glib/garray.c | 71 ++++++++++++++++++++++++++++-----
glib/garray.h | 2 +
glib/glib.symbols | 1 +
glib/tests/array-test.c | 38 +++++++++++++++++
5 files changed, 103 insertions(+), 10 deletions(-)
---
diff --git a/docs/reference/glib/glib-sections.txt b/docs/reference/glib/glib-sections.txt
index b59ca76..45b2e91 100644
--- a/docs/reference/glib/glib-sections.txt
+++ b/docs/reference/glib/glib-sections.txt
@@ -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>
diff --git a/glib/garray.c b/glib/garray.c
index 5a5f9fa..5cd002a 100644
--- a/glib/garray.c
+++ b/glib/garray.c
@@ -110,6 +110,7 @@ struct _GRealArray
guint zero_terminated : 1;
guint clear : 1;
gint ref_count;
+ GDestroyNotify clear_func;
};
/**
@@ -211,6 +212,34 @@ GArray* g_array_sized_new (gboolean zero_terminated,
}
/**
+ * 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;
diff --git a/glib/garray.h b/glib/garray.h
index d96aade..eb37b92 100644
--- a/glib/garray.h
+++ b/glib/garray.h
@@ -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
diff --git a/glib/glib.symbols b/glib/glib.symbols
index 1b01bb4..d13420f 100644
--- a/glib/glib.symbols
+++ b/glib/glib.symbols
@@ -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
diff --git a/glib/tests/array-test.c b/glib/tests/array-test.c
index 7caab87..5f9ccd5 100644
--- a/glib/tests/array-test.c
+++ b/glib/tests/array-test.c
@@ -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);
[
Date Prev][
Date Next] [
Thread Prev][
Thread Next]
[
Thread Index]
[
Date Index]
[
Author Index]