492 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
			
		
		
	
	
			492 lines
		
	
	
		
			8.0 KiB
		
	
	
	
		
			C++
		
	
	
		
			Executable File
		
	
	
	
	
/* AMX Mod X
 | 
						|
*
 | 
						|
* by the AMX Mod X Development Team
 | 
						|
*  originally developed by OLO
 | 
						|
*
 | 
						|
*
 | 
						|
*  This program is free software; you can redistribute it and/or modify it
 | 
						|
*  under the terms of the GNU General Public License as published by the
 | 
						|
*  Free Software Foundation; either version 2 of the License, or (at
 | 
						|
*  your option) any later version.
 | 
						|
*
 | 
						|
*  This program is distributed in the hope that it will be useful, but
 | 
						|
*  WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 | 
						|
*  General Public License for more details.
 | 
						|
*
 | 
						|
*  You should have received a copy of the GNU General Public License
 | 
						|
*  along with this program; if not, write to the Free Software Foundation,
 | 
						|
*  Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
 | 
						|
*
 | 
						|
*  In addition, as a special exception, the author gives permission to
 | 
						|
*  link the code of this program with the Half-Life Game Engine ("HL
 | 
						|
*  Engine") and Modified Game Libraries ("MODs") developed by Valve,
 | 
						|
*  L.L.C ("Valve"). You must obey the GNU General Public License in all
 | 
						|
*  respects for all of the code used other than the HL Engine and MODs
 | 
						|
*  from Valve. If you modify this file, you may extend this exception
 | 
						|
*  to your version of the file, but you are not obligated to do so. If
 | 
						|
*  you do not wish to do so, delete this exception statement from your
 | 
						|
*  version.
 | 
						|
*/
 | 
						|
 | 
						|
#ifndef __CVECTOR_H__
 | 
						|
#define __CVECTOR_H__
 | 
						|
 | 
						|
#include <assert.h>
 | 
						|
 | 
						|
// Vector
 | 
						|
template <class T> class CVector
 | 
						|
{
 | 
						|
	bool Grow()
 | 
						|
	{
 | 
						|
		// automatic grow
 | 
						|
		size_t newSize = m_Size * 2;
 | 
						|
		if (newSize == 0)
 | 
						|
			newSize = 8;					// a good init value
 | 
						|
		T *newData = new T[newSize];
 | 
						|
		if (!newData)
 | 
						|
			return false;
 | 
						|
		if (m_Data)
 | 
						|
		{
 | 
						|
			for (size_t i=0; i<m_CurrentUsedSize; i++)
 | 
						|
				newData[i] = m_Data[i];
 | 
						|
			delete [] m_Data;
 | 
						|
		}
 | 
						|
		m_Data = newData;
 | 
						|
		m_Size = newSize;
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	bool GrowIfNeeded()
 | 
						|
	{
 | 
						|
		if (m_CurrentUsedSize >= m_Size)
 | 
						|
			return Grow();
 | 
						|
		else
 | 
						|
			return true;
 | 
						|
	}
 | 
						|
 | 
						|
	bool ChangeSize(size_t size)
 | 
						|
	{
 | 
						|
		// change size
 | 
						|
		if (size == m_Size)
 | 
						|
			return true;
 | 
						|
 | 
						|
		if (!size)
 | 
						|
		{
 | 
						|
			if (m_Data)
 | 
						|
			{
 | 
						|
				delete [] m_Data;
 | 
						|
				m_Data = NULL;
 | 
						|
				m_Size = 0;
 | 
						|
			}
 | 
						|
			return true;
 | 
						|
		}
 | 
						|
 | 
						|
		T *newData = new T[size];
 | 
						|
		if (!newData)
 | 
						|
			return false;
 | 
						|
		if (m_Data)
 | 
						|
		{
 | 
						|
			size_t end = (m_CurrentUsedSize < size) ? (m_CurrentUsedSize) : size;
 | 
						|
			for (size_t i=0; i<end; i++)
 | 
						|
				newData[i] = m_Data[i];
 | 
						|
			delete [] m_Data;
 | 
						|
		}
 | 
						|
		m_Data = newData;
 | 
						|
		m_Size = size;
 | 
						|
		if (m_CurrentUsedSize > m_Size)
 | 
						|
			m_CurrentUsedSize = m_Size;
 | 
						|
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	void FreeMemIfPossible()
 | 
						|
	{
 | 
						|
		if (!m_Data)
 | 
						|
			return;
 | 
						|
 | 
						|
		if (!m_CurrentUsedSize)
 | 
						|
		{
 | 
						|
			ChangeSize(0);
 | 
						|
			return;
 | 
						|
		}
 | 
						|
 | 
						|
		size_t newSize = m_Size;
 | 
						|
		while (m_CurrentUsedSize <= newSize / 2)
 | 
						|
			newSize /= 2;
 | 
						|
 | 
						|
		if (newSize != m_Size)
 | 
						|
			ChangeSize(newSize);
 | 
						|
	}
 | 
						|
protected:
 | 
						|
	T *m_Data;
 | 
						|
	size_t m_Size;
 | 
						|
	size_t m_CurrentUsedSize;
 | 
						|
public:
 | 
						|
	class iterator
 | 
						|
	{
 | 
						|
	protected:
 | 
						|
		T *m_Ptr;
 | 
						|
	public:
 | 
						|
		// constructors / destructors
 | 
						|
		iterator()
 | 
						|
		{
 | 
						|
			m_Ptr = NULL;
 | 
						|
		}
 | 
						|
 | 
						|
		iterator(T * ptr)
 | 
						|
		{
 | 
						|
			m_Ptr = ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		// member functions
 | 
						|
		T * base()
 | 
						|
		{
 | 
						|
			return m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		const T * base() const
 | 
						|
		{
 | 
						|
			return m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		// operators
 | 
						|
		T & operator*()
 | 
						|
		{
 | 
						|
			return *m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		T * operator->()
 | 
						|
		{
 | 
						|
			return m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		iterator & operator++()		// preincrement
 | 
						|
		{
 | 
						|
			++m_Ptr;
 | 
						|
			return (*this);
 | 
						|
		}
 | 
						|
 | 
						|
		iterator operator++(int)	// postincrement
 | 
						|
		{
 | 
						|
			iterator tmp = *this;
 | 
						|
			++m_Ptr;
 | 
						|
			return tmp;
 | 
						|
		}
 | 
						|
 | 
						|
		iterator & operator--()		// predecrement
 | 
						|
		{
 | 
						|
			--m_Ptr;
 | 
						|
			return (*this);
 | 
						|
		}
 | 
						|
 | 
						|
		iterator operator--(int)	// postdecrememnt
 | 
						|
		{
 | 
						|
			iterator tmp = *this;
 | 
						|
			--m_Ptr;
 | 
						|
			return tmp;
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator==(T * right) const
 | 
						|
		{
 | 
						|
			return (m_Ptr == right);
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator==(const iterator & right) const
 | 
						|
		{
 | 
						|
			return (m_Ptr == right.m_Ptr);
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator!=(T * right) const
 | 
						|
		{
 | 
						|
			return (m_Ptr != right);
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator!=(const iterator & right) const
 | 
						|
		{
 | 
						|
			return (m_Ptr != right.m_Ptr);
 | 
						|
		}
 | 
						|
 | 
						|
		iterator & operator+=(size_t offset)
 | 
						|
		{
 | 
						|
			m_Ptr += offset;
 | 
						|
			return (*this);
 | 
						|
		}
 | 
						|
 | 
						|
		iterator & operator-=(size_t offset)
 | 
						|
		{
 | 
						|
			m_Ptr -= offset;
 | 
						|
			return (*this);
 | 
						|
		}
 | 
						|
 | 
						|
		iterator operator+(size_t offset) const
 | 
						|
		{
 | 
						|
			iterator tmp(*this);
 | 
						|
			tmp.m_Ptr += offset;
 | 
						|
			return tmp;
 | 
						|
		}
 | 
						|
 | 
						|
		iterator operator-(size_t offset) const
 | 
						|
		{
 | 
						|
			iterator tmp(*this);
 | 
						|
			tmp.m_Ptr -= offset;
 | 
						|
			return tmp;
 | 
						|
		}
 | 
						|
 | 
						|
		T & operator[](size_t offset)
 | 
						|
		{
 | 
						|
			return (*(*this + offset));
 | 
						|
		}
 | 
						|
 | 
						|
		const T & operator[](size_t offset) const
 | 
						|
		{
 | 
						|
			return (*(*this + offset));
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator<(const iterator & right) const
 | 
						|
		{
 | 
						|
			return m_Ptr < right.m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator>(const iterator & right) const
 | 
						|
		{
 | 
						|
			return m_Ptr > right.m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator<=(const iterator & right) const
 | 
						|
		{
 | 
						|
			return m_Ptr <= right.m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		bool operator>=(const iterator & right) const
 | 
						|
		{
 | 
						|
			return m_Ptr >= right.m_Ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		size_t operator-(const iterator & right) const
 | 
						|
		{
 | 
						|
			return m_Ptr - right.m_Ptr;
 | 
						|
		}
 | 
						|
	};
 | 
						|
 | 
						|
	// constructors / destructors
 | 
						|
	CVector<T>()
 | 
						|
	{
 | 
						|
		m_Size = 0;
 | 
						|
		m_CurrentUsedSize = 0;
 | 
						|
		m_Data = NULL;
 | 
						|
	}
 | 
						|
 | 
						|
	CVector<T>(const CVector<T> & other)
 | 
						|
	{
 | 
						|
		// copy data
 | 
						|
		m_Data = new T [other.m_CurrentUsedSize];
 | 
						|
		m_Size = other.m_CurrentUsedSize;
 | 
						|
		m_CurrentUsedSize = other.m_CurrentUsedSize;
 | 
						|
		for (size_t i=0; i<other.m_CurrentUsedSize; i++)
 | 
						|
			m_Data[i] = other.m_Data[i];
 | 
						|
	}
 | 
						|
 | 
						|
	~CVector<T>()
 | 
						|
	{
 | 
						|
		clear();
 | 
						|
	}
 | 
						|
 | 
						|
	// interface
 | 
						|
	size_t size() const
 | 
						|
	{
 | 
						|
		return m_CurrentUsedSize;
 | 
						|
	}
 | 
						|
 | 
						|
	size_t capacity() const
 | 
						|
	{
 | 
						|
		return m_Size;
 | 
						|
	}
 | 
						|
 | 
						|
	iterator begin() const
 | 
						|
	{
 | 
						|
		return iterator(m_Data);
 | 
						|
	}
 | 
						|
 | 
						|
	iterator end() const
 | 
						|
	{
 | 
						|
		return iterator(m_Data + m_CurrentUsedSize);
 | 
						|
	}
 | 
						|
 | 
						|
	iterator iterAt(size_t pos)
 | 
						|
	{
 | 
						|
		if (pos > m_CurrentUsedSize)
 | 
						|
			assert(0);
 | 
						|
		return iterator(m_Data + pos);
 | 
						|
	}
 | 
						|
 | 
						|
	bool reserve(size_t newSize)
 | 
						|
	{
 | 
						|
		if (newSize > m_Size)
 | 
						|
			return ChangeSize(newSize);
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	bool push_back(const T & elem)
 | 
						|
	{
 | 
						|
		++m_CurrentUsedSize;
 | 
						|
		if (!GrowIfNeeded())
 | 
						|
		{
 | 
						|
			--m_CurrentUsedSize;
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		m_Data[m_CurrentUsedSize - 1] = elem;
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	void pop_back()
 | 
						|
	{
 | 
						|
		--m_CurrentUsedSize;
 | 
						|
		if (m_CurrentUsedSize < 0)
 | 
						|
			m_CurrentUsedSize = 0;
 | 
						|
 | 
						|
		FreeMemIfPossible();
 | 
						|
	}
 | 
						|
 | 
						|
	bool resize(size_t newSize)
 | 
						|
	{
 | 
						|
		if (!ChangeSize(newSize))
 | 
						|
			return false;
 | 
						|
		m_CurrentUsedSize = newSize;
 | 
						|
		return true;
 | 
						|
	}
 | 
						|
 | 
						|
	bool empty() const
 | 
						|
	{
 | 
						|
		return (m_CurrentUsedSize == 0);
 | 
						|
	}
 | 
						|
 | 
						|
	T & at(size_t pos)
 | 
						|
	{
 | 
						|
		if (pos > m_CurrentUsedSize)
 | 
						|
		{
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		return m_Data[pos];
 | 
						|
	}
 | 
						|
 | 
						|
	const  T & at(size_t pos) const
 | 
						|
	{
 | 
						|
		if (pos > m_CurrentUsedSize)
 | 
						|
		{
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		return m_Data[pos];
 | 
						|
	}
 | 
						|
 | 
						|
	T & operator[](size_t pos)
 | 
						|
	{
 | 
						|
		return at(pos);
 | 
						|
	}
 | 
						|
 | 
						|
	const T & operator[](size_t pos) const
 | 
						|
	{
 | 
						|
		return at(pos);
 | 
						|
	}
 | 
						|
 | 
						|
	T & front()
 | 
						|
	{
 | 
						|
		if (m_CurrentUsedSize < 1)
 | 
						|
		{
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		return m_Data[0];
 | 
						|
	}
 | 
						|
 | 
						|
	const T & front() const
 | 
						|
	{
 | 
						|
		if (m_CurrentUsedSize < 1)
 | 
						|
		{
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		return m_Data[0];
 | 
						|
	}
 | 
						|
 | 
						|
	T & back()
 | 
						|
	{
 | 
						|
		if (m_CurrentUsedSize < 1)
 | 
						|
		{
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		return m_Data[m_CurrentUsedSize - 1];
 | 
						|
	}
 | 
						|
 | 
						|
	const T & back() const
 | 
						|
	{
 | 
						|
		if (m_CurrentUsedSize < 1)
 | 
						|
		{
 | 
						|
			assert(0);
 | 
						|
		}
 | 
						|
		return m_Data[m_CurrentUsedSize - 1];
 | 
						|
	}
 | 
						|
 | 
						|
	iterator insert(iterator where, const T & value)
 | 
						|
	{
 | 
						|
		// validate iter
 | 
						|
		if (where < m_Data || where > (m_Data + m_CurrentUsedSize))
 | 
						|
			return iterator(0);
 | 
						|
 | 
						|
		size_t ofs = where - begin();
 | 
						|
 | 
						|
		++m_CurrentUsedSize;
 | 
						|
		if (!GrowIfNeeded())
 | 
						|
		{
 | 
						|
			--m_CurrentUsedSize;
 | 
						|
			return false;
 | 
						|
		}
 | 
						|
 | 
						|
		where = begin() + ofs;
 | 
						|
 | 
						|
		// Move subsequent entries
 | 
						|
		for (T *ptr = m_Data + m_CurrentUsedSize - 2; ptr >= where.base(); --ptr)
 | 
						|
			*(ptr + 1) = *ptr;
 | 
						|
 | 
						|
		*where.base() = value;
 | 
						|
 | 
						|
		return where;
 | 
						|
	}
 | 
						|
 | 
						|
	iterator erase(iterator where)
 | 
						|
	{
 | 
						|
		// validate iter
 | 
						|
		if (where < m_Data || where >= (m_Data + m_CurrentUsedSize))
 | 
						|
			return iterator(0);
 | 
						|
 | 
						|
		size_t ofs = where - begin();
 | 
						|
 | 
						|
		if (m_CurrentUsedSize > 1)
 | 
						|
		{
 | 
						|
			// move
 | 
						|
			T *theend = m_Data + m_CurrentUsedSize;
 | 
						|
			for (T *ptr = where.base() + 1; ptr < theend; ++ptr)
 | 
						|
				*(ptr - 1) = *ptr;
 | 
						|
		}
 | 
						|
 | 
						|
		--m_CurrentUsedSize;
 | 
						|
 | 
						|
		FreeMemIfPossible();
 | 
						|
 | 
						|
		return begin() + ofs;
 | 
						|
	}
 | 
						|
 | 
						|
	void clear()
 | 
						|
	{
 | 
						|
		m_Size = 0;
 | 
						|
		m_CurrentUsedSize = 0;
 | 
						|
		if (m_Data)
 | 
						|
		{
 | 
						|
			delete [] m_Data;
 | 
						|
			m_Data = NULL;
 | 
						|
		}
 | 
						|
	}
 | 
						|
};
 | 
						|
 | 
						|
#endif // __CVECTOR_H__
 | 
						|
 |