Files
core/ASCFontConverter/Hash.cpp

378 lines
7.5 KiB
C++

#include "stdafx.h"
#include "MemoryUtils.h"
#include "StringExt.h"
#include "Hash.h"
//------------------------------------------------------------------------
struct THashBucket
{
StringExt *seKey;
union
{
void *p;
int i;
} uValue;
THashBucket *pNext;
};
struct THashIter
{
int nHashIndex;
THashBucket *pBucket;
};
//------------------------------------------------------------------------
CHash::CHash(BOOL bDeleteKeys)
{
m_bDeleteKeys = bDeleteKeys;
m_nBucketsCount = 7;
m_ppTable = (THashBucket **)MemUtilsMallocArray( m_nBucketsCount, sizeof(THashBucket *));
for ( int nHashIndex = 0; nHashIndex < m_nBucketsCount; ++nHashIndex )
m_ppTable[ nHashIndex ] = NULL;
m_nLength = 0;
}
CHash::~CHash()
{
THashBucket *pBucket = NULL;
for ( int nHashIndex = 0; nHashIndex < m_nBucketsCount; ++nHashIndex )
{
while ( m_ppTable[ nHashIndex ] )
{
pBucket = m_ppTable[ nHashIndex ];
m_ppTable[ nHashIndex ] = pBucket->pNext;
if (m_bDeleteKeys)
{
delete pBucket->seKey;
}
delete pBucket;
}
}
MemUtilsFree( m_ppTable );
}
void CHash::Add(StringExt *seKey, void *pValue)
{
if ( m_nLength >= m_nBucketsCount )
Expand();
THashBucket *pBucket = new THashBucket;
pBucket->seKey = seKey;
pBucket->uValue.p = pValue;
int nHashIndex = Hash( seKey );
pBucket->pNext = m_ppTable[ nHashIndex ];
m_ppTable[ nHashIndex ] = pBucket;
++m_nLength;
}
void CHash::Add(StringExt *seKey, int nValue)
{
if ( m_nLength >= m_nBucketsCount )
Expand();
THashBucket *pBucket = new THashBucket;
pBucket->seKey = seKey;
pBucket->uValue.i = nValue;
int nHashIndex = Hash( seKey );
pBucket->pNext = m_ppTable[ nHashIndex ];
m_ppTable[ nHashIndex ] = pBucket;
++m_nLength;
}
void CHash::Replace(StringExt *seKey, void *pValue)
{
THashBucket *pBucket = NULL;
int nHashIndex = 0;
if ( ( pBucket = Find( seKey, &nHashIndex ) ) )
{
pBucket->uValue.p = pValue;
delete seKey;
}
else
Add( seKey, pValue);
}
void CHash::Replace(StringExt *seKey, int nValue)
{
THashBucket *pBucket = NULL;
int nHashIndex = 0;
if ( ( pBucket = Find( seKey, &nHashIndex ) ) )
{
pBucket->uValue.i = nValue;
delete seKey;
}
else
Add( seKey, nValue);
}
void *CHash::Lookup(StringExt *seKey)
{
THashBucket *pBucket = NULL;
int nHashIndex = 0;
if ( !( pBucket = Find( seKey, &nHashIndex ) ) )
return NULL;
return pBucket->uValue.p;
}
int CHash::LookupInt(StringExt *seKey)
{
THashBucket *pBucket = NULL;
int nHashIndex = 0;
if ( !( pBucket = Find( seKey, &nHashIndex ) ) )
return 0;
return pBucket->uValue.i;
}
void *CHash::Lookup(char *sKey)
{
THashBucket *pBucket = NULL;
int nHashIndex = 0;
if ( !( pBucket = Find( sKey, &nHashIndex ) ) )
return NULL;
return pBucket->uValue.p;
}
int CHash::LookupInt(char *sKey)
{
THashBucket *pBucket = NULL;
int nHashIndex = 0;
if ( !( pBucket = Find( sKey, &nHashIndex ) ) )
return 0;
return pBucket->uValue.i;
}
void *CHash::Remove(StringExt *seKey)
{
THashBucket *pBucket;
THashBucket **ppBucket;
int nHashIndex = 0;
if ( !( pBucket = Find( seKey, &nHashIndex ) ) )
return NULL;
ppBucket = &m_ppTable[ nHashIndex ];
while ( *ppBucket != pBucket )
ppBucket = &((*ppBucket)->pNext);
*ppBucket = pBucket->pNext;
if ( m_bDeleteKeys )
delete pBucket->seKey;
void *pValue = pBucket->uValue.p;
delete pBucket;
--m_nLength;
return pValue;
}
int CHash::RemoveInt(StringExt *seKey)
{
THashBucket *pBucket;
THashBucket **ppBucket;
int nHashIndex = 0;
if ( !( pBucket = Find( seKey, &nHashIndex) ) )
return 0;
ppBucket = &m_ppTable[ nHashIndex ];
while ( *ppBucket != pBucket )
ppBucket = &((*ppBucket)->pNext);
*ppBucket = pBucket->pNext;
if (m_bDeleteKeys)
delete pBucket->seKey;
int nValue = pBucket->uValue.i;
delete pBucket;
--m_nLength;
return nValue;
}
void *CHash::Remove(char *sKey)
{
THashBucket *pBucket;
THashBucket **ppBucket;
int nHashIndex = 0;
if ( !( pBucket = Find( sKey, &nHashIndex ) ) )
return NULL;
ppBucket = &m_ppTable[ nHashIndex ];
while ( *ppBucket != pBucket )
ppBucket = &((*ppBucket)->pNext);
*ppBucket = pBucket->pNext;
if (m_bDeleteKeys)
delete pBucket->pNext;
void *pValue = pBucket->uValue.p;
delete pBucket;
--m_nLength;
return pValue;
}
int CHash::RemoveInt(char *sKey)
{
THashBucket *pBucket;
THashBucket **ppBucket;
int nHashIndex = 0;
if ( !( pBucket = Find( sKey, &nHashIndex ) ) )
return 0;
ppBucket = &m_ppTable[ nHashIndex ];
while (*ppBucket != pBucket )
ppBucket = &((*ppBucket)->pNext);
*ppBucket = pBucket->pNext;
if ( m_bDeleteKeys )
delete pBucket->seKey;
int nValue = pBucket->uValue.i;
delete pBucket;
--m_nLength;
return nValue;
}
void CHash::StartIter(THashIter **ppIter)
{
*ppIter = new THashIter;
(*ppIter)->nHashIndex = -1;
(*ppIter)->pBucket = NULL;
}
BOOL CHash::GetNext(THashIter **ppIter, StringExt **pseKey, void **ppValue)
{
if (!*ppIter)
return FALSE;
if ((*ppIter)->pBucket)
(*ppIter)->pBucket = (*ppIter)->pBucket->pNext;
while (!(*ppIter)->pBucket)
{
if (++(*ppIter)->nHashIndex == m_nBucketsCount)
{
delete *ppIter;
*ppIter = NULL;
return FALSE;
}
(*ppIter)->pBucket = m_ppTable[(*ppIter)->nHashIndex];
}
*pseKey = (*ppIter)->pBucket->seKey;
*ppValue = (*ppIter)->pBucket->uValue.p;
return TRUE;
}
BOOL CHash::GetNext(THashIter **ppIter, StringExt **pseKey, int *pnValue)
{
if (!*ppIter)
return FALSE;
if ((*ppIter)->pBucket)
(*ppIter)->pBucket = (*ppIter)->pBucket->pNext;
while (!(*ppIter)->pBucket)
{
if (++(*ppIter)->nHashIndex == m_nBucketsCount)
{
delete *ppIter;
*ppIter = NULL;
return FALSE;
}
(*ppIter)->pBucket = m_ppTable[(*ppIter)->nHashIndex ];
}
*pseKey = (*ppIter)->pBucket->seKey;
*pnValue = (*ppIter)->pBucket->uValue.i;
return TRUE;
}
void CHash::DeleteIter(THashIter **ppIter)
{
delete *ppIter;
*ppIter = NULL;
}
void CHash::Expand()
{
int nHashIndex = 0;
int nOldSize = m_nBucketsCount;
THashBucket **ppOldTab = m_ppTable;
m_nBucketsCount = 2 * m_nBucketsCount + 1;
m_ppTable = (THashBucket **)MemUtilsMallocArray( m_nBucketsCount, sizeof(THashBucket *) );
for ( nHashIndex = 0; nHashIndex < m_nBucketsCount; ++nHashIndex )
m_ppTable[ nHashIndex ] = NULL;
for (int nIndex = 0; nIndex < nOldSize; ++nIndex )
{
while ( ppOldTab[nIndex] )
{
THashBucket *pBucket = ppOldTab[ nIndex ];
ppOldTab[ nIndex ] = ppOldTab[ nIndex ]->pNext;
nHashIndex = Hash( pBucket->seKey );
pBucket->pNext = m_ppTable[ nHashIndex ];
m_ppTable[ nHashIndex ] = pBucket;
}
}
MemUtilsFree( ppOldTab );
}
THashBucket *CHash::Find(StringExt *seKey, int *pnHashIndex)
{
THashBucket *pBucket;
*pnHashIndex = Hash( seKey );
for ( pBucket = m_ppTable[ *pnHashIndex ]; pBucket; pBucket = pBucket->pNext )
{
if ( !pBucket->seKey->Compare( seKey ) )
return pBucket;
}
return NULL;
}
THashBucket *CHash::Find(char *sKey, int *pnHashIndex)
{
THashBucket *pBucket;
*pnHashIndex = Hash( sKey );
for ( pBucket = m_ppTable[ *pnHashIndex ]; pBucket; pBucket = pBucket->pNext )
{
if ( !pBucket->seKey->Compare( sKey ) )
return pBucket;
}
return NULL;
}
int CHash::Hash(StringExt *seKey)
{
char *sTemp;
unsigned int nHash = 0;
int nIndex;
for ( sTemp = seKey->GetBuffer(), nIndex = 0; nIndex < seKey->GetLength(); ++sTemp, ++nIndex )
nHash = 17 * nHash + (int)(*sTemp & 0xff);
return (int)(nHash % m_nBucketsCount);
}
int CHash::Hash(char *sKey)
{
char *sTemp;
unsigned int nHash = 0;
for ( sTemp = sKey; *sTemp; ++sTemp )
nHash = 17 * nHash + (int)(*sTemp & 0xff);
return (int)(nHash % m_nBucketsCount);
}