// Licensed to the .NET Foundation under one or more agreements. // The .NET Foundation licenses this file to you under the MIT license. // See the LICENSE file in the project root for more information. // ============================================================ // // List.hpp // // // Defines the List class // // ============================================================ #ifndef __BINDER__LIST_HPP__ #define __BINDER__LIST_HPP__ #include "bindertypes.hpp" #include "ex.h" namespace BINDER_SPACE { // // ListNode // typedef void *LISTNODE; template class ListNode { public: ListNode(Type item); virtual ~ListNode(); void SetNext(ListNode *pNode); void SetPrev(ListNode *pNode); Type GetItem(); ListNode *GetNext(); ListNode *GetPrev(); private: Type _type; ListNode *_pNext; ListNode *_pPrev; }; // // List // template class List { public: List(); ~List(); LISTNODE AddHead(const Type &item); LISTNODE AddTail(const Type &item); LISTNODE GetHeadPosition(); LISTNODE GetTailPosition(); void RemoveAt(LISTNODE pNode); void RemoveAll(); LISTNODE Find(const Type &item); int GetCount(); Type GetNext(LISTNODE &pNode); Type GetAt(LISTNODE pNode); LISTNODE AddSorted(const Type &item, LPVOID pfn); public: DWORD _dwSig; private: ListNode *_pHead; ListNode *_pTail; int _iCount; }; // // ListNode Implementation // template ListNode::ListNode(Type item) : _type(item) , _pNext(NULL) , _pPrev(NULL) { } template ListNode::~ListNode() { } template void ListNode::SetNext(ListNode *pNode) { _pNext = pNode; } template void ListNode::SetPrev(ListNode *pNode) { _pPrev = pNode; } template Type ListNode::GetItem() { return _type; } template ListNode *ListNode::GetNext() { return _pNext; } template ListNode *ListNode::GetPrev() { return _pPrev; } // // List Implementation // template List::List() : _pHead(NULL) , _pTail(NULL) , _iCount(0) { _dwSig = 0x5453494c; /* 'TSIL' */ } template List::~List() { HRESULT hr = S_OK; EX_TRY { RemoveAll(); } EX_CATCH_HRESULT(hr); } template LISTNODE List::AddHead(const Type &item) { ListNode *pNode = NULL; NEW_CONSTR(pNode, ListNode(item)); if (pNode) { _iCount++; pNode->SetNext(_pHead); pNode->SetPrev(NULL); if (_pHead == NULL) { _pTail = pNode; } else { _pHead->SetPrev(pNode); } _pHead = pNode; } return (LISTNODE)pNode; } template LISTNODE List::AddSorted(const Type &item, LPVOID pfn) { ListNode *pNode = NULL; LISTNODE pCurrNode = NULL; LISTNODE pPrevNode = NULL; int i; Type curItem; LONG (*pFN) (const Type item1, const Type item2); pFN = (LONG (*) (const Type item1, const Type item2))pfn; if(_pHead == NULL) { return AddHead(item); } else { pCurrNode = GetHeadPosition(); curItem = ((ListNode *) pCurrNode)->GetItem(); for (i = 0; i < _iCount; i++) { if (pFN(item, curItem) < 1) { NEW_CONSTR(pNode, ListNode(item)); if (pNode) { pNode->SetPrev((ListNode *)pPrevNode); pNode->SetNext((ListNode *)pCurrNode); // update pPrevNode if(pPrevNode) { ((ListNode *)pPrevNode)->SetNext(pNode); } else { _pHead = pNode; } // update pCurrNode ((ListNode *)pCurrNode)->SetPrev(pNode); _iCount++; } break; } pPrevNode = pCurrNode; GetNext(pCurrNode); if(i+1 == _iCount) { return AddTail(item); } else { _ASSERTE(pCurrNode); curItem = GetAt(pCurrNode); } } } return (LISTNODE)pNode; } template LISTNODE List::AddTail(const Type &item) { ListNode *pNode = NULL; NEW_CONSTR(pNode, ListNode(item)); if (pNode) { _iCount++; if (_pTail) { pNode->SetPrev(_pTail); _pTail->SetNext(pNode); _pTail = pNode; } else { _pHead = _pTail = pNode; } } return (LISTNODE)pNode; } template int List::GetCount() { return _iCount; } template LISTNODE List::GetHeadPosition() { return (LISTNODE)_pHead; } template LISTNODE List::GetTailPosition() { return (LISTNODE)_pTail; } template Type List::GetNext(LISTNODE &pNode) { ListNode *pListNode = (ListNode *)pNode; // Faults if you pass NULL _ASSERTE(pNode); Type item = pListNode->GetItem(); pNode = (LISTNODE)(pListNode->GetNext()); return item; } template void List::RemoveAll() { int i; LISTNODE listNode = NULL; ListNode *pDelNode = NULL; listNode = GetHeadPosition(); for (i = 0; i < _iCount; i++) { pDelNode = (ListNode *)listNode; GetNext(listNode); SAFE_DELETE(pDelNode); } _iCount = 0; _pHead = NULL; _pTail = NULL; } template void List::RemoveAt(LISTNODE pNode) { ListNode *pListNode = (ListNode *)pNode; ListNode *pPrevNode = NULL; ListNode *pNextNode = NULL; if (pNode) { pPrevNode = pListNode->GetPrev(); pNextNode = pListNode->GetNext(); if (pPrevNode) { pPrevNode->SetNext(pNextNode); if (pNextNode) { pNextNode->SetPrev(pPrevNode); } else { // We're removing the last node, so we have a new tail _pTail = pPrevNode; } SAFE_DELETE(pListNode); } else { // No previous, so we are the head of the list _pHead = pNextNode; if (pNextNode) { pNextNode->SetPrev(NULL); } else { // No previous, or next. There was only one node. _pHead = NULL; _pTail = NULL; } SAFE_DELETE(pListNode); } _iCount--; } } template LISTNODE List::Find(const Type &item) { int i; Type curItem; LISTNODE pNode = NULL; LISTNODE pMatchNode = NULL; ListNode * pListNode = NULL; pNode = GetHeadPosition(); for (i = 0; i < _iCount; i++) { pListNode = (ListNode *)pNode; curItem = GetNext(pNode); if (curItem == item) { pMatchNode = (LISTNODE)pListNode; break; } } return pMatchNode; } template Type List::GetAt(LISTNODE pNode) { ListNode *pListNode = (ListNode *)pNode; // Faults if you pass NULL _ASSERTE(pNode); return pListNode->GetItem(); } }; #endif