#ifndef _LIST_H #define _LIST_H #include "msoedbg.h" // ================================================================================= // CNode class definition and implementation // ================================================================================= template class CNode { private: CNode *m_pNext, *m_pPrev; Value_T m_pValue; public: CNode(): m_pNext(NULL), m_pPrev(NULL), m_pValue(0) {} CNode* GetNext() {return m_pNext;} CNode* GetPrev() {return m_pPrev;} void SetNext(CNode *pNext) {m_pNext = pNext;} void SetPrev(CNode *pPrev) {m_pPrev = pPrev;} Value_T GetValue() {return m_pValue;} static HRESULT CreateNode(CNode **ppNode, Value_T value); }; //*************************************************** template HRESULT CNode::CreateNode(CNode **ppNode, Value_T value) { HRESULT hr = S_OK; CNode *pNode = new CNode; if (NULL == pNode) { hr = E_OUTOFMEMORY; goto Exit; } pNode->m_pValue = value; Exit: *ppNode = pNode; return hr; } // ================================================================================= // CList template class // Basic list for keeping some class Value_T // Value_T must have AddRef and Release defined // ================================================================================= template class CList { private: CNode *m_pHead; ULONG m_cCount; public: CList(); ~CList(); void ClearList(); ULONG GetCount() {return m_cCount;} HRESULT AddValue(Value_T value, DWORD *pdwCookie); HRESULT RemoveValue(DWORD dwCookie); HRESULT GetNext(Value_T *value, DWORD *pdwCookie); }; // ================================================================================= // CList function implementaions // ================================================================================= template CList::CList(): m_pHead(NULL), m_cCount(0) { } //*************************************************** template CList::~CList() { ClearList(); } //*************************************************** template void CList::ClearList() { CNode *pNext; while (m_pHead) { pNext = m_pHead->GetNext(); (m_pHead->GetValue())->Release(); delete m_pHead; m_pHead = pNext; } m_cCount = 0; } //*************************************************** template HRESULT CList::AddValue(Value_T value, DWORD *pdwCookie) { CNode *pNode = NULL; HRESULT hr = CNode::CreateNode(&pNode, value); if (SUCCEEDED(hr)) { value->AddRef(); m_cCount++; if (m_pHead) { m_pHead->SetPrev(pNode); pNode->SetNext(m_pHead); } m_pHead = pNode; *pdwCookie = reinterpret_cast(pNode); } else *pdwCookie = 0; return hr; } //*************************************************** template HRESULT CList::RemoveValue(DWORD dwCookie) { CNode *pCurr = reinterpret_cast< CNode* >(dwCookie); CNode *pPrev = pCurr->GetPrev(), *pNext = pCurr->GetNext(); Assert(pCurr); if (pPrev) pPrev->SetNext(pNext); else m_pHead = pNext; if (pNext) pNext->SetPrev(pPrev); (pCurr->GetValue())->Release(); delete pCurr; m_cCount--; return S_OK; } //*************************************************** // *pdwCookie must equal 0 for first time. template HRESULT CList::GetNext(Value_T *pValue, DWORD* pdwCookie) { CNode *pNode = reinterpret_cast< CNode* >(*pdwCookie); if (0 == m_cCount) return E_FAIL; if (pNode) { pNode = pNode->GetNext(); if (!pNode) { *pdwCookie = 0; *pValue = 0; return E_FAIL; } } else pNode = m_pHead; if (pNode) { *pValue = pNode->GetValue(); *pdwCookie = reinterpret_cast(pNode); (*pValue)->AddRef(); } else { *pValue = NULL; *pdwCookie = 0; } return S_OK; } #endif