nfs-ganesha 1.4

bst.c

Go to the documentation of this file.
00001 /*
00002  * bstree - Implements a threaded binary search tree.
00003  *
00004  * Copyright (C) 2010 Franck Bui-Huu <fbuihuu@gmail.com>
00005  *
00006  * This library is free software; you can redistribute it and/or
00007  * modify it under the terms of the GNU Lesser General Public License
00008  * as published by the Free Software Foundation; version 2 of the
00009  * License.
00010  *
00011  * This library is distributed in the hope that it will be useful, but
00012  * WITHOUT ANY WARRANTY; without even the implied warranty of
00013  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
00014  * Lesser General Public License for more details.
00015  *
00016  * You should have received a copy of the GNU Lesser General Public
00017  * License along with this library; if not, write to the Free Software
00018  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
00019  * USA
00020  */
00021 #ifdef HAVE_CONFIG_H
00022 #include "config.h"
00023 #endif
00024 #include "avltree.h"
00025 
00026 /*
00027  * This is where the black magic is defined. If you're lucky enough to
00028  * work on a system that doesn't support these kind of tricks then we
00029  * assume UINTPTR_MAX and uintptr_t type are not defined.
00030  *
00031  * Note that the getters returns a pointer when appropriate otherwise
00032  * NULL;
00033  */
00034 #ifdef UINTPTR_MAX
00035 
00036 #define NODE_INIT       { 0, }
00037 
00038 static inline void INIT_NODE(struct bstree_node *node)
00039 {
00040         node->left = 0;
00041         node->right = 0;
00042 }
00043 
00044 static inline void set_thread(struct bstree_node *t, uintptr_t *p)
00045 {
00046         *p = (uintptr_t)t | 1;
00047 }
00048 
00049 static inline struct bstree_node *get_thread(uintptr_t u)
00050 {
00051         return (struct bstree_node *)((u & -(int)(u & 1)) & ~1UL);
00052 }
00053 
00054 static inline void set_link(struct bstree_node *n, uintptr_t *p)
00055 {
00056         *p = (uintptr_t)n;
00057 }
00058 
00059 static inline struct bstree_node *get_link(uintptr_t u)
00060 {
00061         return (struct bstree_node *)(u & ((int)(u & 1) - 1));
00062 }
00063 
00064 #define set_left(l,n)   set_link(l, &(n)->left)
00065 #define set_right(r,n)  set_link(r, &(n)->right)
00066 #define set_prev(p,n)   set_thread(p, &(n)->left)
00067 #define set_next(s,n)   set_thread(s, &(n)->right)
00068 
00069 #define get_left(n)     get_link((n)->left)
00070 #define get_right(n)    get_link((n)->right)
00071 #define get_prev(n)     get_thread((n)->left)
00072 #define get_next(n)     get_thread((n)->right)
00073 
00074 #else
00075 
00076 #define NODE_INIT       { NULL, }
00077 
00078 static inline void INIT_NODE(struct bstree_node *node)
00079 {
00080         node->left = NULL;
00081         node->right = NULL;
00082         node->left_is_thread = 0;
00083         node->right_is_thread = 0;
00084 }
00085 
00086 static inline void set_left(struct bstree_node *l, struct bstree_node *n)
00087 {
00088         n->left = l;
00089         n->left_is_thread = 0;
00090 }
00091 
00092 static inline void set_right(struct bstree_node *r, struct bstree_node *n)
00093 {
00094         n->right = r;
00095         n->right_is_thread = 0;
00096 }
00097 
00098 static inline void set_prev(struct bstree_node *t, struct bstree_node *n)
00099 {
00100         n->left = t;
00101         n->left_is_thread = 1;
00102 }
00103 
00104 static inline void set_next(struct bstree_node *t, struct bstree_node *n)
00105 {
00106         n->right = t;
00107         n->right_is_thread = 1;
00108 }
00109 
00110 static inline struct bstree_node *get_left(const struct bstree_node *n)
00111 {
00112         if (n->left_is_thread)
00113                 return NULL;
00114         return n->left;
00115 }
00116 
00117 static inline struct bstree_node *get_right(const struct bstree_node *n)
00118 {
00119         if (n->right_is_thread)
00120                 return NULL;
00121         return n->right;
00122 }
00123 
00124 static inline struct bstree_node *get_prev(const struct bstree_node *n)
00125 {
00126         if (!n->left_is_thread)
00127                 return NULL;
00128         return n->left;
00129 }
00130 
00131 static inline struct bstree_node *get_next(const struct bstree_node *n)
00132 {
00133         if (!n->right_is_thread)
00134                 return NULL;
00135         return n->right;
00136 }
00137 
00138 #endif  /* UINTPTR_MAX */
00139 
00140 /*
00141  * Iterators
00142  */
00143 static inline struct bstree_node *get_first(struct bstree_node *node)
00144 {
00145         struct bstree_node *left;
00146         while ((left = get_left(node)))
00147                 node = left;
00148         return node;
00149 }
00150 
00151 static inline struct bstree_node *get_last(struct bstree_node *node)
00152 {
00153         struct bstree_node *right;
00154         while ((right = get_right(node)))
00155                 node = right;
00156         return node;
00157 }
00158 
00159 struct bstree_node *bstree_first(const struct bstree *tree)
00160 {
00161         if (tree->root)
00162                 return tree->first;
00163         return NULL;
00164 }
00165 
00166 struct bstree_node *bstree_last(const struct bstree *tree)
00167 {
00168         if (tree->root)
00169                 return tree->last;
00170         return NULL;
00171 }
00172 
00173 struct bstree_node *bstree_next(const struct bstree_node *node)
00174 {
00175         struct bstree_node *right = get_right(node);
00176         if (right)
00177                 return get_first(right);
00178         return get_next(node);
00179 }
00180 
00181 struct bstree_node *bstree_prev(const struct bstree_node *node)
00182 {
00183         struct bstree_node *left = get_left(node);
00184         if (left)
00185                 return get_last(left);
00186         return get_prev(node);
00187 }
00188 
00189 /*
00190  * Main ops: lookup, insert, remove.
00191  */
00192 static struct bstree_node *do_lookup(const struct bstree_node *key,
00193                                      const struct bstree *tree,
00194                                      struct bstree_node **pparent,
00195                                      int *is_left)
00196 {
00197         struct bstree_node *node = tree->root;
00198 
00199         *pparent = NULL;
00200         *is_left = 0;
00201 
00202         while (node) {
00203                 int res = tree->cmp_fn(node, key);
00204                 if (res == 0)
00205                         return node;
00206                 *pparent = node;
00207                 if ((*is_left = res > 0))
00208                         node = get_left(node);
00209                 else
00210                         node = get_right(node);
00211         }
00212         return NULL;
00213 }
00214 
00215 struct bstree_node *bstree_lookup(const struct bstree_node *key,
00216                                   const struct bstree *tree)
00217 {
00218         struct bstree_node *parent;
00219         int is_left;
00220 
00221         return do_lookup(key, tree, &parent, &is_left);
00222 }
00223 
00224 struct bstree_node *bstree_insert(struct bstree_node *node, struct bstree *tree)
00225 {
00226         struct bstree_node *key, *parent;
00227         int is_left;
00228 
00229         key = do_lookup(node, tree, &parent, &is_left);
00230         if (key)
00231                 return key;
00232 
00233         if (!parent) {
00234                 INIT_NODE(node);
00235                 tree->root = tree->first = tree->last = node;
00236                 return NULL;
00237         }
00238         if (is_left) {
00239                 if (parent == tree->first)
00240                         tree->first = node;
00241                 set_prev(get_prev(parent), node);
00242                 set_next(parent, node);
00243                 set_left(node, parent);
00244         } else {
00245                 if (parent == tree->last)
00246                         tree->last = node;
00247                 set_prev(parent, node);
00248                 set_next(get_next(parent), node);
00249                 set_right(node, parent);
00250         }
00251         return NULL;
00252 }
00253 
00254 static void set_child(struct bstree_node *child, struct bstree_node *node, int left)
00255 {
00256         if (left)
00257                 set_left(child, node);
00258         else
00259                 set_right(child, node);
00260 }
00261 
00262 void bstree_remove(struct bstree_node *node, struct bstree *tree)
00263 {
00264         struct bstree_node *left, *right, *next;
00265         struct bstree_node fake_parent, *parent;
00266         int is_left;
00267 
00268         do_lookup(node, tree, &parent, &is_left);
00269 
00270         if (!parent) {
00271                 INIT_NODE(&fake_parent);
00272                 parent = &fake_parent;
00273                 is_left = 0;
00274         }
00275         left  = get_left(node);
00276         right = get_right(node);
00277 
00278         if (!left && !right) {
00279                 if (is_left)
00280                         set_prev(get_prev(node), parent);
00281                 else
00282                         set_next(get_next(node), parent);
00283                 next = parent;
00284                 goto update_first_last;
00285         }
00286         if (!left) {
00287                 next = get_first(right);
00288                 set_prev(get_prev(node), next);
00289                 set_child(right, parent, is_left);
00290                 goto update_first_last;
00291         }
00292         if (!right) {
00293                 next = get_last(left);
00294                 set_next(get_next(node), next);
00295                 set_child(left, parent, is_left);
00296                 goto update_first_last;
00297         }
00298 
00299         next = get_first(right);
00300         if (next != right) {
00301                 /* 'm' is the parent of 'next' */
00302                 struct bstree_node *m = get_next(get_last(next));
00303 
00304                 if (get_right(next))
00305                         set_left(get_right(next), m);
00306                 else
00307                         set_prev(next, m);
00308 
00309                 set_right(right, next);
00310         }
00311         set_child(next, parent, is_left);
00312         set_left(left, next);
00313         set_next(next, get_last(left));
00314 out:
00315         if (parent == &fake_parent)
00316                 tree->root = get_right(parent);
00317         return;
00318 
00319 update_first_last:
00320         if (node == tree->first)
00321                 tree->first = next;
00322         if (node == tree->last)
00323                 tree->last = next;
00324         goto out;
00325 }
00326 
00327 void bstree_replace(struct bstree_node *old, struct bstree_node *new,
00328                     struct bstree *tree)
00329 {
00330         struct bstree_node *parent;
00331         int is_left;
00332 
00333         do_lookup(old, tree, &parent, &is_left);
00334         if (parent)
00335                 set_child(new, parent, is_left);
00336         else
00337                 tree->root = new;
00338 
00339         if (tree->first == old)
00340                 tree->first = new;
00341         if (tree->last == old)
00342                 tree->last = new;
00343 
00344         *new = *old;
00345 }
00346 
00347 int bstree_init(struct bstree *tree, bstree_cmp_fn_t cmp, unsigned long flags)
00348 {
00349         if (flags)
00350                 return -1;
00351         tree->root = NULL;
00352         tree->cmp_fn = cmp;
00353         return 0;
00354 }