UTIL0.C

/*************************************************************/ 
/** **/
/** Microsoft RPC Examples **/
/** Dictionary Application **/
/** Copyright 1992 - 1998 Microsoft Corporation **/
/** **/
/*************************************************************/

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>

#ifndef _LOCAL
#include "replay.h"
#else
#include "play.h"
#endif // _LOCAL

#include "dict0.h"
#include "util0.h"


/*************************************************************************/
/*** RecordNode / RecordTree free routines ***/
/*************************************************************************/

void
RecordTreeNodeFree(
IN RecordTreeNode * node
)
{
if (node == NULL)
return;

MIDL_user_free( node->item->name );
MIDL_user_free( node->item );
node->left = NULL;
node->right = NULL;
MIDL_user_free( node );
}

void
RecordTreeFree(
IN RecordTreeNode * node
)
{
if (node == NULL)
return;

if (node->left != NULL) {
RecordTreeFree(node->left);
}
if (node->right != NULL) {
RecordTreeFree(node->right);
}
RecordTreeNodeFree( node );
}

VDict_Status
RDict_Free_Dict(
IN OUT RDict * r_dict
)
{
RecordTreeFree( r_dict->root );

return(DICT_SUCCESS);
}

/*************************************************************************/
/*** State Allocate / Free routines ***/
/*************************************************************************/

DictState * allocate_state(void)
{
DictState * pstate = (DictState*) MIDL_user_allocate(sizeof(DictState));

pstate->curr_record = (Record*) MIDL_user_allocate(sizeof(Record));
pstate->curr_record->name = (char*) MIDL_user_allocate(81 * sizeof(char));

// initialize curr_record to "minus infinity" in the order
pstate->curr_record->key = -1;
strcpy(pstate->curr_record->name, "");
pstate->ref_count = 0;

return(pstate);
}

void free_state(DictState * state)
{
if (state != NULL) {
if (state->curr_record != NULL) {
if (state->curr_record->name != NULL)
MIDL_user_free(state->curr_record->name);
MIDL_user_free(state->curr_record);
}
MIDL_user_free(state);
}
}

/*************************************************************************/
/*** Rdict Duplicate utilities ***/
/*************************************************************************/

RDict *
RDict_Duplicate(
IN RDict * src
)
{
RDict * dst = (RDict*) MIDL_user_allocate(sizeof(RDict));

dst->root = (RecordTreeNode*) Tree_Duplicate((TreeNode*)src->root);
dst->size = src->size;
dst->state = DictState_Duplicate(src->state);

return(dst);
}

DictState *
DictState_Duplicate(
IN DictState * src
)
{
DictState * dst = (DictState*) MIDL_user_allocate(sizeof(DictState));

dst->curr_record = ItemDuplicate(src->curr_record);
dst->ref_count = src->ref_count;

return(dst);
}

TreeNode *
TreeNode_Duplicate(
IN TreeNode * src
)
{
TreeNode * pnode = (TreeNode*) MIDL_user_allocate(sizeof(TreeNode));

pnode->left = pnode->right = NULL;
pnode->item = ItemDuplicate(src->item);

return(pnode);
}

TreeNode *
Tree_Duplicate(
IN TreeNode * src
)
{
TreeNode * dst;

if (src == NULL)
return((TreeNode*)NULL);

dst = TreeNode_Duplicate(src);
dst->left = Tree_Duplicate(src->left);
dst->right = Tree_Duplicate(src->right);
return(dst);
}

/*************************************************************************/
/*** MIDL_user_allocate / MIDL_user_free ***/
/*************************************************************************/

void __RPC_FAR * __RPC_USER MIDL_user_allocate(size_t count)
{
return(malloc(count));
}

void __RPC_USER MIDL_user_free(void __RPC_FAR * p)
{
free(p);
}

/*************************************************************************/
/*** Utility functions ***/
/*************************************************************************/

/* In the most general case *cmp is a two argument function:
(*cmp)(void *item0, void *item1) which compares two items,
and returns: -1 if item0 < item1;
0 if item0 == item1;
+1 if item0 > item1.
The common case is: each item has a field named "key";
item.key is of type long, or string.
*/

int
comp(void* x, void* y)
{
int res = ((Record*)x)->key - ((Record*)y)->key;

if (res == 0)
return( strcmp( ((Record*)x)->name, ((Record*)y)->name ) );
else
return( res ) ;
}

Record *
ItemDuplicate(
Record * item
)
{
if (item == NULL)
return(NULL);

return( makeRecord( item->key, item->name ) );
}

Record *
makeRecord(
short key,
char * name
)
{
Record * pr = (Record*) MIDL_user_allocate(sizeof(Record));

if (!name)
printf("makeRecord: NULL name\n");

pr->name = (char*) MIDL_user_allocate(strlen(name)+1);
strcpy(pr->name, name);
pr->key = key;

return(pr);
}

void
freeRecord(
Record * pr
)
{
if (pr != NULL) {
if (pr->name != NULL)
MIDL_user_free(pr->name);
MIDL_user_free(pr);
}
}

void
ItemCopy(
IN Record * src,
OUT Record * dest
)
{
int i;

dest->key = src->key;

// copy name, trubcated to 80 characters
for(i=0 ; (src->name[i] != '\0') && (i<80) ; i++)
dest->name[i]=src->name[i];

dest->name[i]='\0';
}

void
printRecord(void* rp)
{
printf("%d : %s\n", ((Record*)rp)->key, ((Record*)rp)->name);
}

void
Dict_Print( /* prints the binary tree (indented right subtree,
followed by the root, followed by the indented
right dubtree) */
Dictionary * dp,
int indent) /* number of spaces to indent subsequent levels */
{
prinTree(0, indent, dp->root, dp->print_rec);
}

char spaces[] =
" ";

void
prinTree(
int lmargin, /* indentation of the root of the tree */
int indent, /* indentation of subsequent levels */
TreeNode *np, /* pointer to the root node */
PrintFun print) /* short, one line, record print routine */
{
if (np == NULL)
return;

prinTree(lmargin+indent, indent, np->right, print);

if (lmargin > sizeof(spaces))
lmargin = sizeof(spaces);;

spaces[lmargin] = 0;
printf(spaces);
spaces[lmargin] = ' ';

(*print)(np->item);

prinTree(lmargin+indent, indent, np->left, print);

}

TreeNode*
makeNode(void * item)
{
TreeNode* tp;

tp = (TreeNode*)MIDL_user_allocate(sizeof(TreeNode));
tp->item = item;
tp->left = tp->right = NULL;

return(tp);
}