nameditemlist.cpp

nameditemlist.cpp

  • Comments 2

#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)
{
}

Page 1 of 1 (1 items)