ReactOS Fundraising Campaign 2012
 
€ 4,410 / € 30,000

Information | Donate

Home | Info | Community | Development | myReactOS | Contact Us

  1. Home
  2. Community
  3. Development
  4. myReactOS
  5. Fundraiser 2012

  1. Main Page
  2. Alphabetical List
  3. Data Structures
  4. Directories
  5. File List
  6. Data Fields
  7. Globals
  8. Related Pages

ReactOS Development > Doxygen

rbtree.h
Go to the documentation of this file.
00001 /*
00002  * Red-black search tree support
00003  *
00004  * Copyright 2009 Henri Verbeet
00005  * Copyright 2009 Andrew Riedi
00006  *
00007  * This library is free software; you can redistribute it and/or
00008  * modify it under the terms of the GNU Lesser General Public
00009  * License as published by the Free Software Foundation; either
00010  * version 2.1 of the License, or (at your option) any later version.
00011  *
00012  * This library is distributed in the hope that it will be useful,
00013  * but WITHOUT ANY WARRANTY; without even the implied warranty of
00014  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00015  * Lesser General Public License for more details.
00016  *
00017  * You should have received a copy of the GNU Lesser General Public
00018  * License along with this library; if not, write to the Free Software
00019  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
00020  */
00021 
00022 #ifndef __WINE_WINE_RBTREE_H
00023 #define __WINE_WINE_RBTREE_H
00024 
00025 #define WINE_RB_ENTRY_VALUE(element, type, field) \
00026     ((type *)((char *)(element) - FIELD_OFFSET(type, field)))
00027 
00028 struct wine_rb_entry
00029 {
00030     struct wine_rb_entry *left;
00031     struct wine_rb_entry *right;
00032     unsigned int flags;
00033 };
00034 
00035 struct wine_rb_stack
00036 {
00037     struct wine_rb_entry ***entries;
00038     size_t count;
00039     size_t size;
00040 };
00041 
00042 struct wine_rb_functions
00043 {
00044     void *(*alloc)(size_t size);
00045     void *(*realloc)(void *ptr, size_t size);
00046     void (*free)(void *ptr);
00047     int (*compare)(const void *key, const struct wine_rb_entry *entry);
00048 };
00049 
00050 struct wine_rb_tree
00051 {
00052     const struct wine_rb_functions *functions;
00053     struct wine_rb_entry *root;
00054     struct wine_rb_stack stack;
00055 };
00056 
00057 typedef void (wine_rb_traverse_func_t)(struct wine_rb_entry *entry, void *context);
00058 
00059 #define WINE_RB_FLAG_RED                0x1
00060 #define WINE_RB_FLAG_STOP               0x2
00061 #define WINE_RB_FLAG_TRAVERSED_LEFT     0x4
00062 #define WINE_RB_FLAG_TRAVERSED_RIGHT    0x8
00063 
00064 static inline void wine_rb_stack_clear(struct wine_rb_stack *stack)
00065 {
00066     stack->count = 0;
00067 }
00068 
00069 static inline void wine_rb_stack_push(struct wine_rb_stack *stack, struct wine_rb_entry **entry)
00070 {
00071     stack->entries[stack->count++] = entry;
00072 }
00073 
00074 static inline int wine_rb_ensure_stack_size(struct wine_rb_tree *tree, size_t size)
00075 {
00076     struct wine_rb_stack *stack = &tree->stack;
00077 
00078     if (size > stack->size)
00079     {
00080         size_t new_size = stack->size << 1;
00081         struct wine_rb_entry ***new_entries = tree->functions->realloc(stack->entries,
00082                 new_size * sizeof(*stack->entries));
00083 
00084         if (!new_entries) return -1;
00085 
00086         stack->entries = new_entries;
00087         stack->size = new_size;
00088     }
00089 
00090     return 0;
00091 }
00092 
00093 static inline int wine_rb_is_red(struct wine_rb_entry *entry)
00094 {
00095     return entry && (entry->flags & WINE_RB_FLAG_RED);
00096 }
00097 
00098 static inline void wine_rb_rotate_left(struct wine_rb_entry **entry)
00099 {
00100     struct wine_rb_entry *e = *entry;
00101     struct wine_rb_entry *right = e->right;
00102 
00103     e->right = right->left;
00104     right->left = e;
00105     right->flags &= ~WINE_RB_FLAG_RED;
00106     right->flags |= e->flags & WINE_RB_FLAG_RED;
00107     e->flags |= WINE_RB_FLAG_RED;
00108     *entry = right;
00109 }
00110 
00111 static inline void wine_rb_rotate_right(struct wine_rb_entry **entry)
00112 {
00113     struct wine_rb_entry *e = *entry;
00114     struct wine_rb_entry *left = e->left;
00115 
00116     e->left = left->right;
00117     left->right = e;
00118     left->flags &= ~WINE_RB_FLAG_RED;
00119     left->flags |= e->flags & WINE_RB_FLAG_RED;
00120     e->flags |= WINE_RB_FLAG_RED;
00121     *entry = left;
00122 }
00123 
00124 static inline void wine_rb_flip_color(struct wine_rb_entry *entry)
00125 {
00126     entry->flags ^= WINE_RB_FLAG_RED;
00127     entry->left->flags ^= WINE_RB_FLAG_RED;
00128     entry->right->flags ^= WINE_RB_FLAG_RED;
00129 }
00130 
00131 static inline void wine_rb_fixup(struct wine_rb_stack *stack)
00132 {
00133     while (stack->count)
00134     {
00135         struct wine_rb_entry **entry = stack->entries[stack->count - 1];
00136 
00137         if ((*entry)->flags & WINE_RB_FLAG_STOP)
00138         {
00139             (*entry)->flags &= ~WINE_RB_FLAG_STOP;
00140             return;
00141         }
00142 
00143         if (wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->left)) wine_rb_rotate_left(entry);
00144         if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->left->left)) wine_rb_rotate_right(entry);
00145         if (wine_rb_is_red((*entry)->left) && wine_rb_is_red((*entry)->right)) wine_rb_flip_color(*entry);
00146         --stack->count;
00147     }
00148 }
00149 
00150 static inline void wine_rb_move_red_left(struct wine_rb_entry **entry)
00151 {
00152     wine_rb_flip_color(*entry);
00153     if (wine_rb_is_red((*entry)->right->left))
00154     {
00155         wine_rb_rotate_right(&(*entry)->right);
00156         wine_rb_rotate_left(entry);
00157         wine_rb_flip_color(*entry);
00158     }
00159 }
00160 
00161 static inline void wine_rb_move_red_right(struct wine_rb_entry **entry)
00162 {
00163     wine_rb_flip_color(*entry);
00164     if (wine_rb_is_red((*entry)->left->left))
00165     {
00166         wine_rb_rotate_right(entry);
00167         wine_rb_flip_color(*entry);
00168     }
00169 }
00170 
00171 static inline void wine_rb_postorder(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
00172 {
00173     struct wine_rb_entry **entry;
00174 
00175     if (!tree->root) return;
00176 
00177     for (entry = &tree->root;;)
00178     {
00179         struct wine_rb_entry *e = *entry;
00180 
00181         if (e->left && !(e->flags & WINE_RB_FLAG_TRAVERSED_LEFT))
00182         {
00183             wine_rb_stack_push(&tree->stack, entry);
00184             e->flags |= WINE_RB_FLAG_TRAVERSED_LEFT;
00185             entry = &e->left;
00186             continue;
00187         }
00188 
00189         if (e->right && !(e->flags & WINE_RB_FLAG_TRAVERSED_RIGHT))
00190         {
00191             wine_rb_stack_push(&tree->stack, entry);
00192             e->flags |= WINE_RB_FLAG_TRAVERSED_RIGHT;
00193             entry = &e->right;
00194             continue;
00195         }
00196 
00197         e->flags &= ~(WINE_RB_FLAG_TRAVERSED_LEFT | WINE_RB_FLAG_TRAVERSED_RIGHT);
00198         callback(e, context);
00199 
00200         if (!tree->stack.count) break;
00201         entry = tree->stack.entries[--tree->stack.count];
00202     }
00203 }
00204 
00205 static inline int wine_rb_init(struct wine_rb_tree *tree, const struct wine_rb_functions *functions)
00206 {
00207     tree->functions = functions;
00208     tree->root = NULL;
00209 
00210     tree->stack.entries = functions->alloc(16 * sizeof(*tree->stack.entries));
00211     if (!tree->stack.entries) return -1;
00212     tree->stack.size = 16;
00213     tree->stack.count = 0;
00214 
00215     return 0;
00216 }
00217 
00218 static inline void wine_rb_for_each_entry(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
00219 {
00220     wine_rb_postorder(tree, callback, context);
00221 }
00222 
00223 static inline void wine_rb_destroy(struct wine_rb_tree *tree, wine_rb_traverse_func_t *callback, void *context)
00224 {
00225     /* Note that we use postorder here because the callback will likely free the entry. */
00226     if (callback) wine_rb_postorder(tree, callback, context);
00227 
00228     tree->root = NULL;
00229     tree->functions->free(tree->stack.entries);
00230 }
00231 
00232 static inline struct wine_rb_entry *wine_rb_get(const struct wine_rb_tree *tree, const void *key)
00233 {
00234     struct wine_rb_entry *entry = tree->root;
00235     while (entry)
00236     {
00237         int c = tree->functions->compare(key, entry);
00238         if (!c) return entry;
00239         entry = c < 0 ? entry->left : entry->right;
00240     }
00241     return NULL;
00242 }
00243 
00244 static inline int wine_rb_put(struct wine_rb_tree *tree, const void *key, struct wine_rb_entry *entry)
00245 {
00246     struct wine_rb_entry **parent = &tree->root;
00247     size_t black_height = 1;
00248 
00249     while (*parent)
00250     {
00251         int c;
00252 
00253         if (!wine_rb_is_red(*parent)) ++black_height;
00254 
00255         wine_rb_stack_push(&tree->stack, parent);
00256 
00257         c = tree->functions->compare(key, *parent);
00258         if (!c)
00259         {
00260             wine_rb_stack_clear(&tree->stack);
00261             return -1;
00262         }
00263         else if (c < 0) parent = &(*parent)->left;
00264         else parent = &(*parent)->right;
00265     }
00266 
00267     /* After insertion, the path length to any node should be <= (black_height + 1) * 2. */
00268     if (wine_rb_ensure_stack_size(tree, black_height << 1) == -1)
00269     {
00270         wine_rb_stack_clear(&tree->stack);
00271         return -1;
00272     }
00273 
00274     entry->flags = WINE_RB_FLAG_RED;
00275     entry->left = NULL;
00276     entry->right = NULL;
00277     *parent = entry;
00278 
00279     wine_rb_fixup(&tree->stack);
00280     tree->root->flags &= ~WINE_RB_FLAG_RED;
00281 
00282     return 0;
00283 }
00284 
00285 static inline void wine_rb_remove(struct wine_rb_tree *tree, const void *key)
00286 {
00287     struct wine_rb_entry **entry = &tree->root;
00288 
00289     while (*entry)
00290     {
00291         if (tree->functions->compare(key, *entry) < 0)
00292         {
00293             wine_rb_stack_push(&tree->stack, entry);
00294             if (!wine_rb_is_red((*entry)->left) && !wine_rb_is_red((*entry)->left->left)) wine_rb_move_red_left(entry);
00295             entry = &(*entry)->left;
00296         }
00297         else
00298         {
00299             if (wine_rb_is_red((*entry)->left)) wine_rb_rotate_right(entry);
00300             if (!tree->functions->compare(key, *entry) && !(*entry)->right)
00301             {
00302                 *entry = NULL;
00303                 break;
00304             }
00305             if (!wine_rb_is_red((*entry)->right) && !wine_rb_is_red((*entry)->right->left))
00306                 wine_rb_move_red_right(entry);
00307             if (!tree->functions->compare(key, *entry))
00308             {
00309                 struct wine_rb_entry **e = &(*entry)->right;
00310                 struct wine_rb_entry *m = *e;
00311                 while (m->left) m = m->left;
00312 
00313                 wine_rb_stack_push(&tree->stack, entry);
00314                 (*entry)->flags |= WINE_RB_FLAG_STOP;
00315 
00316                 while ((*e)->left)
00317                 {
00318                     wine_rb_stack_push(&tree->stack, e);
00319                     if (!wine_rb_is_red((*e)->left) && !wine_rb_is_red((*e)->left->left)) wine_rb_move_red_left(e);
00320                     e = &(*e)->left;
00321                 }
00322                 *e = NULL;
00323                 wine_rb_fixup(&tree->stack);
00324 
00325                 *m = **entry;
00326                 *entry = m;
00327 
00328                 break;
00329             }
00330             else
00331             {
00332                 wine_rb_stack_push(&tree->stack, entry);
00333                 entry = &(*entry)->right;
00334             }
00335         }
00336     }
00337 
00338     wine_rb_fixup(&tree->stack);
00339     if (tree->root) tree->root->flags &= ~WINE_RB_FLAG_RED;
00340 }
00341 
00342 #endif  /* __WINE_WINE_RBTREE_H */

Generated on Sat May 26 2012 04:32:08 for ReactOS by doxygen 1.7.6.1

ReactOS is a registered trademark or a trademark of ReactOS Foundation in the United States and other countries.