reman3/Rayman_X/cpa/tempgrp/ldt/Src/Hash.c

218 lines
7.8 KiB
C

/*------------------------------------------------------------------------------
FILE : Hash.c
CREATED : 98/05/12
AUTHOR : Catalin Cocos
CONTENTS: variable size hash table implementation
------------------------------------------------------------------------------*/
#include "StdInc.h"
#include "Hash.h"
/*creation, initialization, deletion
--------------------------------------*/
/*------------------------------------------------------------------------------
DESC. : creates a new hash
INPUT : A) the dispersion function, with the following characteristics:
- input : pointer to a hash element, or NULL;
- output: > if input is NULL, the maximum index possible + 1
> else, the hash index.
B) the comparison function - similar with the one used for the LDT_tdst_DSArray
C) the element deletion function - used to delete the elements
OUTPUT : the newly created hash or NULL
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
LDT_tdst_DSHash* LDT_DSHs_new(int (* _pfnDispersion ) (void*),
int (* _pfnCompare)(const void**, const void** ),
void (* _pfnDelete) (void*) )
{
LDT_tdst_DSHash* pObj = (LDT_tdst_DSHash*) malloc( sizeof(LDT_tdst_DSHash) );
if( LDT_DSHs_Init( pObj, _pfnDispersion, _pfnCompare, _pfnDelete) )
return pObj; /* success */
free( pObj );
return NULL; /* failure */
}
/*------------------------------------------------------------------------------
DESC. : initializes an existing hash
INPUT : see above
OUTPUT : nonzero if successful
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
int LDT_DSHs_Init(LDT_tdst_DSHash* pObj,
int (* _pfnDispersion ) (void*),
int (* _pfnCompare)(const void**, const void** ),
void (* _pfnDelete) (void*) )
{
int HashDimension;
if(!pObj || !_pfnDispersion || !_pfnCompare || !_pfnDelete ) return 0; /* invalid input */
HashDimension = _pfnDispersion(NULL);
if( !HashDimension ) return 0; /* bad dispersion function */
pObj->pfnDelete = _pfnDelete; /* set the deletion function */
pObj->pfnDispersion = _pfnDispersion; /* set the dispersion function */
pObj->pData = (LDT_tdst_DSArray*) malloc( HashDimension * sizeof(LDT_tdst_DSArray) ); /* allocate the needed memory */
for(HashDimension --; HashDimension>=0; HashDimension--)
{
LDT_DSAr_Init( pObj->pData + HashDimension ); /* initialize the dynamic arrays */
LDT_DSAr_SetSortMethod( pObj->pData + HashDimension, _pfnCompare );
}
return 1; /* success */
}
/*------------------------------------------------------------------------------
DESC. : deletes an existing array
INPUT : - the object
- an integer: DelElements; if non-zero, all elements are freed
(the pfnDelete is called for each element)
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void LDT_DSHs_delete( LDT_tdst_DSHash* pObj, int DelElements)
{
if( pObj )
{
LDT_DSHs_Close( pObj, DelElements ); /* clean-up */
free( pObj ); /* deletion */
}
}
/*------------------------------------------------------------------------------
DESC. : sets the dynamic aray elements granularity
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void LDT_DSHs_SetGranularity( LDT_tdst_DSHash* pObj, int _nGrowBy)
{
int HashDimension = pObj->pfnDispersion( NULL ) - 1 ;
for( ; HashDimension>=0; HashDimension--)
LDT_DSAr_SetGranularity( pObj->pData + HashDimension, _nGrowBy ); /* set the granularity for each array */
}
/* Clean up
-------------*/
/*------------------------------------------------------------------------------
DESC. : frees the unused memory
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void LDT_DSHs_FreeExtra( LDT_tdst_DSHash* pObj )
{
int HashDimension = pObj->pfnDispersion( NULL ) - 1 ;
for( ; HashDimension>=0; HashDimension--)
LDT_DSAr_FreeExtra( pObj->pData + HashDimension );
}
/*------------------------------------------------------------------------------
DESC. : clears the hash, removing all the elements
INPUT : - the object
- an integer: DelElements; if non-zero, all elements are freed
(the pfnDelete is called for each element)
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void LDT_DSHs_RemoveAll( LDT_tdst_DSHash* pObj, int DelElements)
{
LDT_tdst_DSArray* pCrtAr;
void** pData;
void (* Delete ) (void*) = pObj->pfnDelete;
int i;
int HashDimension = pObj->pfnDispersion( NULL ) - 1 ;
for( ; HashDimension>=0; HashDimension--)
{
pCrtAr = pObj->pData + HashDimension;
if(DelElements)
for(i = LDT_DSAr_GetUpperBound( pCrtAr ), pData = pCrtAr->pData; i>=0; i--)
Delete( pData[i]);
LDT_DSAr_RemoveAll( pCrtAr );
}
}
/*------------------------------------------------------------------------------
DESC. : clears the hash memory
INPUT : - the object
- an integer: DelElements; if non-zero, all elements are freed
(the pfnDelete is called for each element)
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void LDT_DSHs_Close( LDT_tdst_DSHash* pObj, int DelElements )
{
LDT_DSHs_RemoveAll( pObj, DelElements );
free( pObj->pData );
pObj->pData = NULL;
}
/* Accessing elements
-----------------------*/
/*------------------------------------------------------------------------------
DESC. : gets the hash element matching the parameter
OUTPUT : the equivalent element in the hash, or NULL if none found
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void* LDT_DSHs_GetEqOf( LDT_tdst_DSHash* pHash, void* pTgt)
{
LDT_tdst_DSArray* pArr;
if( !pTgt ) return NULL;
pArr = pHash->pData + pHash->pfnDispersion( pTgt ); /* get the array */
return LDT_DSAr_GetAt( pArr, LDT_DSAr_Index( pArr, pTgt, NULL )); /* get the element */
}
/*------------------------------------------------------------------------------
DESC. : removes the hash element matching the parameter
OUTPUT : the equivalent element removed, or NULL if none found
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void* LDT_DSHs_RemoveEqOf( LDT_tdst_DSHash* pHash, void* pTgt )
{
LDT_tdst_DSArray* pArr;
if( !pTgt ) return NULL;
pArr = pHash->pData + pHash->pfnDispersion( pTgt ); /* get the array */
return LDT_DSAr_RemoveAt( pArr, LDT_DSAr_Index( pArr, pTgt, NULL ));/* remove the element */
}
/*------------------------------------------------------------------------------
DESC. : inserts the element in the hash table
INPUT : the hash;
the element to insert;
an integer specifying the action to perform if an equivalent element is found in the hash:
0 -> no action
1 -> delete the element if it is not needed (an equivalent is found)
OUTPUT : the element in the hash: the inserted element or the found equivalent.
CREATED : 98/05/12
AUTHOR : Catalin Cocos
------------------------------------------------------------------------------*/
void* LDT_DSHs_Insert( LDT_tdst_DSHash* pHash, void* pTgt, int del)
{
int position;
LDT_tdst_DSArray* pArr;
if( !pTgt ) return NULL;
pArr = pHash->pData + pHash->pfnDispersion( pTgt ); /* get the array */
if(LDT_DSAr_SAdd( pArr, pTgt, 0, &position ) < 0) /* try to insert the element */
{
/* insertion failed */
void* existing = LDT_DSAr_GetAt( pArr, position);
if( del && (existing != pTgt) )
pHash->pfnDelete (pTgt); /* delete the non-inserted element */
return existing;
}
return pTgt;
}