218 lines
7.8 KiB
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;
|
|
}
|