| author | Scott Ehlert <ds@alliedmods.net> |
| Sun Jul 15 08:00:26 2007 +0000 (2007-07-15) | |
| changeset 1116 | 40cc5e9f0f1b |
| parent 1099 | 0c4a41db4436 |
| child 1231 | 17badaf66ce4 |
| permissions | -rw-r--r-- |
| dvander@1098 | 1 |
/** |
| dvander@1098 | 2 |
* vim: set ts=4 : |
| dvander@1098 | 3 |
* =============================================================== |
| dvander@1098 | 4 |
* SourceMod (C)2004-2007 AlliedModders LLC. All rights reserved. |
| dvander@1098 | 5 |
* =============================================================== |
| dvander@1098 | 6 |
* |
| dvander@1098 | 7 |
* This file is not open source and may not be copied without explicit |
| dvander@1098 | 8 |
* written permission of AlliedModders LLC. This file may not be redistributed |
| dvander@1098 | 9 |
* in whole or significant part. |
| dvander@1098 | 10 |
* For information, see LICENSE.txt or http://www.sourcemod.net/license.php |
| dvander@1098 | 11 |
* |
| dvander@1098 | 12 |
* Version: $Id$ |
| dvander@1098 | 13 |
*/ |
| dvander@1098 | 14 |
|
| dvander@1098 | 15 |
|
| dvander@1098 | 16 |
#ifndef _INCLUDE_SM_QUEUE_H |
| dvander@1098 | 17 |
#define _INCLUDE_SM_QUEUE_H |
| dvander@1098 | 18 |
|
| dvander@1098 | 19 |
#include <new> |
| dvander@1098 | 20 |
#include <malloc.h> |
| dvander@1098 | 21 |
#include <sh_stack.h> |
| dvander@1098 | 22 |
|
| dvander@1098 | 23 |
using namespace SourceHook; |
| dvander@1098 | 24 |
|
| dvander@1098 | 25 |
/* |
| dvander@1098 | 26 |
A circular, doubly-linked List with one sentinel node |
| dvander@1098 | 27 |
|
| dvander@1098 | 28 |
Empty: |
| dvander@1098 | 29 |
m_Head = sentinel |
| dvander@1098 | 30 |
m_Head->next = m_Head; |
| dvander@1098 | 31 |
m_Head->prev = m_Head; |
| dvander@1098 | 32 |
One element: |
| dvander@1098 | 33 |
m_Head = sentinel |
| dvander@1098 | 34 |
m_Head->next = node1 |
| dvander@1098 | 35 |
m_Head->prev = node1 |
| dvander@1098 | 36 |
node1->next = m_Head |
| dvander@1098 | 37 |
node1->prev = m_Head |
| dvander@1098 | 38 |
Two elements: |
| dvander@1098 | 39 |
m_Head = sentinel |
| dvander@1098 | 40 |
m_Head->next = node1 |
| dvander@1098 | 41 |
m_Head->prev = node2 |
| dvander@1098 | 42 |
node1->next = node2 |
| dvander@1098 | 43 |
node1->prev = m_Head |
| dvander@1098 | 44 |
node2->next = m_Head |
| dvander@1098 | 45 |
node2->prev = node1 |
| dvander@1098 | 46 |
*/ |
| dvander@1098 | 47 |
template <class T> |
| dvander@1098 | 48 |
class Queue |
| dvander@1098 | 49 |
{ |
| dvander@1098 | 50 |
public: |
| dvander@1098 | 51 |
class iterator; |
| dvander@1098 | 52 |
friend class iterator; |
| dvander@1098 | 53 |
class QueueNode |
| dvander@1098 | 54 |
{ |
| dvander@1098 | 55 |
public: |
| dvander@1098 | 56 |
T obj; |
| dvander@1098 | 57 |
QueueNode *next; |
| dvander@1098 | 58 |
QueueNode *prev; |
| dvander@1098 | 59 |
}; |
| dvander@1098 | 60 |
private: |
| dvander@1098 | 61 |
// Initializes the sentinel node. |
| dvander@1098 | 62 |
QueueNode *_Initialize() |
| dvander@1098 | 63 |
{ |
| dvander@1098 | 64 |
QueueNode *n = (QueueNode *)malloc(sizeof(QueueNode)); |
| dvander@1098 | 65 |
n->next = n; |
| dvander@1098 | 66 |
n->prev = n; |
| dvander@1098 | 67 |
return n; |
| dvander@1098 | 68 |
} |
| dvander@1098 | 69 |
public: |
| dvander@1098 | 70 |
Queue() : m_Head(_Initialize()), m_Size(0) |
| dvander@1098 | 71 |
{ |
| dvander@1098 | 72 |
} |
| dvander@1098 | 73 |
|
| dvander@1098 | 74 |
Queue(const Queue &src) : m_Head(_Initialize()), m_Size(0) |
| dvander@1098 | 75 |
{ |
| dvander@1098 | 76 |
iterator iter; |
| dvander@1098 | 77 |
for (iter=src.begin(); iter!=src.end(); iter++) |
| dvander@1098 | 78 |
{ |
| dvander@1098 | 79 |
push_back( (*iter) ); |
| dvander@1098 | 80 |
} |
| dvander@1098 | 81 |
} |
| dvander@1098 | 82 |
|
| dvander@1098 | 83 |
~Queue() |
| dvander@1098 | 84 |
{ |
| dvander@1098 | 85 |
clear(); |
| dvander@1098 | 86 |
|
| dvander@1098 | 87 |
// Don't forget to free the sentinel |
| dvander@1098 | 88 |
if (m_Head) |
| dvander@1098 | 89 |
{ |
| dvander@1098 | 90 |
free(m_Head); |
| dvander@1098 | 91 |
m_Head = NULL; |
| dvander@1098 | 92 |
} |
| dvander@1098 | 93 |
|
| dvander@1098 | 94 |
while (!m_FreeNodes.empty()) |
| dvander@1098 | 95 |
{ |
| dvander@1098 | 96 |
free(m_FreeNodes.front()); |
| dvander@1098 | 97 |
m_FreeNodes.pop(); |
| dvander@1098 | 98 |
} |
| dvander@1098 | 99 |
} |
| dvander@1098 | 100 |
|
| dvander@1098 | 101 |
void push(const T &obj) |
| dvander@1098 | 102 |
{ |
| dvander@1098 | 103 |
QueueNode *node; |
| dvander@1098 | 104 |
|
| dvander@1098 | 105 |
if (m_FreeNodes.empty()) |
| dvander@1098 | 106 |
{ |
| dvander@1098 | 107 |
node = (QueueNode *)malloc(sizeof(QueueNode)); |
| dvander@1098 | 108 |
} else { |
| dvander@1098 | 109 |
node = m_FreeNodes.front(); |
| dvander@1098 | 110 |
m_FreeNodes.pop(); |
| dvander@1098 | 111 |
} |
| dvander@1098 | 112 |
|
| dvander@1098 | 113 |
/* Copy the object */ |
| dvander@1098 | 114 |
new (&node->obj) T(obj); |
| dvander@1098 | 115 |
|
| dvander@1098 | 116 |
/* Install into the Queue */ |
| dvander@1098 | 117 |
node->prev = m_Head->prev; |
| dvander@1098 | 118 |
node->next = m_Head; |
| dvander@1098 | 119 |
m_Head->prev->next = node; |
| dvander@1098 | 120 |
m_Head->prev = node; |
| dvander@1098 | 121 |
|
| dvander@1098 | 122 |
m_Size++; |
| dvander@1098 | 123 |
} |
| dvander@1098 | 124 |
|
| dvander@1098 | 125 |
size_t size() const |
| dvander@1098 | 126 |
{ |
| dvander@1098 | 127 |
return m_Size; |
| dvander@1098 | 128 |
} |
| dvander@1098 | 129 |
|
| dvander@1098 | 130 |
void clear() |
| dvander@1098 | 131 |
{ |
| dvander@1098 | 132 |
QueueNode *node = m_Head->next; |
| dvander@1098 | 133 |
QueueNode *temp; |
| dvander@1098 | 134 |
m_Head->next = m_Head; |
| dvander@1098 | 135 |
m_Head->prev = m_Head; |
| dvander@1098 | 136 |
|
| dvander@1098 | 137 |
// Iterate through the nodes until we find g_Head (the sentinel) again |
| dvander@1098 | 138 |
while (node != m_Head) |
| dvander@1098 | 139 |
{ |
| dvander@1098 | 140 |
temp = node->next; |
| dvander@1098 | 141 |
node->obj.~T(); |
| dvander@1098 | 142 |
m_FreeNodes.push(node); |
| dvander@1098 | 143 |
node = temp; |
| dvander@1098 | 144 |
} |
| dvander@1098 | 145 |
m_Size = 0; |
| dvander@1098 | 146 |
} |
| dvander@1098 | 147 |
|
| dvander@1098 | 148 |
bool empty() const |
| dvander@1098 | 149 |
{ |
| dvander@1098 | 150 |
return (m_Size == 0); |
| dvander@1098 | 151 |
} |
| dvander@1098 | 152 |
|
| dvander@1098 | 153 |
private: |
| dvander@1098 | 154 |
QueueNode *m_Head; |
| dvander@1098 | 155 |
size_t m_Size; |
| dvander@1098 | 156 |
CStack<QueueNode *> m_FreeNodes; |
| dvander@1098 | 157 |
public: |
| dvander@1098 | 158 |
class iterator |
| dvander@1098 | 159 |
{ |
| dvander@1098 | 160 |
friend class Queue; |
| dvander@1098 | 161 |
public: |
| dvander@1098 | 162 |
iterator() |
| dvander@1098 | 163 |
{ |
| dvander@1098 | 164 |
m_This = NULL; |
| dvander@1098 | 165 |
} |
| dvander@1098 | 166 |
iterator(const Queue &src) |
| dvander@1098 | 167 |
{ |
| dvander@1098 | 168 |
m_This = src.m_Head; |
| dvander@1098 | 169 |
} |
| dvander@1098 | 170 |
iterator(QueueNode *n) : m_This(n) |
| dvander@1098 | 171 |
{ |
| dvander@1098 | 172 |
} |
| dvander@1098 | 173 |
iterator(const iterator &where) |
| dvander@1098 | 174 |
{ |
| dvander@1098 | 175 |
m_This = where.m_This; |
| dvander@1098 | 176 |
} |
| dvander@1098 | 177 |
//pre decrement |
| dvander@1098 | 178 |
iterator & operator--() |
| dvander@1098 | 179 |
{ |
| dvander@1098 | 180 |
if (m_This) |
| dvander@1098 | 181 |
m_This = m_This->prev; |
| dvander@1098 | 182 |
return *this; |
| dvander@1098 | 183 |
} |
| dvander@1098 | 184 |
//post decrement |
| dvander@1098 | 185 |
iterator operator--(int) |
| dvander@1098 | 186 |
{ |
| dvander@1098 | 187 |
iterator old(*this); |
| dvander@1098 | 188 |
if (m_This) |
| dvander@1098 | 189 |
m_This = m_This->prev; |
| dvander@1098 | 190 |
return old; |
| dvander@1098 | 191 |
} |
| dvander@1098 | 192 |
|
| dvander@1098 | 193 |
//pre increment |
| dvander@1098 | 194 |
iterator & operator++() |
| dvander@1098 | 195 |
{ |
| dvander@1098 | 196 |
if (m_This) |
| dvander@1098 | 197 |
m_This = m_This->next; |
| dvander@1098 | 198 |
return *this; |
| dvander@1098 | 199 |
} |
| dvander@1098 | 200 |
//post increment |
| dvander@1098 | 201 |
iterator operator++(int) |
| dvander@1098 | 202 |
{ |
| dvander@1098 | 203 |
iterator old(*this); |
| dvander@1098 | 204 |
if (m_This) |
| dvander@1098 | 205 |
m_This = m_This->next; |
| dvander@1098 | 206 |
return old; |
| dvander@1098 | 207 |
} |
| dvander@1098 | 208 |
|
| dvander@1098 | 209 |
const T & operator * () const |
| dvander@1098 | 210 |
{ |
| dvander@1098 | 211 |
return m_This->obj; |
| dvander@1098 | 212 |
} |
| dvander@1098 | 213 |
T & operator * () |
| dvander@1098 | 214 |
{ |
| dvander@1098 | 215 |
return m_This->obj; |
| dvander@1098 | 216 |
} |
| dvander@1098 | 217 |
|
| dvander@1098 | 218 |
T * operator -> () |
| dvander@1098 | 219 |
{ |
| dvander@1098 | 220 |
return &(m_This->obj); |
| dvander@1098 | 221 |
} |
| dvander@1098 | 222 |
const T * operator -> () const |
| dvander@1098 | 223 |
{ |
| dvander@1098 | 224 |
return &(m_This->obj); |
| dvander@1098 | 225 |
} |
| dvander@1098 | 226 |
|
| dvander@1098 | 227 |
bool operator != (const iterator &where) const |
| dvander@1098 | 228 |
{ |
| dvander@1098 | 229 |
return (m_This != where.m_This); |
| dvander@1098 | 230 |
} |
| dvander@1098 | 231 |
bool operator ==(const iterator &where) const |
| dvander@1098 | 232 |
{ |
| dvander@1098 | 233 |
return (m_This == where.m_This); |
| dvander@1098 | 234 |
} |
| dvander@1098 | 235 |
private: |
| dvander@1098 | 236 |
QueueNode *m_This; |
| dvander@1098 | 237 |
}; |
| dvander@1098 | 238 |
public: |
| dvander@1098 | 239 |
iterator begin() const |
| dvander@1098 | 240 |
{ |
| dvander@1098 | 241 |
return iterator(m_Head->next); |
| dvander@1098 | 242 |
} |
| dvander@1098 | 243 |
|
| dvander@1098 | 244 |
iterator end() const |
| dvander@1098 | 245 |
{ |
| dvander@1098 | 246 |
return iterator(m_Head); |
| dvander@1098 | 247 |
} |
| dvander@1098 | 248 |
|
| dvander@1098 | 249 |
iterator erase(iterator &where) |
| dvander@1098 | 250 |
{ |
| dvander@1098 | 251 |
QueueNode *pNode = where.m_This; |
| dvander@1098 | 252 |
iterator iter(where); |
| dvander@1098 | 253 |
iter++; |
| dvander@1098 | 254 |
|
| dvander@1098 | 255 |
|
| dvander@1098 | 256 |
// Works for all cases: empty Queue, erasing first element, erasing tail, erasing in the middle... |
| dvander@1098 | 257 |
pNode->prev->next = pNode->next; |
| dvander@1098 | 258 |
pNode->next->prev = pNode->prev; |
| dvander@1098 | 259 |
|
| dvander@1098 | 260 |
pNode->obj.~T(); |
| dvander@1098 | 261 |
m_FreeNodes.push(pNode); |
| dvander@1098 | 262 |
m_Size--; |
| dvander@1098 | 263 |
|
| dvander@1098 | 264 |
return iter; |
| dvander@1098 | 265 |
} |
| dvander@1098 | 266 |
public: |
| dvander@1098 | 267 |
void remove(const T & obj) |
| dvander@1098 | 268 |
{ |
| dvander@1098 | 269 |
iterator b; |
| dvander@1098 | 270 |
for (b=begin(); b!=end(); b++) |
| dvander@1098 | 271 |
{ |
| dvander@1098 | 272 |
if ( (*b) == obj ) |
| dvander@1098 | 273 |
{ |
| dvander@1098 | 274 |
erase( b ); |
| dvander@1098 | 275 |
break; |
| dvander@1098 | 276 |
} |
| dvander@1098 | 277 |
} |
| dvander@1098 | 278 |
} |
| dvander@1098 | 279 |
template <typename U> |
| dvander@1098 | 280 |
iterator find(const U & equ) const |
| dvander@1098 | 281 |
{ |
| dvander@1098 | 282 |
iterator iter; |
| dvander@1098 | 283 |
for (iter=begin(); iter!=end(); iter++) |
| dvander@1098 | 284 |
{ |
| dvander@1098 | 285 |
if ( (*iter) == equ ) |
| dvander@1098 | 286 |
{ |
| dvander@1098 | 287 |
return iter; |
| dvander@1098 | 288 |
} |
| dvander@1098 | 289 |
} |
| dvander@1098 | 290 |
return end(); |
| dvander@1098 | 291 |
} |
| dvander@1098 | 292 |
Queue & operator =(const Queue &src) |
| dvander@1098 | 293 |
{ |
| dvander@1098 | 294 |
clear(); |
| dvander@1098 | 295 |
iterator iter; |
| dvander@1098 | 296 |
for (iter=src.begin(); iter!=src.end(); iter++) |
| dvander@1098 | 297 |
{ |
| dvander@1098 | 298 |
push_back( (*iter) ); |
| dvander@1098 | 299 |
} |
| dvander@1098 | 300 |
return *this; |
| dvander@1098 | 301 |
} |
| dvander@1098 | 302 |
public: |
| dvander@1098 | 303 |
T & first() const |
| dvander@1098 | 304 |
{ |
| dvander@1098 | 305 |
iterator i = begin(); |
| dvander@1098 | 306 |
|
| dvander@1098 | 307 |
return (*i); |
| dvander@1098 | 308 |
} |
| dvander@1098 | 309 |
|
| dvander@1098 | 310 |
void pop() |
| dvander@1098 | 311 |
{ |
| dvander@1099 | 312 |
iterator iter = begin(); |
| dvander@1099 | 313 |
erase(iter); |
| dvander@1098 | 314 |
} |
| dvander@1098 | 315 |
}; |
| dvander@1098 | 316 |
|
| dvander@1098 | 317 |
#endif //_INCLUDE_SM_QUEUE_H |