nameditemlist.cpp
#include "headers.h"
NamedItemList::NamedItemList()
{
this->m_cBuckets = 0;
this->m_Buckets = NULL;
this->m_pMutex = NULL;
}
NamedItemList::~NamedItemList()
{
this->Clear();
if (NULL != this->m_Buckets)
delete[] this->m_Buckets;
if (NULL != this->m_pMutex)
delete this->m_pMutex;
}
HRESULT NamedItemList::Create(int cBuckets, NamedItemList * * ppNamedItemList)
{
AssertOutPtr(ppNamedItemList);
Assert(cBuckets > 0);
HRESULT hr;
int iBucket;
NamedItemList * pNamedItemList = NULL;
*ppNamedItemList = NULL;
pNamedItemList = new NamedItemList();
if (NULL == pNamedItemList)
{
hr = E_OUTOFMEMORY;
goto LError;
}
hr = Mutex::Create(&pNamedItemList->m_pMutex);
if (FAILED(hr))
goto LError;
pNamedItemList->m_Buckets = new NamedItem*[cBuckets];
if (NULL == pNamedItemList->m_Buckets)
{
hr = E_OUTOFMEMORY;
goto LError;
}
pNamedItemList->m_cBuckets = cBuckets;
for (iBucket = 0 ; iBucket < cBuckets ; ++iBucket)
pNamedItemList->m_Buckets[iBucket] = NULL;
*ppNamedItemList = pNamedItemList;
pNamedItemList = NULL;
hr = S_OK;
LError:
if (NULL != pNamedItemList)
delete pNamedItemList;
return hr;
}
void NamedItemList::Clear(void)
{
NamedItem * pNamedItem;
NamedItem * pNext;
int iBucket;
// This could get called due to out-of-memory failure at creation of the mutex.
if (NULL != this->m_pMutex)
this->m_pMutex->Enter();
if (this->m_Buckets != NULL)
{
for (iBucket = 0 ; iBucket < this->m_cBuckets ; ++iBucket)
{
pNamedItem = m_Buckets[iBucket];
while (pNamedItem != NULL)
{
pNext = pNamedItem->m_pNext;
delete pNamedItem;
pNamedItem = pNext;
}
m_Buckets[iBucket] = NULL;
}
}
if (NULL != this->m_pMutex)
this->m_pMutex->Leave();
}
HRESULT NamedItemList::Add(const WCHAR * pszName, DWORD flags)
{
HRESULT hr;
int iBucket;
NamedItem * pNamedItemOld;
NamedItem * pNamedItem = NULL;
this->m_pMutex->Enter();
pNamedItemOld = this->Find(pszName);
if (NULL != pNamedItemOld)
{
if (pNamedItemOld->m_flags == flags)
{
Bug("You've added the same named item twice. That's legal, but weird. "
"You might have a bug.");
hr = S_OK;
}
else
{
Bug("It's a violation of the script engine contract to add the same "
"named item twice with different flags.");
hr = E_UNEXPECTED;
}
goto LError;
}
hr = NamedItem::Create(pszName, &pNamedItem);
if (FAILED(hr))
goto LError;
pNamedItem->m_flags = flags;
iBucket = ComputeHash(pNamedItem->m_bstrName) % this->m_cBuckets;
pNamedItem->m_pNext = this->m_Buckets[iBucket];
this->m_Buckets[iBucket] = pNamedItem;
pNamedItem = NULL;
hr = S_OK;
LError:
if (NULL != pNamedItem)
delete pNamedItem;
this->m_pMutex->Leave();
return hr;
}
NamedItemList::NamedItem * NamedItemList::Find(const WCHAR * psz)
{
AssertReadString(psz);
int iBucket;
NamedItem * pNamedItem;
iBucket = ComputeHash(psz) % this->m_cBuckets;
for(pNamedItem = this->m_Buckets[iBucket] ; NULL != pNamedItem; pNamedItem = pNamedItem->m_pNext)
{
if (0 == wcscmp(psz, pNamedItem->m_bstrName))
break;
}
return pNamedItem;
}
void NamedItemList::Reset(void)
{
int iBucket;
NamedItem * pNamedItem;
NamedItem * pNext;
NamedItem * * ppPrevNext;
this->m_pMutex->Enter();
for (iBucket = 0 ; iBucket < this->m_cBuckets ; ++iBucket)
{
ppPrevNext = &this->m_Buckets[iBucket];
pNamedItem = this->m_Buckets[iBucket];
while (NULL != pNamedItem)
{
pNext = pNamedItem->m_pNext;
if (pNamedItem->IsPersistent())
{
pNamedItem->Reset();
ppPrevNext = &pNamedItem->m_pNext;
}
else
{
*ppPrevNext = pNext;
delete pNamedItem;
}
pNamedItem = pNext;
}
}
this->m_pMutex->Leave();
}
HRESULT NamedItemList::Clone(NamedItemList * * ppNamedItemList)
{
AssertOutPtr(ppNamedItemList);
HRESULT hr;
int iBucket;
NamedItemList * pNamedItemList = NULL;
NamedItem * pNamedItem;
*ppNamedItemList = NULL;
this->m_pMutex->Enter();
hr = NamedItemList::Create(this->m_cBuckets, &pNamedItemList);
if (FAILED(hr))
goto LError;
for (iBucket = 0 ; iBucket < this->m_cBuckets ; ++iBucket)
{
for (pNamedItem = this->m_Buckets[iBucket] ; NULL != pNamedItem ;
pNamedItem = pNamedItem->m_pNext)
{
if (!pNamedItem->IsPersistent())
continue;
hr = pNamedItemList->Add(pNamedItem->m_bstrName, pNamedItem->m_flags);
if (FAILED(hr))
goto LError;
}
}
*ppNamedItemList = pNamedItemList;
pNamedItemList = NULL;
hr = S_OK;
LError:
if (NULL != pNamedItemList)
delete pNamedItemList;
this->m_pMutex->Leave();
return hr;
}
NamedItemList::NamedItem::NamedItem()
{
this->m_pNext = NULL;
this->m_bstrName = NULL;
this->m_flags = 0;
}
NamedItemList::NamedItem::~NamedItem()
{
SysFreeString(this->m_bstrName);
}
HRESULT NamedItemList::NamedItem::Create(const WCHAR * pszName, NamedItem * * ppNamedItem)
{
AssertReadString(pszName);
AssertOutPtr(ppNamedItem);
HRESULT hr;
NamedItem * pNamedItem = NULL;
*ppNamedItem = NULL;
pNamedItem = new NamedItem();
if (NULL == pNamedItem)
{
hr = E_OUTOFMEMORY;
goto LError;
}
pNamedItem->m_bstrName = SysAllocString(pszName);
if (NULL == pNamedItem->m_bstrName)
{
hr = E_OUTOFMEMORY;
goto LError;
}
*ppNamedItem = pNamedItem;
pNamedItem = NULL;
hr = S_OK;
LError:
if (NULL != pNamedItem)
delete pNamedItem;
return hr;
}
BOOL NamedItemList::NamedItem::IsPersistent()
{
return (this->m_flags & SCRIPTITEM_ISPERSISTENT) == 0 ? FALSE : TRUE;
}
void NamedItemList::NamedItem::Reset(void)
{
}