184 lines
3.1 KiB
C++
184 lines
3.1 KiB
C++
/*
|
|
** GENHASH.CPP
|
|
** Sean P. Nolan
|
|
**
|
|
** Generic UNICODE-tagged hash table.
|
|
*/
|
|
|
|
#pragma warning(disable: 4237) // disable "bool" reserved
|
|
|
|
#include "wcsutil.h"
|
|
|
|
/*--------------------------------------------------------------------------+
|
|
| CGenericHash |
|
|
+--------------------------------------------------------------------------*/
|
|
|
|
CGenericHash::CGenericHash(DWORD cBuckets)
|
|
{
|
|
m_chi = cBuckets;
|
|
m_rgphi = NULL;
|
|
}
|
|
|
|
CGenericHash::~CGenericHash()
|
|
{
|
|
if (m_rgphi)
|
|
{
|
|
this->RemoveAll();
|
|
_MsnFree(m_rgphi);
|
|
}
|
|
}
|
|
|
|
LPVOID
|
|
CGenericHash::PvFind(OLECHAR *wszName)
|
|
{
|
|
HITEM *phi = this->FindItem(wszName, NULL);
|
|
|
|
return(phi ? phi->pvData : NULL);
|
|
}
|
|
|
|
BOOL
|
|
CGenericHash::FAdd(OLECHAR *wszName, LPVOID pv)
|
|
{
|
|
BOOL fRet = FALSE;
|
|
HITEM **pphiHead, *phiNew;
|
|
|
|
this->Lock();
|
|
|
|
this->FEnsureBuckets();
|
|
|
|
if (m_rgphi &&
|
|
(phiNew = (HITEM*) _MsnAlloc(sizeof(HITEM))))
|
|
{
|
|
// values
|
|
if (!(phiNew->bstrName = ::SysAllocString(wszName)))
|
|
{
|
|
_MsnFree(phiNew);
|
|
this->Unlock();
|
|
return(FALSE);
|
|
}
|
|
|
|
phiNew->pvData = pv;
|
|
|
|
// link it into the list
|
|
pphiHead = &(m_rgphi[this->GetHashValue(wszName)]);
|
|
|
|
phiNew->phiPrev = NULL;
|
|
phiNew->phiNext = *pphiHead;
|
|
|
|
if (*pphiHead)
|
|
(*pphiHead)->phiPrev = phiNew;
|
|
|
|
*pphiHead = phiNew;
|
|
fRet = TRUE;
|
|
}
|
|
|
|
this->Unlock();
|
|
return(fRet);
|
|
}
|
|
|
|
void
|
|
CGenericHash::Remove(OLECHAR *wszName)
|
|
{
|
|
HITEM *phi, **pphiHead;
|
|
|
|
this->Lock();
|
|
if (phi = this->FindItem(wszName, &pphiHead))
|
|
this->RemoveItem(pphiHead, phi);
|
|
this->Unlock();
|
|
}
|
|
|
|
void
|
|
CGenericHash::RemoveAll()
|
|
{
|
|
HITEM **pphi;
|
|
DWORD ihi;
|
|
|
|
this->Lock();
|
|
if (m_rgphi)
|
|
{
|
|
for (pphi = m_rgphi, ihi = 0; ihi < m_chi; ++ihi, ++pphi)
|
|
{
|
|
while (*pphi)
|
|
this->RemoveItem(pphi, *pphi);
|
|
}
|
|
}
|
|
this->Unlock();
|
|
}
|
|
|
|
BOOL
|
|
CGenericHash::FEnsureBuckets()
|
|
{
|
|
if (!m_rgphi)
|
|
{
|
|
if (m_rgphi = (HITEM**) _MsnAlloc(m_chi * sizeof(HITEM*)))
|
|
::FillMemory(m_rgphi, m_chi * sizeof(HITEM*), 0);
|
|
}
|
|
|
|
return(m_rgphi != NULL);
|
|
}
|
|
|
|
DWORD
|
|
CGenericHash::GetHashValue(OLECHAR *wsz)
|
|
{
|
|
DWORD dwSum = 0;
|
|
OLECHAR *pwch;
|
|
|
|
// nyi - a real hash function
|
|
for (pwch = wsz; *pwch; ++pwch)
|
|
dwSum += (DWORD) *pwch;
|
|
|
|
return(dwSum % m_chi);
|
|
}
|
|
|
|
void
|
|
CGenericHash::FreeHashData(LPVOID pv)
|
|
{
|
|
// default is to do nothing
|
|
return;
|
|
}
|
|
|
|
HITEM*
|
|
CGenericHash::FindItem(OLECHAR *wszName, HITEM ***ppphiHead)
|
|
{
|
|
HITEM **pphiHead;
|
|
HITEM *phi;
|
|
|
|
if (!m_rgphi)
|
|
{
|
|
if (ppphiHead)
|
|
*ppphiHead = NULL;
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
pphiHead = &(m_rgphi[this->GetHashValue(wszName)]);
|
|
|
|
if (ppphiHead)
|
|
*ppphiHead = pphiHead;
|
|
|
|
phi = *pphiHead;
|
|
while (phi && wcsicmp(wszName, phi->bstrName))
|
|
phi = phi->phiNext;
|
|
|
|
return(phi);
|
|
}
|
|
|
|
void
|
|
CGenericHash::RemoveItem(HITEM **pphiHead, HITEM *phi)
|
|
{
|
|
if (phi->phiPrev)
|
|
phi->phiPrev->phiNext = phi->phiNext;
|
|
|
|
if (phi->phiNext)
|
|
phi->phiNext->phiPrev = phi->phiPrev;
|
|
|
|
if (phi == *pphiHead)
|
|
*pphiHead = phi->phiNext;
|
|
|
|
::SysFreeString(phi->bstrName);
|
|
this->FreeHashData(phi->pvData);
|
|
_MsnFree(phi);
|
|
}
|
|
|
|
|