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.
270 lines
5.3 KiB
270 lines
5.3 KiB
/*++
|
|
|
|
Copyright(c) 1995 Microsoft Corporation
|
|
|
|
MODULE NAME
|
|
table.c
|
|
|
|
ABSTRACT
|
|
Generic hash table manipulation routines.
|
|
|
|
AUTHOR
|
|
Anthony Discolo (adiscolo) 28-Jul-1995
|
|
|
|
REVISION HISTORY
|
|
|
|
--*/
|
|
|
|
#define UNICODE
|
|
#define _UNICODE
|
|
|
|
#include <nt.h>
|
|
#include <ntrtl.h>
|
|
#include <nturtl.h>
|
|
|
|
#include <stdlib.h>
|
|
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <npapi.h>
|
|
#include <acd.h>
|
|
#include <debug.h>
|
|
|
|
#include "table.h"
|
|
#include "misc.h"
|
|
|
|
//
|
|
// Generic hash table entry.
|
|
//
|
|
typedef struct _HASH_ENTRY {
|
|
LIST_ENTRY ListEntry;
|
|
LPTSTR pszKey;
|
|
PVOID pData;
|
|
} HASH_ENTRY, *PHASH_ENTRY;
|
|
|
|
|
|
|
|
PHASH_TABLE
|
|
NewTable()
|
|
{
|
|
PHASH_TABLE pTable;
|
|
INT i;
|
|
|
|
pTable = LocalAlloc(LPTR, sizeof (HASH_TABLE));
|
|
if (pTable == NULL) {
|
|
RASAUTO_TRACE("NewTable: LocalAlloc failed");
|
|
return NULL;
|
|
}
|
|
for (i = 0; i < NBUCKETS; i++)
|
|
InitializeListHead(&pTable->ListEntry[i]);
|
|
pTable->ulSize = 0;
|
|
|
|
return pTable;
|
|
} // NewTable
|
|
|
|
|
|
|
|
VOID
|
|
FreeHashTableEntry(
|
|
IN PHASH_ENTRY pHashEntry
|
|
)
|
|
{
|
|
LocalFree(pHashEntry->pszKey);
|
|
if (pHashEntry->pData != NULL)
|
|
LocalFree(pHashEntry->pData);
|
|
LocalFree(pHashEntry);
|
|
} // FreeHashTableEntry
|
|
|
|
|
|
|
|
VOID
|
|
ClearTable(
|
|
IN PHASH_TABLE pTable
|
|
)
|
|
{
|
|
INT i;
|
|
PLIST_ENTRY pHead;
|
|
PHASH_ENTRY pHashEntry;
|
|
|
|
for (i = 0; i < NBUCKETS; i++) {
|
|
while (!IsListEmpty(&pTable->ListEntry[i])) {
|
|
pHead = RemoveHeadList(&pTable->ListEntry[i]);
|
|
pHashEntry = CONTAINING_RECORD(pHead, HASH_ENTRY, ListEntry);
|
|
|
|
FreeHashTableEntry(pHashEntry);
|
|
}
|
|
}
|
|
pTable->ulSize = 0;
|
|
} // ClearTable
|
|
|
|
|
|
|
|
VOID
|
|
EnumTable(
|
|
IN PHASH_TABLE pTable,
|
|
IN PHASH_TABLE_ENUM_PROC pProc,
|
|
IN PVOID pArg
|
|
)
|
|
{
|
|
INT i;
|
|
PLIST_ENTRY pEntry, pNextEntry;
|
|
PHASH_ENTRY pHashEntry;
|
|
|
|
for (i = 0; i < NBUCKETS; i++) {
|
|
pEntry = pTable->ListEntry[i].Flink;
|
|
while (pEntry != &pTable->ListEntry[i]) {
|
|
pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
|
|
|
|
//
|
|
// Get the next entry before calling
|
|
// the enumerator procedure to allow
|
|
// it to call DeleteTableEntry().
|
|
//
|
|
pNextEntry = pEntry->Flink;
|
|
//
|
|
// If the enumerator procedure
|
|
// returns FALSE, terminate the
|
|
// enumeration.
|
|
//
|
|
if (!pProc(pArg, pHashEntry->pszKey, pHashEntry->pData))
|
|
return;
|
|
pEntry = pNextEntry;
|
|
}
|
|
}
|
|
} // EnumTable
|
|
|
|
|
|
VOID
|
|
FreeTable(
|
|
IN PHASH_TABLE pTable
|
|
)
|
|
{
|
|
ClearTable(pTable);
|
|
LocalFree(pTable);
|
|
} // FreeTable
|
|
|
|
|
|
|
|
INT
|
|
HashString(
|
|
IN LPTSTR pszKey
|
|
)
|
|
{
|
|
CHAR ch;
|
|
DWORD dwHashValue = 0;
|
|
LPTSTR p = pszKey;
|
|
|
|
while (*p != L'\0') {
|
|
ch = (CHAR)tolower(*p);
|
|
dwHashValue += (INT)ch * (INT)ch;
|
|
p++;
|
|
}
|
|
|
|
return (INT)(dwHashValue % NBUCKETS);
|
|
} // HashString
|
|
|
|
|
|
|
|
PHASH_ENTRY
|
|
GetTableEntryCommon(
|
|
IN PHASH_TABLE pTable,
|
|
IN LPTSTR pszKey
|
|
)
|
|
{
|
|
INT nBucket = HashString(pszKey);
|
|
PLIST_ENTRY pEntry;
|
|
PHASH_ENTRY pHashEntry;
|
|
|
|
for (pEntry = pTable->ListEntry[nBucket].Flink;
|
|
pEntry != &pTable->ListEntry[nBucket];
|
|
pEntry = pEntry->Flink)
|
|
{
|
|
pHashEntry = CONTAINING_RECORD(pEntry, HASH_ENTRY, ListEntry);
|
|
|
|
if (!_wcsicmp(pHashEntry->pszKey, pszKey))
|
|
return pHashEntry;
|
|
}
|
|
|
|
return NULL;
|
|
} // GetTableEntryCommon
|
|
|
|
|
|
|
|
BOOLEAN
|
|
GetTableEntry(
|
|
IN PHASH_TABLE pTable,
|
|
IN LPTSTR pszKey,
|
|
OUT PVOID *pData
|
|
)
|
|
{
|
|
PHASH_ENTRY pHashEntry;
|
|
|
|
pHashEntry = GetTableEntryCommon(pTable, pszKey);
|
|
if (pHashEntry != NULL) {
|
|
if (pData != NULL)
|
|
*pData = pHashEntry->pData;
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
} // GetTableEntry
|
|
|
|
|
|
|
|
BOOLEAN
|
|
PutTableEntry(
|
|
IN PHASH_TABLE pTable,
|
|
IN LPTSTR pszKey,
|
|
IN PVOID pData
|
|
)
|
|
{
|
|
INT nBucket = HashString(pszKey);
|
|
PHASH_ENTRY pHashEntry;
|
|
|
|
|
|
pHashEntry = GetTableEntryCommon(pTable, pszKey);
|
|
if (pHashEntry == NULL) {
|
|
pHashEntry = LocalAlloc(LPTR, sizeof (HASH_ENTRY));
|
|
if (pHashEntry == NULL) {
|
|
RASAUTO_TRACE("PutTableEntry: LocalAlloc failed");
|
|
return FALSE;
|
|
}
|
|
pHashEntry->pszKey = CopyString(pszKey);
|
|
if (pHashEntry->pszKey == NULL) {
|
|
RASAUTO_TRACE("PutTableEntry: LocalAlloc failed");
|
|
LocalFree(pHashEntry);
|
|
return FALSE;
|
|
}
|
|
InsertHeadList(
|
|
&pTable->ListEntry[nBucket],
|
|
&pHashEntry->ListEntry);
|
|
pTable->ulSize++;
|
|
}
|
|
else {
|
|
if (pHashEntry->pData != pData)
|
|
LocalFree(pHashEntry->pData);
|
|
}
|
|
pHashEntry->pData = pData;
|
|
|
|
return TRUE;
|
|
} // PutTableEntry
|
|
|
|
|
|
|
|
BOOLEAN
|
|
DeleteTableEntry(
|
|
IN PHASH_TABLE pTable,
|
|
IN LPTSTR pszKey
|
|
)
|
|
{
|
|
PHASH_ENTRY pHashEntry;
|
|
|
|
pHashEntry = GetTableEntryCommon(pTable, pszKey);
|
|
if (pHashEntry != NULL) {
|
|
RemoveEntryList(&pHashEntry->ListEntry);
|
|
FreeHashTableEntry(pHashEntry);
|
|
pTable->ulSize--;
|
|
}
|
|
|
|
return (pHashEntry != NULL);
|
|
} // DeleteTableEntry
|
|
|