core/sm_queue.h
author Phong Dang <teame06@gmail.com>
Wed Aug 01 07:29:40 2007 +0000 (2007-08-01)
changeset 1241 2e8046793bc9
parent 1231 17badaf66ce4
child 1330 ab94316bb52b
permissions -rw-r--r--
Added check to make sure player are alive to perform sm_slap, sm_burn, sm_slay.
dvander@1098
     1
/**
dvander@1098
     2
 * vim: set ts=4 :
dvander@1231
     3
 * ================================================================
dvander@1231
     4
 * SourceMod
dvander@1231
     5
 * Copyright (C) 2004-2007 AlliedModders LLC.  All rights reserved.
dvander@1231
     6
 * ================================================================
dvander@1098
     7
 *
dvander@1231
     8
 * This program is free software; you can redistribute it and/or 
dvander@1231
     9
 * modify it under the terms of the GNU General Public License, 
dvander@1231
    10
 * version 3.0, as published by the Free Software Foundation.
dvander@1231
    11
 * 
dvander@1231
    12
 * This program is distributed in the hope that it will be useful,
dvander@1231
    13
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
dvander@1231
    14
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
dvander@1231
    15
 * GNU General Public License for more details.
dvander@1231
    16
 *
dvander@1231
    17
 * You should have received a copy of the GNU General Public License
dvander@1231
    18
 * along with this program.  If not, see <http://www.gnu.org/licenses/>.
dvander@1231
    19
 *
dvander@1231
    20
 * As a special exception, AlliedModders LLC gives you permission to 
dvander@1231
    21
 * link the code of this program (as well as its derivative works) to 
dvander@1231
    22
 * "Half-Life 2," the "Source Engine," the "SourcePawn JIT," and any 
dvander@1231
    23
 * Game MODs that run on software by the Valve Corporation.  You must 
dvander@1231
    24
 * obey the GNU General Public License in all respects for all other 
dvander@1231
    25
 * code used. Additionally, AlliedModders LLC grants this exception 
dvander@1231
    26
 * to all derivative works. AlliedModders LLC defines further 
dvander@1231
    27
 * exceptions, found in LICENSE.txt (as of this writing, version 
dvander@1231
    28
 * JULY-31-2007), or <http://www.sourcemod.net/license.php>.
dvander@1098
    29
 *
dvander@1098
    30
 * Version: $Id$
dvander@1098
    31
 */
dvander@1098
    32
dvander@1098
    33
#ifndef _INCLUDE_SM_QUEUE_H
dvander@1098
    34
#define _INCLUDE_SM_QUEUE_H
dvander@1098
    35
dvander@1098
    36
#include <new>
dvander@1098
    37
#include <malloc.h>
dvander@1098
    38
#include <sh_stack.h>
dvander@1098
    39
dvander@1098
    40
using namespace SourceHook;
dvander@1098
    41
dvander@1098
    42
/*
dvander@1098
    43
	A circular, doubly-linked List with one sentinel node
dvander@1098
    44
dvander@1098
    45
	Empty:
dvander@1098
    46
	m_Head = sentinel
dvander@1098
    47
	m_Head->next = m_Head;
dvander@1098
    48
	m_Head->prev = m_Head;
dvander@1098
    49
	One element:
dvander@1098
    50
	m_Head = sentinel
dvander@1098
    51
	m_Head->next = node1
dvander@1098
    52
	m_Head->prev = node1
dvander@1098
    53
	node1->next = m_Head
dvander@1098
    54
	node1->prev = m_Head
dvander@1098
    55
	Two elements:
dvander@1098
    56
	m_Head = sentinel
dvander@1098
    57
	m_Head->next = node1
dvander@1098
    58
	m_Head->prev = node2
dvander@1098
    59
	node1->next = node2
dvander@1098
    60
	node1->prev = m_Head
dvander@1098
    61
	node2->next = m_Head
dvander@1098
    62
	node2->prev = node1
dvander@1098
    63
*/
dvander@1098
    64
template <class T>
dvander@1098
    65
class Queue
dvander@1098
    66
{
dvander@1098
    67
public:
dvander@1098
    68
	class iterator;
dvander@1098
    69
	friend class iterator;
dvander@1098
    70
	class QueueNode
dvander@1098
    71
	{
dvander@1098
    72
	public:
dvander@1098
    73
		T obj;
dvander@1098
    74
		QueueNode *next;
dvander@1098
    75
		QueueNode *prev;
dvander@1098
    76
	};
dvander@1098
    77
private:
dvander@1098
    78
	// Initializes the sentinel node.
dvander@1098
    79
	QueueNode *_Initialize()
dvander@1098
    80
	{
dvander@1098
    81
		QueueNode *n = (QueueNode *)malloc(sizeof(QueueNode));
dvander@1098
    82
		n->next = n;
dvander@1098
    83
		n->prev = n;
dvander@1098
    84
		return n;
dvander@1098
    85
	}
dvander@1098
    86
public:
dvander@1098
    87
	Queue() : m_Head(_Initialize()), m_Size(0)
dvander@1098
    88
	{
dvander@1098
    89
	}
dvander@1098
    90
dvander@1098
    91
	Queue(const Queue &src) : m_Head(_Initialize()), m_Size(0)
dvander@1098
    92
	{
dvander@1098
    93
		iterator iter;
dvander@1098
    94
		for (iter=src.begin(); iter!=src.end(); iter++)
dvander@1098
    95
		{
dvander@1098
    96
			push_back( (*iter) );
dvander@1098
    97
		}
dvander@1098
    98
	}
dvander@1098
    99
dvander@1098
   100
	~Queue()
dvander@1098
   101
	{
dvander@1098
   102
		clear();
dvander@1098
   103
dvander@1098
   104
		// Don't forget to free the sentinel
dvander@1098
   105
		if (m_Head)
dvander@1098
   106
		{
dvander@1098
   107
			free(m_Head);
dvander@1098
   108
			m_Head = NULL;
dvander@1098
   109
		}
dvander@1098
   110
dvander@1098
   111
		while (!m_FreeNodes.empty())
dvander@1098
   112
		{
dvander@1098
   113
			free(m_FreeNodes.front());
dvander@1098
   114
			m_FreeNodes.pop();
dvander@1098
   115
		}
dvander@1098
   116
	}
dvander@1098
   117
dvander@1098
   118
	void push(const T &obj)
dvander@1098
   119
	{
dvander@1098
   120
		QueueNode *node;
dvander@1098
   121
		
dvander@1098
   122
		if (m_FreeNodes.empty())
dvander@1098
   123
		{
dvander@1098
   124
			node = (QueueNode *)malloc(sizeof(QueueNode));
dvander@1098
   125
		} else {
dvander@1098
   126
			node = m_FreeNodes.front();
dvander@1098
   127
			m_FreeNodes.pop();
dvander@1098
   128
		}
dvander@1098
   129
dvander@1098
   130
		/* Copy the object */
dvander@1098
   131
		new (&node->obj) T(obj);
dvander@1098
   132
dvander@1098
   133
		/* Install into the Queue */
dvander@1098
   134
		node->prev = m_Head->prev;
dvander@1098
   135
		node->next = m_Head;
dvander@1098
   136
		m_Head->prev->next = node;
dvander@1098
   137
		m_Head->prev = node;
dvander@1098
   138
dvander@1098
   139
		m_Size++;
dvander@1098
   140
	}
dvander@1098
   141
dvander@1098
   142
	size_t size() const
dvander@1098
   143
	{
dvander@1098
   144
		return m_Size;
dvander@1098
   145
	}
dvander@1098
   146
dvander@1098
   147
	void clear()
dvander@1098
   148
	{
dvander@1098
   149
		QueueNode *node = m_Head->next;
dvander@1098
   150
		QueueNode *temp;
dvander@1098
   151
		m_Head->next = m_Head;
dvander@1098
   152
		m_Head->prev = m_Head;
dvander@1098
   153
dvander@1098
   154
		// Iterate through the nodes until we find g_Head (the sentinel) again
dvander@1098
   155
		while (node != m_Head)
dvander@1098
   156
		{
dvander@1098
   157
			temp = node->next;
dvander@1098
   158
			node->obj.~T();
dvander@1098
   159
			m_FreeNodes.push(node);
dvander@1098
   160
			node = temp;
dvander@1098
   161
		}
dvander@1098
   162
		m_Size = 0;
dvander@1098
   163
	}
dvander@1098
   164
dvander@1098
   165
	bool empty() const
dvander@1098
   166
	{
dvander@1098
   167
		return (m_Size == 0);
dvander@1098
   168
	}
dvander@1098
   169
dvander@1098
   170
private:
dvander@1098
   171
	QueueNode *m_Head;
dvander@1098
   172
	size_t m_Size;
dvander@1098
   173
	CStack<QueueNode *> m_FreeNodes;
dvander@1098
   174
public:
dvander@1098
   175
	class iterator
dvander@1098
   176
	{
dvander@1098
   177
		friend class Queue;
dvander@1098
   178
	public:
dvander@1098
   179
		iterator()
dvander@1098
   180
		{
dvander@1098
   181
			m_This = NULL;
dvander@1098
   182
		}
dvander@1098
   183
		iterator(const Queue &src)
dvander@1098
   184
		{
dvander@1098
   185
			m_This = src.m_Head;
dvander@1098
   186
		}
dvander@1098
   187
		iterator(QueueNode *n) : m_This(n)
dvander@1098
   188
		{
dvander@1098
   189
		}
dvander@1098
   190
		iterator(const iterator &where)
dvander@1098
   191
		{
dvander@1098
   192
			m_This = where.m_This;
dvander@1098
   193
		}
dvander@1098
   194
		//pre decrement
dvander@1098
   195
		iterator & operator--()
dvander@1098
   196
		{
dvander@1098
   197
			if (m_This)
dvander@1098
   198
				m_This = m_This->prev;
dvander@1098
   199
			return *this;
dvander@1098
   200
		}
dvander@1098
   201
		//post decrement
dvander@1098
   202
		iterator operator--(int)
dvander@1098
   203
		{
dvander@1098
   204
			iterator old(*this);
dvander@1098
   205
			if (m_This)
dvander@1098
   206
				m_This = m_This->prev;
dvander@1098
   207
			return old;
dvander@1098
   208
		}	
dvander@1098
   209
dvander@1098
   210
		//pre increment
dvander@1098
   211
		iterator & operator++()
dvander@1098
   212
		{
dvander@1098
   213
			if (m_This)
dvander@1098
   214
				m_This = m_This->next;
dvander@1098
   215
			return *this;
dvander@1098
   216
		}
dvander@1098
   217
		//post increment
dvander@1098
   218
		iterator operator++(int)
dvander@1098
   219
		{
dvander@1098
   220
			iterator old(*this);
dvander@1098
   221
			if (m_This)
dvander@1098
   222
				m_This = m_This->next;
dvander@1098
   223
			return old;
dvander@1098
   224
		}
dvander@1098
   225
dvander@1098
   226
		const T & operator * () const
dvander@1098
   227
		{
dvander@1098
   228
			return m_This->obj;
dvander@1098
   229
		}
dvander@1098
   230
		T & operator * ()
dvander@1098
   231
		{
dvander@1098
   232
			return m_This->obj;
dvander@1098
   233
		}
dvander@1098
   234
dvander@1098
   235
		T * operator -> ()
dvander@1098
   236
		{
dvander@1098
   237
			return &(m_This->obj);
dvander@1098
   238
		}
dvander@1098
   239
		const T * operator -> () const
dvander@1098
   240
		{
dvander@1098
   241
			return &(m_This->obj);
dvander@1098
   242
		}
dvander@1098
   243
dvander@1098
   244
		bool operator != (const iterator &where) const
dvander@1098
   245
		{
dvander@1098
   246
			return (m_This != where.m_This);
dvander@1098
   247
		}
dvander@1098
   248
		bool operator ==(const iterator &where) const
dvander@1098
   249
		{
dvander@1098
   250
			return (m_This == where.m_This);
dvander@1098
   251
		}
dvander@1098
   252
	private:
dvander@1098
   253
		QueueNode *m_This;
dvander@1098
   254
	};
dvander@1098
   255
public:
dvander@1098
   256
	iterator begin() const
dvander@1098
   257
	{
dvander@1098
   258
		return iterator(m_Head->next);
dvander@1098
   259
	}
dvander@1098
   260
dvander@1098
   261
	iterator end() const
dvander@1098
   262
	{
dvander@1098
   263
		return iterator(m_Head);
dvander@1098
   264
	}
dvander@1098
   265
dvander@1098
   266
	iterator erase(iterator &where)
dvander@1098
   267
	{
dvander@1098
   268
		QueueNode *pNode = where.m_This;
dvander@1098
   269
		iterator iter(where);
dvander@1098
   270
		iter++;
dvander@1098
   271
dvander@1098
   272
dvander@1098
   273
		// Works for all cases: empty Queue, erasing first element, erasing tail, erasing in the middle...
dvander@1098
   274
		pNode->prev->next = pNode->next;
dvander@1098
   275
		pNode->next->prev = pNode->prev;
dvander@1098
   276
dvander@1098
   277
		pNode->obj.~T();
dvander@1098
   278
		m_FreeNodes.push(pNode);
dvander@1098
   279
		m_Size--;
dvander@1098
   280
dvander@1098
   281
		return iter;
dvander@1098
   282
	}
dvander@1098
   283
public:
dvander@1098
   284
	void remove(const T & obj)
dvander@1098
   285
	{
dvander@1098
   286
		iterator b;
dvander@1098
   287
		for (b=begin(); b!=end(); b++)
dvander@1098
   288
		{
dvander@1098
   289
			if ( (*b) == obj )
dvander@1098
   290
			{
dvander@1098
   291
				erase( b );
dvander@1098
   292
				break;
dvander@1098
   293
			}
dvander@1098
   294
		}
dvander@1098
   295
	}
dvander@1098
   296
	template <typename U>
dvander@1098
   297
	iterator find(const U & equ) const
dvander@1098
   298
	{
dvander@1098
   299
		iterator iter;
dvander@1098
   300
		for (iter=begin(); iter!=end(); iter++)
dvander@1098
   301
		{
dvander@1098
   302
			if ( (*iter) == equ )
dvander@1098
   303
			{
dvander@1098
   304
				return iter;
dvander@1098
   305
			}
dvander@1098
   306
		}
dvander@1098
   307
		return end();
dvander@1098
   308
	}
dvander@1098
   309
	Queue & operator =(const Queue &src)
dvander@1098
   310
	{
dvander@1098
   311
		clear();
dvander@1098
   312
		iterator iter;
dvander@1098
   313
		for (iter=src.begin(); iter!=src.end(); iter++)
dvander@1098
   314
		{
dvander@1098
   315
			push_back( (*iter) );
dvander@1098
   316
		}
dvander@1098
   317
		return *this;
dvander@1098
   318
	}
dvander@1098
   319
public:
dvander@1098
   320
	T & first() const
dvander@1098
   321
	{
dvander@1098
   322
		iterator i = begin();
dvander@1098
   323
dvander@1098
   324
		return (*i);
dvander@1098
   325
	}
dvander@1098
   326
dvander@1098
   327
	void pop()
dvander@1098
   328
	{
dvander@1099
   329
		iterator iter = begin();
dvander@1099
   330
		erase(iter);
dvander@1098
   331
	}
dvander@1098
   332
};
dvander@1098
   333
dvander@1098
   334
#endif //_INCLUDE_SM_QUEUE_H