diff --git a/src/functional/search_tsearch.c b/src/functional/search_tsearch.c index b79095f..df257c6 100644 --- a/src/functional/search_tsearch.c +++ b/src/functional/search_tsearch.c @@ -11,6 +11,7 @@ struct e { int v; }; +static int count; static void *root; static struct e tab[100]; static struct e *cur = tab; @@ -23,7 +24,7 @@ static int cmp(const void *a, const void *b) static int wantc = 'a'; static void act(const void *node, VISIT v, int d) { - struct e *e = *(struct e **)node; + struct e *e = *(void**)node; if (v == preorder) if (e->k[0] < wantc) @@ -46,7 +47,7 @@ static char *searchkey; static void getparent(const void *node, VISIT v, int d) { static const void *p; - struct e *e = *(struct e **)node; + struct e *e = *(void**)node; if (v == preorder || v == leaf) if (strcmp(searchkey, e->k) == 0) @@ -55,32 +56,41 @@ static void getparent(const void *node, VISIT v, int d) p = node; } +struct e *get(char *k) +{ + void **p = tfind(&(struct e){.k = k}, &root, cmp); + if (!p) return 0; + return *p; +} + struct e *set(char *k, int v) { - struct e **p; + void **p; cur->k = k; cur->v = v; + if (!get(k)) + count++; p = tsearch(cur++, &root, cmp); - if (!p || strcmp((*p)->k, k) != 0) + if (!p || strcmp(((struct e*)*p)->k, k) != 0) t_error("tsearch %s %d failed\n", k, v); - if (!p) + if (!p) { + count--; return 0; + } return *p; } -struct e **get(char *k) -{ - return tfind(&(struct e){.k = k}, &root, cmp); -} - -struct e **del(char *k) +void *del(char *k) { - return tdelete(&(struct e){.k = k}, &root, cmp); + void *p = tdelete(&(struct e){.k = k}, &root, cmp); + if (p) + count--; + return p; } int main() { struct e *e; - struct e **p; + void *p; set("f", 6); set("b", 2); @@ -91,8 +101,8 @@ int main() { set("a", 1); set("d", 4); - p = get("a"); - if (!p || (*p)->v != 1) + e = get("a"); + if (!e || e->v != 1) t_error("tfind a failed\n"); if (get("z")) t_error("tfind z should fail\n"); @@ -119,9 +129,17 @@ int main() { if (p != parent) t_error("tdelete h failed to return parent (got %p wanted %p)\n", p, parent); - p = root; - if (!del((*p)->k)) - t_error("tdelete root \"%s\" failed (returned 0)\n", (*p)->k); + e = *(void**)root; + if (!del(e->k)) + t_error("tdelete root \"%s\" failed (returned 0)\n", e->k); + + for (; count; count--) { + e = *(void**)root; + if (!tdelete(e, &root, cmp)) + t_error("tdelete k=%s failed during destruction\n", e->k); + } + if (root) + t_error("tree destruction failed: root is nonzero %p\n", root); return t_status; }