Commit e3a19d3b authored by Jacek Caban's avatar Jacek Caban Committed by Alexandre Julliard

rbtree.h: Rewrite wine_rb_put to use parent pointers instead of stack.

parent f9dc4832
...@@ -94,7 +94,7 @@ static inline int wine_rb_is_red(struct wine_rb_entry *entry) ...@@ -94,7 +94,7 @@ static inline int wine_rb_is_red(struct wine_rb_entry *entry)
return entry && (entry->flags & WINE_RB_FLAG_RED); return entry && (entry->flags & WINE_RB_FLAG_RED);
} }
static inline void wine_rb_rotate_left(struct wine_rb_tree *tree, struct wine_rb_entry *e, int change_color) static inline void wine_rb_rotate_left(struct wine_rb_tree *tree, struct wine_rb_entry *e)
{ {
struct wine_rb_entry *right = e->right; struct wine_rb_entry *right = e->right;
...@@ -110,15 +110,9 @@ static inline void wine_rb_rotate_left(struct wine_rb_tree *tree, struct wine_rb ...@@ -110,15 +110,9 @@ static inline void wine_rb_rotate_left(struct wine_rb_tree *tree, struct wine_rb
right->left = e; right->left = e;
right->parent = e->parent; right->parent = e->parent;
e->parent = right; e->parent = right;
if (change_color)
{
right->flags &= ~WINE_RB_FLAG_RED;
right->flags |= e->flags & WINE_RB_FLAG_RED;
e->flags |= WINE_RB_FLAG_RED;
}
} }
static inline void wine_rb_rotate_right(struct wine_rb_tree *tree, struct wine_rb_entry *e, int change_color) static inline void wine_rb_rotate_right(struct wine_rb_tree *tree, struct wine_rb_entry *e)
{ {
struct wine_rb_entry *left = e->left; struct wine_rb_entry *left = e->left;
...@@ -134,12 +128,6 @@ static inline void wine_rb_rotate_right(struct wine_rb_tree *tree, struct wine_r ...@@ -134,12 +128,6 @@ static inline void wine_rb_rotate_right(struct wine_rb_tree *tree, struct wine_r
left->right = e; left->right = e;
left->parent = e->parent; left->parent = e->parent;
e->parent = left; e->parent = left;
if (change_color)
{
left->flags &= ~WINE_RB_FLAG_RED;
left->flags |= e->flags & WINE_RB_FLAG_RED;
e->flags |= WINE_RB_FLAG_RED;
}
} }
static inline void wine_rb_flip_color(struct wine_rb_entry *entry) static inline void wine_rb_flip_color(struct wine_rb_entry *entry)
...@@ -149,25 +137,6 @@ static inline void wine_rb_flip_color(struct wine_rb_entry *entry) ...@@ -149,25 +137,6 @@ static inline void wine_rb_flip_color(struct wine_rb_entry *entry)
entry->right->flags ^= WINE_RB_FLAG_RED; entry->right->flags ^= WINE_RB_FLAG_RED;
} }
static inline void wine_rb_fixup(struct wine_rb_tree *tree, struct wine_rb_stack *stack)
{
while (stack->count)
{
struct wine_rb_entry **entry = stack->entries[stack->count - 1];
if ((*entry)->flags & WINE_RB_FLAG_STOP)
{
(*entry)->flags &= ~WINE_RB_FLAG_STOP;
return;
}
if (wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->left)) wine_rb_rotate_left(tree, *entry, 1);
if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->left->left)) wine_rb_rotate_right(tree, *entry, 1);
if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->right)) wine_rb_flip_color(*entry);
--stack->count;
}
}
static inline struct wine_rb_entry *wine_rb_postorder_head(struct wine_rb_entry *iter) static inline struct wine_rb_entry *wine_rb_postorder_head(struct wine_rb_entry *iter)
{ {
if (!iter) return NULL; if (!iter) return NULL;
...@@ -243,41 +212,66 @@ static inline struct wine_rb_entry *wine_rb_get(const struct wine_rb_tree *tree, ...@@ -243,41 +212,66 @@ static inline struct wine_rb_entry *wine_rb_get(const struct wine_rb_tree *tree,
static inline int wine_rb_put(struct wine_rb_tree *tree, const void *key, struct wine_rb_entry *entry) static inline int wine_rb_put(struct wine_rb_tree *tree, const void *key, struct wine_rb_entry *entry)
{ {
struct wine_rb_entry **iter = &tree->root, *parent = tree->root; struct wine_rb_entry **iter = &tree->root, *parent = tree->root;
size_t black_height = 1;
while (*iter) while (*iter)
{ {
int c; int c;
if (!wine_rb_is_red(*iter)) ++black_height;
wine_rb_stack_push(&tree->stack, iter);
parent = *iter; parent = *iter;
c = tree->functions->compare(key, parent); c = tree->functions->compare(key, parent);
if (!c) if (!c) return -1;
{
wine_rb_stack_clear(&tree->stack);
return -1;
}
else if (c < 0) iter = &parent->left; else if (c < 0) iter = &parent->left;
else iter = &parent->right; else iter = &parent->right;
} }
/* After insertion, the path length to any node should be <= (black_height + 1) * 2. */
if (wine_rb_ensure_stack_size(tree, black_height << 1) == -1)
{
wine_rb_stack_clear(&tree->stack);
return -1;
}
entry->flags = WINE_RB_FLAG_RED; entry->flags = WINE_RB_FLAG_RED;
entry->parent = parent; entry->parent = parent;
entry->left = NULL; entry->left = NULL;
entry->right = NULL; entry->right = NULL;
*iter = entry; *iter = entry;
wine_rb_fixup(tree, &tree->stack); while (wine_rb_is_red(entry->parent))
{
if (entry->parent == entry->parent->parent->left)
{
if (wine_rb_is_red(entry->parent->parent->right))
{
wine_rb_flip_color(entry->parent->parent);
entry = entry->parent->parent;
}
else
{
if (entry == entry->parent->right)
{
entry = entry->parent;
wine_rb_rotate_left(tree, entry);
}
entry->parent->flags &= ~WINE_RB_FLAG_RED;
entry->parent->parent->flags |= WINE_RB_FLAG_RED;
wine_rb_rotate_right(tree, entry->parent->parent);
}
}
else
{
if (wine_rb_is_red(entry->parent->parent->left))
{
wine_rb_flip_color(entry->parent->parent);
entry = entry->parent->parent;
}
else
{
if (entry == entry->parent->left)
{
entry = entry->parent;
wine_rb_rotate_right(tree, entry);
}
entry->parent->flags &= ~WINE_RB_FLAG_RED;
entry->parent->parent->flags |= WINE_RB_FLAG_RED;
wine_rb_rotate_left(tree, entry->parent->parent);
}
}
}
tree->root->flags &= ~WINE_RB_FLAG_RED; tree->root->flags &= ~WINE_RB_FLAG_RED;
return 0; return 0;
...@@ -335,7 +329,7 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key) ...@@ -335,7 +329,7 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key)
{ {
w->flags &= ~WINE_RB_FLAG_RED; w->flags &= ~WINE_RB_FLAG_RED;
parent->flags |= WINE_RB_FLAG_RED; parent->flags |= WINE_RB_FLAG_RED;
wine_rb_rotate_left(tree, parent, 0); wine_rb_rotate_left(tree, parent);
w = parent->right; w = parent->right;
} }
if (wine_rb_is_red(w->left) || wine_rb_is_red(w->right)) if (wine_rb_is_red(w->left) || wine_rb_is_red(w->right))
...@@ -344,14 +338,14 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key) ...@@ -344,14 +338,14 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key)
{ {
w->left->flags &= ~WINE_RB_FLAG_RED; w->left->flags &= ~WINE_RB_FLAG_RED;
w->flags |= WINE_RB_FLAG_RED; w->flags |= WINE_RB_FLAG_RED;
wine_rb_rotate_right(tree, w, 0); wine_rb_rotate_right(tree, w);
w = parent->right; w = parent->right;
} }
w->flags = (w->flags & ~WINE_RB_FLAG_RED) | (parent->flags & WINE_RB_FLAG_RED); w->flags = (w->flags & ~WINE_RB_FLAG_RED) | (parent->flags & WINE_RB_FLAG_RED);
parent->flags &= ~WINE_RB_FLAG_RED; parent->flags &= ~WINE_RB_FLAG_RED;
if (w->right) if (w->right)
w->right->flags &= ~WINE_RB_FLAG_RED; w->right->flags &= ~WINE_RB_FLAG_RED;
wine_rb_rotate_left(tree, parent, 0); wine_rb_rotate_left(tree, parent);
child = NULL; child = NULL;
break; break;
} }
...@@ -363,7 +357,7 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key) ...@@ -363,7 +357,7 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key)
{ {
w->flags &= ~WINE_RB_FLAG_RED; w->flags &= ~WINE_RB_FLAG_RED;
parent->flags |= WINE_RB_FLAG_RED; parent->flags |= WINE_RB_FLAG_RED;
wine_rb_rotate_right(tree, parent, 0); wine_rb_rotate_right(tree, parent);
w = parent->left; w = parent->left;
} }
if (wine_rb_is_red(w->left) || wine_rb_is_red(w->right)) if (wine_rb_is_red(w->left) || wine_rb_is_red(w->right))
...@@ -372,14 +366,14 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key) ...@@ -372,14 +366,14 @@ static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key)
{ {
w->right->flags &= ~WINE_RB_FLAG_RED; w->right->flags &= ~WINE_RB_FLAG_RED;
w->flags |= WINE_RB_FLAG_RED; w->flags |= WINE_RB_FLAG_RED;
wine_rb_rotate_left(tree, w, 0); wine_rb_rotate_left(tree, w);
w = parent->left; w = parent->left;
} }
w->flags = (w->flags & ~WINE_RB_FLAG_RED) | (parent->flags & WINE_RB_FLAG_RED); w->flags = (w->flags & ~WINE_RB_FLAG_RED) | (parent->flags & WINE_RB_FLAG_RED);
parent->flags &= ~WINE_RB_FLAG_RED; parent->flags &= ~WINE_RB_FLAG_RED;
if (w->left) if (w->left)
w->left->flags &= ~WINE_RB_FLAG_RED; w->left->flags &= ~WINE_RB_FLAG_RED;
wine_rb_rotate_right(tree, parent, 0); wine_rb_rotate_right(tree, parent);
child = NULL; child = NULL;
break; break;
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment