core/sm_fastlink.h
author David Anderson <dvander@alliedmods.net>
Fri Jun 01 02:30:29 2007 +0000 (2007-06-01)
changeset 868 bdbf922e246f
parent 854 ffeae23d84b3
child 1131 d109d9e33ee5
permissions -rw-r--r--
-initial import of database natives + config
-initial import of completed database layer
-CreateIdentity now requires a non-optional second pointer. This breaks backwards compatibility for CreateIdentity(), however, this is not a function extension authors are supposed to be calling
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@854
    19
#include <assert.h>
dvander@854
    20
dvander@767
    21
template <typename T>
dvander@767
    22
class FastLink
dvander@767
    23
{
dvander@767
    24
	friend class iterator;
dvander@767
    25
public:
dvander@767
    26
	struct FastLinkNode
dvander@767
    27
	{
dvander@767
    28
		unsigned int prev;
dvander@767
    29
		unsigned int next;
dvander@767
    30
		unsigned int freeNode;
dvander@767
    31
		T obj;
dvander@767
    32
	};
dvander@767
    33
public:
dvander@767
    34
	FastLink(unsigned int maxsize) : m_Size(0), m_FirstLink(0), m_FreeNodes(0), m_LastLink(0)
dvander@767
    35
	{
dvander@767
    36
		m_MaxSize = maxsize;
dvander@767
    37
		m_Nodes = new FastLinkNode[m_MaxSize+1];
dvander@767
    38
	}
dvander@767
    39
public:
dvander@767
    40
	bool push_back(const T & obj)
dvander@767
    41
	{
dvander@767
    42
		unsigned int new_node = GetFreeIndex();
dvander@767
    43
		if (!new_node)
dvander@767
    44
		{
dvander@767
    45
			return false;
dvander@767
    46
		}
dvander@767
    47
		m_Nodes[new_node].obj = obj;
dvander@767
    48
		m_Nodes[new_node].next = 0;
dvander@767
    49
		if (!m_FirstLink)
dvander@767
    50
		{
dvander@767
    51
			m_Nodes[new_node].prev = 0;
dvander@767
    52
			m_FirstLink = new_node;
dvander@767
    53
			m_LastLink = new_node;
dvander@767
    54
		} else {
dvander@767
    55
			m_Nodes[new_node].prev = m_LastLink;
dvander@767
    56
			m_Nodes[m_LastLink].next = new_node;
dvander@767
    57
			m_LastLink = new_node;
dvander@767
    58
		}
dvander@767
    59
		m_Size++;
dvander@767
    60
		return true;
dvander@767
    61
	}
dvander@767
    62
	size_t size() const
dvander@767
    63
	{
dvander@767
    64
		return m_Size;
dvander@767
    65
	}
dvander@767
    66
private:
dvander@767
    67
	unsigned int GetFreeIndex()
dvander@767
    68
	{
dvander@767
    69
		if (m_FreeNodes)
dvander@767
    70
		{
dvander@767
    71
			return m_Nodes[m_FreeNodes--].freeNode;
dvander@767
    72
		} else {
dvander@767
    73
			if (m_LastLink >= m_MaxSize)
dvander@767
    74
			{
dvander@767
    75
				return 0;
dvander@767
    76
			}
dvander@767
    77
			return m_LastLink + 1;
dvander@767
    78
		}
dvander@767
    79
	}
dvander@767
    80
public:
dvander@767
    81
	class iterator
dvander@767
    82
	{
dvander@767
    83
		friend class FastLink;
dvander@767
    84
	public:
dvander@767
    85
		iterator()
dvander@767
    86
		{
dvander@767
    87
			link = NULL;
dvander@767
    88
			position = 0;
dvander@767
    89
		}
dvander@767
    90
		iterator(const FastLink *_link, unsigned int _position)
dvander@767
    91
		{
dvander@767
    92
			link = _link;
dvander@767
    93
			position = _position;
dvander@767
    94
		}
dvander@767
    95
	public:
dvander@767
    96
		bool operator ==(const iterator &where) const
dvander@767
    97
		{
dvander@772
    98
			return (link == where.link && position == where.position);
dvander@767
    99
		}
dvander@767
   100
		bool operator !=(const iterator &where) const
dvander@767
   101
		{
dvander@772
   102
			return (link != where.link || position != where.position);
dvander@767
   103
		}
dvander@767
   104
		T & operator *()
dvander@767
   105
		{
dvander@767
   106
			return link->m_Nodes[position].obj;
dvander@767
   107
		}
dvander@767
   108
		const T & operator *() const
dvander@767
   109
		{
dvander@767
   110
			return link->m_Nodes[position].obj;
dvander@767
   111
		}
dvander@767
   112
		iterator & operator++()
dvander@767
   113
		{
dvander@767
   114
			position = link->m_Nodes[position].next;
dvander@767
   115
			return *this;
dvander@767
   116
		}
dvander@767
   117
	private:
dvander@767
   118
		const FastLink *link;
dvander@767
   119
		unsigned int position;
dvander@767
   120
	};
dvander@767
   121
public:
dvander@767
   122
	iterator begin() const
dvander@767
   123
	{
dvander@767
   124
		return iterator(this, m_FirstLink);
dvander@767
   125
	}
dvander@767
   126
	iterator end() const
dvander@767
   127
	{
dvander@767
   128
		return iterator(this, 0);
dvander@767
   129
	}
dvander@767
   130
	void remove(const T & obj)
dvander@767
   131
	{
dvander@767
   132
		for (iterator iter=begin(); iter!=end(); ++iter)
dvander@767
   133
		{
dvander@767
   134
			if ((*iter) == obj)
dvander@767
   135
			{
dvander@767
   136
				erase(iter);
dvander@767
   137
				return;
dvander@767
   138
			}
dvander@767
   139
		}
dvander@767
   140
	}
dvander@767
   141
	iterator erase(const iterator &where)
dvander@767
   142
	{
dvander@767
   143
		/* Whoa, this better be right! */
dvander@767
   144
		assert(where.link == this);
dvander@767
   145
dvander@767
   146
		iterator iter(where.link, where.position);
dvander@767
   147
		++iter;
dvander@767
   148
dvander@767
   149
		unsigned int index = where.position;
dvander@767
   150
dvander@767
   151
		/* Each case is different, we have no sentinel.
dvander@767
   152
		 * CASE: We're the HEAD AND the TAIL */
dvander@767
   153
		if (index == m_FirstLink
dvander@767
   154
			&& index == m_LastLink)
dvander@767
   155
		{
dvander@767
   156
			m_FirstLink = 0;
dvander@767
   157
			m_LastLink = 0;
dvander@767
   158
		}
dvander@767
   159
		/* We're the HEAD */
dvander@767
   160
		else if (index == m_FirstLink)
dvander@767
   161
		{
dvander@767
   162
			m_FirstLink = m_Nodes[index].next;
dvander@854
   163
			m_Nodes[m_FirstLink].prev = 0;
dvander@767
   164
		}
dvander@767
   165
		/* We're the TAIL */
dvander@767
   166
		else if (index == m_LastLink)
dvander@767
   167
		{
dvander@767
   168
			m_LastLink = m_Nodes[index].prev;
dvander@854
   169
			m_Nodes[m_LastLink].next = 0;
dvander@767
   170
		}
dvander@767
   171
		/* We're in the middle! */
dvander@767
   172
		else
dvander@767
   173
		{
dvander@767
   174
			/* Patch forward reference */
dvander@767
   175
			m_Nodes[m_Nodes[index].next].prev = m_Nodes[index].prev;
dvander@767
   176
			/* Patch backward reference */
dvander@767
   177
			m_Nodes[m_Nodes[index].prev].next = m_Nodes[index].next;
dvander@767
   178
		}
dvander@767
   179
dvander@767
   180
		/* Add us to the free list */
dvander@767
   181
		m_Nodes[++m_FreeNodes].freeNode = index;
dvander@767
   182
dvander@854
   183
		m_Size--;
dvander@854
   184
dvander@767
   185
		return iter;
dvander@767
   186
	}
dvander@767
   187
private:
dvander@767
   188
	size_t m_Size;
dvander@767
   189
	unsigned int m_FirstLink;
dvander@778
   190
	unsigned int m_FreeNodes;
dvander@767
   191
	unsigned int m_LastLink;
dvander@767
   192
	unsigned int m_MaxSize;
dvander@767
   193
	FastLinkNode *m_Nodes;
dvander@767
   194
};
dvander@767
   195
dvander@767
   196
#endif //_INCLUDE_SOURCEMOD_FASTLINK_H_