//----------------------------------------------------------------------------------- // // Torque Network Library // Copyright (C) 2004 GarageGames.com, Inc. // Modifications (C) 2008 Chris Eykamp // For more information see http://www.opentnl.org // // 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. // // For use in products that are not compatible with the terms of the GNU // General Public License, alternative licensing options are available // from GarageGames.com. // // 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 // //------------------------------------------------------------------------------------ #ifndef _TNL_VECTORSAM_H_ #define _TNL_VECTORSAM_H_ //Includes #include #ifndef _TNL_TYPES_H_ #include "tnlTypes.h" #endif #ifndef _TNL_PLATFORM_H_ #include "tnlPlatform.h" #endif #ifndef _TNL_ASSERT_H_ #include "tnlAssert.h" #endif namespace TNL { // ============================================================================= /// A dynamic array template class. /// /// The vector grows as you insert or append /// elements. Insertion is fastest at the end of the array. Resizing /// of the array can be avoided by pre-allocating space using the /// reserve() method. /// /// This is now just a wrapper for stl::vector template class VectorBase { protected: std::vector innerVector; }; template<> class VectorBase { protected: std::vector innerVector; }; template class Vector : public VectorBase { public: Vector(const U32 initialSize = 0); Vector(const Vector& p); Vector(const std::vector& p); Vector(const T *array, U32 length); ~Vector(); Vector& operator=(const Vector& p); S32 size() const; bool empty() const; T& get(S32 index); const T& get(S32 index) const; void push_front(const T&); void push_back(const T&); T& pop_front(); T& pop_back(); T& operator[](U32 index); const T& operator[](U32 index) const; T& operator[](S32 index); const T& operator[](S32 index) const; void reserve(U32 size); void resize(U32 size); void insert(U32 index); void insert(U32 index, const T&); void erase(U32 index); void deleteAndErase(U32 index); void erase_fast(U32 index); void deleteAndErase_fast(U32 index); void clear(); void deleteAndClear(); bool contains(const T&); S32 getIndex(const T&); T& first(); T& last(); const T& first() const; const T& last() const; std::vector& getStlVector(); T* address(); const T* address() const; void reverse(); typedef S32 (QSORT_CALLBACK *compare_func)(T *a, T *b); void sort(compare_func f); }; // Note that tnlVector reserves the space whereas std::vector actually sets the size template inline Vector::Vector(const U32 initialSize) // Constructor { innerVector.reserve(initialSize); } template inline Vector::Vector(const Vector& p) // Copy constructor { innerVector = std::vector(p.innerVector); } template inline Vector::Vector(const std::vector& p) // Constructor to wrap std::vector { innerVector = p; } template inline Vector::Vector(const T *array, U32 length) // Constructor to wrap a C-style array { innerVector = std::vector(array, array + length); } template inline Vector::~Vector() {} // Destructor // returns a modifiable reference to the internal std::vector object //template inline std::vector& Vector::getStlVector() //{ // return innerVector; //} template inline T* Vector::address() { if (innerVector.begin() == innerVector.end()) return NULL; return &(*innerVector.begin()); } template const inline T* Vector::address() const { if (innerVector.begin() == innerVector.end()) return NULL; return &(*innerVector.begin()); } // was U32 template inline void Vector::resize(U32 size) { innerVector.resize(size); } // inserts an empty element at the specified index template inline void Vector::insert(U32 index) { TNLAssert(index <= innerVector.size(), "index out of range"); innerVector.insert(innerVector.begin() + index, 1, T()); } // inserts an object at a specified index template inline void Vector::insert(U32 index, const T &x) { TNLAssert(index <= innerVector.size(), "index out of range"); innerVector.insert(innerVector.begin() + index, x); } template inline void Vector::erase(U32 index) { TNLAssert(index < innerVector.size(), "index out of range"); innerVector.erase(innerVector.begin() + index); } template inline void Vector::deleteAndErase(U32 index) { TNLAssert(index < innerVector.size(), "index out of range"); delete innerVector[index]; erase(index); } template inline void Vector::erase_fast(U32 index) { TNLAssert(index < innerVector.size(), "index out of range"); // CAUTION: this operator does NOT maintain list order // Copy the last element into the deleted 'hole' and decrement the // size of the vector. if(index != innerVector.size() - 1) std::swap(innerVector[index], innerVector[innerVector.size() - 1]); innerVector.pop_back(); } template inline void Vector::deleteAndErase_fast(U32 index) { TNLAssert(index < innerVector.size(), "index out of range"); // CAUTION: this operator does NOT maintain list order // Copy the last element into the deleted 'hole' and decrement the // size of the vector. delete innerVector[index]; erase_fast(index); } template inline T& Vector::first() { TNLAssert(innerVector.size() != 0, "Vector is empty"); return *innerVector.begin(); } template inline const T& Vector::first() const { TNLAssert(innerVector.size() != 0, "Vector is empty"); return *innerVector.begin(); } template inline T& Vector::last() { TNLAssert(innerVector.size() != 0, "Vector is empty"); return *(innerVector.end() - 1); } template inline const T& Vector::last() const { TNLAssert(innerVector.size() != 0, "Vector is empty"); return *(innerVector.end() - 1); } template inline void Vector::clear() { innerVector.clear(); } template inline void Vector::deleteAndClear() { for(U32 i = 0; i < innerVector.size(); i++) delete innerVector[i]; innerVector.clear(); } template inline bool Vector::contains(const T &object) { return getIndex(object) != -1; } template inline S32 Vector::getIndex(const T &object) { for(U32 i = 0; i < innerVector.size(); i++) if(object == innerVector[i]) return i; return -1; } template inline Vector& Vector::operator=(const Vector& p) { innerVector = p.innerVector; return *this; } template inline S32 Vector::size() const { return (S32)innerVector.size(); } template inline bool Vector::empty() const { return innerVector.begin() == innerVector.end(); } template inline T& Vector::get(S32 index) { TNLAssert(U32(index) < innerVector.size(), "index out of range"); return (T&)innerVector[index]; } template inline const T& Vector::get(S32 index) const { TNLAssert(U32(index) < innerVector.size(), "index out of range"); return (T&)innerVector[index]; } template inline void Vector::push_front(const T &x) { insert(0); innerVector[0] = x; } template inline void Vector::push_back(const T &x) { innerVector.push_back(x); } template inline T& Vector::pop_front() { TNLAssert(innerVector.size() != 0, "Vector is empty"); T& t = innerVector[0]; innerVector.erase(innerVector.begin()); return t; } template inline T& Vector::pop_back() { TNLAssert(innerVector.size() != 0, "Vector is empty"); T& t = *(innerVector.end() - 1); innerVector.pop_back(); return t; } template inline T& Vector::operator[](U32 index) { TNLAssert(index < innerVector.size(), "index out of range"); return (T&)innerVector[index]; } template inline const T& Vector::operator[](U32 index) const { TNLAssert(index < innerVector.size(), "index out of range"); return (T&)innerVector[index]; } template inline T& Vector::operator[](S32 index) { TNLAssert(U32(index) < innerVector.size(), "index out of range"); return (T&)innerVector[(U32)index]; } template inline const T& Vector::operator[](S32 index) const { TNLAssert(U32(index) < innerVector.size(), "index out of range"); return (T&)innerVector[(U32)index]; } template inline void Vector::reserve(U32 size) { innerVector.reserve(size); } // Reverses this Vector's elements in place. template inline void Vector::reverse() { for(S32 i = (S32(innerVector.size()) >> 1) - 1; i >= 0; i--) { T temp = innerVector[innerVector.size() - i - 1]; innerVector[innerVector.size() - i - 1] = innerVector[i]; innerVector[i] = temp; } } typedef int (QSORT_CALLBACK *qsort_compare_func)(const void *, const void *); template inline void Vector::sort(compare_func f) { qsort(address(), size(), sizeof(T), (qsort_compare_func) f); } }; #endif //_TNL_TVECTOR_H_