不得不佩服微软的人,复杂的东西写的如此简单
struct CMyPlex { CMyPlex* pNext; void* data(void) { return this + 1; } static CMyPlex* Create(CMyPlex* &pHead, UINT nMax, UINT cbElement); void FreeDataChain(void); }; CMyPlex* CMyPlex::Create(CMyPlex* &pHead, UINT nMax, UINT cbElement) { CMyPlex* pTmp = (CMyPlex*)new BYTE[sizeof(CMyPlex) + nMax * cbElement]; pTmp->pNext = pHead; pHead = pTmp; return pTmp; } void CMyPlex::FreeDataChain(void) { CMyPlex* pTmp = this; while (pTmp != NULL) { BYTE* pBytes = (BYTE*)pTmp; CMyPlex* pNext = pTmp->pNext; delete[] pBytes; pTmp = pNext; } } class CMyMapPtrToPtr { protected: struct CMyAssoc { CMyAssoc* pNext; void* key; void* value; }; public: CMyMapPtrToPtr(int nBlockSize = 10); ~CMyMapPtrToPtr(void); void InitHashTable(UINT nHashSize, BOOL bAllocNow = TRUE); int GetCount(void) const; BOOL IsEmpty(void) const; void SetAt(void* key, void* newValue); UINT GetHashTableSize(void) const; UINT HashKey(void* key) const; void*& operator[](void* key); void RemoveAll(void); BOOL RemoveKey(void* key); protected: CMyAssoc** m_pHashTable; int m_nHashTableSize; struct CMyPlex* m_pBlocks; int m_nBlockSize; CMyAssoc* m_pFreeList; int m_nCount; CMyAssoc* NewMyAssoc(void); void FreeMyAssoc(CMyAssoc* pMyAssoc); CMyAssoc* GetMyAssocAt(void* key, UINT& nHash) const; }; CMyMapPtrToPtr::CMyMapPtrToPtr(int nBlockSize /* = 10 */) : m_nBlockSize(nBlockSize) { m_pHashTable = NULL; m_nHashTableSize = 17; m_pBlocks = NULL; m_nBlockSize = nBlockSize; m_pFreeList = NULL; m_nCount = 0; } CMyMapPtrToPtr::~CMyMapPtrToPtr(void) { RemoveAll(); } void CMyMapPtrToPtr::InitHashTable(UINT nHashSize, BOOL bAllocNow /* = TRUE */) { if (NULL != m_pHashTable) { delete[] m_pHashTable; m_pHashTable = NULL; } if (bAllocNow) { m_pHashTable = new CMyAssoc*[nHashSize]; memset(m_pHashTable, 0, sizeof(CMyAssoc*) * nHashSize); } m_nHashTableSize = nHashSize; } int CMyMapPtrToPtr::GetCount(void) const { return m_nCount; } BOOL CMyMapPtrToPtr::IsEmpty(void) const { BOOL bRet = FALSE; if (0 == m_nCount) { bRet = TRUE; } return bRet; } void CMyMapPtrToPtr::SetAt(void *key, void* newValue) { (*this)[key] =newValue; } UINT CMyMapPtrToPtr::GetHashTableSize(void) const { return m_nHashTableSize; } UINT CMyMapPtrToPtr::HashKey(void* key) const { return ((UINT)(void*)(DWORD)key) >> 4; } void*& CMyMapPtrToPtr::operator[](void* key) { UINT nHash = 0; CMyAssoc* pMyAssoc = NULL; if ((pMyAssoc = GetMyAssocAt(key, nHash)) == NULL) { if (NULL == m_pHashTable) { InitHashTable(m_nHashTableSize); } pMyAssoc = NewMyAssoc(); pMyAssoc->key = key; pMyAssoc->pNext = m_pHashTable[nHash]; m_pHashTable[nHash] = pMyAssoc; } return pMyAssoc->value; } void CMyMapPtrToPtr::RemoveAll(void) { if (NULL != m_pHashTable) { delete[] m_pHashTable; m_pHashTable = NULL; } m_nCount = 0; m_pFreeList = NULL; m_pBlocks->FreeDataChain(); m_pBlocks = NULL; } BOOL CMyMapPtrToPtr::RemoveKey(void* key) { BOOL bRet = FALSE; if (NULL == m_pHashTable) { goto Exit0; } CMyAssoc** ppAssocPre = &m_pHashTable[HashKey(key) % m_nHashTableSize]; CMyAssoc* pMyAssoc = NULL; for (pMyAssoc = *ppAssocPre; pMyAssoc != NULL; pMyAssoc = pMyAssoc->pNext) { if (pMyAssoc->key == key) { *ppAssocPre = pMyAssoc->pNext; FreeMyAssoc(pMyAssoc); bRet = TRUE; goto Exit0; } ppAssocPre = &pMyAssoc->pNext; } Exit0: return bRet; } CMyMapPtrToPtr::CMyAssoc* CMyMapPtrToPtr::NewMyAssoc(void) { if (NULL == m_pFreeList) { CMyPlex* pTmp = CMyPlex::Create(m_pBlocks, m_nBlockSize, sizeof(CMyAssoc)); CMyAssoc* pMyAssoc = (CMyAssoc*)pTmp->data(); pMyAssoc += m_nBlockSize - 1; for (int i = m_nBlockSize - 1; i >= 0; i--, pMyAssoc--) { pMyAssoc->pNext = m_pFreeList; m_pFreeList = pMyAssoc; } } CMyAssoc* pMyAssoc = m_pFreeList; m_pFreeList = pMyAssoc->pNext; m_nCount++; pMyAssoc->key = NULL; pMyAssoc->value = NULL; return pMyAssoc; } void CMyMapPtrToPtr::FreeMyAssoc(CMyAssoc* pMyAssoc) { pMyAssoc->pNext = m_pFreeList; m_pFreeList->pNext = pMyAssoc; m_nCount--; if (0 == m_nCount) { RemoveAll(); } } CMyMapPtrToPtr::CMyAssoc* CMyMapPtrToPtr::GetMyAssocAt(void* key, UINT& nHash) const { CMyAssoc* pMyAssocRet = NULL; nHash = HashKey(key) % m_nHashTableSize; if (NULL == m_pHashTable) { goto Exit0; } CMyAssoc* pMyAssoc = NULL; for (pMyAssoc = m_pHashTable[nHash]; pMyAssoc != NULL; pMyAssoc = pMyAssoc->pNext) { if (pMyAssoc->key == key) { pMyAssocRet = pMyAssoc; goto Exit0; } } Exit0: return pMyAssocRet; }