00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020 #include "rbtree-priv.h"
00021 #include <string.h>
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041 int _p_rbkey_init(p_rbkey *key, const p_term *term)
00042 {
00043 term = p_term_deref(term);
00044 if (!term)
00045 return 0;
00046 key->type = term->header.type;
00047 switch (term->header.type) {
00048 case P_TERM_FUNCTOR:
00049 key->size = term->header.size;
00050 key->name = term->functor.functor_name;
00051 break;
00052 case P_TERM_LIST: {
00053 key->size = 0;
00054 key->name = 0;
00055 break; }
00056 case P_TERM_ATOM:
00057 case P_TERM_STRING:
00058 case P_TERM_REAL:
00059 key->size = 0;
00060 key->name = term;
00061 break;
00062 case P_TERM_INTEGER:
00063 #if defined(P_TERM_64BIT)
00064 key->size = term->header.size;
00065 key->name = 0;
00066 #else
00067 key->size = 0;
00068 key->name = term;
00069 #endif
00070 break;
00071 default: return 0;
00072 }
00073 return 1;
00074 }
00075
00076
00077 P_INLINE int _p_rbkey_compare(const p_rbkey *key, const p_rbnode *node)
00078 {
00079 if (key->type < node->type)
00080 return -1;
00081 else if (key->type > node->type)
00082 return 1;
00083 switch (key->type) {
00084 case P_TERM_FUNCTOR:
00085 if (key->size < node->size)
00086 return -1;
00087 else if (key->size > node->size)
00088 return 1;
00089
00090 case P_TERM_ATOM:
00091 if (key->name < node->name)
00092 return -1;
00093 else if (key->name > node->name)
00094 return 1;
00095 break;
00096 case P_TERM_STRING:
00097 return p_term_strcmp(key->name, node->name);
00098 case P_TERM_REAL:
00099 if (key->name->real.value < node->name->real.value)
00100 return -1;
00101 else if (key->name->real.value > node->name->real.value)
00102 return 1;
00103 break;
00104 case P_TERM_INTEGER:
00105 #if defined(P_TERM_64BIT)
00106 if (((int)(key->size)) < ((int)(node->size)))
00107 return -1;
00108 else if (((int)(key->size)) > ((int)(node->size)))
00109 return 1;
00110 #else
00111 if (key->name->integer.value < node->name->integer.value)
00112 return -1;
00113 else if (key->name->integer.value > node->name->integer.value)
00114 return 1;
00115 #endif
00116 break;
00117 default: break;
00118 }
00119 return 0;
00120 }
00121
00122
00123 int _p_rbkey_compare_keys(const p_rbkey *key1, const p_rbkey *key2)
00124 {
00125 p_rbnode node;
00126 memset(&node, 0, sizeof(node));
00127 node.type = key2->type;
00128 node.size = key2->size;
00129 node.name = key2->name;
00130 return _p_rbkey_compare(key1, &node);
00131 }
00132
00133
00134 void _p_rbtree_init(p_rbtree *tree)
00135 {
00136 tree->root = 0;
00137 }
00138
00139
00140 static void _p_rbnode_free(p_rbnode *node)
00141 {
00142 if (node) {
00143 _p_rbnode_free(node->left);
00144 _p_rbnode_free(node->right);
00145 GC_FREE(node);
00146 }
00147 }
00148 void _p_rbtree_free(p_rbtree *tree)
00149 {
00150 _p_rbnode_free(tree->root);
00151 tree->root = 0;
00152 }
00153
00154
00155
00156 p_rbnode *_p_rbtree_lookup(const p_rbtree *tree, const p_rbkey *key)
00157 {
00158 const p_rbnode *node = tree->root;
00159 int cmp;
00160 while (node != 0) {
00161 cmp = _p_rbkey_compare(key, node);
00162 if (cmp == 0)
00163 return (p_rbnode *)node;
00164 else if (cmp < 0)
00165 node = node->left;
00166 else
00167 node = node->right;
00168 }
00169 return 0;
00170 }
00171
00172
00173 P_INLINE void _p_rbtree_replace_node
00174 (p_rbtree *tree, p_rbnode *node, p_rbnode *replace)
00175 {
00176 p_rbnode *parent = node->parent;
00177 if (!parent)
00178 tree->root = replace;
00179 else if (parent->left == node)
00180 parent->left = replace;
00181 else
00182 parent->right = replace;
00183 if (replace)
00184 replace->parent = parent;
00185 }
00186
00187
00188 P_INLINE void _p_rbtree_rotate_left(p_rbtree *tree, p_rbnode *node)
00189 {
00190 p_rbnode *right = node->right;
00191 _p_rbtree_replace_node(tree, node, right);
00192 node->right = right->left;
00193 if (right->left)
00194 right->left->parent = node;
00195 right->left = node;
00196 node->parent = right;
00197 }
00198
00199
00200 P_INLINE void _p_rbtree_rotate_right(p_rbtree *tree, p_rbnode *node)
00201 {
00202 p_rbnode *left = node->left;
00203 _p_rbtree_replace_node(tree, node, left);
00204 node->left = left->right;
00205 if (left->right)
00206 left->right->parent = node;
00207 left->right = node;
00208 node->parent = left;
00209 }
00210
00211
00212
00213
00214 p_rbnode *_p_rbtree_insert(p_rbtree *tree, const p_rbkey *key)
00215 {
00216 p_rbnode *node = tree->root;
00217 p_rbnode *parent;
00218 p_rbnode *grand_parent;
00219 p_rbnode *uncle;
00220 p_rbnode *orig_node;
00221 int cmp;
00222
00223
00224 if (!node) {
00225 node = GC_NEW(p_rbnode);
00226 if (!node)
00227 return 0;
00228 node->type = key->type;
00229 node->red = 0;
00230 node->size = key->size;
00231 node->name = key->name;
00232 tree->root = node;
00233 return node;
00234 }
00235
00236
00237 parent = 0;
00238 grand_parent = 0;
00239 do {
00240 cmp = _p_rbkey_compare(key, node);
00241 if (cmp == 0)
00242 return node;
00243 grand_parent = parent;
00244 parent = node;
00245 if (cmp < 0)
00246 node = node->left;
00247 else
00248 node = node->right;
00249 } while (node != 0);
00250
00251
00252 orig_node = node = GC_NEW(p_rbnode);
00253 if (!node)
00254 return 0;
00255 node->type = key->type;
00256 node->red = 1;
00257 node->size = key->size;
00258 node->name = key->name;
00259 node->parent = parent;
00260 if (cmp < 0)
00261 parent->left = node;
00262 else
00263 parent->right = node;
00264
00265 for (;;) {
00266
00267 if (!parent->red)
00268 return orig_node;
00269
00270
00271 if (grand_parent) {
00272 if (parent == grand_parent->left)
00273 uncle = grand_parent->right;
00274 else
00275 uncle = grand_parent->left;
00276 } else {
00277 uncle = 0;
00278 }
00279
00280
00281
00282
00283 if (uncle && uncle->red) {
00284 parent->red = 0;
00285 uncle->red = 0;
00286 grand_parent->red = 1;
00287 node = grand_parent;
00288 parent = node->parent;
00289 if (!parent) {
00290
00291 node->red = 0;
00292 return orig_node;
00293 }
00294 grand_parent = parent->parent;
00295 } else {
00296 break;
00297 }
00298 }
00299
00300
00301 if (node == parent->right && parent == grand_parent->left) {
00302 _p_rbtree_rotate_left(tree, parent);
00303 node = parent;
00304 parent = node->parent;
00305 } else if (node == parent->left && parent == grand_parent->right) {
00306 _p_rbtree_rotate_right(tree, parent);
00307 node = parent;
00308 parent = node->parent;
00309 }
00310 parent->red = 0;
00311 grand_parent->red = 1;
00312 if (tree->root == grand_parent)
00313 tree->root = parent;
00314 if (node == parent->left && parent == grand_parent->left)
00315 _p_rbtree_rotate_right(tree, grand_parent);
00316 else
00317 _p_rbtree_rotate_left(tree, grand_parent);
00318
00319
00320 return orig_node;
00321 }
00322
00323
00324 #define _p_rbnode_is_red(node) ((node) ? (node)->red : 0)
00325
00326
00327 static void _p_rbtree_rebalance(p_rbtree *tree, p_rbnode *node)
00328 {
00329 p_rbnode *parent;
00330 p_rbnode *sibling;
00331
00332 for (;;) {
00333
00334 parent = node->parent;
00335 if (!parent)
00336 return;
00337
00338
00339
00340 if (parent->left == node)
00341 sibling = parent->right;
00342 else
00343 sibling = parent->left;
00344 if (sibling && sibling->red) {
00345 parent->red = 1;
00346 sibling->red = 0;
00347 if (node == parent->left)
00348 _p_rbtree_rotate_left(tree, parent);
00349 else
00350 _p_rbtree_rotate_right(tree, parent);
00351 parent = node->parent;
00352 if (parent->left == node)
00353 sibling = parent->right;
00354 else
00355 sibling = parent->left;
00356 }
00357
00358
00359
00360 if (!parent->red && !_p_rbnode_is_red(sibling) &&
00361 !_p_rbnode_is_red(sibling->left) &&
00362 !_p_rbnode_is_red(sibling->right)) {
00363 sibling->red = 1;
00364 node = parent;
00365 } else {
00366 break;
00367 }
00368 }
00369
00370
00371
00372 if (parent->red && !_p_rbnode_is_red(sibling) &&
00373 !_p_rbnode_is_red(sibling->left) &&
00374 !_p_rbnode_is_red(sibling->right)) {
00375 sibling->red = 1;
00376 parent->red = 0;
00377 return;
00378 }
00379
00380
00381 if (node == parent->left) {
00382 if (!_p_rbnode_is_red(sibling) &&
00383 _p_rbnode_is_red(sibling->left) &&
00384 !_p_rbnode_is_red(sibling->right)) {
00385 sibling->red = 1;
00386 sibling->left->red = 0;
00387 _p_rbtree_rotate_right(tree, sibling);
00388 }
00389 } else {
00390 if (!_p_rbnode_is_red(sibling) &&
00391 !_p_rbnode_is_red(sibling->left) &&
00392 _p_rbnode_is_red(sibling->right)) {
00393 sibling->red = 1;
00394 sibling->right->red = 0;
00395 _p_rbtree_rotate_left(tree, sibling);
00396 }
00397 }
00398 parent = node->parent;
00399 if (node == parent->left)
00400 sibling = parent->right;
00401 else
00402 sibling = parent->left;
00403 sibling->red = parent->red;
00404 parent->red = 0;
00405 if (node == parent->left) {
00406 sibling->right->red = 0;
00407 _p_rbtree_rotate_left(tree, parent);
00408 } else {
00409 sibling->left->red = 0;
00410 _p_rbtree_rotate_right(tree, parent);
00411 }
00412 }
00413
00414
00415
00416
00417 p_term *_p_rbtree_remove(p_rbtree *tree, const p_rbkey *key)
00418 {
00419 p_rbnode *node = tree->root;
00420 p_rbnode *child;
00421 p_term *value;
00422 int cmp;
00423
00424
00425 while (node != 0) {
00426 cmp = _p_rbkey_compare(key, node);
00427 if (cmp == 0)
00428 break;
00429 else if (cmp < 0)
00430 node = node->left;
00431 else
00432 node = node->right;
00433 }
00434 if (!node)
00435 return 0;
00436 value = node->value;
00437
00438
00439
00440
00441
00442 if (node->left && node->right) {
00443 child = node->left;
00444 while (child->right != 0)
00445 child = child->right;
00446 node->type = child->type;
00447 node->size = child->size;
00448 node->name = child->name;
00449 node->value = child->value;
00450 node = child;
00451 }
00452
00453
00454 if (node->left)
00455 child = node->left;
00456 else
00457 child = node->right;
00458 if (!node->red) {
00459 node->red = child ? child->red : 0;
00460 _p_rbtree_rebalance(tree, node);
00461 }
00462
00463
00464
00465 _p_rbtree_replace_node(tree, node, child);
00466 if (child && child == tree->root)
00467 child->red = 0;
00468 GC_FREE(node);
00469
00470
00471 return value;
00472 }
00473
00474
00475
00476
00477
00478 p_rbnode *_p_rbtree_visit_all(p_rbtree *tree, p_rbnode *last)
00479 {
00480 p_rbnode *parent;
00481
00482
00483 if (!last)
00484 return tree->root;
00485 else if (last->left)
00486 return last->left;
00487 else if (last->right)
00488 return last->right;
00489
00490
00491 parent = last->parent;
00492 while (parent != 0) {
00493 if (parent->left == last && parent->right)
00494 return parent->right;
00495 last = parent;
00496 parent = parent->parent;
00497 }
00498 return 0;
00499 }