Archived
1
0
Fork 0

common/rbtree: fixed a bug in delete

This commit is contained in:
Henrik Hautakoski 2010-10-02 08:20:48 +02:00
parent 8d7b4a74c7
commit 7209cfb1c4
7 changed files with 52 additions and 37 deletions

View file

@ -11,23 +11,20 @@
* http://www.eternallyconfuzzled.com/tuts/datastructures/jsw_tut_rbtree.aspx
*/
#include <malloc.h>
#include "xalloc.h"
#include "debug.h"
#include "rbtree.h"
#define is_red(n) ((n) != NULL && (n)->color == RB_RED)
#define swap(n,d,q) ((n)->child[(n)->child[d] == (q)])
static rbnode* node_alloc(uint key, void *ptr) {
static rbnode* node_alloc(uint key, void *ptr, size_t len) {
rbnode *n = malloc(sizeof(rbnode));
if (n == NULL)
return NULL;
rbnode *n = xmalloc(sizeof(rbnode));
n->key = key;
n->data = ptr;
n->len = len;
n->color = RB_RED;
n->child[0] = NULL;
n->child[1] = NULL;
@ -46,14 +43,14 @@ static void node_dealloc(rbnode *n, void (*action)(rbnode *)) {
if (action != NULL) {
action(n);
} else if (n->data != NULL) {
free(n->data);
xfree(n->data);
n->data = NULL;
}
node_dealloc(n->child[0], action);
node_dealloc(n->child[1], action);
free(n);
xfree(n);
}
/*
@ -185,7 +182,7 @@ void rbtree_free(rbtree *tree, void (*action)(rbnode *)) {
*
* the function now returns -1 in that situation // H Hautakoski
*/
int rbtree_insert(rbtree *tree, uint key, void *data) {
int rbtree_insert(rbtree *tree, uint key, void *data, size_t len) {
rbnode head = {0};
@ -198,7 +195,7 @@ int rbtree_insert(rbtree *tree, uint key, void *data) {
unsigned char dir = 0, dir2, last, inserted = 0;
if (tree->root == NULL) {
tree->root = node_alloc(key, data);
tree->root = node_alloc(key, data, len);
if (tree->root == NULL)
return 0;
goto done;
@ -212,7 +209,7 @@ int rbtree_insert(rbtree *tree, uint key, void *data) {
for(;;) {
if (q == NULL) {
p->child[dir] = q = node_alloc(key, data);
p->child[dir] = q = node_alloc(key, data, len);
if (q == NULL)
return 0;
inserted = 1;
@ -325,18 +322,15 @@ void* rbtree_delete(rbtree *tree, uint key) {
tree->root->color = RB_BLACK;
/* remove if found */
if (f != NULL) {
ret = q->data;
if (q == tree->root) {
tree->root = NULL;
} else {
if (f != q) {
f->key = q->key;
f->data = q->data;
}
swap(p, 1, q) = swap(q, 0, NULL);
}
free(q);
if (f) {
ret = f->data;
if (f != q) {
f->key = q->key;
f->data = xmemdup(q->data, q->len);
f->len = q->len;
}
swap(p, 1, q) = swap(q, 0, NULL);
xfree(q);
}
return ret;

View file

@ -42,7 +42,7 @@ void rbtree_walk(rbtree *tree, void (*action)(rbnode *));
void rbtree_free(rbtree *tree, void (*action)(rbnode *));
int rbtree_insert(rbtree *tree, uint key, void *data);
int rbtree_insert(rbtree *tree, uint key, void *data, size_t len);
void* rbtree_delete(rbtree *tree, uint key);

View file

@ -75,6 +75,17 @@ bail:
die_errno("xstrdup");
}
void* xmemdup(const void *src, size_t size) {
CHECK_INPUT(src);
void *dest = xmalloc(size);
memcpy(dest, src, size);
return dest;
bail:
die_errno("xmemdup");
}
void xfree(void *ptr) {
CHECK_INPUT(ptr);

View file

@ -21,6 +21,8 @@ void* xrealloc(void *, size_t);
char* xstrdup(const char *);
void* xmemdup(const void *, size_t);
void xfree(void *);
#endif /* __COMMON_XALLOC_H */

View file

@ -42,16 +42,17 @@ static queue_t event_queue;
static int addwatch(const char *path, const char *name) {
rbnode *node;
char *cpath;
char *npath;
int wd;
cpath = path_normalize(path, name, 1);
npath = path_normalize(path, name, 1);
wd = inotify_add_watch(fd, cpath, WATCH_MASK);
wd = inotify_add_watch(fd, npath, WATCH_MASK);
if (wd < 0) {
perror("NOTIFY ADD");
dprint("%i path %s\n", errno == EBADF, cpath);
dprint("%i path %s\n", errno == EBADF, npath);
free(npath);
return -errno;
}
@ -59,12 +60,13 @@ static int addwatch(const char *path, const char *name) {
node = rbtree_search(&tree, wd);
if (node == NULL) {
dprint("added wd = %i on %s\n", wd, cpath);
rbtree_insert(&tree, wd, (void*)cpath);
dprint("added wd = %i on %s\n", wd, npath);
rbtree_insert(&tree, wd, (void*)npath, strlen(npath)+1);
} else {
dprint("updated wd = %i from %s to %s\n", wd, (char*)node->data, cpath);
dprint("updated wd = %i from %s to %s\n", wd, (char*)node->data, npath);
free(node->data);
node->data = (void*) cpath;
node->data = (void*) npath;
node->len = strlen(npath)+1;
}
return wd;

View file

@ -28,6 +28,7 @@ rbtree :
$(CC) $(CFLAGS) \
unit.c \
../src/common/die.c \
../src/common/xalloc.c \
../src/common/rbtree.c \
t_rbtree.c -o test_rbtree

View file

@ -60,7 +60,8 @@ static int rb_assert(rbnode *node) {
/* data */
static rbtree tree;
static uint keyref[NODES];
static uint keyref[NODES];
static char *dataref[NODES];
static uint search_key = -1;
static char search_data[32];
@ -79,7 +80,7 @@ void test_insert() {
data = utest_ran_string(32);
/* insert into rbtree and assert it */
ret = rbtree_insert(&tree, ckey, data);
ret = rbtree_insert(&tree, ckey, data, 32);
rb_assert(tree.root);
dprint("INSERT: %i %s\n", ckey, data);
@ -89,6 +90,7 @@ void test_insert() {
continue;
keyref[i] = ckey;
dataref[i] = data;
if (i == ((NODES/2))) {
search_key = ckey;
@ -99,7 +101,7 @@ void test_insert() {
}
/* insert duplicate key */
assert(rbtree_insert(&tree, search_key, "duplicate") == -1);
assert(rbtree_insert(&tree, search_key, "duplicate", 10) == -1);
rb_assert(tree.root);
}
@ -107,13 +109,16 @@ void test_delete() {
int i;
uint key;
char *data, *dref;
/* remove some values */
for(i=0; i < 10; i++) {
key = keyref[(NODES/2)+i];
dref = dataref[(NODES/2)+i];
rbtree_delete(&tree, key);
data = rbtree_delete(&tree, key);
assert_string(data, dref);
rb_assert(tree.root);
}
}