nfs-ganesha 1.4
|
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 }