Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

416 lines
9.0 KiB

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