|
|
|
|
|
|
|
|
|
|
|
//////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
//<2F>ļ<EFBFBD> TObjectList.h
|
|
|
|
|
|
//<2F><>Ҫ<EFBFBD><D2AA><EFBFBD><EFBFBD>:
|
|
|
|
|
|
// ָ<><D6B8><EFBFBD><EFBFBD><EFBFBD><EFBFBD>ģ<EFBFBD><C4A3><EFBFBD><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
/////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
|
#ifndef _TOBJECTLIST_H
|
|
|
|
|
|
#define _TOBJECTLIST_H
|
|
|
|
|
|
#pragma once
|
|
|
|
|
|
|
|
|
|
|
|
namespace NSet
|
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN64
|
|
|
|
|
|
typedef long DF_LONG; //<2F><><EFBFBD><EFBFBD>32λ<32><CEBB><EFBFBD><EFBFBD>
|
|
|
|
|
|
#else
|
|
|
|
|
|
typedef __int64 DF_LONG; //<2F><><EFBFBD><EFBFBD>64λ<34><CEBB><EFBFBD><EFBFBD>
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
class TObjectList
|
|
|
|
|
|
{
|
|
|
|
|
|
public:
|
|
|
|
|
|
// Construction
|
|
|
|
|
|
TObjectList(int nBlockSize = 10);
|
|
|
|
|
|
TObjectList(TObjectList<T>& pNewList, int nBlockSize = 10);
|
|
|
|
|
|
virtual ~TObjectList();
|
|
|
|
|
|
|
|
|
|
|
|
// Attributes (head and tail)
|
|
|
|
|
|
// count of elements
|
|
|
|
|
|
DF_LONG GetCount() const;
|
|
|
|
|
|
DF_LONG GetSize() const;
|
|
|
|
|
|
bool IsEmpty() const;
|
|
|
|
|
|
|
|
|
|
|
|
// peek at head or tail
|
|
|
|
|
|
T*& GetHead();
|
|
|
|
|
|
const T* GetHead() const;
|
|
|
|
|
|
T*& GetTail();
|
|
|
|
|
|
const T* GetTail() const;
|
|
|
|
|
|
|
|
|
|
|
|
// Operations
|
|
|
|
|
|
// get head or tail (and remove it) - don't call on empty list!
|
|
|
|
|
|
T* RemoveHead();
|
|
|
|
|
|
T* RemoveTail();
|
|
|
|
|
|
|
|
|
|
|
|
// add before head or after tail
|
|
|
|
|
|
POSITION AddHead(T* newElement);
|
|
|
|
|
|
POSITION AddTail(T* newElement);
|
|
|
|
|
|
|
|
|
|
|
|
// add another list of elements before head or after tail
|
|
|
|
|
|
void AddHead(TObjectList<T>* pNewList);
|
|
|
|
|
|
void AddTail(TObjectList<T>* pNewList);
|
|
|
|
|
|
|
|
|
|
|
|
// remove all elements
|
|
|
|
|
|
void RemoveAll();
|
|
|
|
|
|
void DeepErase(); //<2F><><EFBFBD>ȿռ<C8BF><D5BC>ͷţ<CDB7><C5A3><EFBFBD><EFBFBD><EFBFBD>ָ<EFBFBD><D6B8>ָ<EFBFBD><D6B8><EFBFBD>Ŀռ<C4BF>
|
|
|
|
|
|
|
|
|
|
|
|
// iteration
|
|
|
|
|
|
POSITION GetHeadPosition() const;
|
|
|
|
|
|
POSITION GetTailPosition() const;
|
|
|
|
|
|
T*& GetNext(POSITION& rPosition); // return *Position++
|
|
|
|
|
|
const T* GetNext(POSITION& rPosition) const; // return *Position++
|
|
|
|
|
|
T*& GetPrev(POSITION& rPosition); // return *Position--
|
|
|
|
|
|
const T* GetPrev(POSITION& rPosition) const; // return *Position--
|
|
|
|
|
|
|
|
|
|
|
|
// getting/modifying an element at a given position
|
|
|
|
|
|
T*& GetAt(POSITION position);
|
|
|
|
|
|
const T* GetAt(POSITION position) const;
|
|
|
|
|
|
void SetAt(POSITION pos, T* newElement);
|
|
|
|
|
|
|
|
|
|
|
|
void RemoveAt(POSITION position);
|
|
|
|
|
|
bool Swap(POSITION pos1, POSITION pos2); //swap two position element
|
|
|
|
|
|
void MoveToBefore(POSITION pos, POSITION posMove);
|
|
|
|
|
|
void MoveToAfter(POSITION pos, POSITION posMove);
|
|
|
|
|
|
|
|
|
|
|
|
// inserting before or after a given position
|
|
|
|
|
|
POSITION InsertBefore(POSITION position, T* newElement);
|
|
|
|
|
|
POSITION InsertAfter(POSITION position, T* newElement);
|
|
|
|
|
|
|
|
|
|
|
|
// helper functions (note: O(n) speed)
|
|
|
|
|
|
POSITION Find(T* searchValue, POSITION startAfter = NULL) const;
|
|
|
|
|
|
// defaults to starting at the HEAD
|
|
|
|
|
|
// return NULL if not found
|
|
|
|
|
|
POSITION FindIndex(INT_PTR nIndex) const;
|
|
|
|
|
|
// get the 'nIndex'th element (may return NULL)
|
|
|
|
|
|
|
|
|
|
|
|
// Implementation
|
|
|
|
|
|
protected:
|
|
|
|
|
|
struct TNode
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode * pNext;
|
|
|
|
|
|
TNode * pPrev;
|
|
|
|
|
|
T * data;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
struct CBlock // warning variable length structure
|
|
|
|
|
|
{
|
|
|
|
|
|
CBlock* pNext;
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef _WIN64
|
|
|
|
|
|
#if (_AFX_PACKING >= 8)
|
|
|
|
|
|
DWORD dwReserved[1]; // align on 8 byte boundary
|
|
|
|
|
|
#endif
|
|
|
|
|
|
#endif
|
|
|
|
|
|
// BYTE data[maxNum*elementSize];
|
|
|
|
|
|
|
|
|
|
|
|
void* data() { return this+1; }
|
|
|
|
|
|
|
|
|
|
|
|
static CBlock* Create(CBlock*& pHead, DF_LONG nMax, DF_LONG cbElement)
|
|
|
|
|
|
{
|
|
|
|
|
|
CBlock* p = (CBlock*) new BYTE[sizeof(CBlock) + nMax * cbElement];
|
|
|
|
|
|
// may throw exception
|
|
|
|
|
|
p->pNext = (CBlock*)pHead;
|
|
|
|
|
|
pHead = p; // change head (adds in reverse order for simplicity)
|
|
|
|
|
|
return p;
|
|
|
|
|
|
}
|
|
|
|
|
|
// like 'calloc' but no zero fill
|
|
|
|
|
|
// may throw memory exceptions
|
|
|
|
|
|
|
|
|
|
|
|
void FreeDataChain() // free this one and links
|
|
|
|
|
|
{
|
|
|
|
|
|
CBlock* p = this;
|
|
|
|
|
|
while (p != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
BYTE* bytes = (BYTE*) p;
|
|
|
|
|
|
CBlock* pNext = p->pNext;
|
|
|
|
|
|
delete[] bytes;
|
|
|
|
|
|
p = pNext;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
protected:
|
|
|
|
|
|
TNode* m_pNodeHead;
|
|
|
|
|
|
TNode* m_pNodeTail;
|
|
|
|
|
|
TNode* m_pNodeFree;
|
|
|
|
|
|
|
|
|
|
|
|
CBlock* m_pBlocks;
|
|
|
|
|
|
DF_LONG m_nBlockSize;
|
|
|
|
|
|
DF_LONG m_nCount;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
TNode* NewNode(TNode*, TNode*);
|
|
|
|
|
|
void FreeNode(TNode*);
|
|
|
|
|
|
void RemoveAtNoClear(POSITION position);
|
|
|
|
|
|
|
|
|
|
|
|
public:
|
|
|
|
|
|
// local typedefs for class templates
|
|
|
|
|
|
typedef T* BASE_TYPE;
|
|
|
|
|
|
typedef T* BASE_ARG_TYPE;
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
//<2F><>ʵ<EFBFBD><CAB5>
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
TObjectList<T>::TObjectList(int nBlockSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_nBlockSize = nBlockSize;
|
|
|
|
|
|
m_nCount = 0;
|
|
|
|
|
|
m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
|
|
|
|
|
|
m_pBlocks = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
TObjectList<T>::TObjectList(TObjectList<T>& pNewList, int nBlockSize)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_nBlockSize = nBlockSize;
|
|
|
|
|
|
m_nCount = 0;
|
|
|
|
|
|
m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
|
|
|
|
|
|
m_pBlocks = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
// add a list of same elements
|
|
|
|
|
|
AddTail(&pNewList);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
TObjectList<T>::~TObjectList()
|
|
|
|
|
|
{
|
|
|
|
|
|
RemoveAll();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
DF_LONG TObjectList<T>::GetCount() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_nCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
DF_LONG TObjectList<T>::GetSize() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_nCount;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
bool TObjectList<T>::IsEmpty() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return m_nCount == 0;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T*& TObjectList<T>::GetHead()
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(m_pNodeHead != NULL);
|
|
|
|
|
|
return m_pNodeHead->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
const T* TObjectList<T>::GetHead() const
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(m_pNodeHead != NULL);
|
|
|
|
|
|
if(m_pNodeHead == NULL)
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
return m_pNodeHead->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T*& TObjectList<T>::GetTail()
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(m_pNodeTail != NULL);
|
|
|
|
|
|
return m_pNodeTail->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
const T* TObjectList<T>::GetTail() const
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(m_pNodeTail != NULL);
|
|
|
|
|
|
if(m_pNodeTail == NULL)
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
return m_pNodeTail->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T* TObjectList<T>::RemoveHead()
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(m_pNodeHead != NULL); // don't call on empty list !!!
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(m_pNodeHead, sizeof(TNode)));
|
|
|
|
|
|
|
|
|
|
|
|
TNode* pOldNode = m_pNodeHead;
|
|
|
|
|
|
T* returnValue = pOldNode->data;
|
|
|
|
|
|
|
|
|
|
|
|
m_pNodeHead = pOldNode->pNext;
|
|
|
|
|
|
if (m_pNodeHead != NULL)
|
|
|
|
|
|
m_pNodeHead->pPrev = NULL;
|
|
|
|
|
|
else
|
|
|
|
|
|
m_pNodeTail = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
FreeNode(pOldNode);
|
|
|
|
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T* TObjectList<T>::RemoveTail()
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(m_pNodeTail != NULL); // don't call on empty list !!!
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(m_pNodeTail, sizeof(TNode)));
|
|
|
|
|
|
|
|
|
|
|
|
TNode* pOldNode = m_pNodeTail;
|
|
|
|
|
|
T* returnValue = pOldNode->data;
|
|
|
|
|
|
|
|
|
|
|
|
m_pNodeTail = pOldNode->pPrev;
|
|
|
|
|
|
if (m_pNodeTail != NULL)
|
|
|
|
|
|
m_pNodeTail->pNext = NULL;
|
|
|
|
|
|
else
|
|
|
|
|
|
m_pNodeHead = NULL;
|
|
|
|
|
|
|
|
|
|
|
|
FreeNode(pOldNode);
|
|
|
|
|
|
|
|
|
|
|
|
return returnValue;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::AddHead(T* newElement)
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNewNode = NewNode(NULL, m_pNodeHead);
|
|
|
|
|
|
pNewNode->data = newElement;
|
|
|
|
|
|
if (m_pNodeHead != NULL)
|
|
|
|
|
|
m_pNodeHead->pPrev = pNewNode;
|
|
|
|
|
|
else
|
|
|
|
|
|
m_pNodeTail = pNewNode;
|
|
|
|
|
|
m_pNodeHead = pNewNode;
|
|
|
|
|
|
|
|
|
|
|
|
return (POSITION) pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::AddTail(T* newElement)
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNewNode = NewNode(m_pNodeTail, NULL);
|
|
|
|
|
|
pNewNode->data = newElement;
|
|
|
|
|
|
if (m_pNodeTail != NULL)
|
|
|
|
|
|
m_pNodeTail->pNext = pNewNode;
|
|
|
|
|
|
else
|
|
|
|
|
|
m_pNodeHead = pNewNode;
|
|
|
|
|
|
m_pNodeTail = pNewNode;
|
|
|
|
|
|
|
|
|
|
|
|
return (POSITION) pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::AddHead(TObjectList<T>* pNewList)
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(pNewList != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
// add a list of same elements to head (maintain order)
|
|
|
|
|
|
POSITION pos = pNewList->GetTailPosition();
|
|
|
|
|
|
while (pos != NULL)
|
|
|
|
|
|
AddHead(pNewList->GetPrev(pos));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::AddTail(TObjectList<T>* pNewList)
|
|
|
|
|
|
{
|
|
|
|
|
|
ENSURE(pNewList != NULL);
|
|
|
|
|
|
|
|
|
|
|
|
// add a list of same elements
|
|
|
|
|
|
POSITION pos = pNewList->GetHeadPosition();
|
|
|
|
|
|
while (pos != NULL)
|
|
|
|
|
|
AddTail(pNewList->GetNext(pos));
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::RemoveAll()
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pBlocks->FreeDataChain();
|
|
|
|
|
|
|
|
|
|
|
|
m_nCount = 0;
|
|
|
|
|
|
m_pNodeHead = m_pNodeTail = m_pNodeFree = NULL;
|
|
|
|
|
|
m_pBlocks = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::DeepErase()
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = m_pNodeHead;
|
|
|
|
|
|
while(pNode != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNext = pNode->pNext;
|
|
|
|
|
|
delete pNode->data;
|
|
|
|
|
|
//delete pNode;
|
|
|
|
|
|
pNode = pNext;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
m_nCount = 0;
|
|
|
|
|
|
m_pNodeHead = m_pNodeTail = NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
//swap two position element
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
bool TObjectList<T>::Swap(POSITION pos1, POSITION pos2)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(pos1==pos2 || pos1==NULL || pos2==NULL)
|
|
|
|
|
|
return false;
|
|
|
|
|
|
|
|
|
|
|
|
TNode* pNode1 = (TNode*) pos1;
|
|
|
|
|
|
TNode* pNode2 = (TNode*) pos2;
|
|
|
|
|
|
T* pTempData = pNode1->data;
|
|
|
|
|
|
pNode1->data = pNode2->data;
|
|
|
|
|
|
pNode2->data = pTempData;
|
|
|
|
|
|
/*TNode* pTemp;
|
|
|
|
|
|
pTemp = pNode1->pPrev; pNode1->pPrev = pNode2->pPrev; pNode2->pPrev = pTemp;
|
|
|
|
|
|
pTemp = pNode1->pNext; pNode1->pNext = pNode2->pNext; pNode2->pNext = pTemp;
|
|
|
|
|
|
|
|
|
|
|
|
if(pNode1->pPrev == pNode1) pNode1->pPrev = pNode2;
|
|
|
|
|
|
if(pNode1->pNext == pNode1) pNode1->pNext = pNode2;
|
|
|
|
|
|
if(pNode2->pPrev == pNode2) pNode2->pPrev = pNode1;
|
|
|
|
|
|
if(pNode2->pNext == pNode2) pNode2->pNext = pNode1;*/
|
|
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::GetHeadPosition() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return (POSITION) m_pNodeHead;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::GetTailPosition() const
|
|
|
|
|
|
{
|
|
|
|
|
|
return (POSITION) m_pNodeTail;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T*& TObjectList<T>::GetNext(POSITION& rPosition) // return *Position++
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) rPosition;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
rPosition = (POSITION) pNode->pNext;
|
|
|
|
|
|
return pNode->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
const T* TObjectList<T>::GetNext(POSITION& rPosition) const // return *Position++
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) rPosition;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
rPosition = (POSITION) pNode->pNext;
|
|
|
|
|
|
return pNode->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T*& TObjectList<T>::GetPrev(POSITION& rPosition) // return *Position--
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) rPosition;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
rPosition = (POSITION) pNode->pPrev;
|
|
|
|
|
|
return pNode->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
const T* TObjectList<T>::GetPrev(POSITION& rPosition) const // return *Position--
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) rPosition;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
rPosition = (POSITION) pNode->pPrev;
|
|
|
|
|
|
return pNode->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
T*& TObjectList<T>::GetAt(POSITION position)
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) position;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
return pNode->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
const T* TObjectList<T>::GetAt(POSITION position) const
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) position;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
return pNode->data;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::SetAt(POSITION pos, T* newElement)
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) pos;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
if( pNode == NULL )
|
|
|
|
|
|
AfxThrowInvalidArgException();
|
|
|
|
|
|
pNode->data = newElement;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::MoveToBefore(POSITION pos, POSITION posMove)
|
|
|
|
|
|
{
|
|
|
|
|
|
RemoveAtNoClear(posMove); //<2F><><EFBFBD>Ƴ<EFBFBD>Ԫ<EFBFBD><D4AA>
|
|
|
|
|
|
|
|
|
|
|
|
TNode* pOldNode = (TNode*) pos;
|
|
|
|
|
|
TNode* pMoveNode = (TNode*) posMove;
|
|
|
|
|
|
|
|
|
|
|
|
pMoveNode->pPrev = pOldNode->pPrev;
|
|
|
|
|
|
pMoveNode->pNext = pOldNode;
|
|
|
|
|
|
|
|
|
|
|
|
if (pOldNode->pPrev != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(TNode)));
|
|
|
|
|
|
pOldNode->pPrev->pNext = pMoveNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(pOldNode == m_pNodeHead);
|
|
|
|
|
|
m_pNodeHead = pMoveNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
pOldNode->pPrev = pMoveNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::MoveToAfter(POSITION pos, POSITION posMove)
|
|
|
|
|
|
{
|
|
|
|
|
|
RemoveAtNoClear(posMove); //<2F><><EFBFBD>Ƴ<EFBFBD>Ԫ<EFBFBD><D4AA>
|
|
|
|
|
|
|
|
|
|
|
|
TNode* pOldNode = (TNode*) pos;
|
|
|
|
|
|
TNode* pMoveNode = (TNode*) posMove;
|
|
|
|
|
|
|
|
|
|
|
|
pMoveNode->pPrev = pOldNode;
|
|
|
|
|
|
pMoveNode->pNext = pOldNode->pNext;
|
|
|
|
|
|
|
|
|
|
|
|
if (pOldNode->pNext != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(TNode)));
|
|
|
|
|
|
pOldNode->pNext->pPrev = pMoveNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(pOldNode == m_pNodeTail);
|
|
|
|
|
|
m_pNodeTail = pMoveNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
pOldNode->pNext = pMoveNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::RemoveAtNoClear(POSITION position)
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pOldNode = (TNode*) position;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode, sizeof(TNode)));
|
|
|
|
|
|
|
|
|
|
|
|
// remove pOldNode from list
|
|
|
|
|
|
if (pOldNode == m_pNodeHead)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pNodeHead = pOldNode->pNext;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(TNode)));
|
|
|
|
|
|
pOldNode->pPrev->pNext = pOldNode->pNext;
|
|
|
|
|
|
}
|
|
|
|
|
|
if (pOldNode == m_pNodeTail)
|
|
|
|
|
|
{
|
|
|
|
|
|
m_pNodeTail = pOldNode->pPrev;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(TNode)));
|
|
|
|
|
|
pOldNode->pNext->pPrev = pOldNode->pPrev;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::RemoveAt(POSITION position)
|
|
|
|
|
|
{
|
|
|
|
|
|
RemoveAtNoClear(position);
|
|
|
|
|
|
TNode* pOldNode = (TNode*) position;
|
|
|
|
|
|
FreeNode(pOldNode);
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::InsertBefore(POSITION position, T* newElement)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (position == NULL)
|
|
|
|
|
|
return AddHead(newElement); // insert before nothing -> head of the list
|
|
|
|
|
|
|
|
|
|
|
|
// Insert it before position
|
|
|
|
|
|
TNode* pOldNode = (TNode*) position;
|
|
|
|
|
|
TNode* pNewNode = NewNode(pOldNode->pPrev, pOldNode);
|
|
|
|
|
|
pNewNode->data = newElement;
|
|
|
|
|
|
|
|
|
|
|
|
if (pOldNode->pPrev != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode->pPrev, sizeof(TNode)));
|
|
|
|
|
|
pOldNode->pPrev->pNext = pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(pOldNode == m_pNodeHead);
|
|
|
|
|
|
m_pNodeHead = pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
pOldNode->pPrev = pNewNode;
|
|
|
|
|
|
return (POSITION) pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::InsertAfter(POSITION position, T* newElement)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (position == NULL)
|
|
|
|
|
|
return AddTail(newElement); // insert after nothing -> tail of the list
|
|
|
|
|
|
|
|
|
|
|
|
// Insert it before position
|
|
|
|
|
|
TNode* pOldNode = (TNode*) position;
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode, sizeof(TNode)));
|
|
|
|
|
|
TNode* pNewNode = NewNode(pOldNode, pOldNode->pNext);
|
|
|
|
|
|
pNewNode->data = newElement;
|
|
|
|
|
|
|
|
|
|
|
|
if (pOldNode->pNext != NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pOldNode->pNext, sizeof(TNode)));
|
|
|
|
|
|
pOldNode->pNext->pPrev = pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(pOldNode == m_pNodeTail);
|
|
|
|
|
|
m_pNodeTail = pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
pOldNode->pNext = pNewNode;
|
|
|
|
|
|
return (POSITION) pNewNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::Find(T* searchValue, POSITION startAfter ) const
|
|
|
|
|
|
{
|
|
|
|
|
|
TNode* pNode = (TNode*) startAfter;
|
|
|
|
|
|
if (pNode == NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
pNode = m_pNodeHead; // start at head
|
|
|
|
|
|
}
|
|
|
|
|
|
else
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
pNode = pNode->pNext; // start after the one specified
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
for (; pNode != NULL; pNode = pNode->pNext)
|
|
|
|
|
|
if (pNode->data == searchValue)
|
|
|
|
|
|
return (POSITION)pNode;
|
|
|
|
|
|
return NULL;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
POSITION TObjectList<T>::FindIndex(INT_PTR nIndex) const
|
|
|
|
|
|
{
|
|
|
|
|
|
if (nIndex >= m_nCount || nIndex < 0)
|
|
|
|
|
|
return NULL; // went too far
|
|
|
|
|
|
|
|
|
|
|
|
TNode* pNode = m_pNodeHead;
|
|
|
|
|
|
while (nIndex--)
|
|
|
|
|
|
{
|
|
|
|
|
|
ASSERT(AfxIsValidAddress(pNode, sizeof(TNode)));
|
|
|
|
|
|
pNode = pNode->pNext;
|
|
|
|
|
|
}
|
|
|
|
|
|
return (POSITION) pNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
typename TObjectList<T>::TNode* TObjectList<T>::NewNode(TNode*pPrev , TNode* pNext)
|
|
|
|
|
|
{
|
|
|
|
|
|
if (m_pNodeFree == NULL)
|
|
|
|
|
|
{
|
|
|
|
|
|
if(m_nBlockSize<=0)
|
|
|
|
|
|
m_nBlockSize = 10;
|
|
|
|
|
|
|
|
|
|
|
|
CBlock* pNewBlock = CBlock::Create(m_pBlocks, m_nBlockSize, sizeof(TNode));
|
|
|
|
|
|
|
|
|
|
|
|
// chain them into free list
|
|
|
|
|
|
TNode* pNode = (TNode*) pNewBlock->data();
|
|
|
|
|
|
pNode += m_nBlockSize - 1;
|
|
|
|
|
|
|
|
|
|
|
|
for(DF_LONG i=m_nBlockSize-1; i>=0; i--,pNode--)
|
|
|
|
|
|
{
|
|
|
|
|
|
pNode->pNext = m_pNodeFree;
|
|
|
|
|
|
m_pNodeFree = pNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
TNode *pNode = m_pNodeFree;
|
|
|
|
|
|
m_pNodeFree = m_pNodeFree->pNext;
|
|
|
|
|
|
pNode->pPrev = pPrev;
|
|
|
|
|
|
pNode->pNext = pNext;
|
|
|
|
|
|
pNode->data = NULL;
|
|
|
|
|
|
m_nCount++;
|
|
|
|
|
|
|
|
|
|
|
|
return pNode;
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
template <class T>
|
|
|
|
|
|
void TObjectList<T>::FreeNode(TNode* pNode)
|
|
|
|
|
|
{
|
|
|
|
|
|
pNode->pNext = m_pNodeFree;
|
|
|
|
|
|
m_pNodeFree = pNode;
|
|
|
|
|
|
m_nCount--;
|
|
|
|
|
|
|
|
|
|
|
|
// if no more elements, cleanup completely
|
|
|
|
|
|
if (m_nCount == 0)
|
|
|
|
|
|
RemoveAll();
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#undef DF_LONG //ȡ<><C8A1><EFBFBD><EFBFBD><EFBFBD>Ͷ<EFBFBD><CDB6><EFBFBD>
|
|
|
|
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
using namespace NSet;
|
|
|
|
|
|
|
|
|
|
|
|
#endif
|