rbtree

changeset 6:028a21468abf

added rbshell test
author John Tsiombikas <nuclear@member.fsf.org>
date Wed, 12 Oct 2011 07:03:03 +0300
parents 56a08d00bb41
children 2c0baa1fd419
files .hgignore src/rbtree.h test/rbshell/Makefile test/rbshell/sym.c test/rbshell/sym.h test/rbshell/test.c
diffstat 6 files changed, 315 insertions(+), 0 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Wed Oct 12 05:25:34 2011 +0300
     1.2 +++ b/.hgignore	Wed Oct 12 07:03:03 2011 +0300
     1.3 @@ -4,3 +4,4 @@
     1.4  ^Makefile$
     1.5  rbtree\.a$
     1.6  rbtree\.so
     1.7 +^test/.*test$
     2.1 --- a/src/rbtree.h	Wed Oct 12 05:25:34 2011 +0300
     2.2 +++ b/src/rbtree.h	Wed Oct 12 07:03:03 2011 +0300
     2.3 @@ -36,6 +36,7 @@
     2.4  void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free);
     2.5  void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func);
     2.6  void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls);
     2.7 +/* TODO add user deep copy function */
     2.8  
     2.9  void rb_clear(struct rbtree *rb);
    2.10  int rb_copy(struct rbtree *dest, struct rbtree *src);
     3.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     3.2 +++ b/test/rbshell/Makefile	Wed Oct 12 07:03:03 2011 +0300
     3.3 @@ -0,0 +1,14 @@
     3.4 +src = $(wildcard *.c)
     3.5 +obj = $(src:.c=.o)
     3.6 +bin = test
     3.7 +
     3.8 +CC = gcc
     3.9 +CFLAGS = -pedantic -Wall -g -I../../src -I/usr/local/include
    3.10 +LDFLAGS = -L../.. -L/usr/local/lib -lrbtree
    3.11 +
    3.12 +$(bin): $(obj)
    3.13 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    3.14 +
    3.15 +.PHONY: clean
    3.16 +clean:
    3.17 +	rm -f $(obj) $(bin)
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/rbshell/sym.c	Wed Oct 12 07:03:03 2011 +0300
     4.3 @@ -0,0 +1,73 @@
     4.4 +#include <stdio.h>
     4.5 +#include <stdlib.h>
     4.6 +#include <string.h>
     4.7 +#include "sym.h"
     4.8 +#include "rbtree.h"
     4.9 +
    4.10 +struct symbol {
    4.11 +	char *name;
    4.12 +	int id, arity;
    4.13 +};
    4.14 +
    4.15 +static void del_func(struct rbnode *node, void *cls);
    4.16 +
    4.17 +struct rbtree *symbols;
    4.18 +
    4.19 +int init_sym(void)
    4.20 +{
    4.21 +	if(!(symbols = rb_create(RB_KEY_STRING))) {
    4.22 +		fprintf(stderr, "failed to create symbol table\n");
    4.23 +		return -1;
    4.24 +	}
    4.25 +	rb_set_delete_func(symbols, del_func, 0);
    4.26 +	return 0;
    4.27 +}
    4.28 +
    4.29 +void destroy_sym(void)
    4.30 +{
    4.31 +	rb_free(symbols);
    4.32 +}
    4.33 +
    4.34 +int add_sym(const char *name, int id, int arity)
    4.35 +{
    4.36 +	struct symbol *sym;
    4.37 +
    4.38 +	if(!(sym = malloc(sizeof *sym)) || !(sym->name = malloc(strlen(name) + 1))) {
    4.39 +		perror("failed to allocate symbol");
    4.40 +		free(sym);
    4.41 +		return -1;
    4.42 +	}
    4.43 +	strcpy(sym->name, name);
    4.44 +	sym->id = id;
    4.45 +	sym->arity = arity;
    4.46 +
    4.47 +	return rb_insert(symbols, sym->name, sym);
    4.48 +}
    4.49 +
    4.50 +int sym_lookup(const char *str)
    4.51 +{
    4.52 +	struct rbnode *node;
    4.53 +
    4.54 +	if(!(node = rb_find(symbols, (char*)str))) {
    4.55 +		fprintf(stderr, "undefined symbol: %s\n", str);
    4.56 +		return -1;
    4.57 +	}
    4.58 +	return ((struct symbol*)node->data)->id;
    4.59 +}
    4.60 +
    4.61 +int sym_arity(const char *str)
    4.62 +{
    4.63 +	struct rbnode *node;
    4.64 +
    4.65 +	if(!(node = rb_find(symbols, (char*)str))) {
    4.66 +		fprintf(stderr, "undefined symbol: %s\n", str);
    4.67 +		return -1;
    4.68 +	}
    4.69 +	return ((struct symbol*)node->data)->arity;
    4.70 +}
    4.71 +
    4.72 +static void del_func(struct rbnode *node, void *cls)
    4.73 +{
    4.74 +	free(((struct symbol*)node->data)->name);
    4.75 +	free(node->data);
    4.76 +}
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/rbshell/sym.h	Wed Oct 12 07:03:03 2011 +0300
     5.3 @@ -0,0 +1,12 @@
     5.4 +#ifndef SYM_H_
     5.5 +#define SYM_H_
     5.6 +
     5.7 +int init_sym(void);
     5.8 +void destroy_sym(void);
     5.9 +
    5.10 +int add_sym(const char *name, int id, int arity);
    5.11 +
    5.12 +int sym_lookup(const char *str);
    5.13 +int sym_arity(const char *str);
    5.14 +
    5.15 +#endif	/* SYM_H_ */
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/rbshell/test.c	Wed Oct 12 07:03:03 2011 +0300
     6.3 @@ -0,0 +1,214 @@
     6.4 +#include <stdio.h>
     6.5 +#include <stdlib.h>
     6.6 +#include <string.h>
     6.7 +#include <ctype.h>
     6.8 +#include "rbtree.h"
     6.9 +#include "sym.h"
    6.10 +
    6.11 +#define SEP	" \t\r\n,\"\'"
    6.12 +
    6.13 +/* commands */
    6.14 +enum {
    6.15 +	CMD_CREATE,
    6.16 +	CMD_DESTROY,
    6.17 +	CMD_CLEAR,
    6.18 +	CMD_COPY,
    6.19 +	CMD_SIZE,
    6.20 +	CMD_INSERT,
    6.21 +	CMD_DELETE,
    6.22 +	CMD_FIND,
    6.23 +	CMD_PRINT,
    6.24 +
    6.25 +	MAX_CMD
    6.26 +};
    6.27 +
    6.28 +int runcmd(int cmd, int argc, char **argv);
    6.29 +
    6.30 +#define NUM_TREES	8
    6.31 +struct rbtree *trees[NUM_TREES];
    6.32 +
    6.33 +
    6.34 +int main(void)
    6.35 +{
    6.36 +	char buf[512];
    6.37 +
    6.38 +	/* init symbol table */
    6.39 +	if(init_sym() == -1) {
    6.40 +		return 1;
    6.41 +	}
    6.42 +	add_sym("create", CMD_CREATE, 0);
    6.43 +	add_sym("destroy", CMD_DESTROY, 1);
    6.44 +	add_sym("clear", CMD_CLEAR, 1);
    6.45 +	add_sym("copy", CMD_COPY, 2);
    6.46 +	add_sym("size", CMD_SIZE, 1);
    6.47 +	add_sym("insert", CMD_INSERT, 2);
    6.48 +	add_sym("delete", CMD_DELETE, 2);
    6.49 +	add_sym("find", CMD_FIND, 2);
    6.50 +	add_sym("print", CMD_PRINT, 1);
    6.51 +
    6.52 +	for(;;) {
    6.53 +		int argc = 0;
    6.54 +		char *argv[8];
    6.55 +		int cmd_id, cmd_arity;
    6.56 +
    6.57 +		printf("rbshell> ");
    6.58 +		fflush(stdout);
    6.59 +
    6.60 +		if(!fgets(buf, sizeof buf, stdin)) {
    6.61 +			putchar('\n');
    6.62 +			break;
    6.63 +		}
    6.64 +
    6.65 +		if(!(argv[argc] = strtok(buf, SEP)) || argv[argc][0] == '#') {
    6.66 +			return 0;	/* empty / comment */
    6.67 +		}
    6.68 +		argc++;
    6.69 +
    6.70 +		if((cmd_id = sym_lookup(argv[0])) == -1) {
    6.71 +			continue;
    6.72 +		}
    6.73 +		cmd_arity = sym_arity(argv[0]);
    6.74 +
    6.75 +		while((argv[argc] = strtok(0, SEP))) {
    6.76 +			argc++;
    6.77 +			if(argc >= sizeof argv / sizeof *argv) {
    6.78 +				break;
    6.79 +			}
    6.80 +		}
    6.81 +
    6.82 +		if(argc - 1 != cmd_arity) {
    6.83 +			fprintf(stderr, "too many (%d) arguments for %s, expected %d\n", argc - 1, argv[0], cmd_arity);
    6.84 +			continue;
    6.85 +		}
    6.86 +
    6.87 +		runcmd(cmd_id, argc, argv);
    6.88 +	}
    6.89 +
    6.90 +	destroy_sym();
    6.91 +	return 0;
    6.92 +}
    6.93 +
    6.94 +#define CHECKINT(i)		\
    6.95 +	if(!isdigit(argv[i][0])) { \
    6.96 +		fprintf(stderr, "expected number, got: %s\n", argv[i]); \
    6.97 +		return -1; \
    6.98 +	}
    6.99 +
   6.100 +#define CHECKVALID(idx)	\
   6.101 +	if((idx) < 0 || (idx) >= NUM_TREES || !trees[idx]) { \
   6.102 +		fprintf(stderr, "invalid tree specified: %d\n", idx); \
   6.103 +		return -1; \
   6.104 +	}
   6.105 +
   6.106 +
   6.107 +int runcmd(int cmd, int argc, char **argv)
   6.108 +{
   6.109 +	int i, idx, idx2, n;
   6.110 +	struct rbnode *node;
   6.111 +
   6.112 +	switch(cmd) {
   6.113 +	case CMD_CREATE:
   6.114 +		for(i=0; i<NUM_TREES; i++) {
   6.115 +			if(trees[i] == 0) {
   6.116 +				if(!(trees[i] = rb_create(RB_KEY_INT))) {
   6.117 +					fprintf(stderr, "failed to create a new tree\n");
   6.118 +					return -1;
   6.119 +				}
   6.120 +				printf("created new tree: %d\n", i);
   6.121 +				break;
   6.122 +			}
   6.123 +		}
   6.124 +		if(i == NUM_TREES) {
   6.125 +			fprintf(stderr, "can't create more trees\n");
   6.126 +			return -1;
   6.127 +		}
   6.128 +		break;
   6.129 +
   6.130 +	case CMD_DESTROY:
   6.131 +		CHECKINT(1);
   6.132 +		idx = atoi(argv[1]);
   6.133 +		CHECKVALID(idx);
   6.134 +
   6.135 +		rb_free(trees[idx]);
   6.136 +		trees[idx] = 0;
   6.137 +		printf("destroyed tree: %d\n", idx);
   6.138 +		break;
   6.139 +
   6.140 +	case CMD_CLEAR:
   6.141 +		CHECKINT(1);
   6.142 +		idx = atoi(argv[1]);
   6.143 +		CHECKVALID(idx);
   6.144 +
   6.145 +		rb_clear(trees[idx]);
   6.146 +		printf("cleared tree: %d\n", idx);
   6.147 +		break;
   6.148 +
   6.149 +	case CMD_COPY:
   6.150 +		CHECKINT(1);
   6.151 +		CHECKINT(2);
   6.152 +		idx = atoi(argv[1]);
   6.153 +		idx2 = atoi(argv[2]);
   6.154 +		CHECKVALID(idx);
   6.155 +		CHECKVALID(idx2);
   6.156 +
   6.157 +		rb_copy(trees[idx2], trees[idx]);
   6.158 +		printf("copied %d -> %d\n", idx, idx2);
   6.159 +		break;
   6.160 +
   6.161 +	case CMD_SIZE:
   6.162 +		CHECKINT(1);
   6.163 +		idx = atoi(argv[1]);
   6.164 +		CHECKVALID(idx);
   6.165 +
   6.166 +		printf("tree size: %d\n", rb_size(trees[idx]));
   6.167 +		break;
   6.168 +
   6.169 +	case CMD_INSERT:
   6.170 +		CHECKINT(1);
   6.171 +		CHECKINT(2);
   6.172 +		idx = atoi(argv[1]);
   6.173 +		CHECKVALID(idx);
   6.174 +
   6.175 +		n = atoi(argv[2]);
   6.176 +		rb_inserti(trees[idx], n, 0);
   6.177 +		printf("inserted: %d\n", n);
   6.178 +		break;
   6.179 +
   6.180 +	case CMD_DELETE:
   6.181 +	case CMD_FIND:
   6.182 +		CHECKINT(1);
   6.183 +		CHECKINT(2);
   6.184 +		idx = atoi(argv[1]);
   6.185 +		CHECKVALID(idx);
   6.186 +		n = atoi(argv[2]);
   6.187 +
   6.188 +		if(!rb_findi(trees[idx], n)) {
   6.189 +			fprintf(stderr, "%d not found\n", n);
   6.190 +		} else {
   6.191 +			if(cmd == CMD_DELETE) {
   6.192 +				rb_deletei(trees[idx], n);
   6.193 +				printf("deleted %d\n", n);
   6.194 +			} else {
   6.195 +				printf("found %d\n", n);
   6.196 +			}
   6.197 +		}
   6.198 +		break;
   6.199 +
   6.200 +	case CMD_PRINT:
   6.201 +		CHECKINT(1);
   6.202 +		idx = atoi(argv[1]);
   6.203 +		CHECKVALID(idx);
   6.204 +
   6.205 +		rb_begin(trees[idx]);
   6.206 +		while((node = rb_next(trees[idx]))) {
   6.207 +			printf("%d ", rb_node_keyi(node));
   6.208 +		}
   6.209 +		putchar('\n');
   6.210 +		break;
   6.211 +
   6.212 +	default:
   6.213 +		/* can't happen */
   6.214 +		break;
   6.215 +	}
   6.216 +	return 0;
   6.217 +}