dvander@767: /**
dvander@767: * vim: set ts=4 :
ds@1330: * =============================================================================
dvander@1231: * SourceMod
ds@1947: * Copyright (C) 2004-2008 AlliedModders LLC. All rights reserved.
ds@1330: * =============================================================================
dvander@767: *
ds@1330: * This program is free software; you can redistribute it and/or modify it under
ds@1330: * the terms of the GNU General Public License, version 3.0, as published by the
ds@1330: * Free Software Foundation.
dvander@1231: *
ds@1330: * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1330: * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1330: * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more
ds@1330: * details.
dvander@1231: *
ds@1330: * You should have received a copy of the GNU General Public License along with
ds@1330: * this program. If not, see .
dvander@1231: *
ds@1330: * As a special exception, AlliedModders LLC gives you permission to link the
ds@1330: * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1330: * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1330: * by the Valve Corporation. You must obey the GNU General Public License in
ds@1330: * all respects for all other code used. Additionally, AlliedModders LLC grants
ds@1330: * this exception to all derivative works. AlliedModders LLC defines further
ds@1330: * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1330: * or .
dvander@767: *
dvander@767: * Version: $Id$
dvander@767: */
dvander@767:
dvander@767: #ifndef _INCLUDE_SOURCEMOD_FASTLINK_H_
dvander@767: #define _INCLUDE_SOURCEMOD_FASTLINK_H_
dvander@767:
dvander@854: #include
dvander@854:
dvander@767: template
dvander@767: class FastLink
dvander@767: {
dvander@767: public:
dvander@767: struct FastLinkNode
dvander@767: {
dvander@767: unsigned int prev;
dvander@767: unsigned int next;
dvander@767: unsigned int freeNode;
dvander@767: T obj;
dvander@767: };
dvander@767: public:
dvander@1131: FastLink(unsigned int maxsize) : m_Size(0), m_FirstLink(0), m_FreeNodes(0), m_LastLink(0), m_UsableIndex(0)
dvander@767: {
dvander@767: m_MaxSize = maxsize;
dvander@767: m_Nodes = new FastLinkNode[m_MaxSize+1];
dvander@767: }
dvander@767: public:
dvander@767: bool push_back(const T & obj)
dvander@767: {
dvander@767: unsigned int new_node = GetFreeIndex();
dvander@767: if (!new_node)
dvander@767: {
dvander@767: return false;
dvander@767: }
dvander@767: m_Nodes[new_node].obj = obj;
dvander@767: m_Nodes[new_node].next = 0;
dvander@767: if (!m_FirstLink)
dvander@767: {
dvander@767: m_Nodes[new_node].prev = 0;
dvander@767: m_FirstLink = new_node;
dvander@767: m_LastLink = new_node;
dvander@767: } else {
dvander@767: m_Nodes[new_node].prev = m_LastLink;
dvander@767: m_Nodes[m_LastLink].next = new_node;
dvander@767: m_LastLink = new_node;
dvander@767: }
dvander@767: m_Size++;
dvander@767: return true;
dvander@767: }
dvander@767: size_t size() const
dvander@767: {
dvander@767: return m_Size;
dvander@767: }
dvander@767: private:
dvander@767: unsigned int GetFreeIndex()
dvander@767: {
dvander@767: if (m_FreeNodes)
dvander@767: {
dvander@767: return m_Nodes[m_FreeNodes--].freeNode;
dvander@767: } else {
dvander@1131: if (m_UsableIndex >= m_MaxSize)
dvander@767: {
dvander@767: return 0;
dvander@767: }
dvander@1131: m_UsableIndex++;
dvander@1131: return m_UsableIndex;
dvander@767: }
dvander@767: }
dvander@767: public:
dvander@767: class iterator
dvander@767: {
dvander@767: friend class FastLink;
dvander@767: public:
dvander@767: iterator()
dvander@767: {
dvander@767: link = NULL;
dvander@767: position = 0;
dvander@767: }
dvander@767: iterator(const FastLink *_link, unsigned int _position)
dvander@767: {
dvander@767: link = _link;
dvander@767: position = _position;
dvander@767: }
dvander@767: public:
dvander@767: bool operator ==(const iterator &where) const
dvander@767: {
dvander@772: return (link == where.link && position == where.position);
dvander@767: }
dvander@767: bool operator !=(const iterator &where) const
dvander@767: {
dvander@772: return (link != where.link || position != where.position);
dvander@767: }
dvander@767: T & operator *()
dvander@767: {
dvander@767: return link->m_Nodes[position].obj;
dvander@767: }
dvander@767: const T & operator *() const
dvander@767: {
dvander@767: return link->m_Nodes[position].obj;
dvander@767: }
dvander@767: iterator & operator++()
dvander@767: {
dvander@767: position = link->m_Nodes[position].next;
dvander@767: return *this;
dvander@767: }
dvander@767: private:
dvander@767: const FastLink *link;
dvander@767: unsigned int position;
dvander@767: };
dvander@767: public:
dvander@767: iterator begin() const
dvander@767: {
dvander@767: return iterator(this, m_FirstLink);
dvander@767: }
dvander@767: iterator end() const
dvander@767: {
dvander@767: return iterator(this, 0);
dvander@767: }
dvander@767: void remove(const T & obj)
dvander@767: {
dvander@767: for (iterator iter=begin(); iter!=end(); ++iter)
dvander@767: {
dvander@767: if ((*iter) == obj)
dvander@767: {
dvander@767: erase(iter);
dvander@767: return;
dvander@767: }
dvander@767: }
dvander@767: }
dvander@767: iterator erase(const iterator &where)
dvander@767: {
dvander@767: /* Whoa, this better be right! */
dvander@767: assert(where.link == this);
dvander@767:
dvander@767: iterator iter(where.link, where.position);
dvander@767: ++iter;
dvander@767:
dvander@767: unsigned int index = where.position;
dvander@767:
dvander@767: /* Each case is different, we have no sentinel.
dvander@767: * CASE: We're the HEAD AND the TAIL */
dvander@767: if (index == m_FirstLink
dvander@767: && index == m_LastLink)
dvander@767: {
dvander@767: m_FirstLink = 0;
dvander@767: m_LastLink = 0;
dvander@767: }
dvander@767: /* We're the HEAD */
dvander@767: else if (index == m_FirstLink)
dvander@767: {
dvander@767: m_FirstLink = m_Nodes[index].next;
dvander@854: m_Nodes[m_FirstLink].prev = 0;
dvander@767: }
dvander@767: /* We're the TAIL */
dvander@767: else if (index == m_LastLink)
dvander@767: {
dvander@767: m_LastLink = m_Nodes[index].prev;
dvander@854: m_Nodes[m_LastLink].next = 0;
dvander@767: }
dvander@767: /* We're in the middle! */
dvander@767: else
dvander@767: {
dvander@767: /* Patch forward reference */
dvander@767: m_Nodes[m_Nodes[index].next].prev = m_Nodes[index].prev;
dvander@767: /* Patch backward reference */
dvander@767: m_Nodes[m_Nodes[index].prev].next = m_Nodes[index].next;
dvander@767: }
dvander@767:
dvander@767: /* Add us to the free list */
dvander@767: m_Nodes[++m_FreeNodes].freeNode = index;
dvander@767:
dvander@854: m_Size--;
dvander@854:
dvander@767: return iter;
dvander@767: }
dvander@1131: #if defined MENU_DEBUG
dvander@1131: public:
dvander@1131: #else
dvander@767: private:
dvander@1131: #endif
dvander@767: size_t m_Size;
dvander@767: unsigned int m_FirstLink;
dvander@778: unsigned int m_FreeNodes;
dvander@767: unsigned int m_LastLink;
dvander@767: unsigned int m_MaxSize;
dvander@1131: unsigned int m_UsableIndex;
dvander@767: FastLinkNode *m_Nodes;
dvander@767: };
dvander@767:
dvander@767: #endif //_INCLUDE_SOURCEMOD_FASTLINK_H_