417 lines
9 KiB
C
417 lines
9 KiB
C
/*++
|
|
|
|
Copyright (c) 1999, Microsoft Corporation
|
|
|
|
Module Name:
|
|
|
|
sample\hashtable.c
|
|
|
|
Abstract:
|
|
|
|
The file contains a hash table implementation.
|
|
|
|
--*/
|
|
|
|
#include "pchsample.h"
|
|
#pragma hdrstop
|
|
|
|
|
|
DWORD
|
|
HT_Create(
|
|
IN HANDLE hHeap,
|
|
IN ULONG ulNumBuckets,
|
|
IN PDISPLAY_FUNCTION pfnDisplay OPTIONAL,
|
|
IN PFREE_FUNCTION pfnFree,
|
|
IN PHASH_FUNCTION pfnHash,
|
|
IN PCOMPARE_FUNCTION pfnCompare,
|
|
OUT PHASH_TABLE *pphtHashTable)
|
|
/*++
|
|
|
|
Routine Description
|
|
Creates a hash table.
|
|
|
|
Locks
|
|
None
|
|
|
|
Arguments
|
|
hHeap heap to use for allocation
|
|
ulNumBuckets # buckets in the hash table
|
|
pfnDisplay function used to display a hash table entry
|
|
pfnFree function used to free a hash table entry
|
|
pfnHash function used to compute the hash of an entry
|
|
pfnCompare function used to compare two hash table entries
|
|
pphtHashTable pointer to the hash table address
|
|
|
|
Return Value
|
|
NO_ERROR if success
|
|
Failure code o/w
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
ULONG i = 0, ulSize = 0;
|
|
PHASH_TABLE phtTable;
|
|
|
|
// validate parameters
|
|
if (!hHeap or
|
|
!ulNumBuckets or
|
|
!pfnFree or
|
|
!pfnHash or
|
|
!pfnCompare or
|
|
!pphtHashTable)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
*pphtHashTable = NULL;
|
|
|
|
do // breakout loop
|
|
{
|
|
// allocate the hash table structure
|
|
ulSize = sizeof(HASH_TABLE);
|
|
phtTable = HeapAlloc(hHeap, 0, ulSize);
|
|
if (phtTable is NULL)
|
|
{
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// allocate the buckets
|
|
ulSize = ulNumBuckets * sizeof(LIST_ENTRY);
|
|
phtTable->pleBuckets = HeapAlloc(hHeap, 0, ulSize);
|
|
if (phtTable->pleBuckets is NULL)
|
|
{
|
|
HeapFree(hHeap, 0, phtTable); // undo allocation
|
|
dwErr = GetLastError();
|
|
break;
|
|
}
|
|
|
|
// initialize the buckets
|
|
for (i = 0; i < ulNumBuckets; i++)
|
|
InitializeListHead(phtTable->pleBuckets + i);
|
|
|
|
// initialize the hash table structure's members
|
|
phtTable->ulNumBuckets = ulNumBuckets;
|
|
phtTable->ulNumEntries = 0;
|
|
phtTable->pfnDisplay = pfnDisplay;
|
|
phtTable->pfnFree = pfnFree;
|
|
phtTable->pfnHash = pfnHash;
|
|
phtTable->pfnCompare = pfnCompare;
|
|
|
|
*pphtHashTable = phtTable;
|
|
} while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
HT_Destroy(
|
|
IN HANDLE hHeap,
|
|
IN PHASH_TABLE phtHashTable)
|
|
/*++
|
|
|
|
Routine Description
|
|
Destroys a hash table.
|
|
Frees up memory allocated for hash table entries.
|
|
|
|
Locks
|
|
Assumes the hash table is locked for writing.
|
|
|
|
Arguments
|
|
hHeap heap to use for deallocation
|
|
phtHashTable pointer to the hash table to be destroyed
|
|
|
|
Return Value
|
|
NO_ERROR always
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
PLIST_ENTRY pleList = NULL;
|
|
|
|
// validate parameters
|
|
if (!hHeap or
|
|
!phtHashTable)
|
|
return NO_ERROR;
|
|
|
|
// deallocate the entries
|
|
for (i = 0; i < phtHashTable->ulNumBuckets; i++)
|
|
{
|
|
pleList = phtHashTable->pleBuckets + i;
|
|
FreeList(pleList, phtHashTable->pfnFree);
|
|
}
|
|
|
|
// deallocate the buckets
|
|
HeapFree(hHeap, 0, phtHashTable->pleBuckets);
|
|
|
|
// deallocate the hash table structure
|
|
HeapFree(hHeap, 0, phtHashTable);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
HT_Cleanup(
|
|
IN PHASH_TABLE phtHashTable)
|
|
/*++
|
|
|
|
Routine Description
|
|
Cleans up all hash table entries.
|
|
|
|
Locks
|
|
Assumes the hash table is locked for writing.
|
|
|
|
Arguments
|
|
phtHashTable pointer to the hash table to be cleaned up
|
|
|
|
Return Value
|
|
NO_ERROR always
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
PLIST_ENTRY pleList = NULL;
|
|
|
|
// validate parameters
|
|
if (!phtHashTable)
|
|
return NO_ERROR;
|
|
|
|
// deallocate the entries
|
|
for (i = 0; i < phtHashTable->ulNumBuckets; i++)
|
|
{
|
|
pleList = phtHashTable->pleBuckets + i;
|
|
FreeList(pleList, phtHashTable->pfnFree);
|
|
}
|
|
|
|
phtHashTable->ulNumEntries = 0;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
HT_InsertEntry(
|
|
IN PHASH_TABLE phtHashTable,
|
|
IN PLIST_ENTRY pleEntry)
|
|
/*++
|
|
|
|
Routine Description
|
|
Inserts the specified entry in the hash table.
|
|
Memory for the entry should already have been allocated.
|
|
|
|
Locks
|
|
Assumes the hash table is locked for writing.
|
|
|
|
Arguments
|
|
phtHashTable pointer to the hash table to be modified
|
|
pleEntry entry to be inserted
|
|
|
|
Return Value
|
|
NO_ERROR if success
|
|
Error code o/w (entry exists)
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
PLIST_ENTRY pleList = NULL;
|
|
|
|
// validate parameters
|
|
if (!phtHashTable or !pleEntry)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
do // breakout loop
|
|
{
|
|
// entry exists, fail
|
|
if (HT_IsPresentEntry(phtHashTable, pleEntry))
|
|
{
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
break;
|
|
}
|
|
|
|
// insert the entry in the hash table
|
|
pleList = phtHashTable->pleBuckets +
|
|
(*phtHashTable->pfnHash)(pleEntry);
|
|
InsertHeadList(pleList, pleEntry);
|
|
phtHashTable->ulNumEntries++;
|
|
} while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
HT_GetEntry(
|
|
IN PHASH_TABLE phtHashTable,
|
|
IN PLIST_ENTRY pleKey,
|
|
OUT PLIST_ENTRY *ppleEntry)
|
|
/*++
|
|
|
|
Routine Description
|
|
Gets the hash table entry with the given key.
|
|
|
|
Locks
|
|
Assumes the hash table is locked for reading.
|
|
|
|
Arguments
|
|
phtHashTable pointer to the hash table to be searched
|
|
pleKey key to be searched for
|
|
ppleEntry pointer to matching entry's address
|
|
|
|
Return Value
|
|
NO_ERROR entry exisits
|
|
ERROR_INVALID_PARAMETER o/w (entry does not exist)
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
PLIST_ENTRY pleList = NULL;
|
|
|
|
// validate parameters
|
|
if (!phtHashTable or !pleKey or !ppleEntry)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
pleList = phtHashTable->pleBuckets +
|
|
(*phtHashTable->pfnHash)(pleKey);
|
|
|
|
FindList(pleList, pleKey, ppleEntry, phtHashTable->pfnCompare);
|
|
|
|
// entry not found, fail
|
|
if (*ppleEntry is NULL)
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HT_DeleteEntry(
|
|
IN PHASH_TABLE phtHashTable,
|
|
IN PLIST_ENTRY pleKey,
|
|
OUT PLIST_ENTRY *ppleEntry)
|
|
/*++
|
|
|
|
Routine Description
|
|
Deletes the entry with the given key from the hash table.
|
|
Memory for the entry is not deleted.
|
|
|
|
Locks
|
|
Assumes the hash table is locked for writing.
|
|
|
|
Arguments
|
|
phtHashTable pointer to the hash table to be searched
|
|
pleKey key to be deleted
|
|
ppleEntry pointer to matching entry's address
|
|
|
|
Return Value
|
|
NO_ERROR entry exisits
|
|
ERROR_INVALID_PARAMETER o/w (entry does not exist)
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
// validate parameters
|
|
if (!phtHashTable or !pleKey or !ppleEntry)
|
|
return ERROR_INVALID_PARAMETER;
|
|
|
|
do // breakout loop
|
|
{
|
|
dwErr = HT_GetEntry(phtHashTable, pleKey, ppleEntry);
|
|
|
|
// entry not found, fail
|
|
if (dwErr != NO_ERROR)
|
|
break;
|
|
|
|
// entry found, delete from hash table and reset pointers
|
|
RemoveEntryList(*ppleEntry);
|
|
phtHashTable->ulNumEntries--;
|
|
} while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
|
|
BOOL
|
|
HT_IsPresentEntry(
|
|
IN PHASH_TABLE phtHashTable,
|
|
IN PLIST_ENTRY pleKey)
|
|
/*++
|
|
|
|
Routine Description
|
|
Is key present in the hash table?
|
|
|
|
Locks
|
|
Assumes the hash table is locked for reading.
|
|
|
|
Arguments
|
|
phtHashTable pointer to the hash table to be searched
|
|
pleKey key to be deleted
|
|
|
|
Return Value
|
|
TRUE entry exisits
|
|
FALSE o/w
|
|
|
|
--*/
|
|
{
|
|
DWORD dwErr;
|
|
PLIST_ENTRY pleEntry = NULL;
|
|
|
|
// validate parameters
|
|
if (!phtHashTable or !pleKey)
|
|
return FALSE;
|
|
|
|
dwErr = HT_GetEntry(phtHashTable, pleKey, &pleEntry);
|
|
|
|
// entry not found, fail
|
|
if (dwErr != NO_ERROR)
|
|
return FALSE;
|
|
|
|
// entry found, delete from hash table
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
|
|
DWORD
|
|
HT_MapCar(
|
|
IN PHASH_TABLE phtHashTable,
|
|
IN PVOID_FUNCTION pfnVoidFunction
|
|
)
|
|
/*++
|
|
|
|
Routine Description
|
|
Applies the specified function to all entries in a hash table.
|
|
|
|
Locks
|
|
Assumes the hash table is locked for reading.
|
|
|
|
Arguments
|
|
phtHashTable pointer to the hash table to be mapcar'ed
|
|
pfnVoidFunction pointer to function to apply to all entries
|
|
|
|
Return Value
|
|
NO_ERROR always
|
|
|
|
--*/
|
|
{
|
|
ULONG i;
|
|
PLIST_ENTRY pleList = NULL;
|
|
|
|
// validate parameters
|
|
if (!phtHashTable or !pfnVoidFunction)
|
|
return NO_ERROR;
|
|
|
|
for (i = 0; i < phtHashTable->ulNumBuckets; i++)
|
|
{
|
|
pleList = phtHashTable->pleBuckets + i;
|
|
MapCarList(pleList, pfnVoidFunction);
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|