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 }