nfs-ganesha 1.4
|
00001 /* 00002 * splaytree - Implements a top-down threaded splay 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 <assert.h> 00025 00026 #include "avltree.h" 00027 00028 00029 #ifdef UINTPTR_MAX 00030 00031 #define NODE_INIT { 0, } 00032 00033 static inline void INIT_NODE(struct splaytree_node *node) 00034 { 00035 node->left = 0; 00036 node->right = 0; 00037 } 00038 00039 static inline void set_thread(struct splaytree_node *t, uintptr_t *p) 00040 { 00041 *p = (uintptr_t)t | 1; 00042 } 00043 00044 static inline struct splaytree_node *get_thread(uintptr_t u) 00045 { 00046 return (struct splaytree_node *)((u & -(int)(u & 1)) & ~1UL); 00047 } 00048 00049 static inline void set_link(struct splaytree_node *n, uintptr_t *p) 00050 { 00051 *p = (uintptr_t)n; 00052 } 00053 00054 static inline struct splaytree_node *get_link(uintptr_t u) 00055 { 00056 return (struct splaytree_node *)(u & ((int)(u & 1) - 1)); 00057 } 00058 00059 #define set_left(l,n) set_link(l, &(n)->left) 00060 #define set_right(r,n) set_link(r, &(n)->right) 00061 #define set_prev(p,n) set_thread(p, &(n)->left) 00062 #define set_next(s,n) set_thread(s, &(n)->right) 00063 00064 #define get_left(n) get_link((n)->left) 00065 #define get_right(n) get_link((n)->right) 00066 #define get_prev(n) get_thread((n)->left) 00067 #define get_next(n) get_thread((n)->right) 00068 00069 #else /* !UINTPTR_MAX */ 00070 00071 #define NODE_INIT { NULL, } 00072 00073 static inline void INIT_NODE(struct splaytree_node *node) 00074 { 00075 node->left = NULL; 00076 node->right = NULL; 00077 node->left_is_thread = 0; 00078 node->right_is_thread = 0; 00079 } 00080 00081 static inline void set_left(struct splaytree_node *l, struct splaytree_node *n) 00082 { 00083 n->left = l; 00084 n->left_is_thread = 0; 00085 } 00086 00087 static inline void set_right(struct splaytree_node *r, struct splaytree_node *n) 00088 { 00089 n->right = r; 00090 n->right_is_thread = 0; 00091 } 00092 00093 static inline void set_prev(struct splaytree_node *t, struct splaytree_node *n) 00094 { 00095 n->left = t; 00096 n->left_is_thread = 1; 00097 } 00098 00099 static inline void set_next(struct splaytree_node *t, struct splaytree_node *n) 00100 { 00101 n->right = t; 00102 n->right_is_thread = 1; 00103 } 00104 00105 static inline struct splaytree_node *get_left(const struct splaytree_node *n) 00106 { 00107 if (!n->left_is_thread) 00108 return n->left; 00109 return NULL; 00110 } 00111 00112 static inline struct splaytree_node *get_right(const struct splaytree_node *n) 00113 { 00114 if (!n->right_is_thread) 00115 return n->right; 00116 return NULL; 00117 } 00118 00119 static inline struct splaytree_node *get_prev(const struct splaytree_node *n) 00120 { 00121 if (n->left_is_thread) 00122 return n->left; 00123 return NULL; 00124 } 00125 00126 static inline struct splaytree_node *get_next(const struct splaytree_node *n) 00127 { 00128 if (n->right_is_thread) 00129 return n->right; 00130 return NULL; 00131 } 00132 00133 #endif /* UINTPTR_MAX */ 00134 00135 /* 00136 * Iterators 00137 */ 00138 static inline struct splaytree_node *get_first(struct splaytree_node *node) 00139 { 00140 struct splaytree_node *left; 00141 while ((left = get_left(node))) 00142 node = left; 00143 return node; 00144 } 00145 00146 static inline struct splaytree_node *get_last(struct splaytree_node *node) 00147 { 00148 struct splaytree_node *right; 00149 while ((right = get_right(node))) 00150 node = right; 00151 return node; 00152 } 00153 00154 struct splaytree_node *splaytree_first(const struct splaytree *tree) 00155 { 00156 return tree->first; 00157 } 00158 00159 struct splaytree_node *splaytree_last(const struct splaytree *tree) 00160 { 00161 return tree->last; 00162 } 00163 00164 struct splaytree_node *splaytree_next(const struct splaytree_node *node) 00165 { 00166 struct splaytree_node *right = get_right(node); 00167 if (right) 00168 return get_first(right); 00169 return get_next(node); 00170 } 00171 00172 struct splaytree_node *splaytree_prev(const struct splaytree_node *node) 00173 { 00174 struct splaytree_node *left = get_left(node); 00175 if (left) 00176 return get_last(left); 00177 return get_prev(node); 00178 } 00179 00180 static inline void rotate_right(struct splaytree_node *node) 00181 { 00182 struct splaytree_node *left = get_left(node); /* can't be NULL */ 00183 struct splaytree_node *r = get_right(left); 00184 00185 if (r) 00186 set_left(r, node); 00187 else 00188 set_prev(left, node); 00189 set_right(node, left); 00190 } 00191 00192 static inline void rotate_left(struct splaytree_node *node) 00193 { 00194 struct splaytree_node *right = get_right(node); /* can't be NULL */ 00195 struct splaytree_node *l = get_left(right); 00196 00197 if (l) 00198 set_right(l, node); 00199 else 00200 set_next(right, node); 00201 set_left(node, right); 00202 } 00203 00204 static int do_splay(const struct splaytree_node *key, 00205 struct splaytree *tree) 00206 { 00207 struct splaytree_node subroots = NODE_INIT; 00208 struct splaytree_node *subleft = &subroots, *subright = &subroots; 00209 struct splaytree_node *root = tree->root; 00210 splaytree_cmp_fn_t cmp = tree->cmp_fn; 00211 int rv; 00212 00213 for (;;) { 00214 rv = cmp(key, root); 00215 if (rv == 0) 00216 break; 00217 if (rv < 0) { 00218 struct splaytree_node *left; 00219 00220 left = get_left(root); 00221 if (!left) 00222 break; 00223 if ((rv = cmp(key, left)) < 0) { 00224 rotate_right(root); 00225 root = left; 00226 left = get_left(root); 00227 if (!left) 00228 break; 00229 } 00230 /* link left */ 00231 set_left(root, subright); 00232 subright = root; 00233 root = left; 00234 } else { 00235 struct splaytree_node *right; 00236 00237 right = get_right(root); 00238 if (!right) 00239 break; 00240 if ((rv = cmp(key, right)) > 0) { 00241 rotate_left(root); 00242 root = right; 00243 right = get_right(root); 00244 if (!right) 00245 break; 00246 } 00247 /* link right */ 00248 set_right(root, subleft); 00249 subleft = root; 00250 root = right; 00251 } 00252 } 00253 /* assemble */ 00254 if (get_left(root)) 00255 set_right(get_left(root), subleft); 00256 else 00257 set_next(root, subleft); 00258 00259 if (get_right(root)) 00260 set_left(get_right(root), subright); 00261 else 00262 set_prev(root, subright); 00263 00264 set_left(get_right(&subroots), root); 00265 set_right(get_left(&subroots), root); 00266 tree->root = root; 00267 return rv; 00268 } 00269 00270 struct splaytree_node *splaytree_lookup(const struct splaytree_node *key, 00271 struct splaytree *tree) 00272 { 00273 if (!tree->root) 00274 return NULL; 00275 if (do_splay(key, tree) != 0) 00276 return NULL; 00277 return tree->root; 00278 } 00279 00280 struct splaytree_node *splaytree_insert(struct splaytree_node *node, 00281 struct splaytree *tree) 00282 { 00283 struct splaytree_node *root = tree->root; 00284 int res; 00285 00286 if (!root) { 00287 INIT_NODE(node); 00288 tree->root = node; 00289 tree->first = node; 00290 tree->last = node; 00291 return NULL; 00292 } 00293 00294 res = do_splay(node, tree); 00295 if (res == 0) 00296 return tree->root; 00297 00298 root = tree->root; 00299 if (res < 0) { 00300 struct splaytree_node *left = get_left(root); 00301 00302 set_left(left, node); 00303 set_right(root, node); 00304 if (left) 00305 set_next(node, get_last(left)); 00306 else 00307 tree->first = node; 00308 set_prev(node, root); 00309 } else { 00310 struct splaytree_node *right = get_right(root); 00311 00312 set_right(right, node); 00313 set_left(root, node); 00314 if (right) 00315 set_prev(node, get_first(right)); 00316 else 00317 tree->last = node; 00318 set_next(node, root); 00319 } 00320 tree->root = node; 00321 return NULL; 00322 } 00323 00324 void splaytree_remove(struct splaytree_node *node, struct splaytree *tree) 00325 { 00326 struct splaytree_node *right, *left, *prev; 00327 00328 do_splay(node, tree); 00329 assert(tree->root == node); /* 'node' must be present */ 00330 00331 right = get_right(node); 00332 left = get_left(node); 00333 if (!left) { 00334 tree->root = right; 00335 tree->first = splaytree_next(node); 00336 prev = NULL; 00337 } else { 00338 tree->root = left; 00339 do_splay(node, tree); 00340 set_right(right, tree->root); 00341 prev = tree->root; 00342 } 00343 if (right) 00344 set_prev(prev, get_first(right)); 00345 else 00346 tree->last = prev; 00347 } 00348 00349 void splaytree_replace(struct splaytree_node *old, struct splaytree_node *new, 00350 struct splaytree *tree) 00351 { 00352 do_splay(old, tree); 00353 assert(tree->root == old); 00354 00355 tree->root = new; 00356 if (tree->first == old) 00357 tree->first = new; 00358 if (tree->last == old) 00359 tree->last = new; 00360 00361 *new = *old; 00362 } 00363 00364 int splaytree_init(struct splaytree *tree, splaytree_cmp_fn_t cmp, unsigned long flags) 00365 { 00366 if (flags) 00367 return -1; 00368 tree->root = NULL; 00369 tree->first = NULL; 00370 tree->last = NULL; 00371 tree->cmp_fn = cmp; 00372 return 0; 00373 }