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
26 #define WINE_RB_ENTRY_VALUE(element, type, field) \
27 ((type *)((char *)(element) - offsetof(type, field)))
31 struct wine_rb_entry
*parent
;
32 struct wine_rb_entry
*left
;
33 struct wine_rb_entry
*right
;
37 typedef int (*wine_rb_compare_func_t
)(const void *key
, const struct wine_rb_entry
*entry
);
41 wine_rb_compare_func_t compare
;
42 struct wine_rb_entry
*root
;
45 typedef void (wine_rb_traverse_func_t
)(struct wine_rb_entry
*entry
, void *context
);
47 #define WINE_RB_FLAG_RED 0x1
49 static inline int wine_rb_is_red(struct wine_rb_entry
*entry
)
51 return entry
&& (entry
->flags
& WINE_RB_FLAG_RED
);
54 static inline void wine_rb_rotate_left(struct wine_rb_tree
*tree
, struct wine_rb_entry
*e
)
56 struct wine_rb_entry
*right
= e
->right
;
60 else if (e
->parent
->left
== e
)
61 e
->parent
->left
= right
;
63 e
->parent
->right
= right
;
65 e
->right
= right
->left
;
66 if (e
->right
) e
->right
->parent
= e
;
68 right
->parent
= e
->parent
;
72 static inline void wine_rb_rotate_right(struct wine_rb_tree
*tree
, struct wine_rb_entry
*e
)
74 struct wine_rb_entry
*left
= e
->left
;
78 else if (e
->parent
->left
== e
)
79 e
->parent
->left
= left
;
81 e
->parent
->right
= left
;
83 e
->left
= left
->right
;
84 if (e
->left
) e
->left
->parent
= e
;
86 left
->parent
= e
->parent
;
90 static inline void wine_rb_flip_color(struct wine_rb_entry
*entry
)
92 entry
->flags
^= WINE_RB_FLAG_RED
;
93 entry
->left
->flags
^= WINE_RB_FLAG_RED
;
94 entry
->right
->flags
^= WINE_RB_FLAG_RED
;
97 static inline struct wine_rb_entry
*wine_rb_postorder_head(struct wine_rb_entry
*iter
)
99 if (!iter
) return NULL
;
102 while (iter
->left
) iter
= iter
->left
;
103 if (!iter
->right
) return iter
;
108 static inline struct wine_rb_entry
*wine_rb_postorder_next(struct wine_rb_entry
*iter
)
110 if (!iter
->parent
) return NULL
;
111 if (iter
== iter
->parent
->right
|| !iter
->parent
->right
) return iter
->parent
;
112 return wine_rb_postorder_head(iter
->parent
->right
);
115 static inline void wine_rb_postorder(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
117 struct wine_rb_entry
*iter
, *next
;
119 for (iter
= wine_rb_postorder_head(tree
->root
); iter
; iter
= next
)
121 next
= wine_rb_postorder_next(iter
);
122 callback(iter
, context
);
126 static inline void wine_rb_init(struct wine_rb_tree
*tree
, wine_rb_compare_func_t compare
)
128 tree
->compare
= compare
;
132 static inline void wine_rb_for_each_entry(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
134 wine_rb_postorder(tree
, callback
, context
);
137 static inline void wine_rb_clear(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
139 /* Note that we use postorder here because the callback will likely free the entry. */
140 if (callback
) wine_rb_postorder(tree
, callback
, context
);
144 static inline void wine_rb_destroy(struct wine_rb_tree
*tree
, wine_rb_traverse_func_t
*callback
, void *context
)
146 wine_rb_clear(tree
, callback
, context
);
149 static inline struct wine_rb_entry
*wine_rb_get(const struct wine_rb_tree
*tree
, const void *key
)
151 struct wine_rb_entry
*entry
= tree
->root
;
154 int c
= tree
->compare(key
, entry
);
155 if (!c
) return entry
;
156 entry
= c
< 0 ? entry
->left
: entry
->right
;
161 static inline int wine_rb_put(struct wine_rb_tree
*tree
, const void *key
, struct wine_rb_entry
*entry
)
163 struct wine_rb_entry
**iter
= &tree
->root
, *parent
= tree
->root
;
170 c
= tree
->compare(key
, parent
);
172 else if (c
< 0) iter
= &parent
->left
;
173 else iter
= &parent
->right
;
176 entry
->flags
= WINE_RB_FLAG_RED
;
177 entry
->parent
= parent
;
182 while (wine_rb_is_red(entry
->parent
))
184 if (entry
->parent
== entry
->parent
->parent
->left
)
186 if (wine_rb_is_red(entry
->parent
->parent
->right
))
188 wine_rb_flip_color(entry
->parent
->parent
);
189 entry
= entry
->parent
->parent
;
193 if (entry
== entry
->parent
->right
)
195 entry
= entry
->parent
;
196 wine_rb_rotate_left(tree
, entry
);
198 entry
->parent
->flags
&= ~WINE_RB_FLAG_RED
;
199 entry
->parent
->parent
->flags
|= WINE_RB_FLAG_RED
;
200 wine_rb_rotate_right(tree
, entry
->parent
->parent
);
205 if (wine_rb_is_red(entry
->parent
->parent
->left
))
207 wine_rb_flip_color(entry
->parent
->parent
);
208 entry
= entry
->parent
->parent
;
212 if (entry
== entry
->parent
->left
)
214 entry
= entry
->parent
;
215 wine_rb_rotate_right(tree
, entry
);
217 entry
->parent
->flags
&= ~WINE_RB_FLAG_RED
;
218 entry
->parent
->parent
->flags
|= WINE_RB_FLAG_RED
;
219 wine_rb_rotate_left(tree
, entry
->parent
->parent
);
224 tree
->root
->flags
&= ~WINE_RB_FLAG_RED
;
229 static inline void wine_rb_remove(struct wine_rb_tree
*tree
, const void *key
)
231 struct wine_rb_entry
*entry
, *iter
, *child
, *parent
, *w
;
234 if (!(entry
= wine_rb_get(tree
, key
))) return;
236 if (entry
->right
&& entry
->left
)
237 for(iter
= entry
->right
; iter
->left
; iter
= iter
->left
);
241 child
= iter
->left
? iter
->left
: iter
->right
;
245 else if (iter
== iter
->parent
->left
)
246 iter
->parent
->left
= child
;
248 iter
->parent
->right
= child
;
250 if (child
) child
->parent
= iter
->parent
;
251 parent
= iter
->parent
;
253 need_fixup
= !wine_rb_is_red(iter
);
260 else if (entry
== iter
->parent
->left
)
261 iter
->parent
->left
= iter
;
263 iter
->parent
->right
= iter
;
265 if (iter
->right
) iter
->right
->parent
= iter
;
266 if (iter
->left
) iter
->left
->parent
= iter
;
267 if (parent
== entry
) parent
= iter
;
272 while (parent
&& !wine_rb_is_red(child
))
274 if (child
== parent
->left
)
277 if (wine_rb_is_red(w
))
279 w
->flags
&= ~WINE_RB_FLAG_RED
;
280 parent
->flags
|= WINE_RB_FLAG_RED
;
281 wine_rb_rotate_left(tree
, parent
);
284 if (wine_rb_is_red(w
->left
) || wine_rb_is_red(w
->right
))
286 if (!wine_rb_is_red(w
->right
))
288 w
->left
->flags
&= ~WINE_RB_FLAG_RED
;
289 w
->flags
|= WINE_RB_FLAG_RED
;
290 wine_rb_rotate_right(tree
, w
);
293 w
->flags
= (w
->flags
& ~WINE_RB_FLAG_RED
) | (parent
->flags
& WINE_RB_FLAG_RED
);
294 parent
->flags
&= ~WINE_RB_FLAG_RED
;
296 w
->right
->flags
&= ~WINE_RB_FLAG_RED
;
297 wine_rb_rotate_left(tree
, parent
);
305 if (wine_rb_is_red(w
))
307 w
->flags
&= ~WINE_RB_FLAG_RED
;
308 parent
->flags
|= WINE_RB_FLAG_RED
;
309 wine_rb_rotate_right(tree
, parent
);
312 if (wine_rb_is_red(w
->left
) || wine_rb_is_red(w
->right
))
314 if (!wine_rb_is_red(w
->left
))
316 w
->right
->flags
&= ~WINE_RB_FLAG_RED
;
317 w
->flags
|= WINE_RB_FLAG_RED
;
318 wine_rb_rotate_left(tree
, w
);
321 w
->flags
= (w
->flags
& ~WINE_RB_FLAG_RED
) | (parent
->flags
& WINE_RB_FLAG_RED
);
322 parent
->flags
&= ~WINE_RB_FLAG_RED
;
324 w
->left
->flags
&= ~WINE_RB_FLAG_RED
;
325 wine_rb_rotate_right(tree
, parent
);
330 w
->flags
|= WINE_RB_FLAG_RED
;
332 parent
= child
->parent
;
334 if (child
) child
->flags
&= ~WINE_RB_FLAG_RED
;
337 if (tree
->root
) tree
->root
->flags
&= ~WINE_RB_FLAG_RED
;
340 #endif /* __WINE_WINE_RBTREE_H */