singrdk/base/Windows/bootd/hashtab.cpp

388 lines
9.3 KiB
C++

//////////////////////////////////////////////////////////////////////////////
//
// Abstract: Implementation of Template CHashTable64<> and class CHashTable64PVOID.
//
// NOTE: The keys 0 and ~0 are both reserved for internal use.
//
#pragma once
#include <winlean.h>
#include "hashtab.h"
//////////////////////////////////////////////////////////////////////////////
#undef EMPTY
#undef DELETED
#define EMPTY 0
#define DELETED ~0u
CHashTable32PVOID::CHashTable32PVOID()
{
m_pTable = NULL;
m_nSize = 0;
m_nValid = 0;
}
CHashTable32PVOID::CHashTable32PVOID(INT nInitialSize)
{
m_pTable = NULL;
m_nSize = 0;
m_nValid = 0;
Resize(nInitialSize);
}
CHashTable32PVOID::~CHashTable32PVOID()
{
if (m_pTable) {
delete[] m_pTable;
m_pTable = NULL;
}
m_nSize = 0;
m_nValid = 0;
}
CHashTable32PVOID::Entry * CHashTable32PVOID::FindEntry(UINT32 key)
{
if (key == EMPTY || key == DELETED || m_nSize <= 0) {
return NULL;
}
INT offset = Offset(key);
INT orig_offset = offset;
for (;;) {
if (m_pTable[offset].key == EMPTY) {
break; // EMPTY, stop.
}
else if (m_pTable[offset].key == key) { // Match, return TRUE
if (offset != orig_offset) { // Increase locality.
Swap(m_pTable[offset], m_pTable[orig_offset]);
offset = orig_offset;
}
return &m_pTable[offset];
}
else { // Not, try next bucket.
offset = (offset + 1) % m_nSize;
}
}
return NULL;
}
PVOID CHashTable32PVOID::Find(UINT32 key)
{
Entry *pEntry = FindEntry(key);
return pEntry ? pEntry->value : NULL;
}
BOOL CHashTable32PVOID::Change(UINT32 key, PVOID value)
{
Entry *pEntry = FindEntry(key);
if (pEntry) {
pEntry->value = value;
return TRUE;
}
return Insert(key, value);
}
BOOL CHashTable32PVOID::Insert(UINT32 key, PVOID value)
{
if (key == EMPTY || key == DELETED) {
return FALSE;
}
if ((m_nValid + 1) > (m_nSize / 2)) { // Table is never > 1/2 full!
if (m_nSize == 0) {
if (!Resize(32))
return FALSE;
}
else {
if (!Resize(m_nSize * 2))
return FALSE;
}
}
INT offset = Offset(key);
for (;;) {
if (m_pTable[offset].key == EMPTY || m_pTable[offset].key == DELETED) {
// EMPTY, Insert
m_pTable[offset].key = key;
m_pTable[offset].value = value;
m_nValid++;
return TRUE;
}
else { // Not, try next bucket.
offset = (offset + 1) % m_nSize;
}
}
// return FALSE;
}
BOOL CHashTable32PVOID::Delete(UINT32 key)
{
if (key == EMPTY || key == DELETED) {
return FALSE;
}
if (m_nSize == 0) {
return FALSE;
}
INT offset = Offset(key);
// First, find the value.
for (;;) {
if (m_pTable[offset].key == EMPTY) { // EMPTY, stop.
return FALSE;
}
else if (m_pTable[offset].key == key) { // Match, return TRUE
m_pTable[offset].key = DELETED;
m_pTable[offset].value = 0;
m_nValid--;
return TRUE;
}
else { // Not, try next bucket.
offset = (offset + 1) % m_nSize;
}
}
// return FALSE;
}
BOOL CHashTable32PVOID::Resize(INT nNewSize)
{
Entry *pOldTable = m_pTable;
INT nOldSize = m_nSize;
m_pTable = new Entry[nNewSize];
if (m_pTable == NULL) {
return FALSE;
}
for (INT i = 0; i < nNewSize; i++) {
m_pTable[i].key = EMPTY;
m_pTable[i].value = 0;
}
m_nSize = nNewSize;
m_nValid = 0;
if (pOldTable) {
for (INT i = 0; i < nOldSize; i++) {
if (pOldTable[i].key != EMPTY && pOldTable[i].key != DELETED) {
Insert(pOldTable[i].key, pOldTable[i].value);
}
}
delete[] pOldTable;
pOldTable = NULL;
}
return TRUE;
}
PVOID CHashTable32PVOID::Enumerate(UINT32& key, INT& nIterator)
{
for (; (INT)nIterator < m_nSize; nIterator++) {
if (m_pTable[nIterator].key == EMPTY ||
m_pTable[nIterator].key == DELETED) {
continue;
}
key = m_pTable[nIterator].key;
return m_pTable[nIterator++].value;
}
key = EMPTY;
nIterator = 0;
return NULL;
}
//////////////////////////////////////////////////////////////////////////////
#undef EMPTY
#undef DELETED
#define EMPTY 0
#define DELETED ~0uI64
CHashTable64PVOID::CHashTable64PVOID()
{
m_pTable = NULL;
m_nSize = 0;
m_nValid = 0;
}
CHashTable64PVOID::CHashTable64PVOID(INT nInitialSize)
{
m_pTable = NULL;
m_nSize = 0;
m_nValid = 0;
Resize(nInitialSize);
}
CHashTable64PVOID::~CHashTable64PVOID()
{
if (m_pTable) {
delete[] m_pTable;
m_pTable = NULL;
}
m_nSize = 0;
m_nValid = 0;
}
CHashTable64PVOID::Entry * CHashTable64PVOID::FindEntry(UINT64 key)
{
if (key == EMPTY || key == DELETED || m_nSize <= 0) {
return NULL;
}
INT offset = Offset(key);
INT orig_offset = offset;
for (;;) {
if (m_pTable[offset].key == EMPTY) {
break; // EMPTY, stop.
}
else if (m_pTable[offset].key == key) { // Match, return TRUE
if (offset != orig_offset) { // Increase locality.
Swap(m_pTable[offset], m_pTable[orig_offset]);
offset = orig_offset;
}
return &m_pTable[offset];
}
else { // Not, try next bucket.
offset = (offset + 1) % m_nSize;
}
}
return NULL;
}
PVOID CHashTable64PVOID::Find(UINT64 key)
{
Entry *pEntry = FindEntry(key);
return pEntry ? pEntry->value : NULL;
}
BOOL CHashTable64PVOID::Change(UINT64 key, PVOID value)
{
Entry *pEntry = FindEntry(key);
if (pEntry) {
pEntry->value = value;
return TRUE;
}
return Insert(key, value);
}
BOOL CHashTable64PVOID::Insert(UINT64 key, PVOID value)
{
if (key == EMPTY || key == DELETED) {
return FALSE;
}
if ((m_nValid + 1) > (m_nSize / 2)) { // Table is never > 1/2 full!
if (m_nSize == 0) {
if (!Resize(32))
return FALSE;
}
else {
if (!Resize(m_nSize * 2))
return FALSE;
}
}
INT offset = Offset(key);
for (;;) {
if (m_pTable[offset].key == EMPTY || m_pTable[offset].key == DELETED) {
// EMPTY, Insert
m_pTable[offset].key = key;
m_pTable[offset].value = value;
m_nValid++;
return TRUE;
}
else { // Not, try next bucket.
offset = (offset + 1) % m_nSize;
}
}
// return FALSE;
}
BOOL CHashTable64PVOID::Delete(UINT64 key)
{
if (key == EMPTY || key == DELETED) {
return FALSE;
}
if (m_nSize == 0) {
return FALSE;
}
INT offset = Offset(key);
// First, find the value.
for (;;) {
if (m_pTable[offset].key == EMPTY) { // EMPTY, stop.
return FALSE;
}
else if (m_pTable[offset].key == key) { // Match, return TRUE
m_pTable[offset].key = DELETED;
m_pTable[offset].value = 0;
m_nValid--;
return TRUE;
}
else { // Not, try next bucket.
offset = (offset + 1) % m_nSize;
}
}
// return FALSE;
}
BOOL CHashTable64PVOID::Resize(INT nNewSize)
{
Entry *pOldTable = m_pTable;
INT nOldSize = m_nSize;
m_pTable = new Entry[nNewSize];
if (m_pTable == NULL) {
return FALSE;
}
for (INT i = 0; i < nNewSize; i++) {
m_pTable[i].key = EMPTY;
m_pTable[i].value = 0;
}
m_nSize = nNewSize;
m_nValid = 0;
if (pOldTable) {
for (INT i = 0; i < nOldSize; i++) {
if (pOldTable[i].key != EMPTY && pOldTable[i].key != DELETED) {
Insert(pOldTable[i].key, pOldTable[i].value);
}
}
delete[] pOldTable;
pOldTable = NULL;
}
return TRUE;
}
PVOID CHashTable64PVOID::Enumerate(UINT64& key, INT& nIterator)
{
for (; (INT)nIterator < m_nSize; nIterator++) {
if (m_pTable[nIterator].key == EMPTY ||
m_pTable[nIterator].key == DELETED) {
continue;
}
key = m_pTable[nIterator].key;
return m_pTable[nIterator++].value;
}
key = EMPTY;
nIterator = 0;
return NULL;
}
//
///////////////////////////////////////////////////////////////// End of File.