314 lines
6.1 KiB
C++
Executable File
314 lines
6.1 KiB
C++
Executable File
/* AMX Mod X
|
|
*
|
|
* by the AMX Mod X Development Team
|
|
* originally developed by OLO
|
|
*
|
|
*
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
* under the terms of the GNU General Public License as published by the
|
|
* Free Software Foundation; either version 2 of the License, or (at
|
|
* your option) any later version.
|
|
*
|
|
* This program is distributed in the hope that it will be useful, but
|
|
* WITHOUT ANY WARRANTY; without even the implied warranty of
|
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
|
|
* General Public License for more details.
|
|
*
|
|
* You should have received a copy of the GNU General Public License
|
|
* along with this program; if not, write to the Free Software Foundation,
|
|
* Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
|
*
|
|
* In addition, as a special exception, the author gives permission to
|
|
* link the code of this program with the Half-Life Game Engine ("HL
|
|
* Engine") and Modified Game Libraries ("MODs") developed by Valve,
|
|
* L.L.C ("Valve"). You must obey the GNU General Public License in all
|
|
* respects for all of the code used other than the HL Engine and MODs
|
|
* from Valve. If you modify this file, you may extend this exception
|
|
* to your version of the file, but you are not obligated to do so. If
|
|
* you do not wish to do so, delete this exception statement from your
|
|
* version.
|
|
*/
|
|
|
|
#ifndef CLIST_H
|
|
#define CLIST_H
|
|
|
|
// *****************************************************
|
|
// class CList
|
|
// *****************************************************
|
|
// Linked list
|
|
template <typename T, typename F = char* >
|
|
class CList
|
|
{
|
|
private:
|
|
// One list element
|
|
class CElement
|
|
{
|
|
T *m_pObject; // pointer to the object
|
|
CElement *m_pNext; // pointer to the next element
|
|
CElement *m_pPrev; // pointer to the previous element
|
|
public:
|
|
// dereference operator
|
|
T& operator* ()
|
|
{
|
|
return *m_pObject;
|
|
}
|
|
|
|
// constructor
|
|
CElement(T *pObj)
|
|
{
|
|
m_pObject = pObj;
|
|
m_pNext = NULL;
|
|
m_pPrev = NULL;
|
|
}
|
|
|
|
// destructor
|
|
~CElement()
|
|
{
|
|
delete m_pObject;
|
|
if (m_pNext)
|
|
m_pNext->m_pPrev = m_pPrev;
|
|
if (m_pPrev)
|
|
m_pPrev->m_pNext = m_pNext;
|
|
}
|
|
|
|
// returns object pointer
|
|
T *GetObj()
|
|
{
|
|
return m_pObject;
|
|
}
|
|
|
|
// returns next element pointer
|
|
CElement *GetNext()
|
|
{
|
|
return m_pNext;
|
|
}
|
|
|
|
// sets next element
|
|
void SetNext(CElement *newNext)
|
|
{
|
|
m_pNext = newNext;
|
|
}
|
|
|
|
// returns previous element pointer
|
|
CElement *GetPrev()
|
|
{
|
|
return m_pPrev;
|
|
}
|
|
|
|
// sets previous element
|
|
void SetPrev(CElement *newPrev)
|
|
{
|
|
m_pPrev = newPrev;
|
|
}
|
|
};
|
|
|
|
// CList<T,F> class
|
|
CElement *m_pHead; // head of the linked list
|
|
CElement *m_pTail; // tail of the linked list
|
|
public:
|
|
// iterator class
|
|
class iterator
|
|
{
|
|
friend class CList<T,F>;
|
|
CList<T,F> *m_pList; // The list that created this iterator
|
|
CElement *m_CurPos; // Current position in the list
|
|
public:
|
|
iterator()
|
|
{
|
|
m_pList = NULL;
|
|
m_CurPos = NULL;
|
|
}
|
|
|
|
// constructor based on list, element
|
|
iterator(CList<T,F> *pList, CElement *startPos)
|
|
{
|
|
m_pList = pList;
|
|
m_CurPos = startPos;
|
|
}
|
|
|
|
// constructor based on other iterator
|
|
iterator(const iterator &other)
|
|
{
|
|
m_pList = other.m_pList;
|
|
m_CurPos = other.m_CurPos;
|
|
}
|
|
|
|
// dereference operator
|
|
T & operator* () const
|
|
{
|
|
return *m_CurPos->GetObj();
|
|
}
|
|
|
|
T * operator-> () const
|
|
{
|
|
return m_CurPos->GetObj();
|
|
}
|
|
|
|
// validity check operator
|
|
inline operator bool () const
|
|
{
|
|
return m_pList!=NULL && m_CurPos!=NULL && m_CurPos->GetObj()!=NULL;
|
|
}
|
|
|
|
// pre increment operator
|
|
inline iterator& operator ++ ()
|
|
{
|
|
m_CurPos = m_CurPos->GetNext();
|
|
return *this;
|
|
}
|
|
|
|
// post increment operator
|
|
inline iterator operator++(int)
|
|
{
|
|
iterator tmp(*this);
|
|
m_CurPos = m_CurPos->next;
|
|
return tmp;
|
|
}
|
|
|
|
// returns iterator that points to next element
|
|
iterator GetNext()
|
|
{
|
|
iterator tmp(*this);
|
|
return ++tmp;
|
|
}
|
|
|
|
iterator remove()
|
|
{
|
|
return m_pList->remove(*this);
|
|
}
|
|
iterator put(T *obj)
|
|
{
|
|
return m_pList->put(obj, *this);
|
|
}
|
|
};
|
|
|
|
CList<T,F>()
|
|
{
|
|
m_pHead = NULL;
|
|
m_pTail = NULL;
|
|
}
|
|
~CList<T,F>()
|
|
{
|
|
clear();
|
|
}
|
|
|
|
// removes the object referenced by where
|
|
// sets where to the next object
|
|
// returns an iterator pointing to the next object
|
|
iterator remove(iterator &where)
|
|
{
|
|
iterator tmp(where.GetNext());
|
|
if (where.m_CurPos == m_pHead)
|
|
m_pHead = where.m_CurPos->GetNext();
|
|
if (where.m_CurPos == m_pTail)
|
|
m_pTail = where.m_CurPos->GetPrev();
|
|
delete where.m_CurPos;
|
|
where = tmp;
|
|
return tmp;
|
|
}
|
|
|
|
// puts an element to the end of the list
|
|
// returns an iterator pointing to it
|
|
iterator put_back(T *pObj)
|
|
{
|
|
CElement *pTmp = new CElement(pObj);
|
|
if (!m_pHead)
|
|
{
|
|
m_pHead = pTmp;
|
|
m_pTail = pTmp;
|
|
}
|
|
else
|
|
{
|
|
pTmp->SetNext(NULL);
|
|
pTmp->SetPrev(m_pTail);
|
|
m_pTail->SetNext(pTmp);
|
|
m_pTail = pTmp;
|
|
}
|
|
return iterator(this, pTmp);
|
|
}
|
|
|
|
iterator put_front(T *pObj)
|
|
{
|
|
CElement *pTmp = new CElement(pObj);
|
|
if (!m_pHead)
|
|
{
|
|
m_pHead = pTmp;
|
|
m_pTail = pTmp;
|
|
}
|
|
else
|
|
{
|
|
pTmp->SetNext(m_pHead);
|
|
pTmp->SetPrev(NULL);
|
|
m_pHead->SetPrev(pTmp);
|
|
m_pHead = pTmp;
|
|
}
|
|
return iterator(this, pTmp);
|
|
}
|
|
|
|
// alias for put_back
|
|
iterator put(T *pObj)
|
|
{
|
|
return put_back(pObj);
|
|
}
|
|
|
|
// puts an element after where
|
|
// alters where to point to the new element
|
|
// returns an iterator pointing to the new element
|
|
iterator put(T *pObj, iterator &where)
|
|
{
|
|
CElement *pTmp = new CElement(pObj);
|
|
if (where.m_CurPos->GetNext())
|
|
where.m_CurPos->GetNext()->SetPrev(pTmp);
|
|
else // where = tail
|
|
m_pTail = pTmp;
|
|
|
|
pTmp->SetPrev(where.m_CurPos);
|
|
pTmp->SetNext(where.m_CurPos->GetNext());
|
|
|
|
where.m_CurPos->SetNext(pTmp);
|
|
return ++where;
|
|
}
|
|
|
|
iterator begin()
|
|
{
|
|
return iterator(this, m_pHead);
|
|
}
|
|
|
|
void clear()
|
|
{
|
|
iterator iter = begin();
|
|
while (iter) iter.remove();
|
|
}
|
|
|
|
iterator find(iterator startOn, const F &desc)
|
|
{
|
|
iterator iter = startOn;
|
|
while(iter)
|
|
{
|
|
if (*iter == desc)
|
|
break;
|
|
++iter;
|
|
}
|
|
return iter;
|
|
}
|
|
|
|
iterator find(const F &desc)
|
|
{
|
|
return find(begin(), desc);
|
|
}
|
|
|
|
int size()
|
|
{
|
|
iterator iter = begin();
|
|
int i=0;
|
|
while (iter)
|
|
{
|
|
++i;
|
|
++iter;
|
|
}
|
|
return i;
|
|
}
|
|
};
|
|
#endif
|
|
|