From 73f61e13d752fd0946df435e29ff431ab0097a6a Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Sat, 7 Nov 2015 11:20:19 -0500 Subject: [PATCH] core/set: Add function for finding set intersections Finding an inline intersection is really easy using iterators, so I wrote this function to modify one of the set rather than returning a new one. Signed-off-by: Anna Schumaker --- core/set.c | 15 ++++++++++++++ include/core/set.h | 2 ++ tests/core/set.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 67 insertions(+) create mode 100644 core/set.c diff --git a/core/set.c b/core/set.c new file mode 100644 index 00000000..9557c528 --- /dev/null +++ b/core/set.c @@ -0,0 +1,15 @@ +/* + * Copyright 2015 (c) Anna Schumaker. + */ + +#include + +void set_inline_intersect(const struct set *lhs, struct set *rhs) +{ + struct set_iter it_rhs; + + set_for_each(rhs, &it_rhs) { + if (!set_has(lhs, it_rhs.it_val)) + g_hash_table_iter_remove(&it_rhs.it_iter); + } +} diff --git a/include/core/set.h b/include/core/set.h index 5746affa..496e9f88 100644 --- a/include/core/set.h +++ b/include/core/set.h @@ -49,6 +49,8 @@ static inline unsigned int set_size(struct set *set) return g_hash_table_size(set->s_set); } +/* Remove values from set2 that are not also in set1. */ +void set_inline_intersect(const struct set *, struct set *); static inline bool set_iter_next(struct set_iter *it) diff --git a/tests/core/set.c b/tests/core/set.c index 52d97142..96bba1bc 100644 --- a/tests/core/set.c +++ b/tests/core/set.c @@ -40,6 +40,56 @@ void test_set() set_deinit(&set); } +void test_intersection() +{ + struct set set1 = SET_INIT(); + struct set set2 = SET_INIT(); + unsigned int i; + + /* Test intersection between two empty sets. */ + set_inline_intersect(&set1, &set2); + test_equal(set_size(&set1), 0); + test_equal(set_size(&set2), 0); + + + /* Add values 5 - 14 to set2, but keep set1 empty. */ + for (i = 5; i < 15; i++) + set_insert(&set2, i); + set_inline_intersect(&set1, &set2); + test_equal(set_size(&set1), 0); + test_equal(set_size(&set2), 0); + + + /* Add values 0 - 9 to set1, but keep set2 empty. */ + for (i = 0; i < 10; i++) + set_insert(&set1, i); + set_inline_intersect(&set1, &set2); + test_equal(set_size(&set1), 10); + test_equal(set_size(&set2), 0); + + + /* Add values 5 - 14 back into set2. */ + for (i = 5; i < 15; i++) + set_insert(&set2, i); + set_inline_intersect(&set1, &set2); + test_equal(set_size(&set1), 10); + test_equal(set_size(&set2), 5); + + + /* Set1 should now contain values 5 - 9. */ + for (i = 0; i < 15; i++) { + if (i >= 5 && i < 10) { + test_loop_equal(set_has(&set2, i), (bool)true, i); + } else { + test_loop_equal(set_has(&set2, i), (bool)false, i); + } + } test_loop_passed(); + + set_deinit(&set1); + set_deinit(&set2); +} + DECLARE_UNIT_TESTS( UNIT_TEST("Set", test_set), + UNIT_TEST("Set Intersection", test_intersection), );