Blame src/functional/search_tsearch.c

Szabolcs Nagy 54f9b9
#ifndef _XOPEN_SOURCE
Szabolcs Nagy 54f9b9
#define _XOPEN_SOURCE 700
Szabolcs Nagy 54f9b9
#endif
Szabolcs Nagy 132e38
#include <stdlib.h>
Szabolcs Nagy 132e38
#include <string.h>
Szabolcs Nagy 132e38
#include <search.h>
Szabolcs Nagy 132e38
#include "test.h"
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
struct e {
Szabolcs Nagy 132e38
	char *k;
Szabolcs Nagy 132e38
	int v;
Szabolcs Nagy 132e38
};
Szabolcs Nagy 132e38
Szabolcs Nagy ec0d49
static int count;
Szabolcs Nagy 132e38
static void *root;
Szabolcs Nagy 132e38
static struct e tab[100];
Szabolcs Nagy 132e38
static struct e *cur = tab;
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
static int cmp(const void *a, const void *b)
Szabolcs Nagy 132e38
{
Szabolcs Nagy 132e38
	return strcmp(((struct e*)a)->k, ((struct e*)b)->k);
Szabolcs Nagy 132e38
}
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
static int wantc = 'a';
Szabolcs Nagy 132e38
static void act(const void *node, VISIT v, int d)
Szabolcs Nagy 132e38
{
Szabolcs Nagy ec0d49
	struct e *e = *(void**)node;
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
	if (v == preorder)
Szabolcs Nagy 132e38
		if (e->k[0] < wantc)
Szabolcs Nagy 132e38
			t_error("preorder visited node \"%s\" before \"%c\"\n", e->k, wantc);
Szabolcs Nagy 132e38
	if (v == endorder)
Szabolcs Nagy 132e38
		if (e->k[0] > wantc)
Szabolcs Nagy 132e38
			t_error("endorder visited node \"%s\" after \"%c\"\n", e->k, wantc);
Szabolcs Nagy 132e38
	if (v == postorder)
Szabolcs Nagy 132e38
		if (e->k[0] != wantc)
Szabolcs Nagy 132e38
			t_error("postorder visited node \"%s\", wanted \"%c\"\n", e->k, wantc);
Szabolcs Nagy 132e38
	if (v == leaf)
Szabolcs Nagy 132e38
		if (e->k[0] != wantc)
Szabolcs Nagy 132e38
			t_error("visited leaf node \"%s\", wanted \"%c\"\n", e->k, wantc);
Szabolcs Nagy 132e38
	if (v == postorder || v == leaf)
Szabolcs Nagy 132e38
		wantc++;
Szabolcs Nagy 132e38
}
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
static const void *parent;
Szabolcs Nagy 132e38
static char *searchkey;
Szabolcs Nagy 132e38
static void getparent(const void *node, VISIT v, int d)
Szabolcs Nagy 132e38
{
Szabolcs Nagy 132e38
	static const void *p;
Szabolcs Nagy ec0d49
	struct e *e = *(void**)node;
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
	if (v == preorder || v == leaf)
Szabolcs Nagy 132e38
		if (strcmp(searchkey, e->k) == 0)
Szabolcs Nagy 132e38
			parent = p;
Szabolcs Nagy 132e38
	if (v == preorder || v == postorder)
Szabolcs Nagy 132e38
		p = node;
Szabolcs Nagy 132e38
}
Szabolcs Nagy 132e38
Szabolcs Nagy ec0d49
struct e *get(char *k)
Szabolcs Nagy ec0d49
{
Szabolcs Nagy ec0d49
	void **p = tfind(&(struct e){.k = k}, &root, cmp);
Szabolcs Nagy ec0d49
	if (!p) return 0;
Szabolcs Nagy ec0d49
	return *p;
Szabolcs Nagy ec0d49
}
Szabolcs Nagy ec0d49
Szabolcs Nagy 132e38
struct e *set(char *k, int v)
Szabolcs Nagy 132e38
{
Szabolcs Nagy ec0d49
	void **p;
Szabolcs Nagy 132e38
	cur->k = k;
Szabolcs Nagy 132e38
	cur->v = v;
Szabolcs Nagy ec0d49
	if (!get(k))
Szabolcs Nagy ec0d49
		count++;
Szabolcs Nagy 132e38
	p = tsearch(cur++, &root, cmp);
Szabolcs Nagy ec0d49
	if (!p || strcmp(((struct e*)*p)->k, k) != 0)
Szabolcs Nagy 132e38
		t_error("tsearch %s %d failed\n", k, v);
Szabolcs Nagy ec0d49
	if (!p) {
Szabolcs Nagy ec0d49
		count--;
Szabolcs Nagy 132e38
		return 0;
Szabolcs Nagy ec0d49
	}
Szabolcs Nagy 132e38
	return *p;
Szabolcs Nagy 132e38
}
Szabolcs Nagy 132e38
Szabolcs Nagy ec0d49
void *del(char *k)
Szabolcs Nagy 132e38
{
Szabolcs Nagy ec0d49
	void *p = tdelete(&(struct e){.k = k}, &root, cmp);
Szabolcs Nagy ec0d49
	if (p)
Szabolcs Nagy ec0d49
		count--;
Szabolcs Nagy ec0d49
	return p;
Szabolcs Nagy 132e38
}
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
int main() {
Szabolcs Nagy 132e38
	struct e *e;
Szabolcs Nagy ec0d49
	void *p;
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
	set("f", 6);
Szabolcs Nagy 132e38
	set("b", 2);
Szabolcs Nagy 132e38
	set("c", 3);
Szabolcs Nagy 132e38
	set("e", 5);
Szabolcs Nagy 132e38
	set("h", 8);
Szabolcs Nagy 132e38
	set("g", 7);
Szabolcs Nagy 132e38
	set("a", 1);
Szabolcs Nagy 132e38
	set("d", 4);
Szabolcs Nagy 132e38
Szabolcs Nagy ec0d49
	e = get("a");
Szabolcs Nagy ec0d49
	if (!e || e->v != 1)
Szabolcs Nagy 132e38
		t_error("tfind a failed\n");
Szabolcs Nagy 132e38
	if (get("z"))
Szabolcs Nagy 132e38
		t_error("tfind z should fail\n");
Szabolcs Nagy 132e38
	e = set("g", 9);
Szabolcs Nagy 132e38
	if (e && e->v != 7)
Szabolcs Nagy 132e38
		t_error("tsearch g 9 returned data %d, wanted 7\n", e->v);
Szabolcs Nagy 132e38
	e = set("g", 9);
Szabolcs Nagy 132e38
	if (e && e->v != 7)
Szabolcs Nagy 132e38
		t_error("tsearch g 9 returned data %d, wanted 7\n", e->v);
Szabolcs Nagy 132e38
	e = set("i", 9);
Szabolcs Nagy 132e38
	if (e && e->v != 9)
Szabolcs Nagy 132e38
		t_error("tsearch i 9 returned data %d, wanted 9\n", e->v);
Szabolcs Nagy 132e38
	if (del("foobar"))
Szabolcs Nagy 132e38
		t_error("tdelete foobar should fail\n");
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
	twalk(root, act);
Szabolcs Nagy 132e38
	if (wantc!='j')
Szabolcs Nagy 132e38
		t_error("twalk did not visit all nodes (wanted 'j' got '%c')\n", wantc);
Szabolcs Nagy 132e38
	searchkey = "h";
Szabolcs Nagy 132e38
	twalk(root, getparent);
Szabolcs Nagy 132e38
	if (parent == 0)
Szabolcs Nagy 132e38
		t_error("twalk search for key \"%s\" failed\n", searchkey);
Szabolcs Nagy 132e38
	p = del("h");
Szabolcs Nagy 132e38
	if (p != parent)
Szabolcs Nagy 132e38
		t_error("tdelete h failed to return parent (got %p wanted %p)\n", p, parent);
Szabolcs Nagy 132e38
Szabolcs Nagy ec0d49
	e = *(void**)root;
Szabolcs Nagy ec0d49
	if (!del(e->k))
Szabolcs Nagy ec0d49
		t_error("tdelete root \"%s\" failed (returned 0)\n", e->k);
Szabolcs Nagy ec0d49
Szabolcs Nagy ec0d49
	for (; count; count--) {
Szabolcs Nagy ec0d49
		e = *(void**)root;
Szabolcs Nagy ec0d49
		if (!tdelete(e, &root, cmp))
Szabolcs Nagy ec0d49
			t_error("tdelete k=%s failed during destruction\n", e->k);
Szabolcs Nagy ec0d49
	}
Szabolcs Nagy ec0d49
	if (root)
Szabolcs Nagy ec0d49
		t_error("tree destruction failed: root is nonzero %p\n", root);
Szabolcs Nagy 132e38
Szabolcs Nagy 132e38
	return t_status;
Szabolcs Nagy 132e38
}