version 1.1.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; |
} |
} |