core/sm_fastlink.h
author David Anderson <dvander@alliedmods.net>
Tue May 22 20:50:48 2007 +0000 (2007-05-22)
changeset 833 732bedfcbe3e
parent 778 07e49a8cf046
child 854 ffeae23d84b3
permissions -rw-r--r--
added ReplaceString and ReplaceStringEx (phew!)
dvander@767
     1
/**
dvander@767
     2
 * vim: set ts=4 :
dvander@767
     3
 * ===============================================================
dvander@767
     4
 * SourceMod (C)2004-2007 AlliedModders LLC.  All rights reserved.
dvander@767
     5
 * ===============================================================
dvander@767
     6
 *
dvander@767
     7
 * This file is not open source and may not be copied without explicit
dvander@767
     8
 * written permission of AlliedModders LLC.  This file may not be redistributed 
dvander@767
     9
 * in whole or significant part.
dvander@767
    10
 * For information, see LICENSE.txt or http://www.sourcemod.net/license.php
dvander@767
    11
 *
dvander@767
    12
 * Version: $Id$
dvander@767
    13
 */
dvander@767
    14
dvander@767
    15
dvander@767
    16
#ifndef _INCLUDE_SOURCEMOD_FASTLINK_H_
dvander@767
    17
#define _INCLUDE_SOURCEMOD_FASTLINK_H_
dvander@767
    18
dvander@767
    19
template <typename T>
dvander@767
    20
class FastLink
dvander@767
    21
{
dvander@767
    22
	friend class iterator;
dvander@767
    23
public:
dvander@767
    24
	struct FastLinkNode
dvander@767
    25
	{
dvander@767
    26
		unsigned int prev;
dvander@767
    27
		unsigned int next;
dvander@767
    28
		unsigned int freeNode;
dvander@767
    29
		T obj;
dvander@767
    30
	};
dvander@767
    31
public:
dvander@767
    32
	FastLink(unsigned int maxsize) : m_Size(0), m_FirstLink(0), m_FreeNodes(0), m_LastLink(0)
dvander@767
    33
	{
dvander@767
    34
		m_MaxSize = maxsize;
dvander@767
    35
		m_Nodes = new FastLinkNode[m_MaxSize+1];
dvander@767
    36
	}
dvander@767
    37
public:
dvander@767
    38
	bool push_back(const T & obj)
dvander@767
    39
	{
dvander@767
    40
		unsigned int new_node = GetFreeIndex();
dvander@767
    41
		if (!new_node)
dvander@767
    42
		{
dvander@767
    43
			return false;
dvander@767
    44
		}
dvander@767
    45
		m_Nodes[new_node].obj = obj;
dvander@767
    46
		m_Nodes[new_node].next = 0;
dvander@767
    47
		if (!m_FirstLink)
dvander@767
    48
		{
dvander@767
    49
			m_Nodes[new_node].prev = 0;
dvander@767
    50
			m_FirstLink = new_node;
dvander@767
    51
			m_LastLink = new_node;
dvander@767
    52
		} else {
dvander@767
    53
			m_Nodes[new_node].prev = m_LastLink;
dvander@767
    54
			m_Nodes[m_LastLink].next = new_node;
dvander@767
    55
			m_LastLink = new_node;
dvander@767
    56
		}
dvander@767
    57
		m_Size++;
dvander@767
    58
		return true;
dvander@767
    59
	}
dvander@767
    60
	size_t size() const
dvander@767
    61
	{
dvander@767
    62
		return m_Size;
dvander@767
    63
	}
dvander@767
    64
private:
dvander@767
    65
	unsigned int GetFreeIndex()
dvander@767
    66
	{
dvander@767
    67
		if (m_FreeNodes)
dvander@767
    68
		{
dvander@767
    69
			return m_Nodes[m_FreeNodes--].freeNode;
dvander@767
    70
		} else {
dvander@767
    71
			if (m_LastLink >= m_MaxSize)
dvander@767
    72
			{
dvander@767
    73
				return 0;
dvander@767
    74
			}
dvander@767
    75
			return m_LastLink + 1;
dvander@767
    76
		}
dvander@767
    77
	}
dvander@767
    78
public:
dvander@767
    79
	class iterator
dvander@767
    80
	{
dvander@767
    81
		friend class FastLink;
dvander@767
    82
	public:
dvander@767
    83
		iterator()
dvander@767
    84
		{
dvander@767
    85
			link = NULL;
dvander@767
    86
			position = 0;
dvander@767
    87
		}
dvander@767
    88
		iterator(const FastLink *_link, unsigned int _position)
dvander@767
    89
		{
dvander@767
    90
			link = _link;
dvander@767
    91
			position = _position;
dvander@767
    92
		}
dvander@767
    93
	public:
dvander@767
    94
		bool operator ==(const iterator &where) const
dvander@767
    95
		{
dvander@772
    96
			return (link == where.link && position == where.position);
dvander@767
    97
		}
dvander@767
    98
		bool operator !=(const iterator &where) const
dvander@767
    99
		{
dvander@772
   100
			return (link != where.link || position != where.position);
dvander@767
   101
		}
dvander@767
   102
		T & operator *()
dvander@767
   103
		{
dvander@767
   104
			return link->m_Nodes[position].obj;
dvander@767
   105
		}
dvander@767
   106
		const T & operator *() const
dvander@767
   107
		{
dvander@767
   108
			return link->m_Nodes[position].obj;
dvander@767
   109
		}
dvander@767
   110
		iterator & operator++()
dvander@767
   111
		{
dvander@767
   112
			position = link->m_Nodes[position].next;
dvander@767
   113
			return *this;
dvander@767
   114
		}
dvander@767
   115
	private:
dvander@767
   116
		const FastLink *link;
dvander@767
   117
		unsigned int position;
dvander@767
   118
	};
dvander@767
   119
public:
dvander@767
   120
	iterator begin() const
dvander@767
   121
	{
dvander@767
   122
		return iterator(this, m_FirstLink);
dvander@767
   123
	}
dvander@767
   124
	iterator end() const
dvander@767
   125
	{
dvander@767
   126
		return iterator(this, 0);
dvander@767
   127
	}
dvander@767
   128
	void remove(const T & obj)
dvander@767
   129
	{
dvander@767
   130
		for (iterator iter=begin(); iter!=end(); ++iter)
dvander@767
   131
		{
dvander@767
   132
			if ((*iter) == obj)
dvander@767
   133
			{
dvander@767
   134
				erase(iter);
dvander@767
   135
				return;
dvander@767
   136
			}
dvander@767
   137
		}
dvander@767
   138
	}
dvander@767
   139
	iterator erase(const iterator &where)
dvander@767
   140
	{
dvander@767
   141
		/* Whoa, this better be right! */
dvander@767
   142
		assert(where.link == this);
dvander@767
   143
dvander@767
   144
		iterator iter(where.link, where.position);
dvander@767
   145
		++iter;
dvander@767
   146
dvander@767
   147
		unsigned int index = where.position;
dvander@767
   148
dvander@767
   149
		/* Each case is different, we have no sentinel.
dvander@767
   150
		 * CASE: We're the HEAD AND the TAIL */
dvander@767
   151
		if (index == m_FirstLink
dvander@767
   152
			&& index == m_LastLink)
dvander@767
   153
		{
dvander@767
   154
			m_FirstLink = 0;
dvander@767
   155
			m_LastLink = 0;
dvander@767
   156
		}
dvander@767
   157
		/* We're the HEAD */
dvander@767
   158
		else if (index == m_FirstLink)
dvander@767
   159
		{
dvander@767
   160
			m_FirstLink = m_Nodes[index].next;
dvander@767
   161
			m_Nodes[index].prev = 0;
dvander@767
   162
		}
dvander@767
   163
		/* We're the TAIL */
dvander@767
   164
		else if (index == m_LastLink)
dvander@767
   165
		{
dvander@767
   166
			m_LastLink = m_Nodes[index].prev;
dvander@767
   167
			m_Nodes[index].next = 0;
dvander@767
   168
		}
dvander@767
   169
		/* We're in the middle! */
dvander@767
   170
		else
dvander@767
   171
		{
dvander@767
   172
			/* Patch forward reference */
dvander@767
   173
			m_Nodes[m_Nodes[index].next].prev = m_Nodes[index].prev;
dvander@767
   174
			/* Patch backward reference */
dvander@767
   175
			m_Nodes[m_Nodes[index].prev].next = m_Nodes[index].next;
dvander@767
   176
		}
dvander@767
   177
dvander@767
   178
		/* Add us to the free list */
dvander@767
   179
		m_Nodes[++m_FreeNodes].freeNode = index;
dvander@767
   180
dvander@767
   181
		return iter;
dvander@767
   182
	}
dvander@767
   183
private:
dvander@767
   184
	size_t m_Size;
dvander@767
   185
	unsigned int m_FirstLink;
dvander@778
   186
	unsigned int m_FreeNodes;
dvander@767
   187
	unsigned int m_LastLink;
dvander@767
   188
	unsigned int m_MaxSize;
dvander@767
   189
	FastLinkNode *m_Nodes;
dvander@767
   190
};
dvander@767
   191
dvander@767
   192
#endif //_INCLUDE_SOURCEMOD_FASTLINK_H_