Seaside/SpyCustom/sdk/utlintrusivelist.h
2021-06-16 18:49:07 +03:00

797 lines
14 KiB
C++

#ifndef UTILINTRUSIVELIST_H
#define UTILINTRUSIVELIST_H
#ifdef _WIN32
#pragma once
#endif
#include "basetypes.h"
#include "utlmemory.h"
#include "dbg.h"
namespace IntrusiveList
{
#ifdef SUPERSLOW_DEBUG_VERSION
template<class T> inline void ValidateDList(T* head)
{
if (head)
{
Assert(head->m_pPrev == 0);
}
while (head)
{
if (head->m_pNext)
{
Assert(head->m_pNext->m_pPrev == head);
}
if (head->m_pPrev)
{
Assert(head->m_pPrev->m_pNext == head);
}
head = head->m_pNext;
}
}
#else
template<class T> inline void ValidateDList(T* )
{
}
#endif
template <class T> inline void MoveDNodeBackwards(T* which, T*& head)
{
if (which->m_pPrev)
{
T* p = which->m_pPrev;
T* pp = p->m_pPrev;
T* n = which->m_pNext;
Assert(p->m_pNext == which);
if (n)
{
Assert(n->m_pPrev == which);
n->m_pPrev = p;
}
if (pp)
{
Assert(pp->m_pNext == p);
pp->m_pNext = which;
}
else
{
head = which;
}
which->m_pNext = p;
which->m_pPrev = pp;
p->m_pNext = n;
p->m_pPrev = which;
}
ValidateDList(head);
}
template<class T> inline void RemoveFromDList(T*& head, T* which)
{
if (which->m_pPrev)
{
Assert(which->m_pPrev->m_pNext == which);
which->m_pPrev->m_pNext = which->m_pNext;
if (which->m_pNext)
{
Assert(which->m_pNext->m_pPrev == which);
which->m_pNext->m_pPrev = which->m_pPrev;
}
}
else
{
if (head == which)
{
head = which->m_pNext;
if (head)
{
Assert(head->m_pPrev == which);
head->m_pPrev = 0;
}
}
}
which->m_pNext = which->m_pPrev = 0;
ValidateDList(head);
}
template<class T> bool OnDList(T const* head, T const* which)
{
return (head == which) || (which->m_pNext != 0) || (which->m_pPrev != 0);
}
template<class T> void AddToDTail(T*& head, T* node)
{
node->m_pNext = 0;
if (!head)
{
head = node;
}
else
{
T* ptr = head;
while (ptr->m_pNext)
{
ptr = ptr->m_pNext;
}
ptr->m_pNext = node;
node->m_pPrev = ptr;
}
}
template<class T> inline void AddToDHead(T*& head, T* which)
{
which->m_pNext = head;
if (head)
{
head->m_pPrev = which;
}
which->m_pPrev = 0;
head = which;
ValidateDList(head);
}
template<class T> inline void AddToDHeadWithTailPtr(T*& head, T* which, T*& tailptr)
{
which->m_pNext = head;
if (head)
{
head->m_pPrev = which;
}
else
{
tailptr = which;
}
which->m_pPrev = 0;
head = which;
ValidateDList(head);
}
template<class T> inline void AddToDTailWithTailPtr(T*& head, T* which, T*& tailptr)
{
if (!tailptr)
{
Assert(!head);
which->m_pPrev = which->m_pNext = 0;
tailptr = head = which;
}
else
{
which->m_pNext = 0;
which->m_pPrev = tailptr;
tailptr->m_pNext = which;
tailptr = which;
}
ValidateDList(head);
}
template<class T> inline void RemoveFromDListWithTailPtr(T*& head, T* which, T*& tailptr)
{
if (which == tailptr)
{
tailptr = which->m_pPrev;
}
if (which->m_pPrev)
{
Assert(which->m_pPrev->m_pNext == which);
which->m_pPrev->m_pNext = which->m_pNext;
if (which->m_pNext)
{
Assert(which->m_pNext->m_pPrev == which);
which->m_pNext->m_pPrev = which->m_pPrev;
}
}
else
{
if (head == which)
{
head = which->m_pNext;
if (head)
{
Assert(head->m_pPrev == which);
head->m_pPrev = 0;
}
}
}
which->m_pNext = which->m_pPrev = 0;
ValidateDList(head);
}
template<class T> inline void DeleteFromDListWithTailPtr(T*& head, T* which, T*& tailptr)
{
T* tmp = which;
if (which == tailptr)
{
tailptr = which->m_pPrev;
}
if (which->m_pPrev)
{
Assert(which->m_pPrev->m_pNext == which);
which->m_pPrev->m_pNext = which->m_pNext;
if (which->m_pNext)
{
Assert(which->m_pNext->m_pPrev == which);
which->m_pNext->m_pPrev = which->m_pPrev;
}
}
else
{
if (head == which)
{
head = which->m_pNext;
if (head)
{
Assert(head->m_pPrev == which);
head->m_pPrev = 0;
}
}
}
which->m_pNext = which->m_pPrev = 0;
delete tmp;
ValidateDList(head);
}
template<class T> inline void AddToDPriority(T*& head, T* which)
{
T* prevnode = 0;
for (T* curnode = head; curnode; curnode = curnode->m_pNext)
{
if (which->m_Priority >= curnode->m_Priority)
break;
prevnode = curnode;
}
if (!prevnode)
{
AddToDHead(head, which);
}
else
{
which->m_pNext = prevnode->m_pNext;
prevnode->m_pNext = which;
which->m_pPrev = prevnode;
if (which->m_pNext)
which->m_pNext->m_pPrev = which;
}
}
template<class T> inline void AddToDPriorityLowestFirst(T*& head, T* which)
{
T* prevnode = 0;
for (T* curnode = head; curnode; curnode = curnode->m_pNext)
{
if (which->m_Priority <= curnode->m_Priority)
break;
prevnode = curnode;
}
if (!prevnode)
{
AddToDHead(head, which);
}
else
{
which->m_pNext = prevnode->m_pNext;
prevnode->m_pNext = which;
which->m_pPrev = prevnode;
if (which->m_pNext)
which->m_pNext->m_pPrev = which;
}
}
template<class T> T* LastNode(T* head)
{
if (head)
{
while (head->m_pNext)
{
head = head->m_pNext;
}
}
return head;
}
template<class T, class V> void RemoveFromList(T*& head, V* which)
{
if (head == which)
{
head = which->m_pNext;
}
else
{
for (T* i = head; i; i = i->m_pNext)
{
if (i->m_pNext == which)
{
i->m_pNext = which->m_pNext;
return;
}
}
}
}
template<class T, class V> void DeleteFromList(T*& head, V* which)
{
T* tmp;
if (head == which)
{
tmp = which->m_pNext;
delete(head);
head = tmp;
}
else
{
for (T* i = head; i; i = i->m_pNext)
{
if (i->m_pNext == which)
{
tmp = which->m_pNext;
delete(which);
i->m_pNext = tmp;
return;
}
}
}
}
template<class T, class V> int PositionInList(T* head, V* node)
{
int pos = 0;
while (head)
{
if (head == node) return pos;
head = head->m_pNext;
pos++;
}
return -1;
}
template<class T> T* NthNode(T* head, int idx)
{
while (idx && head)
{
idx--;
head = head->m_pNext;
}
return head;
}
template<class T, class V> static inline void AddToHead(T*& head, V* node)
{
node->m_pNext = head;
head = node;
}
template<class T, class V> static inline void AddToTail(T*& head, V* node)
{
node->m_pNext = NULL;
if (!head)
head = node;
else
{
T* pLastNode = head;
while (pLastNode->m_pNext)
pLastNode = pLastNode->m_pNext;
pLastNode->m_pNext = node;
}
}
template<class T, class V> static inline void AddToHead(T*& head, T*& tail, V* node)
{
if (!head)
{
tail = node;
}
node->m_pNext = head;
head = node;
}
template<class T> static inline T* PrevNode(T* head, T* node)
{
T* i;
for (i = head; i; i = i->m_pNext)
{
if (i->m_pNext == node)
break;
}
return i;
}
template<class T, class V> void AddToEnd(T*& head, V* node)
{
node->m_pNext = 0;
if (!head)
{
head = node;
}
else
{
T* ptr = head;
while (ptr->m_pNext)
{
ptr = ptr->m_pNext;
}
ptr->m_pNext = node;
}
}
template<class T, class V> void AddToEndWithTail(T*& head, T*& tail, V* node)
{
Assert((head && tail) || ((!head) && (!tail)));
node->m_pNext = 0;
if (!head)
{
head = tail = node;
}
else
{
tail->m_pNext = node;
tail = node;
}
}
template<class T> void AddSortedByName(T*& head, T* node)
{
if ((!head) ||
(stricmp(node->m_Name, head->m_Name) == -1))
{
node->m_pNext = head;
head = node;
}
else
{
T* t;
for (t = head; t->m_pNext; t = t->m_pNext)
if (stricmp(t->m_pNext->m_Name, node->m_Name) >= 0)
break;
node->m_pNext = t->m_pNext;
t->m_pNext = node;
}
}
template<class T> int ListLength(T* head)
{
int len = 0;
while (head)
{
len++;
head = head->m_pNext;
}
return len;
}
template<class T> void KillList(T*& head)
{
while (head)
{
delete head;
}
}
template<class T> void DeleteList(T*& head)
{
while (head)
{
T* tmp = head->m_pNext;
delete head;
head = tmp;
}
}
template <class T> static inline T* FindNamedNode(T* head, char const* name)
{
for (; head && stricmp(head->m_Name, name); head = head->m_pNext)
{
}
return head;
}
template <class T> static inline T* FindNamedNodeCaseSensitive(T* head, char const* name)
{
for (; head && strcmp(head->m_Name, name); head = head->m_pNext)
{
}
return head;
}
template <class T, class U, class V> static inline T* FindNodeByField(T* head, U data, U V::* field)
{
while (head)
{
if (data == (*head).*field)
return head;
head = head->m_pNext;
}
return 0;
}
template <class T, class U, class V> static inline T* FindNodeByFieldWithPrev(T* head, U data, U V::* field, T*& prev)
{
prev = 0;
for (T* i = head; i; i = i->m_pNext)
{
if (data == (*i).*field)
return i;
prev = i;
}
prev = 0;
return 0;
}
template<class T> void SortList(T*& head, int (*comparefn)(T* a, T* b))
{
int didswap = 1;
while (didswap)
{
didswap = 0;
T* prev = 0;
for (T* i = head; i && i->m_pNext; i = i->m_pNext)
{
int rslt = (*comparefn)(i, i->m_pNext);
if (rslt == -1)
{
didswap = 1;
T* newfirst = i->m_pNext;
if (prev)
{
prev->m_pNext = newfirst;
i->m_pNext = newfirst->m_pNext;
newfirst->m_pNext = i;
}
else
{
head = i->m_pNext;
i->m_pNext = newfirst->m_pNext;
newfirst->m_pNext = i;
}
i = newfirst;
}
prev = i;
}
}
}
template <class T> void SortDList(T*& head, int (*comparefn)(T* a, T* b))
{
SortList(head, comparefn);
T* prev = 0;
for (T* i = head; i; i = i->m_pNext)
{
i->m_pPrev = prev;
prev = i;
}
}
template <class T> T* ReversedList(T* head)
{
T* pNewHead = NULL;
while (head)
{
T* pNext = head->m_pNext;
#ifdef INTERVIEW_QUESTION
head->m_pNext = pNewHead;
pNewHead = head;
#else
AddToHead(pNewHead, head);
#endif
head = pNext;
}
return pNewHead;
}
};
template<class T> class CUtlIntrusiveList
{
public:
T* m_pHead;
FORCEINLINE T* Head(void) const
{
return m_pHead;
}
FORCEINLINE CUtlIntrusiveList(void)
{
m_pHead = NULL;
}
FORCEINLINE void RemoveAll(void)
{
m_pHead = NULL;
}
FORCEINLINE void AddToHead(T* node)
{
IntrusiveList::AddToHead(m_pHead, node);
}
FORCEINLINE void AddToTail(T* node)
{
IntrusiveList::AddToTail(m_pHead, node);
}
void RemoveNode(T* which)
{
IntrusiveList::RemoveFromList(m_pHead, which);
}
void KillList(void)
{
while (m_pHead)
{
delete m_pHead;
}
}
T* PrevNode(T* node)
{
return IntrusiveList::PrevNode(m_pHead, node);
}
int NthNode(int n)
{
return NthNode(m_pHead, n);
}
void Purge(void)
{
while (m_pHead)
{
T* tmp = m_pHead->m_pNext;
delete m_pHead;
m_pHead = tmp;
}
}
int Count(void) const
{
return IntrusiveList::ListLength(m_pHead);
}
FORCEINLINE T* FindNamedNodeCaseSensitive(char const* pName) const
{
return IntrusiveList::FindNamedNodeCaseSensitive(m_pHead, pName);
}
T* RemoveHead(void)
{
if (m_pHead)
{
T* pRet = m_pHead;
m_pHead = pRet->m_pNext;
return pRet;
}
else
return NULL;
}
};
template<class T> class CUtlIntrusiveDList : public CUtlIntrusiveList<T>
{
public:
FORCEINLINE void AddToHead(T* node)
{
IntrusiveList::AddToDHead(CUtlIntrusiveList<T>::m_pHead, node);
}
FORCEINLINE void AddToTail(T* node)
{
IntrusiveList::AddToDTail(CUtlIntrusiveList<T>::m_pHead, node);
}
void RemoveNode(T* which)
{
IntrusiveList::RemoveFromDList(CUtlIntrusiveList<T>::m_pHead, which);
}
T* RemoveHead(void)
{
if (CUtlIntrusiveList<T>::m_pHead)
{
T* pRet = CUtlIntrusiveList<T>::m_pHead;
CUtlIntrusiveList<T>::m_pHead = CUtlIntrusiveList<T>::m_pHead->m_pNext;
if (CUtlIntrusiveList<T>::m_pHead)
CUtlIntrusiveList<T>::m_pHead->m_pPrev = NULL;
return pRet;
}
else
return NULL;
}
T* PrevNode(T* node)
{
return (node) ? node->m_Prev : NULL;
}
};
template<class T> class CUtlIntrusiveDListWithTailPtr : public CUtlIntrusiveDList<T>
{
public:
T* m_pTailPtr;
FORCEINLINE CUtlIntrusiveDListWithTailPtr(void) : CUtlIntrusiveDList<T>()
{
m_pTailPtr = NULL;
}
FORCEINLINE void AddToHead(T* node)
{
IntrusiveList::AddToDHeadWithTailPtr(CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr);
}
FORCEINLINE void AddToTail(T* node)
{
IntrusiveList::AddToDTailWithTailPtr(CUtlIntrusiveList<T>::m_pHead, node, m_pTailPtr);
}
void RemoveNode(T* pWhich)
{
IntrusiveList::RemoveFromDListWithTailPtr(CUtlIntrusiveList<T>::m_pHead, pWhich, m_pTailPtr);
}
void Purge(void)
{
CUtlIntrusiveList<T>::Purge();
m_pTailPtr = NULL;
}
void Kill(void)
{
CUtlIntrusiveList<T>::Purge();
m_pTailPtr = NULL;
}
T* RemoveHead(void)
{
if (CUtlIntrusiveDList<T>::m_pHead)
{
T* pRet = CUtlIntrusiveDList<T>::m_pHead;
CUtlIntrusiveDList<T>::m_pHead = CUtlIntrusiveDList<T>::m_pHead->m_pNext;
if (CUtlIntrusiveDList<T>::m_pHead)
CUtlIntrusiveDList<T>::m_pHead->m_pPrev = NULL;
if (!CUtlIntrusiveDList<T>::m_pHead)
m_pTailPtr = NULL;
ValidateDList(CUtlIntrusiveDList<T>::m_pHead);
return pRet;
}
else
return NULL;
}
T* PrevNode(T* node)
{
return (node) ? node->m_Prev : NULL;
}
};
template<class T> void PrependDListWithTailToDList(CUtlIntrusiveDListWithTailPtr<T>& src,
CUtlIntrusiveDList<T>& dest)
{
if (src.m_pHead)
{
src.m_pTailPtr->m_pNext = dest.m_pHead;
if (dest.m_pHead)
dest.m_pHead->m_pPrev = src.m_pTailPtr;
dest.m_pHead = src.m_pHead;
IntrusiveList::ValidateDList(dest.m_pHead);
}
}
#endif