|
|
| version 1.1, 2012/02/21 16:23:02 | version 1.1.1.3, 2013/07/22 10:46:12 |
|---|---|
| Line 1 | Line 1 |
| /* | /* |
| * Copyright (c) 2004-2005, 2007, 2009-2011 | * Copyright (c) 2004-2005, 2007, 2009-2013 |
| * Todd C. Miller <Todd.Miller@courtesan.com> | * Todd C. Miller <Todd.Miller@courtesan.com> |
| * | * |
| * Permission to use, copy, modify, and distribute this software for any | * Permission to use, copy, modify, and distribute this software for any |
| Line 43 | Line 43 |
| #include <config.h> | #include <config.h> |
| #include <sys/types.h> | #include <sys/types.h> |
| #include <sys/param.h> | |
| #include <stdio.h> | #include <stdio.h> |
| #ifdef STDC_HEADERS | #ifdef STDC_HEADERS |
| Line 57 | Line 56 |
| #include "missing.h" | #include "missing.h" |
| #include "alloc.h" | #include "alloc.h" |
| #include "sudo_debug.h" | |
| #include "redblack.h" | #include "redblack.h" |
| static void rbrepair(struct rbtree *, struct rbnode *); | static void rbrepair(struct rbtree *, struct rbnode *); |
| Line 90 struct rbtree * | Line 90 struct rbtree * |
| rbcreate(int (*compar)(const void *, const void*)) | rbcreate(int (*compar)(const void *, const void*)) |
| { | { |
| struct rbtree *tree; | struct rbtree *tree; |
| debug_decl(rbcreate, SUDO_DEBUG_RBTREE) | |
| tree = (struct rbtree *) emalloc(sizeof(*tree)); | tree = (struct rbtree *) emalloc(sizeof(*tree)); |
| tree->compar = compar; | tree->compar = compar; |
| Line 110 rbcreate(int (*compar)(const void *, const void*)) | Line 111 rbcreate(int (*compar)(const void *, const void*)) |
| tree->root.color = black; | tree->root.color = black; |
| tree->root.data = NULL; | tree->root.data = NULL; |
| return tree; | debug_return_ptr(tree); |
| } | } |
| /* | /* |
| Line 120 static void | Line 121 static void |
| rotate_left(struct rbtree *tree, struct rbnode *node) | rotate_left(struct rbtree *tree, struct rbnode *node) |
| { | { |
| struct rbnode *child; | struct rbnode *child; |
| debug_decl(rotate_left, SUDO_DEBUG_RBTREE) | |
| child = node->right; | child = node->right; |
| node->right = child->left; | node->right = child->left; |
| Line 134 rotate_left(struct rbtree *tree, struct rbnode *node) | Line 136 rotate_left(struct rbtree *tree, struct rbnode *node) |
| node->parent->right = child; | node->parent->right = child; |
| child->left = node; | child->left = node; |
| node->parent = child; | node->parent = child; |
| debug_return; | |
| } | } |
| /* | /* |
| Line 143 static void | Line 147 static void |
| rotate_right(struct rbtree *tree, struct rbnode *node) | rotate_right(struct rbtree *tree, struct rbnode *node) |
| { | { |
| struct rbnode *child; | struct rbnode *child; |
| debug_decl(rotate_right, SUDO_DEBUG_RBTREE) | |
| child = node->left; | child = node->left; |
| node->left = child->right; | node->left = child->right; |
| Line 157 rotate_right(struct rbtree *tree, struct rbnode *node) | Line 162 rotate_right(struct rbtree *tree, struct rbnode *node) |
| node->parent->right = child; | node->parent->right = child; |
| child->right = node; | child->right = node; |
| node->parent = child; | node->parent = child; |
| debug_return; | |
| } | } |
| /* | /* |
| Line 170 rbinsert(struct rbtree *tree, void *data) | Line 177 rbinsert(struct rbtree *tree, void *data) |
| struct rbnode *node = rbfirst(tree); | struct rbnode *node = rbfirst(tree); |
| struct rbnode *parent = rbroot(tree); | struct rbnode *parent = rbroot(tree); |
| int res; | int res; |
| debug_decl(rbinsert, SUDO_DEBUG_RBTREE) | |
| /* Find correct insertion point. */ | /* Find correct insertion point. */ |
| while (node != rbnil(tree)) { | while (node != rbnil(tree)) { |
| parent = node; | parent = node; |
| if ((res = tree->compar(data, node->data)) == 0) | if ((res = tree->compar(data, node->data)) == 0) |
| return node; | debug_return_ptr(node); |
| node = res < 0 ? node->left : node->right; | node = res < 0 ? node->left : node->right; |
| } | } |
| Line 249 rbinsert(struct rbtree *tree, void *data) | Line 257 rbinsert(struct rbtree *tree, void *data) |
| } | } |
| } | } |
| rbfirst(tree)->color = black; /* first node is always black */ | rbfirst(tree)->color = black; /* first node is always black */ |
| return NULL; | debug_return_ptr(NULL); |
| } | } |
| /* | /* |
| Line 261 rbfind(struct rbtree *tree, void *key) | Line 269 rbfind(struct rbtree *tree, void *key) |
| { | { |
| struct rbnode *node = rbfirst(tree); | struct rbnode *node = rbfirst(tree); |
| int res; | int res; |
| debug_decl(rbfind, SUDO_DEBUG_RBTREE) | |
| while (node != rbnil(tree)) { | while (node != rbnil(tree)) { |
| if ((res = tree->compar(key, node->data)) == 0) | if ((res = tree->compar(key, node->data)) == 0) |
| return node; | debug_return_ptr(node); |
| node = res < 0 ? node->left : node->right; | node = res < 0 ? node->left : node->right; |
| } | } |
| return NULL; | debug_return_ptr(NULL); |
| } | } |
| /* | /* |
| Line 280 rbapply_node(struct rbtree *tree, struct rbnode *node, | Line 289 rbapply_node(struct rbtree *tree, struct rbnode *node, |
| int (*func)(void *, void *), void *cookie, enum rbtraversal order) | int (*func)(void *, void *), void *cookie, enum rbtraversal order) |
| { | { |
| int error; | int error; |
| debug_decl(rbapply_node, SUDO_DEBUG_RBTREE) | |
| if (node != rbnil(tree)) { | if (node != rbnil(tree)) { |
| if (order == preorder) | if (order == preorder) |
| if ((error = func(node->data, cookie)) != 0) | if ((error = func(node->data, cookie)) != 0) |
| return error; | debug_return_int(error); |
| if ((error = rbapply_node(tree, node->left, func, cookie, order)) != 0) | if ((error = rbapply_node(tree, node->left, func, cookie, order)) != 0) |
| return error; | debug_return_int(error); |
| if (order == inorder) | if (order == inorder) |
| if ((error = func(node->data, cookie)) != 0) | if ((error = func(node->data, cookie)) != 0) |
| return error; | debug_return_int(error); |
| if ((error = rbapply_node(tree, node->right, func, cookie, order)) != 0) | if ((error = rbapply_node(tree, node->right, func, cookie, order)) != 0) |
| return error; | debug_return_int(error); |
| if (order == postorder) | if (order == postorder) |
| if ((error = func(node->data, cookie)) != 0) | if ((error = func(node->data, cookie)) != 0) |
| return error; | debug_return_int(error); |
| } | } |
| return 0; | debug_return_int(0); |
| } | } |
| /* | /* |
| Line 306 static struct rbnode * | Line 316 static struct rbnode * |
| rbsuccessor(struct rbtree *tree, struct rbnode *node) | rbsuccessor(struct rbtree *tree, struct rbnode *node) |
| { | { |
| struct rbnode *succ; | struct rbnode *succ; |
| debug_decl(rbsuccessor, SUDO_DEBUG_RBTREE) | |
| if ((succ = node->right) != rbnil(tree)) { | if ((succ = node->right) != rbnil(tree)) { |
| while (succ->left != rbnil(tree)) | while (succ->left != rbnil(tree)) |
| Line 317 rbsuccessor(struct rbtree *tree, struct rbnode *node) | Line 328 rbsuccessor(struct rbtree *tree, struct rbnode *node) |
| if (succ == rbroot(tree)) | if (succ == rbroot(tree)) |
| succ = rbnil(tree); | succ = rbnil(tree); |
| } | } |
| return succ; | debug_return_ptr(succ); |
| } | } |
| /* | /* |
| Line 326 rbsuccessor(struct rbtree *tree, struct rbnode *node) | Line 337 rbsuccessor(struct rbtree *tree, struct rbnode *node) |
| static void | static void |
| _rbdestroy(struct rbtree *tree, struct rbnode *node, void (*destroy)(void *)) | _rbdestroy(struct rbtree *tree, struct rbnode *node, void (*destroy)(void *)) |
| { | { |
| debug_decl(_rbdestroy, SUDO_DEBUG_RBTREE) | |
| if (node != rbnil(tree)) { | if (node != rbnil(tree)) { |
| _rbdestroy(tree, node->left, destroy); | _rbdestroy(tree, node->left, destroy); |
| _rbdestroy(tree, node->right, destroy); | _rbdestroy(tree, node->right, destroy); |
| Line 333 _rbdestroy(struct rbtree *tree, struct rbnode *node, v | Line 345 _rbdestroy(struct rbtree *tree, struct rbnode *node, v |
| destroy(node->data); | destroy(node->data); |
| efree(node); | efree(node); |
| } | } |
| debug_return; | |
| } | } |
| /* | /* |
| Line 342 _rbdestroy(struct rbtree *tree, struct rbnode *node, v | Line 355 _rbdestroy(struct rbtree *tree, struct rbnode *node, v |
| void | void |
| rbdestroy(struct rbtree *tree, void (*destroy)(void *)) | rbdestroy(struct rbtree *tree, void (*destroy)(void *)) |
| { | { |
| debug_decl(rbdestroy, SUDO_DEBUG_RBTREE) | |
| _rbdestroy(tree, rbfirst(tree), destroy); | _rbdestroy(tree, rbfirst(tree), destroy); |
| efree(tree); | efree(tree); |
| debug_return; | |
| } | } |
| /* | /* |
| Line 353 void *rbdelete(struct rbtree *tree, struct rbnode *z) | Line 368 void *rbdelete(struct rbtree *tree, struct rbnode *z) |
| { | { |
| struct rbnode *x, *y; | struct rbnode *x, *y; |
| void *data = z->data; | void *data = z->data; |
| debug_decl(rbdelete, SUDO_DEBUG_RBTREE) | |
| if (z->left == rbnil(tree) || z->right == rbnil(tree)) | if (z->left == rbnil(tree) || z->right == rbnil(tree)) |
| y = z; | y = z; |
| Line 383 void *rbdelete(struct rbtree *tree, struct rbnode *z) | Line 399 void *rbdelete(struct rbtree *tree, struct rbnode *z) |
| } | } |
| free(z); | free(z); |
| return data; | debug_return_ptr(data); |
| } | } |
| /* | /* |
| Line 394 static void | Line 410 static void |
| rbrepair(struct rbtree *tree, struct rbnode *node) | rbrepair(struct rbtree *tree, struct rbnode *node) |
| { | { |
| struct rbnode *sibling; | struct rbnode *sibling; |
| debug_decl(rbrepair, SUDO_DEBUG_RBTREE) | |
| while (node->color == black && node != rbroot(tree)) { | while (node->color == black && node != rbfirst(tree)) { |
| if (node == node->parent->left) { | if (node == node->parent->left) { |
| sibling = node->parent->right; | sibling = node->parent->right; |
| if (sibling->color == red) { | if (sibling->color == red) { |
| Line 418 rbrepair(struct rbtree *tree, struct rbnode *node) | Line 435 rbrepair(struct rbtree *tree, struct rbnode *node) |
| node->parent->color = black; | node->parent->color = black; |
| sibling->right->color = black; | sibling->right->color = black; |
| rotate_left(tree, node->parent); | rotate_left(tree, node->parent); |
| node = rbroot(tree); /* exit loop */ | node = rbfirst(tree); /* exit loop */ |
| } | } |
| } else { /* if (node == node->parent->right) */ | } else { /* if (node == node->parent->right) */ |
| sibling = node->parent->left; | sibling = node->parent->left; |
| Line 442 rbrepair(struct rbtree *tree, struct rbnode *node) | Line 459 rbrepair(struct rbtree *tree, struct rbnode *node) |
| node->parent->color = black; | node->parent->color = black; |
| sibling->left->color = black; | sibling->left->color = black; |
| rotate_right(tree, node->parent); | rotate_right(tree, node->parent); |
| node = rbroot(tree); /* exit loop */ | node = rbfirst(tree); /* exit loop */ |
| } | } |
| } | } |
| } | } |
| node->color = black; | node->color = black; |
| debug_return; | |
| } | } |