core/set: Add new struct to act as a set

The glib library doesn't have a dedicated "set" container, so I need to
create a wrapper around a hash table to accomplish the same results.

Signed-off-by: Anna Schumaker <Anna@OcarinaProject.net>
This commit is contained in:
Anna Schumaker 2015-11-07 10:38:48 -05:00
parent 9e0c4404fc
commit 4d065508cd
4 changed files with 129 additions and 12 deletions

70
include/core/set.h Normal file
View File

@ -0,0 +1,70 @@
/*
* Copyright 2015 (c) Anna Schumaker.
*/
#ifndef OCARINA_CORE_SET_H
#define OCARINA_CORE_SET_H
#include <glib.h>
#include <stdbool.h>
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 */

25
tests/core/.gitignore vendored
View File

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

View File

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

45
tests/core/set.c Normal file
View File

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