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 <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-11-07 11:20:19 -05:00
parent 4d065508cd
commit 73f61e13d7
3 changed files with 67 additions and 0 deletions

15
core/set.c Normal file
View File

@ -0,0 +1,15 @@
/*
* Copyright 2015 (c) Anna Schumaker.
*/
#include <core/set.h>
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);
}
}

View File

@ -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)

View File

@ -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),
);