////////////////////////////////////////////////////////////////////////////// // // File: hashtab.cpp // Copyright (c) Microsoft Corporation. All rights reserved. // Abstract: Implementation of Template CHashTable64<> and class CHashTable64PVOID. // // NOTE: The keys 0 and ~0 are both reserved for internal use. // #pragma once #include #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.