2 * Red-black search tree support
4 * Copyright 2009 Henri Verbeet
5 * Copyright 2009 Andrew Riedi
6 * Copyright 2016 Jacek Caban for CodeWeavers
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2.1 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, write to the Free Software
20 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
23 #ifndef __WINE_WINE_RBTREE_H
24 #define __WINE_WINE_RBTREE_H
27 # define WINE_RB_ENTRY_VALUE(element, type, field) ({ \
28 const typeof(((type *)0)->field) *__ptr = (element); \
29 (type *)((char *)__ptr - offsetof(type, field)); })
31 # define WINE_RB_ENTRY_VALUE(element, type, field) \
32 ((type *)((char *)(element) - offsetof(type, field)))
37 struct wine_rb_entry
*parent
;
38 struct wine_rb_entry
*left
;
39 struct wine_rb_entry
*right
;
43 typedef int (*wine_rb_compare_func_t
)(const void *key
, const struct wine_rb_entry
*entry
);
47 wine_rb_compare_func_t compare
;
48 struct wine_rb_entry
*root
;
51 typedef void (wine_rb_traverse_func_t
)(struct wine_rb_entry
*entry
, void *context
);
53 #define WINE_RB_FLAG_RED 0x1
55 static inline int wine_rb_is_red(struct wine_rb_entry
*entry
)
57 return entry
&& (entry
->flags
& WINE_RB_FLAG_RED
);
60 static inline void wine_rb_rotate_left(struct wine_rb_tree
*tree
, struct wine_rb_entry
*e
)
62 struct wine_rb_entry
*right
= e
->right
;
66 else if (e
->parent
->left
== e
)
67 e
->parent
->left
= right
;
69 e
->parent
->right
= right
;
71 e
->right
= right
->left
;
72 if (e
->right
) e
->right
->parent
= e
;
74 right
->parent
= e
->parent
;
78 static inline void wine_rb_rotate_right(struct wine_rb_tree
*tree
, struct wine_rb_entry
*e
)
80 struct wine_rb_entry
*left
= e
->left
;
84 else if (e
->parent
->left
== e
)
85 e
->parent
->left
= left
;
87 e
->parent
->right
= left
;
89 e
->left
= left
->right
;
90 if (e
->left
) e
->left
->parent
= e
;
92 left
->parent
= e
->parent
;
96 static inline void wine_rb_flip_color(struct wine_rb_entry
*entry
)
98 entry
->flags
^= WINE_RB_FLAG_RED
;
99 entry
->left
->flags
^= WINE_RB_FLAG_RED
;
100 entry
->right
->flags
^= WINE_RB_FLAG_RED
;
103 static inline struct wine_rb_entry
*wine_rb_head(struct wine_rb_entry
*iter
)
105 if (!iter
) return NULL
;
106 while (iter
->left
) iter
= iter
->left
;
110 static inline struct wine_rb_entry
*wine_rb_next(struct wine_rb_entry
*iter
)
112 if (iter
->right
) return wine_rb_head(iter
->right
);
113 while (iter
->parent
&& iter
->parent
->right
== iter
) iter
= iter
->parent
;
117 static inline struct wine_rb_entry
*wine_rb_postorder_head(struct wine_rb_entry
*iter
)
119 if (!iter
) return NULL
;
122 while (iter
->left
) iter
= iter
->left
;
123 if (!iter
->right
) return iter
;
128 static inline struct wine_rb_entry
*wine_rb_postorder_next(struct wine_rb_entry
*iter
)
130 if (!iter
->parent
) return NULL
;
131 if (iter
== iter
->parent
->right
|| !iter
->parent
->right
) return iter
->parent
;
132 return wine_rb_postorder_head(iter
->parent
->right
);
135 /* iterate through the tree */
136 #define WINE_RB_FOR_EACH(cursor, tree) \
137 for ((cursor) = wine_rb_head((tree)->root); (cursor); (cursor) = wine_rb_next(cursor))
139 /* iterate through the tree using a tree entry */
140 #define WINE_RB_FOR_EACH_ENTRY(elem, tree, type, field) \
141 for ((elem) = WINE_RB_ENTRY_VALUE(wine_rb_head((tree)->root), type, field); \
143 (elem) = WINE_RB_ENTRY_VALUE(wine_rb_next(&elem->field), type, field))
146 static inline void wine_rb_postorder(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
148 struct wine_rb_entry
*iter
, *next
;
150 for (iter
= wine_rb_postorder_head(tree
->root
); iter
; iter
= next
)
152 next
= wine_rb_postorder_next(iter
);
153 callback(iter
, context
);
157 static inline void wine_rb_init(struct wine_rb_tree
*tree
, wine_rb_compare_func_t compare
)
159 tree
->compare
= compare
;
163 static inline void wine_rb_for_each_entry(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
165 struct wine_rb_entry
*iter
;
166 WINE_RB_FOR_EACH(iter
, tree
) callback(iter
, context
);
169 static inline void wine_rb_clear(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
171 /* Note that we use postorder here because the callback will likely free the entry. */
172 if (callback
) wine_rb_postorder(tree
, callback
, context
);
176 static inline void wine_rb_destroy(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
178 wine_rb_clear(tree
, callback
, context
);
181 static inline struct wine_rb_entry
*wine_rb_get(const struct wine_rb_tree
*tree
, const void *key
)
183 struct wine_rb_entry
*entry
= tree
->root
;
186 int c
= tree
->compare(key
, entry
);
187 if (!c
) return entry
;
188 entry
= c
< 0 ? entry
->left
: entry
->right
;
193 static inline int wine_rb_put(struct wine_rb_tree
*tree
, const void *key
, struct wine_rb_entry
*entry
)
195 struct wine_rb_entry
**iter
= &tree
->root
, *parent
= tree
->root
;
202 c
= tree
->compare(key
, parent
);
204 else if (c
< 0) iter
= &parent
->left
;
205 else iter
= &parent
->right
;
208 entry
->flags
= WINE_RB_FLAG_RED
;
209 entry
->parent
= parent
;
214 while (wine_rb_is_red(entry
->parent
))
216 if (entry
->parent
== entry
->parent
->parent
->left
)
218 if (wine_rb_is_red(entry
->parent
->parent
->right
))
220 wine_rb_flip_color(entry
->parent
->parent
);
221 entry
= entry
->parent
->parent
;
225 if (entry
== entry
->parent
->right
)
227 entry
= entry
->parent
;
228 wine_rb_rotate_left(tree
, entry
);
230 entry
->parent
->flags
&= ~WINE_RB_FLAG_RED
;
231 entry
->parent
->parent
->flags
|= WINE_RB_FLAG_RED
;
232 wine_rb_rotate_right(tree
, entry
->parent
->parent
);
237 if (wine_rb_is_red(entry
->parent
->parent
->left
))
239 wine_rb_flip_color(entry
->parent
->parent
);
240 entry
= entry
->parent
->parent
;
244 if (entry
== entry
->parent
->left
)
246 entry
= entry
->parent
;
247 wine_rb_rotate_right(tree
, entry
);
249 entry
->parent
->flags
&= ~WINE_RB_FLAG_RED
;
250 entry
->parent
->parent
->flags
|= WINE_RB_FLAG_RED
;
251 wine_rb_rotate_left(tree
, entry
->parent
->parent
);
256 tree
->root
->flags
&= ~WINE_RB_FLAG_RED
;
261 static inline void wine_rb_remove(struct wine_rb_tree
*tree
, struct wine_rb_entry
*entry
)
263 struct wine_rb_entry
*iter
, *child
, *parent
, *w
;
266 if (entry
->right
&& entry
->left
)
267 for(iter
= entry
->right
; iter
->left
; iter
= iter
->left
);
271 child
= iter
->left
? iter
->left
: iter
->right
;
275 else if (iter
== iter
->parent
->left
)
276 iter
->parent
->left
= child
;
278 iter
->parent
->right
= child
;
280 if (child
) child
->parent
= iter
->parent
;
281 parent
= iter
->parent
;
283 need_fixup
= !wine_rb_is_red(iter
);
290 else if (entry
== iter
->parent
->left
)
291 iter
->parent
->left
= iter
;
293 iter
->parent
->right
= iter
;
295 if (iter
->right
) iter
->right
->parent
= iter
;
296 if (iter
->left
) iter
->left
->parent
= iter
;
297 if (parent
== entry
) parent
= iter
;
302 while (parent
&& !wine_rb_is_red(child
))
304 if (child
== parent
->left
)
307 if (wine_rb_is_red(w
))
309 w
->flags
&= ~WINE_RB_FLAG_RED
;
310 parent
->flags
|= WINE_RB_FLAG_RED
;
311 wine_rb_rotate_left(tree
, parent
);
314 if (wine_rb_is_red(w
->left
) || wine_rb_is_red(w
->right
))
316 if (!wine_rb_is_red(w
->right
))
318 w
->left
->flags
&= ~WINE_RB_FLAG_RED
;
319 w
->flags
|= WINE_RB_FLAG_RED
;
320 wine_rb_rotate_right(tree
, w
);
323 w
->flags
= (w
->flags
& ~WINE_RB_FLAG_RED
) | (parent
->flags
& WINE_RB_FLAG_RED
);
324 parent
->flags
&= ~WINE_RB_FLAG_RED
;
326 w
->right
->flags
&= ~WINE_RB_FLAG_RED
;
327 wine_rb_rotate_left(tree
, parent
);
335 if (wine_rb_is_red(w
))
337 w
->flags
&= ~WINE_RB_FLAG_RED
;
338 parent
->flags
|= WINE_RB_FLAG_RED
;
339 wine_rb_rotate_right(tree
, parent
);
342 if (wine_rb_is_red(w
->left
) || wine_rb_is_red(w
->right
))
344 if (!wine_rb_is_red(w
->left
))
346 w
->right
->flags
&= ~WINE_RB_FLAG_RED
;
347 w
->flags
|= WINE_RB_FLAG_RED
;
348 wine_rb_rotate_left(tree
, w
);
351 w
->flags
= (w
->flags
& ~WINE_RB_FLAG_RED
) | (parent
->flags
& WINE_RB_FLAG_RED
);
352 parent
->flags
&= ~WINE_RB_FLAG_RED
;
354 w
->left
->flags
&= ~WINE_RB_FLAG_RED
;
355 wine_rb_rotate_right(tree
, parent
);
360 w
->flags
|= WINE_RB_FLAG_RED
;
362 parent
= child
->parent
;
364 if (child
) child
->flags
&= ~WINE_RB_FLAG_RED
;
367 if (tree
->root
) tree
->root
->flags
&= ~WINE_RB_FLAG_RED
;
370 static inline void wine_rb_remove_key(struct wine_rb_tree
*tree
, const void *key
)
372 struct wine_rb_entry
*entry
= wine_rb_get(tree
, key
);
373 if (entry
) wine_rb_remove(tree
, entry
);
376 #endif /* __WINE_WINE_RBTREE_H */