//**@@@*@@@**************************************************** // // Microsoft Windows // Copyright (C) Microsoft Corporation. All rights reserved. // //**@@@*@@@**************************************************** // // FileName: tlist.h // // Abstract: This is the header and implementation file for a template // list class // // ---------------------------------------------------------------------------- #pragma once typedef void* LISTPOS; template class TItem { public: TItem() throw(); ~TItem() throw(); TItem * pNext; TItem * pPrev; T* pData; }; template TItem::TItem() : pNext(NULL), pPrev(NULL), pData(NULL) { return; } template TItem::~TItem() { return; } template class TList { public: TList() throw(); ~TList() throw(); BOOL GetHead( T** ppHead ) const throw(); LISTPOS GetHeadPosition() const throw(); LISTPOS GetTailPosition() const throw(); LISTPOS AddHead(__drv_aliasesMem T* pNewHead) throw(); LISTPOS AddTail(__drv_aliasesMem T* pNewTail) throw(); BOOL RemoveTail(T** ppOldTail) throw(); BOOL RemoveHead(T** ppOldHead) throw(); void RemoveAll() throw(); LISTPOS Find( T* pSearchValue ) const throw(); void RemoveAt(LISTPOS pos) throw(); BOOL GetNext(LISTPOS& rPos, T**ppThisData) const throw(); BOOL IsEmpty() const throw(); DWORD GetCount() const throw(); HRESULT Initialize(DWORD dwValue) throw(); BOOL GetAt( LONG index, T** ppElement) const throw(); BOOL GetAt( LISTPOS pos, T** ppElement) const throw(); LISTPOS InsertBefore(LISTPOS pos, T* pNewElement) throw(); LISTPOS InsertAfter(LISTPOS pos, T* pNewElement) throw(); void MoveHeadList(TList *pFromList) throw(); private: TItem* m_pHead; TItem* m_pTail; LONG m_lCount; }; template TList::TList() : m_pHead(NULL), m_pTail(NULL), m_lCount(0) { return; } template TList::~TList() { ATLASSERT(NULL == m_pHead); ATLASSERT(NULL == m_pTail); ATLASSERT(0 == m_lCount); return; } template BOOL TList::GetHead(T** ppHead) const { if (!m_pHead) { *ppHead = NULL; return FALSE; } *ppHead = m_pHead->pData; return TRUE; } template LISTPOS TList::GetHeadPosition() const { return reinterpret_cast(m_pHead); } template LISTPOS TList::GetTailPosition() const { return reinterpret_cast(m_pTail); } template LISTPOS TList::AddTail(__drv_aliasesMem T* pNewTail) { TItem* pNewItem; pNewItem = new TItem; if (NULL == pNewItem) { return( reinterpret_cast( NULL )); } pNewItem->pData = pNewTail; pNewItem->pPrev = m_pTail; pNewItem->pNext = NULL; if (NULL == m_pTail) { m_pHead = pNewItem; } else { m_pTail->pNext = pNewItem; } m_pTail = pNewItem; m_lCount++; return( reinterpret_cast( pNewItem ) ); } template LISTPOS TList::AddHead(__drv_aliasesMem T* pNewHead) { TItem *pNewItem; pNewItem = new TItem; if ( !pNewItem ) { return( reinterpret_cast( NULL ) ); } pNewItem->pData = pNewHead; pNewItem->pNext = m_pHead; pNewItem->pPrev = NULL; if ( NULL != m_pHead ) { m_pHead->pPrev = pNewItem; } else { m_pTail = pNewItem; } m_pHead = pNewItem; m_lCount++; return( reinterpret_cast( pNewItem ) ); } template void TList::MoveHeadList(TList *pFromList) { // Link head item of this list to tail item of other list if (NULL != m_pHead) m_pHead->pPrev = pFromList->m_pTail; if (NULL != pFromList->m_pTail) pFromList->m_pTail->pNext = m_pHead; // Adjust this list's head and tail pointers if (pFromList->m_pHead) m_pHead = pFromList->m_pHead; if (NULL == m_pTail) m_pTail = pFromList->m_pTail; // Adjust this list's count m_lCount += pFromList->m_lCount; // Reset other list's head and tail pointers and count pFromList->m_pHead = NULL; pFromList->m_pTail = NULL; pFromList->m_lCount = 0; } template BOOL TList::RemoveTail( T** ppOldTail) { if (!ppOldTail || !m_pTail) { return FALSE; } TItem *pOldItem = m_pTail; *ppOldTail = pOldItem->pData; m_pTail = pOldItem->pPrev; if ( NULL != m_pTail ) { m_pTail->pNext = NULL; } else { m_pHead = NULL; } delete pOldItem; m_lCount--; ATLASSERT(m_lCount >= 0); return( TRUE ); } template BOOL TList::RemoveHead(T** ppOldHead) { if ( !ppOldHead || !m_pHead ) { return( FALSE ); } TItem *pOldItem = m_pHead; *ppOldHead = pOldItem->pData; m_pHead = pOldItem->pNext; if ( NULL != m_pHead ) { m_pHead->pPrev = NULL; } else { m_pTail = NULL; } delete pOldItem; m_lCount--; ATLASSERT(m_lCount >= 0); return( TRUE ); } template void TList::RemoveAll() { TItem *pNext; while( NULL != m_pHead ) { pNext = m_pHead->pNext; delete m_pHead; m_pHead = pNext; } m_lCount = 0; m_pTail = NULL; return; } template LISTPOS TList::Find( T* pSearchValue ) const { TItem *pItem = m_pHead; for ( ; NULL != pItem; pItem = pItem->pNext ) { if ( pItem->pData == pSearchValue ) { return( reinterpret_cast(pItem) ); } } return( reinterpret_cast(NULL) ); } template void TList::RemoveAt(LISTPOS pos) { // ATLASSERT( NULL != pos ) TItem *pOldItem = reinterpret_cast< TItem* >(pos); // remove pOldItem from list if ( pOldItem == m_pHead ) { m_pHead = pOldItem->pNext; } else { ATLASSERT( pOldItem->pPrev ); pOldItem->pPrev->pNext = pOldItem->pNext; } if (pOldItem == m_pTail) { m_pTail = pOldItem->pPrev; } else { ATLASSERT( pOldItem->pNext ); pOldItem->pNext->pPrev = pOldItem->pPrev; } delete pOldItem; m_lCount--; ATLASSERT(m_lCount >= 0); return; } template BOOL TList::GetNext(LISTPOS& rPos, T**ppThisData) const { TItem *pItem = reinterpret_cast< TItem* >(rPos); if ( !pItem ) { return( FALSE ); } rPos = reinterpret_cast(pItem->pNext); if (ppThisData) { *ppThisData = pItem->pData; } return( TRUE ); } template BOOL TList::IsEmpty() const { return (0 == m_lCount); } template HRESULT TList::Initialize(DWORD dwValue) { HRESULT hr = S_OK; return hr; } template DWORD TList::GetCount() const { return static_cast(m_lCount); } template LISTPOS TList::InsertBefore(LISTPOS pos, T* pNewElement) { TItem* pOldItem = reinterpret_cast*>(pos); TItem* pNewItem; if ((pOldItem == NULL) || (pOldItem->pPrev == NULL)) { return (AddHead(pNewElement)); // insert before nothing -> head of the list } // Insert it before pos pNewItem = new TItem; if (!pNewItem) { return (reinterpret_cast(NULL)); } pNewItem->pData = pNewElement; pNewItem->pPrev = pOldItem->pPrev; pNewItem->pNext = pOldItem; pOldItem->pPrev->pNext = pNewItem; pOldItem->pPrev = pNewItem; m_lCount++; return (reinterpret_cast(pNewItem)); } template LISTPOS TList::InsertAfter(LISTPOS pos, T* pNewElement) { TItem* pOldItem = reinterpret_cast*>(pos); TItem* pNewItem; if ((pOldItem == NULL) || (pOldItem->pNext == NULL)) { return (AddTail(pNewElement)); // insert after nothing -> tail of the list } // Insert it after pos pNewItem = new TItem; if (!pNewItem) { return (reinterpret_cast(NULL)); } pNewItem->pData = pNewElement; pNewItem->pPrev = pOldItem; pNewItem->pNext = pOldItem->pNext; pOldItem->pNext->pPrev = pNewItem; pOldItem->pNext = pNewItem; m_lCount++; return (reinterpret_cast(pNewItem)); } template BOOL TList::GetAt( LONG index, T** ppElement) const { if (ppElement == NULL) { return false; } *ppElement = NULL; if ((index < 0) || (index > (m_lCount - 1))) { return false; } T* pElement = NULL; BOOL bRes = TRUE; LISTPOS pos = GetHeadPosition(); for (int i = 0; bRes && (i <= index); i++) { bRes = GetNext(pos, &pElement); } if (bRes) { *ppElement = pElement; } return bRes; } template BOOL TList::GetAt(LISTPOS pos, T**ppThisData) const { TItem *pItem = reinterpret_cast< TItem* >(pos); if ( !pItem ) { return( FALSE ); } *ppThisData = pItem->pData; return( TRUE ); }