summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul J Stevens <paul@nfg.nl>2010-08-10 11:13:35 +0200
committerPaul J Stevens <paul@nfg.nl>2010-08-10 11:13:35 +0200
commit385c3feeb4c0db62c842fc63c78de38c901fa227 (patch)
treee084ccca25c5cc8dcd134381fe7612b1901d1613
parent88edf66634cdc3d0027662eb2029c10c036700d9 (diff)
finish initial sorted-set implementation
-rw-r--r--src/dm_sset.c94
-rw-r--r--src/dm_sset.h2
-rw-r--r--test/check_dbmail_sset.c148
3 files changed, 231 insertions, 13 deletions
diff --git a/src/dm_sset.c b/src/dm_sset.c
index 4dde0fbe..403959f0 100644
--- a/src/dm_sset.c
+++ b/src/dm_sset.c
@@ -77,19 +77,37 @@ void * Sset_del(T S, const void * a)
return t;
}
-void Sset_map(T S, int (*func)(void *, void *, void *), void *data)
+struct mapper_data {
+ int (*func)(void *, void *);
+ void *data;
+};
+
+static int mapper(void *key, void *value, void *data)
+{
+ struct mapper_data *m = (struct mapper_data *)data;
+ return m->func(key, m->data)?1:0;
+}
+
+void Sset_map(T S, int (*func)(void *, void *), void *data)
{
- g_tree_foreach((GTree *)S->root, (GTraverseFunc)func, data);
+ struct mapper_data m;
+ m.func = func;
+ m.data = data;
+ g_tree_foreach((GTree *)S->root, (GTraverseFunc)mapper, &m);
}
void Sset_free(T *S)
{
T s = *S;
- if (s) free(s);
+ if (s) {
+ g_tree_destroy((GTree *)s->root);
+ s->root = NULL;
+ free(s);
+ }
s = NULL;
}
-static int sset_copy(void *a, void *b, void *c)
+static int sset_copy(void *a, void *c)
{
T t = (T)c;
if (! Sset_has(c, a)) {
@@ -110,19 +128,81 @@ T Sset_or(T a, T b) // a + b
return c;
}
+struct sset_match_helper {
+ T i;
+ T o;
+};
+
+static int sset_match_and(void *a, void *c)
+{
+ struct sset_match_helper *m = (struct sset_match_helper *)c;
+ T t = m->o;
+
+ if (Sset_has(m->i, a)) {
+ void * item = malloc(t->size);
+ memcpy(item, (const void *)a, t->size);
+ Sset_add(m->o, item);
+ }
+ return 0;
+}
+
T Sset_and(T a, T b) // a * b
{
- return a;
+ T c = Sset_new(a->cmp, a->size);
+ T s;
+ struct sset_match_helper h;
+ if (Sset_len(a) < Sset_len(b)) {
+ s = a;
+ h.i = b;
+ } else {
+ s = b;
+ h.i = a;
+ }
+ h.o = c;
+
+ Sset_map(s, sset_match_and, &h);
+
+ return c;
+}
+
+static int sset_match_not(void *a, void *c)
+{
+ struct sset_match_helper *m = (struct sset_match_helper *)c;
+ T t = m->o;
+
+ if (! Sset_has(m->i, a)) {
+ void * item = malloc(t->size);
+ memcpy(item, (const void *)a, t->size);
+ Sset_add(m->o, item);
+ }
+ return 0;
}
T Sset_not(T a, T b) // a - b
{
- return a;
+ T c = Sset_new(a->cmp, a->size);
+ struct sset_match_helper h;
+ h.o = c;
+
+ h.i = b;
+ Sset_map(a, sset_match_not, &h);
+
+ return c;
}
T Sset_xor(T a, T b) // a / b
{
- return a;
+ T c = Sset_new(a->cmp, a->size);
+ struct sset_match_helper h;
+ h.o = c;
+
+ h.i = b;
+ Sset_map(a, sset_match_not, &h);
+
+ h.i = a;
+ Sset_map(b, sset_match_not, &h);
+
+ return c;
}
diff --git a/src/dm_sset.h b/src/dm_sset.h
index f114f8ff..1bba5eec 100644
--- a/src/dm_sset.h
+++ b/src/dm_sset.h
@@ -39,7 +39,7 @@ extern int Sset_has(T, const void *);
extern void Sset_add(T, const void *);
extern int Sset_len(T);
extern void * Sset_del(T, const void *);
-extern void Sset_map(T, int (*func)(void *, void *, void *), void *);
+extern void Sset_map(T, int (*func)(void *, void *), void *);
extern void Sset_free(T *);
extern T Sset_or(T, T); // a + b
diff --git a/test/check_dbmail_sset.c b/test/check_dbmail_sset.c
index 7ad5cb67..9623a47f 100644
--- a/test/check_dbmail_sset.c
+++ b/test/check_dbmail_sset.c
@@ -69,7 +69,7 @@ Sset_T V, W;
struct item {
- int key;
+ long long int key;
long long int value;
};
@@ -115,6 +115,7 @@ START_TEST(test_sset_add)
}
end_clock("Sset_add: ");
+ fail_unless(Sset_len(V) == n, "sset holds: [%d]:", Sset_len(V));
free(k);
}
END_TEST
@@ -124,7 +125,6 @@ START_TEST(test_sset_del)
int i, n = 1000000;
struct item p, *t, *k;
- start_clock();
t = k = malloc(sizeof(struct item) * n);
for (i = 0; i<n; i++, t++) {
@@ -150,7 +150,7 @@ END_TEST
START_TEST(test_sset_or)
{
- int i, n = 1000000;
+ long long int i, n = 1000000;
struct item *t, *k, *l;
t = k = malloc(sizeof(struct item) * n);
@@ -172,7 +172,140 @@ START_TEST(test_sset_or)
Sset_T p = Sset_or(V, W);
end_clock("Sset_or: ");
- printf("[%d]", Sset_len(p));
+ fail_unless(Sset_len(p) == Sset_len(V) + Sset_len(W), "Sset_or failed");
+
+ Sset_free(&p);
+
+ free(k);
+ free(l);
+}
+END_TEST
+
+START_TEST(test_sset_and1)
+{
+ long long int i, n = 1000000;
+ struct item *t, *k, *l;
+
+ k = malloc(sizeof(struct item) * n);
+ l = malloc(sizeof(struct item) * n);
+
+ for (t = k, i = 0; i<n; i+=2, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(V, (void *)t);
+ }
+
+ for (t = l, i = 1; i<=n; i+=2, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(W, (void *)t);
+ }
+
+ start_clock();
+ Sset_T p = Sset_and(V, W);
+ end_clock("Sset_and1: ");
+
+ fail_unless(Sset_len(p) == 0, "Sset_and1 failed");
+
+ Sset_free(&p);
+
+ free(k);
+ free(l);
+}
+END_TEST
+
+START_TEST(test_sset_and2)
+{
+ long long int i, n = 1000000;
+ struct item *t, *k, *l;
+
+ k = malloc(sizeof(struct item) * n);
+ l = malloc(sizeof(struct item) * n);
+
+ for (t = k, i = 0; i<n; i++, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(V, (void *)t);
+ }
+
+ for (t = l, i = 0; i<n; i++, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(W, (void *)t);
+ }
+
+ start_clock();
+ Sset_T p = Sset_and(V, W);
+ end_clock("Sset_and2: ");
+
+ fail_unless(Sset_len(p) == n, "Sset_and2 failed");
+
+ Sset_free(&p);
+
+ free(k);
+ free(l);
+}
+END_TEST
+
+START_TEST(test_sset_not)
+{
+ long long int i, n = 1000000;
+ struct item *t, *k, *l;
+
+ k = malloc(sizeof(struct item) * n);
+ l = malloc(sizeof(struct item) * n);
+
+ for (t = k, i = 0; i<n; i+=2, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(V, (void *)t);
+ }
+
+ for (t = l, i = 1; i<=n; i+=2, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(W, (void *)t);
+ }
+
+ start_clock();
+ Sset_T p = Sset_not(V, W);
+ end_clock("Sset_not: ");
+
+ fail_unless(Sset_len(p) == Sset_len(V), "Sset_not failed");
+
+ Sset_free(&p);
+
+ free(k);
+ free(l);
+}
+END_TEST
+
+START_TEST(test_sset_xor)
+{
+ long long int i, n = 1000000;
+ struct item *t, *k, *l;
+
+ k = malloc(sizeof(struct item) * n);
+ l = malloc(sizeof(struct item) * n);
+
+ for (t = k, i = 0; i<n; i+=2, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(V, (void *)t);
+ }
+
+ for (t = l, i = 1; i<=n; i+=2, t++) {
+ t->key = i;
+ t->value = i;
+ Sset_add(W, (void *)t);
+ }
+
+ start_clock();
+ Sset_T p = Sset_xor(V, W);
+ end_clock("Sset_xor: ");
+
+ fail_unless(Sset_len(p) == n, "Sset_xor failed");
+
Sset_free(&p);
free(k);
@@ -191,9 +324,14 @@ Suite *dbmail_sset_suite(void)
tcase_add_checked_fixture(tc_sset, setup, teardown);
tcase_add_test(tc_sset, test_sset_add);
+ /*
tcase_add_test(tc_sset, test_sset_del);
tcase_add_test(tc_sset, test_sset_or);
-
+ tcase_add_test(tc_sset, test_sset_and1);
+ tcase_add_test(tc_sset, test_sset_and2);
+ tcase_add_test(tc_sset, test_sset_not);
+ tcase_add_test(tc_sset, test_sset_xor);
+*/
return s;
}