windows-nt/Source/XPSP1/NT/enduser/speech/tts/prompts/engine/hash.cpp
2020-09-26 16:20:57 +08:00

285 lines
6.4 KiB
C++

//////////////////////////////////////////////////////////////////////
// Hash.cpp: implementation of the CHash class.
//
// Created by JOEM 03-2000
// Copyright (C) 2000 Microsoft Corporation
// All Rights Reserved
//
/////////////////////////////////////////////////////// JOEM 3-2000 //
#include "stdafx.h"
#include "Hash.h"
#include "common.h"
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////// JOEM 3-2000 //
CHashNode::CHashNode()
{
m_pszKey = NULL;
m_pValue = NULL;
m_pNext = NULL;
}
CHashNode::~CHashNode()
{
if ( m_pszKey )
{
free(m_pszKey);
m_pszKey = NULL;
}
if ( m_pValue )
{
m_pValue->Release();
m_pValue = NULL;
}
if ( m_pNext )
{
delete m_pNext;
m_pNext = NULL;
}
}
//////////////////////////////////////////////////////////////////////
// Construction/Destruction
/////////////////////////////////////////////////////// JOEM 3-2000 //
CHash::CHash()
{
memset (m_heads, 0, sizeof(m_heads));
}
//////////////////////////////////////////////////////////////////////
// CHash
/////////////////////////////////////////////////////// JOEM 3-2000 //
CHash::~CHash()
{
for (int i=0; i < HASH_SIZE; i++)
{
if (m_heads[i])
{
delete m_heads[i];
}
}
}
//////////////////////////////////////////////////////////////////////
// CHash
//
// BuildEntry
/////////////////////////////////////////////////////// JOEM 3-2000 //
HRESULT CHash::BuildEntry(const WCHAR* pszKey, IUnknown* pValue)
{
SPDBG_FUNC( "CHash::BuildEntry" );
HRESULT hr = S_OK;
CHashNode* pNewNode = NULL;
CHashNode* pTempNode = NULL;
CHashNode* pLastNode = NULL;
int iIndex;
SPDBG_ASSERT (pszKey);
SPDBG_ASSERT (pValue);
if (pszKey && *pszKey)
{
iIndex = HashValue((WCHAR*)pszKey);
pTempNode = m_heads[iIndex];
// Look for the key, see if we already have an entry
while (pTempNode)
{
if ( wcscmp(pTempNode->m_pszKey, pszKey) == 0)
{
break;
}
pLastNode = pTempNode;
pTempNode = pTempNode->m_pNext;
}
// If there is an entry, report error
if (pTempNode)
{
hr = E_INVALIDARG;
}
if ( SUCCEEDED(hr) )
{
pNewNode = new CHashNode;
if ( !pNewNode )
{
hr = E_OUTOFMEMORY;
}
}
if ( SUCCEEDED(hr) )
{
if ( (pNewNode->m_pszKey = wcsdup (pszKey)) == NULL )
{
hr = E_OUTOFMEMORY;
}
}
if ( SUCCEEDED(hr) )
{
pNewNode->m_pValue = pValue;
pValue->AddRef();
if (pLastNode)
{
pLastNode->m_pNext = pNewNode;
}
else
{
m_heads[iIndex] = pNewNode;
}
}
if ( FAILED(hr) && pNewNode )
{
free (pNewNode);
pNewNode = NULL;
}
}
SPDBG_REPORT_ON_FAIL( hr );
return hr;
}
//////////////////////////////////////////////////////////////////////
// CHash
//
// DeleteEntry
/////////////////////////////////////////////////////// JOEM 3-2000 //
HRESULT CHash::DeleteEntry(const WCHAR *pszKey)
{
SPDBG_FUNC( "CHash::DeleteEntry" );
HRESULT hr = E_INVALIDARG;
CHashNode* pTempNode = NULL;
CHashNode* pLastNode = NULL;
int iIndex;
SPDBG_ASSERT (pszKey);
iIndex = HashValue((WCHAR*)pszKey);
pTempNode = m_heads[iIndex];
while (pTempNode)
{
if ( wcscmp (pTempNode->m_pszKey, pszKey) == 0 )
{
CHashNode* pRem = pTempNode;
if (pLastNode)
{
pLastNode->m_pNext = pRem->m_pNext;
}
else
{
m_heads[iIndex] = pRem->m_pNext;
}
pRem->m_pNext = NULL; //Avoid cleaning up the rest of the chain
delete pRem;
hr = S_OK;
break;
}
pLastNode = pTempNode;
pTempNode = pTempNode->m_pNext;
}
SPDBG_REPORT_ON_FAIL( hr );
return hr;
}
//////////////////////////////////////////////////////////////////////
// CHash
//
// Find
/////////////////////////////////////////////////////// JOEM 3-2000 //
IUnknown* CHash::Find(const WCHAR *pszKey)
{
SPDBG_FUNC( "CHash::Find" );
CHashNode* pTempNode = NULL;
SPDBG_ASSERT (*pszKey);
pTempNode = m_heads[HashValue((WCHAR*)pszKey)];
while (pTempNode)
{
if ( wcscmp (pTempNode->m_pszKey, pszKey) == 0 )
{
return pTempNode->m_pValue;
}
pTempNode = pTempNode->m_pNext;
}
return NULL;
}
//////////////////////////////////////////////////////////////////////
// CHash
//
// NextKey
/////////////////////////////////////////////////////// JOEM 3-2000 //
HRESULT CHash::NextKey(USHORT *punIdx1, USHORT* punIdx2, WCHAR** ppszKey)
{
SPDBG_FUNC( "CHash::NextKey" );
CHashNode* pNode = NULL;
USHORT i = 0;
SPDBG_ASSERT (punIdx1);
SPDBG_ASSERT (punIdx2);
*ppszKey = NULL;
if (m_heads)
{
while (*punIdx1 < HASH_SIZE )
{
if ((pNode = m_heads[*punIdx1]) != NULL)
{
for ( i=0; i<*punIdx2 && pNode->m_pNext; i++)
{
pNode = pNode->m_pNext;
}
if (i==*punIdx2)
{
(*punIdx2)++;
*ppszKey = pNode->m_pszKey;
break;
}
}
(*punIdx1)++;
*punIdx2 = 0;
}
}
return S_OK;
}
//////////////////////////////////////////////////////////////////////
// CHash
//
// HashValue
/////////////////////////////////////////////////////// JOEM 3-2000 //
int CHash::HashValue (WCHAR *pszKey)
{
SPDBG_FUNC( "CHash::HashValue" );
USHORT unVal = 0;
SPDBG_ASSERT (pszKey);
for (unVal=0; *pszKey ; pszKey++)
{
unVal = (64*unVal + *pszKey) % HASH_SIZE;
}
return unVal;
}