Files
Yajbir Singh f1b860b25c
Some checks failed
check / markdownlint (push) Has been cancelled
check / spellchecker (push) Has been cancelled
updated
2025-12-11 19:03:17 +05:30

411 lines
9.3 KiB
C++

/*
* (c) Copyright Ascensio System SIA 2010-2023
*
* This program is a free software product. You can redistribute it and/or
* modify it under the terms of the GNU Affero General Public License (AGPL)
* version 3 as published by the Free Software Foundation. In accordance with
* Section 7(a) of the GNU AGPL its Section 15 shall be amended to the effect
* that Ascensio System SIA expressly excludes the warranty of non-infringement
* of any third-party rights.
*
* This program is distributed WITHOUT ANY WARRANTY; without even the implied
* warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. For
* details, see the GNU AGPL at: http://www.gnu.org/licenses/agpl-3.0.html
*
* You can contact Ascensio System SIA at 20A-6 Ernesta Birznieka-Upish
* street, Riga, Latvia, EU, LV-1050.
*
* The interactive user interfaces in modified source and object code versions
* of the Program must display Appropriate Legal Notices, as required under
* Section 5 of the GNU AGPL version 3.
*
* Pursuant to Section 7(b) of the License you must retain the original Product
* logo when distributing the program. Pursuant to Section 7(e) we decline to
* grant you any rights under trademark law for use of our trademarks.
*
* All the Product's GUI elements, including illustrations and icon sets, as
* well as technical writing content are licensed under the terms of the
* Creative Commons Attribution-ShareAlike 4.0 International. See the License
* terms at http://creativecommons.org/licenses/by-sa/4.0/legalcode
*
*/
#include "MemoryUtils.h"
#include "StringExt.h"
#include "Hash.h"
#include "Utils.h"
namespace NSFontConverter
{
//------------------------------------------------------------------------
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);
}
}