diff --git a/include/core/set.h b/include/core/set.h new file mode 100644 index 00000000..5746affa --- /dev/null +++ b/include/core/set.h @@ -0,0 +1,70 @@ +/* + * Copyright 2015 (c) Anna Schumaker. + */ +#ifndef OCARINA_CORE_SET_H +#define OCARINA_CORE_SET_H + +#include +#include + + +struct set { + GHashTable *s_set; +}; + +struct set_iter { + unsigned int it_val; + GHashTableIter it_iter; +}; + + +#define SET_INIT() \ + { \ + .s_set = g_hash_table_new(g_direct_hash, g_direct_equal), \ + } + + +static inline void set_deinit(struct set *set) +{ + g_hash_table_destroy(set->s_set); +} + +static inline void set_insert(struct set *set, unsigned int value) +{ + g_hash_table_add(set->s_set, GUINT_TO_POINTER(value)); +} + +static inline void set_remove(struct set *set, unsigned int value) +{ + g_hash_table_remove(set->s_set, GUINT_TO_POINTER(value)); +} + +static inline bool set_has(const struct set *set, unsigned int value) +{ + return g_hash_table_contains(set->s_set, GUINT_TO_POINTER(value)); +} + +static inline unsigned int set_size(struct set *set) +{ + return g_hash_table_size(set->s_set); +} + + + +static inline bool set_iter_next(struct set_iter *it) +{ + gpointer key; + bool ret = g_hash_table_iter_next(&it->it_iter, &key, NULL); + it->it_val = GPOINTER_TO_INT(key); + return ret; +} + +static inline void set_iter_init(const struct set *set, struct set_iter *it) +{ + g_hash_table_iter_init(&it->it_iter, set->s_set); +} + +#define set_for_each(set, it) \ + for (set_iter_init(set, it); set_iter_next(it); ) + +#endif /* OCARINA_CORE_SET_H */ diff --git a/tests/core/.gitignore b/tests/core/.gitignore index 42a64a8f..06c07df3 100644 --- a/tests/core/.gitignore +++ b/tests/core/.gitignore @@ -1,15 +1,16 @@ -version -string -file -date +audio database -index -filter -idle -random -queue -library -playlist +date deck driver -audio +file +filter +idle +index +library +playlist +queue +random +set +string +version diff --git a/tests/core/Sconscript b/tests/core/Sconscript index 3556bbed..ca2045d6 100644 --- a/tests/core/Sconscript +++ b/tests/core/Sconscript @@ -18,6 +18,7 @@ res += [ CoreTest("string", "string.c") ] res += [ CoreTest("random", "random.c") ] res += [ CoreTest("file", "file.c") ] res += [ CoreTest("date", "date.c") ] +res += [ CoreTest("set", "set.c") ] res += [ CoreTest("database", "database.cpp") ] res += [ CoreTest("index", "index.cpp") ] res += [ CoreTest("filter", "filter.cpp") ] diff --git a/tests/core/set.c b/tests/core/set.c new file mode 100644 index 00000000..52d97142 --- /dev/null +++ b/tests/core/set.c @@ -0,0 +1,45 @@ +/* + * Copyright 2015 (c) Anna Schumaker. + */ +#include +#include + + +void test_set() +{ + struct set set = SET_INIT(); + unsigned int i, N = 10; + struct set_iter it; + + /* Insert N items. */ + for (i = 0; i < N; i++) { + set_insert(&set, i); + set_insert(&set, i); + test_loop_equal(set_size(&set), i + 1, i); + test_loop_equal(set_has(&set, i), (bool)true, i); + } test_loop_passed(); + + set_insert(&set, 0); + test_equal(set_size(&set), N); + + /* Remove even items. */ + for (i = 0; i < N; i += 2) { + set_remove(&set, i); + set_remove(&set, i); + test_loop_equal(set_has(&set, i), (bool)false, i); + } test_loop_passed(); + test_equal(set_size(&set), N / 2); + + /* Test iterating. */ + i = 1; + set_for_each(&set, &it) { + test_loop_equal(it.it_val, i, i); + i += 2; + } test_loop_passed(); + + set_deinit(&set); +} + +DECLARE_UNIT_TESTS( + UNIT_TEST("Set", test_set), +);