rbtree

changeset 9:8d7233ff61d3

merged fixes with rbshell
author John Tsiombikas <nuclear@member.fsf.org>
date Mon, 16 Apr 2012 00:26:38 +0300
parents b266386d19ce 2c0baa1fd419
children b45febfd2922
files src/rbtree.h
diffstat 7 files changed, 318 insertions(+), 1 deletions(-) [+]
line diff
     1.1 --- a/.hgignore	Mon Apr 16 00:25:05 2012 +0300
     1.2 +++ b/.hgignore	Mon Apr 16 00:26:38 2012 +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.c	Mon Apr 16 00:25:05 2012 +0300
     2.2 +++ b/src/rbtree.c	Mon Apr 16 00:26:38 2012 +0300
     2.3 @@ -261,7 +261,9 @@
     2.4  	del_tree(node->left, delfunc, cls);
     2.5  	del_tree(node->right, delfunc, cls);
     2.6  
     2.7 -	delfunc(node, cls);
     2.8 +	if(delfunc) {
     2.9 +		delfunc(node, cls);
    2.10 +	}
    2.11  	free(node);
    2.12  }
    2.13  
     3.1 --- a/src/rbtree.h	Mon Apr 16 00:25:05 2012 +0300
     3.2 +++ b/src/rbtree.h	Mon Apr 16 00:26:38 2012 +0300
     3.3 @@ -36,6 +36,7 @@
     3.4  void rb_set_allocator(struct rbtree *rb, rb_alloc_func_t alloc, rb_free_func_t free);
     3.5  void rb_set_compare_func(struct rbtree *rb, rb_cmp_func_t func);
     3.6  void rb_set_delete_func(struct rbtree *rb, rb_del_func_t func, void *cls);
     3.7 +/* TODO add user deep copy function */
     3.8  
     3.9  void rb_clear(struct rbtree *rb);
    3.10  int rb_copy(struct rbtree *dest, struct rbtree *src);
     4.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     4.2 +++ b/test/rbshell/Makefile	Mon Apr 16 00:26:38 2012 +0300
     4.3 @@ -0,0 +1,14 @@
     4.4 +src = $(wildcard *.c)
     4.5 +obj = $(src:.c=.o)
     4.6 +bin = test
     4.7 +
     4.8 +CC = gcc
     4.9 +CFLAGS = -pedantic -Wall -g -I../../src -I/usr/local/include
    4.10 +LDFLAGS = -L../.. -L/usr/local/lib -lrbtree
    4.11 +
    4.12 +$(bin): $(obj)
    4.13 +	$(CC) -o $@ $(obj) $(LDFLAGS)
    4.14 +
    4.15 +.PHONY: clean
    4.16 +clean:
    4.17 +	rm -f $(obj) $(bin)
     5.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     5.2 +++ b/test/rbshell/sym.c	Mon Apr 16 00:26:38 2012 +0300
     5.3 @@ -0,0 +1,73 @@
     5.4 +#include <stdio.h>
     5.5 +#include <stdlib.h>
     5.6 +#include <string.h>
     5.7 +#include "sym.h"
     5.8 +#include "rbtree.h"
     5.9 +
    5.10 +struct symbol {
    5.11 +	char *name;
    5.12 +	int id, arity;
    5.13 +};
    5.14 +
    5.15 +static void del_func(struct rbnode *node, void *cls);
    5.16 +
    5.17 +struct rbtree *symbols;
    5.18 +
    5.19 +int init_sym(void)
    5.20 +{
    5.21 +	if(!(symbols = rb_create(RB_KEY_STRING))) {
    5.22 +		fprintf(stderr, "failed to create symbol table\n");
    5.23 +		return -1;
    5.24 +	}
    5.25 +	rb_set_delete_func(symbols, del_func, 0);
    5.26 +	return 0;
    5.27 +}
    5.28 +
    5.29 +void destroy_sym(void)
    5.30 +{
    5.31 +	rb_free(symbols);
    5.32 +}
    5.33 +
    5.34 +int add_sym(const char *name, int id, int arity)
    5.35 +{
    5.36 +	struct symbol *sym;
    5.37 +
    5.38 +	if(!(sym = malloc(sizeof *sym)) || !(sym->name = malloc(strlen(name) + 1))) {
    5.39 +		perror("failed to allocate symbol");
    5.40 +		free(sym);
    5.41 +		return -1;
    5.42 +	}
    5.43 +	strcpy(sym->name, name);
    5.44 +	sym->id = id;
    5.45 +	sym->arity = arity;
    5.46 +
    5.47 +	return rb_insert(symbols, sym->name, sym);
    5.48 +}
    5.49 +
    5.50 +int sym_lookup(const char *str)
    5.51 +{
    5.52 +	struct rbnode *node;
    5.53 +
    5.54 +	if(!(node = rb_find(symbols, (char*)str))) {
    5.55 +		fprintf(stderr, "undefined symbol: %s\n", str);
    5.56 +		return -1;
    5.57 +	}
    5.58 +	return ((struct symbol*)node->data)->id;
    5.59 +}
    5.60 +
    5.61 +int sym_arity(const char *str)
    5.62 +{
    5.63 +	struct rbnode *node;
    5.64 +
    5.65 +	if(!(node = rb_find(symbols, (char*)str))) {
    5.66 +		fprintf(stderr, "undefined symbol: %s\n", str);
    5.67 +		return -1;
    5.68 +	}
    5.69 +	return ((struct symbol*)node->data)->arity;
    5.70 +}
    5.71 +
    5.72 +static void del_func(struct rbnode *node, void *cls)
    5.73 +{
    5.74 +	free(((struct symbol*)node->data)->name);
    5.75 +	free(node->data);
    5.76 +}
     6.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     6.2 +++ b/test/rbshell/sym.h	Mon Apr 16 00:26:38 2012 +0300
     6.3 @@ -0,0 +1,12 @@
     6.4 +#ifndef SYM_H_
     6.5 +#define SYM_H_
     6.6 +
     6.7 +int init_sym(void);
     6.8 +void destroy_sym(void);
     6.9 +
    6.10 +int add_sym(const char *name, int id, int arity);
    6.11 +
    6.12 +int sym_lookup(const char *str);
    6.13 +int sym_arity(const char *str);
    6.14 +
    6.15 +#endif	/* SYM_H_ */
     7.1 --- /dev/null	Thu Jan 01 00:00:00 1970 +0000
     7.2 +++ b/test/rbshell/test.c	Mon Apr 16 00:26:38 2012 +0300
     7.3 @@ -0,0 +1,214 @@
     7.4 +#include <stdio.h>
     7.5 +#include <stdlib.h>
     7.6 +#include <string.h>
     7.7 +#include <ctype.h>
     7.8 +#include "rbtree.h"
     7.9 +#include "sym.h"
    7.10 +
    7.11 +#define SEP	" \t\r\n,\"\'"
    7.12 +
    7.13 +/* commands */
    7.14 +enum {
    7.15 +	CMD_CREATE,
    7.16 +	CMD_DESTROY,
    7.17 +	CMD_CLEAR,
    7.18 +	CMD_COPY,
    7.19 +	CMD_SIZE,
    7.20 +	CMD_INSERT,
    7.21 +	CMD_DELETE,
    7.22 +	CMD_FIND,
    7.23 +	CMD_PRINT,
    7.24 +
    7.25 +	MAX_CMD
    7.26 +};
    7.27 +
    7.28 +int runcmd(int cmd, int argc, char **argv);
    7.29 +
    7.30 +#define NUM_TREES	8
    7.31 +struct rbtree *trees[NUM_TREES];
    7.32 +
    7.33 +
    7.34 +int main(void)
    7.35 +{
    7.36 +	char buf[512];
    7.37 +
    7.38 +	/* init symbol table */
    7.39 +	if(init_sym() == -1) {
    7.40 +		return 1;
    7.41 +	}
    7.42 +	add_sym("create", CMD_CREATE, 0);
    7.43 +	add_sym("destroy", CMD_DESTROY, 1);
    7.44 +	add_sym("clear", CMD_CLEAR, 1);
    7.45 +	add_sym("copy", CMD_COPY, 2);
    7.46 +	add_sym("size", CMD_SIZE, 1);
    7.47 +	add_sym("insert", CMD_INSERT, 2);
    7.48 +	add_sym("delete", CMD_DELETE, 2);
    7.49 +	add_sym("find", CMD_FIND, 2);
    7.50 +	add_sym("print", CMD_PRINT, 1);
    7.51 +
    7.52 +	for(;;) {
    7.53 +		int argc = 0;
    7.54 +		char *argv[8];
    7.55 +		int cmd_id, cmd_arity;
    7.56 +
    7.57 +		printf("rbshell> ");
    7.58 +		fflush(stdout);
    7.59 +
    7.60 +		if(!fgets(buf, sizeof buf, stdin)) {
    7.61 +			putchar('\n');
    7.62 +			break;
    7.63 +		}
    7.64 +
    7.65 +		if(!(argv[argc] = strtok(buf, SEP)) || argv[argc][0] == '#') {
    7.66 +			return 0;	/* empty / comment */
    7.67 +		}
    7.68 +		argc++;
    7.69 +
    7.70 +		if((cmd_id = sym_lookup(argv[0])) == -1) {
    7.71 +			continue;
    7.72 +		}
    7.73 +		cmd_arity = sym_arity(argv[0]);
    7.74 +
    7.75 +		while((argv[argc] = strtok(0, SEP))) {
    7.76 +			argc++;
    7.77 +			if(argc >= sizeof argv / sizeof *argv) {
    7.78 +				break;
    7.79 +			}
    7.80 +		}
    7.81 +
    7.82 +		if(argc - 1 != cmd_arity) {
    7.83 +			fprintf(stderr, "too many (%d) arguments for %s, expected %d\n", argc - 1, argv[0], cmd_arity);
    7.84 +			continue;
    7.85 +		}
    7.86 +
    7.87 +		runcmd(cmd_id, argc, argv);
    7.88 +	}
    7.89 +
    7.90 +	destroy_sym();
    7.91 +	return 0;
    7.92 +}
    7.93 +
    7.94 +#define CHECKINT(i)		\
    7.95 +	if(!isdigit(argv[i][0])) { \
    7.96 +		fprintf(stderr, "expected number, got: %s\n", argv[i]); \
    7.97 +		return -1; \
    7.98 +	}
    7.99 +
   7.100 +#define CHECKVALID(idx)	\
   7.101 +	if((idx) < 0 || (idx) >= NUM_TREES || !trees[idx]) { \
   7.102 +		fprintf(stderr, "invalid tree specified: %d\n", idx); \
   7.103 +		return -1; \
   7.104 +	}
   7.105 +
   7.106 +
   7.107 +int runcmd(int cmd, int argc, char **argv)
   7.108 +{
   7.109 +	int i, idx, idx2, n;
   7.110 +	struct rbnode *node;
   7.111 +
   7.112 +	switch(cmd) {
   7.113 +	case CMD_CREATE:
   7.114 +		for(i=0; i<NUM_TREES; i++) {
   7.115 +			if(trees[i] == 0) {
   7.116 +				if(!(trees[i] = rb_create(RB_KEY_INT))) {
   7.117 +					fprintf(stderr, "failed to create a new tree\n");
   7.118 +					return -1;
   7.119 +				}
   7.120 +				printf("created new tree: %d\n", i);
   7.121 +				break;
   7.122 +			}
   7.123 +		}
   7.124 +		if(i == NUM_TREES) {
   7.125 +			fprintf(stderr, "can't create more trees\n");
   7.126 +			return -1;
   7.127 +		}
   7.128 +		break;
   7.129 +
   7.130 +	case CMD_DESTROY:
   7.131 +		CHECKINT(1);
   7.132 +		idx = atoi(argv[1]);
   7.133 +		CHECKVALID(idx);
   7.134 +
   7.135 +		rb_free(trees[idx]);
   7.136 +		trees[idx] = 0;
   7.137 +		printf("destroyed tree: %d\n", idx);
   7.138 +		break;
   7.139 +
   7.140 +	case CMD_CLEAR:
   7.141 +		CHECKINT(1);
   7.142 +		idx = atoi(argv[1]);
   7.143 +		CHECKVALID(idx);
   7.144 +
   7.145 +		rb_clear(trees[idx]);
   7.146 +		printf("cleared tree: %d\n", idx);
   7.147 +		break;
   7.148 +
   7.149 +	case CMD_COPY:
   7.150 +		CHECKINT(1);
   7.151 +		CHECKINT(2);
   7.152 +		idx = atoi(argv[1]);
   7.153 +		idx2 = atoi(argv[2]);
   7.154 +		CHECKVALID(idx);
   7.155 +		CHECKVALID(idx2);
   7.156 +
   7.157 +		rb_copy(trees[idx2], trees[idx]);
   7.158 +		printf("copied %d -> %d\n", idx, idx2);
   7.159 +		break;
   7.160 +
   7.161 +	case CMD_SIZE:
   7.162 +		CHECKINT(1);
   7.163 +		idx = atoi(argv[1]);
   7.164 +		CHECKVALID(idx);
   7.165 +
   7.166 +		printf("tree size: %d\n", rb_size(trees[idx]));
   7.167 +		break;
   7.168 +
   7.169 +	case CMD_INSERT:
   7.170 +		CHECKINT(1);
   7.171 +		CHECKINT(2);
   7.172 +		idx = atoi(argv[1]);
   7.173 +		CHECKVALID(idx);
   7.174 +
   7.175 +		n = atoi(argv[2]);
   7.176 +		rb_inserti(trees[idx], n, 0);
   7.177 +		printf("inserted: %d\n", n);
   7.178 +		break;
   7.179 +
   7.180 +	case CMD_DELETE:
   7.181 +	case CMD_FIND:
   7.182 +		CHECKINT(1);
   7.183 +		CHECKINT(2);
   7.184 +		idx = atoi(argv[1]);
   7.185 +		CHECKVALID(idx);
   7.186 +		n = atoi(argv[2]);
   7.187 +
   7.188 +		if(!rb_findi(trees[idx], n)) {
   7.189 +			fprintf(stderr, "%d not found\n", n);
   7.190 +		} else {
   7.191 +			if(cmd == CMD_DELETE) {
   7.192 +				rb_deletei(trees[idx], n);
   7.193 +				printf("deleted %d\n", n);
   7.194 +			} else {
   7.195 +				printf("found %d\n", n);
   7.196 +			}
   7.197 +		}
   7.198 +		break;
   7.199 +
   7.200 +	case CMD_PRINT:
   7.201 +		CHECKINT(1);
   7.202 +		idx = atoi(argv[1]);
   7.203 +		CHECKVALID(idx);
   7.204 +
   7.205 +		rb_begin(trees[idx]);
   7.206 +		while((node = rb_next(trees[idx]))) {
   7.207 +			printf("%d ", rb_node_keyi(node));
   7.208 +		}
   7.209 +		putchar('\n');
   7.210 +		break;
   7.211 +
   7.212 +	default:
   7.213 +		/* can't happen */
   7.214 +		break;
   7.215 +	}
   7.216 +	return 0;
   7.217 +}