From 92f331cd9f54128a71d804b39b51f5cd6d0c0ae8 Mon Sep 17 00:00:00 2001 From: Georges Basile Stavracas Neto Date: Tue, 24 Mar 2020 18:53:27 -0300 Subject: [PATCH] range-tree: Add API to remove data It'll be useful to remove entries without knowing their range. --- src/views/gcal-range-tree.c | 42 +++++++++++++++++++++++++++++++++++++ src/views/gcal-range-tree.h | 3 +++ tests/test-range-tree.c | 41 ++++++++++++++++++++++++++++++++++++ 3 files changed, 86 insertions(+) diff --git a/src/views/gcal-range-tree.c b/src/views/gcal-range-tree.c index ec75425c..ad77488c 100644 --- a/src/views/gcal-range-tree.c +++ b/src/views/gcal-range-tree.c @@ -473,6 +473,27 @@ count_entries_at_range (GDateTime *start, return GCAL_TRAVERSE_CONTINUE; } + +static inline gboolean +remove_data_func (GDateTime *start, + GDateTime *end, + gpointer data, + gpointer user_data) +{ + struct { + GcalRangeTree *range_tree; + gpointer *data; + } *remove_data = user_data; + + if (remove_data->data == data) + { + gcal_range_tree_remove_range (remove_data->range_tree, start, end, data); + return GCAL_TRAVERSE_STOP; + } + + return GCAL_TRAVERSE_CONTINUE; +} + static void gcal_range_tree_free (GcalRangeTree *self) { @@ -630,6 +651,27 @@ gcal_range_tree_remove_range (GcalRangeTree *self, self->root = remove_node (self->root, start, end, data); } +/** + * gcal_range_tree_remove_data: + * @self: a #GcalRangeTree + * @data: user data + * + * Removes the first instance of @data found in the range tree. + */ +void +gcal_range_tree_remove_data (GcalRangeTree *self, + gpointer data) +{ + struct { + GcalRangeTree *range_tree; + gpointer *data; + } remove_data = { self, data }; + + g_return_if_fail (self); + + gcal_range_tree_traverse (self, G_IN_ORDER, remove_data_func, &remove_data); +} + /** * gcal_range_tree_traverse: * @self: a #GcalRangeTree diff --git a/src/views/gcal-range-tree.h b/src/views/gcal-range-tree.h index e1ff6077..53cff2f3 100644 --- a/src/views/gcal-range-tree.h +++ b/src/views/gcal-range-tree.h @@ -68,6 +68,9 @@ void gcal_range_tree_remove_range (GcalRangeTree GDateTime *end, gpointer data); +void gcal_range_tree_remove_data (GcalRangeTree *self, + gpointer data); + void gcal_range_tree_traverse (GcalRangeTree *self, GTraverseType type, GcalRangeTraverseFunc func, diff --git a/tests/test-range-tree.c b/tests/test-range-tree.c index ed9974bb..8315b435 100644 --- a/tests/test-range-tree.c +++ b/tests/test-range-tree.c @@ -138,6 +138,46 @@ range_tree_smaller_range (void) /*********************************************************************************************************************/ +static void +range_tree_remove_data (void) +{ + g_autoptr (GcalRangeTree) range_tree = NULL; + g_autoptr (GDateTime) start = NULL; + g_autoptr (GDateTime) end = NULL; + + range_tree = gcal_range_tree_new (); + g_assert_nonnull (range_tree); + + start = g_date_time_new_local (2020, 3, 17, 9, 30, 0); + end = g_date_time_add_hours (start, 1); + + gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + + gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 2); + + gcal_range_tree_add_range (range_tree, start, end, (gpointer) 0xbadcafe); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 3); + + /* Remove the 2 deadbeefs */ + gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 2); + + gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + + /* Try again */ + gcal_range_tree_remove_data (range_tree, (gpointer) 0xdeadbeef); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 1); + + /* Remove bad cafe */ + gcal_range_tree_remove_data (range_tree, (gpointer) 0xbadcafe); + g_assert_cmpint (gcal_range_tree_count_entries_at_range (range_tree, start, end), ==, 0); +} + +/*********************************************************************************************************************/ + gint main (gint argc, gchar *argv[]) @@ -150,6 +190,7 @@ main (gint argc, g_test_add_func ("/range-tree/insert", range_tree_insert); g_test_add_func ("/range-tree/traverse", range_tree_traverse); g_test_add_func ("/range-tree/smaller-range", range_tree_smaller_range); + g_test_add_func ("/range-tree/remove-data", range_tree_remove_data); return g_test_run (); }