DICT0.C
/*************************************************************/ 
/**                                                         **/ 
/**                 Microsoft RPC Examples                  **/ 
/**                 Dictionary Application                  **/ 
/**           Copyright 1992 - 1998 Microsoft Corporation   **/ 
/**                                                         **/ 
/*************************************************************/ 
 
#include <stdlib.h> 
#include <stdio.h> 
#include <ctype.h> 
 
#include <rpc.h> 
#include <rpcndr.h> 
#include "dict0.h" 
 
/************************************************************************/ 
TreeNode Dumbo; 
// volatile 
TreeNode *Dummy = &Dumbo;   // a global dummy node 
 
#define ROTATELEFT  tmp=t->right; t->right=tmp->left; tmp->left=t; t=tmp 
#define ROTATERIGHT tmp=t->left; t->left=tmp->right; tmp->right=t; t=tmp 
#define LINKLEFT    tmp=t; t=t->right; l=l->right=tmp 
#define LINKRIGHT   tmp=t; t=t->left; r=r->left=tmp 
#define ASSEMBLE    r->left=t->right; l->right=t->left; \ 
                    t->left=Dummy->right; t->right=Dummy->left 
/************************************************************************/ 
 
/************************************************************************ 
 Basic structure declarations from dict0.h: 
 
typedef struct tnode { 
    struct tnode *left;             // left child pointer 
    struct tnode *right;            // right child pointer 
    void *item;                     // pointer to some structure 
} TreeNode; 
 
typedef struct dictnode { 
    TreeNode *root;                 // pointer to the root of a SAT 
    long size;                      // number of records in dictionary 
    void * state;                   // reserved for state info 
    cmp_rec_func cmp_rec;           // pointer to a comparison function 
    TreeNode* (*splay)(TreeNode *, void *, cmp_rec_func); 
                                    // pointer to a splay function 
    void (*print_rec)(void *);      // one line print function 
} Dictionary; 
 
#define DICT_CURR_ITEM(pDict)       pDict->root->item 
 
typedef enum { 
    SUCCESS, 
    ITEM_ALREADY_PRESENT, 
    ITEM_NOT_FOUND, 
    FIRST_ITEM, 
    LAST_ITEM, 
    EMPTY_DICTIONARY, 
    NULL_ITEM 
} Dict_Status; 
**************************************************************************/ 
 
 
/*************************************************************************/ 
/***    Minimal Dictionary Operations:                                 ***/ 
/***                                                                   ***/ 
/***    Dictionary *Dict_New(Cmp_rec*, Splay*, print_rec*)             ***/ 
/***                                                                   ***/ 
/***    Dict_Status Dict_Find(Dictionary*, Item*)                      ***/ 
/***    Dict_Status Dict_Next(Dictionary*, Item*)                      ***/ 
/***    Dict_Status Dict_Prev(Dictionary*, Item*)                      ***/ 
/***    Dict_Status Dict_Insert(Dictionary*, Item*)                    ***/ 
/***    Dict_Status Dict_Delete(Dictionary*, Item**)                   ***/ 
/***                                                                   ***/ 
/***    Item* DICT_CURR_ITEM(Dict*)                                    ***/ 
/*************************************************************************/ 
 
#define TreeNode_New(pnode, pitem) pnode = \ 
    (TreeNode*) MIDL_user_allocate (sizeof(TreeNode)); \ 
    pnode->left = pnode->right = NULL; pnode->item = pitem; 
 
Dictionary* 
Dict_New(                    // returns a new dictionary node 
    int (*cmp_rec)           // pointer to item comparison function 
        (void *, void *), 
    TreeNode* (*splay)       // pointer to a splay function 
        (TreeNode *, void *, cmp_rec_func), 
    void (*print_rec)        // pointer to one line item print routine 
        (void *) ) 
{ 
    Dictionary* dp; 
 
    dp = (Dictionary*) MIDL_user_allocate(sizeof(Dictionary)); 
    dp->root = NULL; 
    dp->size = 0; 
    dp->state = NULL; 
    dp->print_rec = print_rec; 
    dp->splay = splay; 
    dp->cmp_rec = cmp_rec; 
    return(dp); 
} 
 
Dict_Status 
Dict_Find( 
    Dictionary* dp,     // Dictionary to be searched. 
    void* item)         // Item searched for. 
{ 
    int keycmp; 
    TreeNode* t; 
 
    if (dp->root == NULL) 
        return (EMPTY_DICTIONARY); 
    if (item == NULL) 
        return(NULL_ITEM); 
    t = dp->root = dp->splay(dp->root, item, dp->cmp_rec); 
    keycmp = (dp->cmp_rec)( t->item, item ); 
    if (keycmp != 0) 
        return(ITEM_NOT_FOUND); 
    else return(SUCCESS); 
} 
 
Dict_Status 
Dict_Next( 
    Dictionary* dp,     // Dictionary to be searched. 
    void* item)         // A Key item.  Advance to successor of item in dp. 
{ 
    TreeNode* t; 
    int keycmp; 
 
    if (dp->root == NULL) 
        return (EMPTY_DICTIONARY); 
    if (item == NULL) { 
        dp->root = tdSplayLeft(dp->root); 
        return(SUCCESS); 
    } 
    if (item == DICT_CURR_ITEM(dp)) { 
        t = dp->root; 
        keycmp = 0; 
    } 
    else { 
        dp->root = t = dp->splay(dp->root, item, dp->cmp_rec); 
        keycmp = (dp->cmp_rec) (item, t->item); 
    } 
    if (keycmp < 0) 
        return(SUCCESS); 
    else if (t->right == NULL) { 
        return(LAST_ITEM); 
    } 
    else { 
        t = dp->root; 
        dp->root = tdSplayLeft(t->right); 
        dp->root->left = t; 
        t->right = NULL; 
        return(SUCCESS); 
    } 
} 
 
Dict_Status 
Dict_Prev( 
    Dictionary* dp,     // Dictionary to be searched. 
    void* item)         // A Key item.  Retreat to predecessor of item in dp. 
{ 
    TreeNode* t; 
    int keycmp; 
 
    if (dp->root == NULL) 
        return (EMPTY_DICTIONARY); 
    if (item == NULL) { 
        dp->root = tdSplayRight(dp->root); 
        return(SUCCESS); 
    } 
    if (item == DICT_CURR_ITEM(dp)) { 
        t = dp->root; 
        keycmp = 0; 
    } 
    else { 
        dp->root = t = dp->splay(dp->root, item, dp->cmp_rec); 
        keycmp = (dp->cmp_rec) (item, t->item); 
    } 
    if (keycmp > 0) 
        return(SUCCESS); 
    else if (t->left == NULL) { 
        return(FIRST_ITEM); 
    } 
    else { 
        t = dp->root; 
        dp->root = tdSplayRight(t->left); 
        dp->root->right = t; 
        t->left = NULL; 
        return(SUCCESS); 
    } 
} 
 
Dict_Status 
Dict_Insert(            // insert the given item into the tree 
    Dictionary* dp,     // the modified dictionary 
    void* item)         // the item to be inserted 
{ 
    int keycmp; 
    TreeNode *t, *newNode; 
 
    if (item == NULL) 
        return(NULL_ITEM); 
    if (dp->root == NULL) { 
        TreeNode_New(newNode, item); 
        dp->root = newNode; 
        dp->size++; 
        return(SUCCESS); 
    } 
    t = dp->root = dp->splay(dp->root, item, dp->cmp_rec); 
    keycmp = (dp->cmp_rec)( t->item, item ); 
    if (keycmp == 0) 
        return(ITEM_ALREADY_PRESENT); 
 
    TreeNode_New(newNode, item); 
    if (keycmp < 0) {   // t->item < item 
        newNode->right = t->right; 
        t->right = NULL; 
        newNode->left = t; 
    } 
    else { 
        newNode->left = t->left; 
        t->left = NULL; 
        newNode->right = t; 
    } 
    dp->root = newNode; 
    dp->size++; 
    return(SUCCESS); 
} 
 
 
Dict_Status 
Dict_Delete(            // delete the given item into from the tree 
    Dictionary* dp,     // the modified dictionary 
    void** pItem)       // IN: points to the (key) item to be deleted 
                        // OUT: points to the item just deleted 
{ 
    TreeNode *t, *r; 
    int keycmp; 
    void* item = *pItem; 
    t = dp->root; 
 
    if (item == NULL) 
        return(NULL_ITEM); 
    if (dp->root == NULL) 
        return (EMPTY_DICTIONARY); 
    if (item == DICT_CURR_ITEM(dp)) 
        keycmp = 0; 
    else { 
        dp->root = t = dp->splay(dp->root, item, dp->cmp_rec); 
        keycmp = (dp->cmp_rec)( item, t->item ); 
    } 
    if (keycmp != 0) 
        return(ITEM_NOT_FOUND); 
    *pItem = DICT_CURR_ITEM(dp); 
 
    if (t->left == NULL) { 
        dp->root = t->right; 
    } 
    else if ((r = t->right) == NULL) { 
        dp->root = t->left; 
    } 
    else  { 
        r = tdSplayLeft(r); 
        // at this point r->left == NULL 
        r->left = t->left; 
        dp->root = r; 
    } 
    t->left = t->right = t->item = NULL; 
    MIDL_user_free(t); 
    dp->size--; 
    return(SUCCESS); 
} 
 
 
/*************************************************************************/ 
/*****              Core functions (internal)                        *****/ 
/*************************************************************************/ 
 
TreeNode *              // returns the new root 
tdSplay(                // general top down splay 
    TreeNode *root,     // the current root of the tree 
    void *keyItem,      // pointer to a "key item" searched for 
    int (*cmp)(void *, void *) ) 
                        // pointer to a comparison function 
{ 
    TreeNode* t=root;   // current search point 
    TreeNode* l;        // root of "left subtree" < keyItem 
    TreeNode* r;        // root of "right subtree" > keyItem 
    int kcmpt, kcmpleft, kcmpright; 
                        // cash comparison results 
    TreeNode* tmp; 
 
/***/ 
    Dummy = &Dumbo; 
    l = Dummy; 
    r = Dummy; 
/***/ 
 
    if ( (root == NULL) || ((*cmp)(keyItem, root->item) == 0) ) 
        return(root); 
    Dummy->left = Dummy->right = NULL; 
    while ( (kcmpt = (*cmp)(keyItem, t->item)) != 0 ) { 
        if ( kcmpt < 0 ) { 
            if ( t->left == NULL ) 
                break; 
            if ( (kcmpleft = (*cmp)(keyItem, t->left->item)) == 0 ) { 
                LINKRIGHT; 
            } 
            else if ( kcmpleft < 0 ) { 
                ROTATERIGHT; 
                if ( t->left != NULL ) { 
                    LINKRIGHT; 
                } 
            } 
            else { // keyItem > t->left->item 
                LINKRIGHT; 
                if ( t->right != NULL ) { 
                    LINKLEFT; 
                } 
            } 
        } 
        else { // keyItem > t->item 
            if ( t->right == NULL ) 
                break; 
            if ( (kcmpright = (*cmp)(keyItem, t->right->item)) == 0 ) { 
                LINKLEFT; 
            } 
            else if ( kcmpright > 0 ) { 
                ROTATELEFT; 
                if ( t->right != NULL ) { 
                    LINKLEFT; 
                } 
            } 
            else { // keyItem < t->right->item 
                LINKLEFT; 
                if ( t->left != NULL ) { 
                    LINKRIGHT; 
                } 
            } 
        } 
    } 
 
    ASSEMBLE; 
    return(t); 
} 
 
TreeNode* 
tdSplayLeft(TreeNode* root) 
{ 
    TreeNode* t=root;   // current "search" point 
    TreeNode* l=Dummy;  // root of "left subtree" < keyItem 
    TreeNode* r=Dummy;  // root of "right subtree" > keyItem 
    TreeNode* tmp; 
 
    if ( (t == NULL) || (t->left == NULL) ) 
        return(t); 
    if ( t->left->left == NULL ) { 
        ROTATERIGHT; 
        return(t); 
    } 
    Dummy->left = Dummy->right = NULL; 
    while ( t->left != NULL ) { 
        ROTATERIGHT; 
        if ( t->left != NULL ) { 
            LINKRIGHT; 
        } 
    } 
 
    ASSEMBLE; 
    return(t); 
} 
 
TreeNode* 
tdSplayRight(TreeNode* root) 
{ 
    TreeNode* t=root;   // current "search" point 
    TreeNode* l=Dummy;  // root of "left subtree" < keyItem 
    TreeNode* r=Dummy;  // root of "right subtree" > keyItem 
    TreeNode* tmp; 
 
    if ( (t == NULL) || (t->right == NULL) ) 
        return(t); 
    Dummy->left = Dummy->right = NULL; 
    while ( t->right != NULL ) { 
        ROTATELEFT; 
        if ( t->right != NULL ) { 
            LINKLEFT; 
        } 
    } 
 
    ASSEMBLE; 
    return(t); 
}