/*------------------------------------------------------------------------------ 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; }