2014-05-31 00:14:47 +06:00
|
|
|
#ifndef __LINKLIST__
|
|
|
|
#define __LINKLIST__
|
|
|
|
|
|
|
|
template <class T>
|
2014-08-03 19:38:53 +06:00
|
|
|
class CLinkSA
|
2014-05-31 00:14:47 +06:00
|
|
|
{
|
2017-03-03 01:47:09 +05:00
|
|
|
template <class T>
|
|
|
|
friend class CLinkListSA;
|
|
|
|
|
2014-05-31 00:14:47 +06:00
|
|
|
public:
|
2014-08-03 19:38:53 +06:00
|
|
|
inline void Insert(CLinkSA<T>* pAttach) {
|
2014-05-31 00:14:47 +06:00
|
|
|
pAttach->m_pNext = m_pNext;
|
|
|
|
m_pNext->m_pPrev = pAttach;
|
2014-08-03 19:38:53 +06:00
|
|
|
|
2014-05-31 00:14:47 +06:00
|
|
|
pAttach->m_pPrev = this;
|
|
|
|
m_pNext = pAttach;
|
|
|
|
}
|
|
|
|
|
2016-11-20 19:58:39 +05:00
|
|
|
inline void InsertBefore(CLinkSA<T>* pAttach) {
|
|
|
|
pAttach->m_pPrev = m_pPrev;
|
|
|
|
m_pPrev->m_pNext = pAttach;
|
|
|
|
|
|
|
|
pAttach->m_pNext = this;
|
|
|
|
m_pPrev = pAttach;
|
|
|
|
}
|
|
|
|
|
2014-05-31 00:14:47 +06:00
|
|
|
inline void Remove(void) {
|
|
|
|
m_pNext->m_pPrev = m_pPrev;
|
|
|
|
m_pPrev->m_pNext = m_pNext;
|
|
|
|
}
|
|
|
|
|
2017-03-03 01:47:09 +05:00
|
|
|
inline T& operator*(void) {
|
|
|
|
return m_pItem;
|
|
|
|
}
|
|
|
|
|
|
|
|
inline const T& operator*(void) const {
|
2014-05-31 00:14:47 +06:00
|
|
|
return m_pItem;
|
|
|
|
}
|
|
|
|
|
2017-03-03 01:47:09 +05:00
|
|
|
private:
|
2014-05-31 00:14:47 +06:00
|
|
|
T m_pItem; // 0-4
|
|
|
|
// an item
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* m_pPrev; // 4-8
|
2014-05-31 00:14:47 +06:00
|
|
|
//next link in the list
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* m_pNext; // 8-12
|
2014-05-31 00:14:47 +06:00
|
|
|
//prev link in the list
|
|
|
|
};
|
|
|
|
|
|
|
|
template <class T>
|
2014-08-03 19:38:53 +06:00
|
|
|
class CLinkListSA {
|
2014-05-31 00:14:47 +06:00
|
|
|
public:
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkListSA(void)
|
2014-05-31 00:14:47 +06:00
|
|
|
: m_plnLinks(nullptr)
|
|
|
|
{
|
|
|
|
}
|
|
|
|
|
2016-11-20 19:58:39 +05:00
|
|
|
void Init(size_t nNumLinks) {
|
2014-08-03 19:38:53 +06:00
|
|
|
m_plnLinks = new CLinkSA<T>[nNumLinks];
|
2014-05-31 00:14:47 +06:00
|
|
|
|
|
|
|
m_lnListHead.m_pNext = &m_lnListTail;
|
|
|
|
m_lnListTail.m_pPrev = &m_lnListHead;
|
|
|
|
|
|
|
|
m_lnFreeListHead.m_pNext = &m_lnFreeListTail;
|
|
|
|
m_lnFreeListTail.m_pPrev = &m_lnFreeListHead;
|
|
|
|
|
2016-11-20 19:58:39 +05:00
|
|
|
for(size_t i = nNumLinks; i > 0; --i) {
|
|
|
|
m_lnFreeListHead.Insert(&m_plnLinks[i - 1]);
|
2014-05-31 00:14:47 +06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void Shutdown(void) {
|
|
|
|
delete[] m_plnLinks;
|
|
|
|
|
|
|
|
m_plnLinks = nullptr;
|
|
|
|
}
|
|
|
|
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* InsertSorted(const T& pItem) {
|
|
|
|
CLinkSA<T>* pLink = m_lnFreeListHead.m_pNext;
|
2014-05-31 00:14:47 +06:00
|
|
|
|
|
|
|
if(pLink == &m_lnFreeListTail) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
pLink->m_pItem = pItem;
|
|
|
|
|
|
|
|
pLink->Remove();
|
|
|
|
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* pInsertAfter = &m_lnListHead;
|
2014-05-31 00:14:47 +06:00
|
|
|
|
|
|
|
while(pInsertAfter->m_pNext != &m_lnListTail && pInsertAfter->m_pNext->m_pItem < pItem) {
|
|
|
|
pInsertAfter = pInsertAfter->m_pNext;
|
|
|
|
}
|
|
|
|
|
|
|
|
pInsertAfter->Insert(pLink);
|
|
|
|
|
|
|
|
return pLink;
|
|
|
|
}
|
|
|
|
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* Insert(const T& pItem) {
|
|
|
|
CLinkSA<T>* pLink = m_lnFreeListHead.m_pNext;
|
2014-05-31 00:14:47 +06:00
|
|
|
|
|
|
|
if(pLink == &m_lnFreeListTail) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
pLink->m_pItem = pItem;
|
|
|
|
|
|
|
|
pLink->Remove();
|
|
|
|
m_lnListHead.Insert(pLink);
|
|
|
|
|
|
|
|
return pLink;
|
|
|
|
}
|
|
|
|
|
2016-11-20 19:58:39 +05:00
|
|
|
CLinkSA<T>* InsertFront(const T& pItem) {
|
|
|
|
return Insert(pItem);
|
|
|
|
}
|
|
|
|
|
|
|
|
CLinkSA<T>* InsertBack(const T& pItem) {
|
|
|
|
CLinkSA<T>* pLink = m_lnFreeListHead.m_pNext;
|
|
|
|
|
|
|
|
if(pLink == &m_lnFreeListTail) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
|
|
|
|
|
|
|
pLink->m_pItem = pItem;
|
|
|
|
|
|
|
|
pLink->Remove();
|
|
|
|
m_lnListTail.InsertBefore(pLink);
|
|
|
|
|
|
|
|
return pLink;
|
|
|
|
}
|
|
|
|
|
2014-05-31 00:14:47 +06:00
|
|
|
void Clear(void) {
|
|
|
|
while(m_lnListHead.m_pNext != &m_lnListTail) {
|
2016-11-20 19:58:39 +05:00
|
|
|
Remove( m_lnListHead.m_pNext );
|
2014-05-31 00:14:47 +06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-03 19:38:53 +06:00
|
|
|
void Remove(CLinkSA<T>* pLink) {
|
2014-05-31 00:14:47 +06:00
|
|
|
pLink->Remove();
|
|
|
|
m_lnFreeListHead.Insert(pLink);
|
|
|
|
}
|
|
|
|
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* Next(CLinkSA<T>* pCurrent) {
|
2016-11-20 19:58:39 +05:00
|
|
|
if(pCurrent == nullptr) {
|
2014-05-31 00:14:47 +06:00
|
|
|
pCurrent = &m_lnListHead;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pCurrent->m_pNext == &m_lnListTail) {
|
2016-11-20 19:58:39 +05:00
|
|
|
return nullptr;
|
2014-05-31 00:14:47 +06:00
|
|
|
}
|
2017-03-03 01:47:09 +05:00
|
|
|
return pCurrent->m_pNext;
|
2014-05-31 00:14:47 +06:00
|
|
|
}
|
|
|
|
|
2016-11-20 19:58:39 +05:00
|
|
|
CLinkSA<T>* Prev(CLinkSA<T>* pCurrent) {
|
|
|
|
if(pCurrent == nullptr) {
|
|
|
|
pCurrent = &m_lnListTail;
|
|
|
|
}
|
|
|
|
|
|
|
|
if(pCurrent->m_pPrev == &m_lnListHead) {
|
|
|
|
return nullptr;
|
|
|
|
}
|
2017-03-03 01:47:09 +05:00
|
|
|
return pCurrent->m_pPrev;
|
2016-11-20 19:58:39 +05:00
|
|
|
}
|
|
|
|
|
2017-03-03 01:47:09 +05:00
|
|
|
private:
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T> m_lnListHead; // 0-12
|
2014-05-31 00:14:47 +06:00
|
|
|
//head of the list of active links
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T> m_lnListTail; // 12-24
|
2014-05-31 00:14:47 +06:00
|
|
|
//tail of the list of active links
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T> m_lnFreeListHead; // 24-36
|
2014-05-31 00:14:47 +06:00
|
|
|
//head of the list of free links
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T> m_lnFreeListTail; // 36-48
|
2014-05-31 00:14:47 +06:00
|
|
|
//tail of the list of free links
|
2014-08-03 19:38:53 +06:00
|
|
|
CLinkSA<T>* m_plnLinks; // 48-52
|
2014-05-31 00:14:47 +06:00
|
|
|
//pointer to actual array of links
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif
|