amxmodx/dlls/nvault/sdk/sh_list.h

298 lines
4.8 KiB
C
Raw Normal View History

2005-09-18 06:59:36 +04:00
/* ======== SourceMM ========
* Copyright (C) 2004-2005 Metamod:Source Development Team
* No warranties of any kind
*
* License: zlib/libpng
*
* Author(s): David "BAILOPAN" Anderson
* ============================
*/
#ifndef _INCLUDE_SMM_LIST_H
#define _INCLUDE_SMM_LIST_H
2006-04-07 14:25:45 +04:00
// MSVC8 fix for offsetof macro redefition warnings
#ifdef _MSC_VER
#if _MSC_VER >= 1400
#undef offsetof
#endif
#endif
#include <new>
#include <stdlib.h>
2005-09-18 06:59:36 +04:00
//namespace SourceHook
//{
//This class is from CSDM for AMX Mod X
2006-01-25 01:51:29 +03:00
/*
A circular, doubly-linked list with one sentinel node
Empty:
m_Head = sentinel
m_Head->next = m_Head;
m_Head->prev = m_Head;
One element:
m_Head = sentinel
m_Head->next = node1
m_Head->prev = node1
node1->next = m_Head
node1->prev = m_Head
Two elements:
m_Head = sentinel
m_Head->next = node1
m_Head->prev = node2
node1->next = node2
node1->prev = m_Head
node2->next = m_Head
node2->prev = node1
*/
2005-09-18 06:59:36 +04:00
template <class T>
class List
{
public:
class iterator;
friend class iterator;
class ListNode
{
public:
ListNode(const T & o) : obj(o) { };
ListNode() { };
T obj;
ListNode *next;
ListNode *prev;
};
private:
2006-01-25 01:51:29 +03:00
// Initializes the sentinel node.
// BAIL used malloc instead of new in order to bypass the need for a constructor.
2005-09-18 06:59:36 +04:00
ListNode *_Initialize()
{
ListNode *n = (ListNode *)malloc(sizeof(ListNode));
2006-01-25 01:51:29 +03:00
n->next = n;
n->prev = n;
2005-09-18 06:59:36 +04:00
return n;
}
public:
List() : m_Head(_Initialize()), m_Size(0)
{
}
List(const List &src) : m_Head(_Initialize()), m_Size(0)
{
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
push_back( (*iter) );
}
~List()
{
clear();
2006-01-25 01:51:29 +03:00
// Don't forget to free the sentinel
2005-09-18 06:59:36 +04:00
if (m_Head)
{
free(m_Head);
m_Head = NULL;
}
}
void push_back(const T &obj)
{
ListNode *node = new ListNode(obj);
2006-01-25 01:51:29 +03:00
node->prev = m_Head->prev;
node->next = m_Head;
m_Head->prev->next = node;
m_Head->prev = node;
2005-09-18 06:59:36 +04:00
m_Size++;
}
size_t size()
{
return m_Size;
}
2006-01-25 01:51:29 +03:00
2005-09-18 06:59:36 +04:00
void clear()
{
ListNode *node = m_Head->next;
ListNode *temp;
2006-01-25 01:51:29 +03:00
m_Head->next = m_Head;
m_Head->prev = m_Head;
// Iterate through the nodes until we find g_Head (the sentinel) again
while (node != m_Head)
2005-09-18 06:59:36 +04:00
{
temp = node->next;
delete node;
node = temp;
}
m_Size = 0;
}
bool empty()
{
2006-01-25 01:51:29 +03:00
return (m_Size == 0);
2005-09-18 06:59:36 +04:00
}
T & back()
{
return m_Head->prev->obj;
}
private:
ListNode *m_Head;
size_t m_Size;
public:
class iterator
{
2006-01-25 01:51:29 +03:00
friend class List;
2005-09-18 06:59:36 +04:00
public:
iterator()
{
m_This = NULL;
}
iterator(const List &src)
{
m_This = src.m_Head;
}
iterator(ListNode *n) : m_This(n)
{
}
iterator(const iterator &where)
{
m_This = where.m_This;
}
//pre decrement
2005-09-18 06:59:36 +04:00
iterator & operator--()
{
if (m_This)
m_This = m_This->prev;
return *this;
}
//post decrement
iterator operator--(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->prev;
return old;
}
2006-01-25 01:51:29 +03:00
2005-09-18 06:59:36 +04:00
//pre increment
iterator & operator++()
{
if (m_This)
m_This = m_This->next;
return *this;
}
//post increment
iterator operator++(int)
{
iterator old(*this);
if (m_This)
m_This = m_This->next;
return old;
}
2006-01-25 01:51:29 +03:00
const T & operator * () const
2005-09-18 06:59:36 +04:00
{
return m_This->obj;
}
T & operator * ()
{
return m_This->obj;
}
2006-01-25 01:51:29 +03:00
T * operator -> ()
2005-09-18 06:59:36 +04:00
{
return &(m_This->obj);
}
const T * operator -> () const
{
return &(m_This->obj);
}
2006-01-25 01:51:29 +03:00
2005-09-18 06:59:36 +04:00
bool operator != (const iterator &where) const
{
return (m_This != where.m_This);
}
bool operator ==(const iterator &where) const
{
return (m_This == where.m_This);
}
private:
ListNode *m_This;
};
public:
iterator begin() const
{
2006-01-25 01:51:29 +03:00
return iterator(m_Head->next);
2005-09-18 06:59:36 +04:00
}
iterator end() const
{
return iterator(m_Head);
}
iterator erase(iterator &where)
{
ListNode *pNode = where.m_This;
iterator iter(where);
iter++;
2006-01-25 01:51:29 +03:00
// Works for all cases: empty list, erasing first element, erasing tail, erasing in the middle...
pNode->prev->next = pNode->next;
pNode->next->prev = pNode->prev;
2005-09-18 06:59:36 +04:00
delete pNode;
m_Size--;
return iter;
}
2006-01-25 01:51:29 +03:00
iterator insert(iterator where, const T &obj)
{
// Insert obj right before where
ListNode *node = new ListNode(obj);
ListNode *pWhereNode = where.m_This;
pWhereNode->prev->next = node;
node->prev = pWhereNode->prev;
pWhereNode->prev = node;
node->next = pWhereNode;
m_Size++;
return iterator(node);
}
2005-09-18 06:59:36 +04:00
public:
void remove(const T & obj)
{
iterator b;
for (b=begin(); b!=end(); b++)
{
if ( (*b) == obj )
{
erase( b );
break;
}
}
}
template <typename U>
iterator find(const U & equ)
{
iterator iter;
for (iter=begin(); iter!=end(); iter++)
{
if ( (*iter) == equ )
return iter;
}
return end();
}
2006-01-25 01:51:29 +03:00
List & operator =(const List &src)
2005-09-18 06:59:36 +04:00
{
clear();
2005-09-18 06:59:36 +04:00
iterator iter;
for (iter=src.begin(); iter!=src.end(); iter++)
push_back( (*iter) );
return *this;
}
};
//}; //NAMESPACE
#endif //_INCLUDE_CSDM_LIST_H