123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824 |
- //-----------------------------------------------------------------------------
- // Copyright (c) 2013 GarageGames, LLC
- //
- // Permission is hereby granted, free of charge, to any person obtaining a copy
- // of this software and associated documentation files (the "Software"), to
- // deal in the Software without restriction, including without limitation the
- // rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
- // sell copies of the Software, and to permit persons to whom the Software is
- // furnished to do so, subject to the following conditions:
- //
- // The above copyright notice and this permission notice shall be included in
- // all copies or substantial portions of the Software.
- //
- // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
- // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
- // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
- // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
- // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
- // FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS
- // IN THE SOFTWARE.
- //-----------------------------------------------------------------------------
- #ifndef _VECTOR_H_
- #define _VECTOR_H_
- //Includes
- #ifndef _PLATFORM_H_
- #include "platform/platform.h"
- #endif
- //-----------------------------------------------------------------------------
- /// Size of memory blocks to allocate at a time for vectors.
- const static S32 VectorBlockSize = 16;
- #ifdef TORQUE_DEBUG
- extern bool VectorResize(U32 *aSize, U32 *aCount, void **arrayPtr, U32 newCount, U32 elemSize,
- const char* fileName,
- const U32 lineNum);
- #else
- extern bool VectorResize(U32 *aSize, U32 *aCount, void **arrayPtr, U32 newCount, U32 elemSize);
- #endif
- /// Use the following macro to bind a vector to a particular line
- /// of the owning class for memory tracking purposes
- #ifdef TORQUE_DEBUG
- #define VECTOR_SET_ASSOCIATION(x) x.setFileAssociation(__FILE__, __LINE__)
- #else
- #define VECTOR_SET_ASSOCIATION(x)
- #endif
- //-----------------------------------------------------------------------------
- /// A dynamic array 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.
- ///
- /// <b>***WARNING***</b>
- ///
- /// This template does not initialize, construct or destruct any of
- /// it's elements. This means don't use this template for elements
- /// (classes) that need these operations. This template is intended
- /// to be used for simple structures that have no constructors or
- /// destructors.
- ///
- /// @nosubgrouping
- template<class T>
- class Vector
- {
- protected:
- U32 mElementCount;
- U32 mArraySize;
- T* mArray;
- #ifdef TORQUE_DEBUG
- const char* mFileAssociation;
- U32 mLineAssociation;
- #endif
- bool resize(U32); // resizes, but does no construction/destruction
- void destroy(U32 start, U32 end); ///< Destructs elements from <i>start</i> to <i>end-1</i>
- void construct(U32 start, U32 end); ///< Constructs elements from <i>start</i> to <i>end-1</i>
- void construct(U32 start, U32 end, const T* array);
- public:
- Vector(const U32 initialSize = 0);
- Vector(const U32 initialSize, const char* fileName, const U32 lineNum);
- Vector(const char* fileName, const U32 lineNum);
- Vector(const Vector&);
- ~Vector();
- #ifdef TORQUE_DEBUG
- void setFileAssociation(const char* file, const U32 line);
- #endif
- /// @name STL interface
- /// @{
- typedef T value_type;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T* iterator;
- typedef const T* const_iterator;
- typedef S32 difference_type;
- typedef U32 size_type;
- typedef difference_type (QSORT_CALLBACK *compare_func)(const T *a, const T *b);
- Vector<T>& operator=(const Vector<T>& p);
- iterator begin();
- const_iterator begin() const;
- iterator end();
- const_iterator end() const;
- S32 size() const;
- bool empty() const;
- bool contains(const T&) const;
- void insert(iterator, const T&);
- void erase(iterator);
- T& front();
- const T& front() const;
- T& back();
- const T& back() const;
- void push_front(const T&);
- void push_back(const T&);
- U32 push_front_unique(const T&);
- U32 push_back_unique(const T&);
- S32 find_next( const T&, U32 start = 0 ) const;
- void pop_front();
- void pop_back();
- T& operator[](U32);
- const T& operator[](U32) const;
- T& operator[](S32 i) { return operator[](U32(i)); }
- const T& operator[](S32 i ) const { return operator[](U32(i)); }
- T& at(U32);
- const T& at(U32) const;
- void reserve(U32);
- U32 capacity() const;
- /// @}
- /// @name Extended interface
- /// @{
- U32 memSize() const;
- T* address() const;
- U32 setSize(U32);
- void increment( U32 = 1);
- void increment(const T* array, U32 = 1);
- void decrement(U32 = 1);
- void insert(U32);
- void erase(U32);
- void erase_fast(U32);
- void erase_fast(iterator);
- void clear();
- void compact();
- void sort(compare_func f);
- T& first();
- T& last();
- const T& first() const;
- const T& last() const;
- void set(void * addr, U32 sz);
- void merge(const Vector& p);
- /// @}
- };
- template<class T> inline Vector<T>::~Vector()
- {
- dFree(mArray);
- }
- template<class T> inline Vector<T>::Vector(const U32 initialSize)
- {
- #ifdef TORQUE_DEBUG
- mFileAssociation = NULL;
- mLineAssociation = 0;
- #endif
- mArray = 0;
- mElementCount = 0;
- mArraySize = 0;
- if(initialSize)
- reserve(initialSize);
- }
- template<class T> inline Vector<T>::Vector(const U32 initialSize,
- const char* fileName,
- const U32 lineNum)
- {
- #ifdef TORQUE_DEBUG
- mFileAssociation = fileName;
- mLineAssociation = lineNum;
- #else
- TORQUE_UNUSED( fileName );
- TORQUE_UNUSED( lineNum );
- #endif
- mArray = 0;
- mElementCount = 0;
- mArraySize = 0;
- if(initialSize)
- reserve(initialSize);
- }
- template<class T> inline Vector<T>::Vector(const char* fileName,
- const U32 lineNum)
- {
- #ifdef TORQUE_DEBUG
- mFileAssociation = fileName;
- mLineAssociation = lineNum;
- #else
- TORQUE_UNUSED( fileName );
- TORQUE_UNUSED( lineNum );
- #endif
- mArray = 0;
- mElementCount = 0;
- mArraySize = 0;
- }
- template<class T> inline Vector<T>::Vector(const Vector& p)
- {
- #ifdef TORQUE_DEBUG
- mFileAssociation = p.mFileAssociation;
- mLineAssociation = p.mLineAssociation;
- #endif
- mArray = 0;
- resize(p.mElementCount);
- if (p.mElementCount)
- dMemcpy(mArray,p.mArray,mElementCount * sizeof(value_type));
- }
- #ifdef TORQUE_DEBUG
- template<class T> inline void Vector<T>::setFileAssociation(const char* file,
- const U32 line)
- {
- mFileAssociation = file;
- mLineAssociation = line;
- }
- #endif
- template<class T> inline void Vector<T>::destroy(U32 start, U32 end) // destroys from start to end-1
- {
- // This check is a little generous as we can legitimately get (0,0) as
- // our parameters... so it won't detect every invalid case but it does
- // remain simple.
- AssertFatal(start <= mElementCount && end <= mElementCount, "Vector<T>::destroy - out of bounds start/end.");
- // destroys from start to end-1
- while(start < end)
- destructInPlace(&mArray[start++]);
- }
- template<class T> inline void Vector<T>::construct(U32 start, U32 end) // destroys from start to end-1
- {
- AssertFatal(start <= mElementCount && end <= mElementCount, "Vector<T>::construct - out of bounds start/end.");
- while(start < end)
- constructInPlace(&mArray[start++]);
- }
- template<class T> inline void Vector<T>::construct(U32 start, U32 end, const T* array) // destroys from start to end-1
- {
- AssertFatal(start <= mElementCount && end <= mElementCount, "Vector<T>::construct - out of bounds start/end.");
- for (int i = 0; start + i < end; i++) {
- constructInPlace(&mArray[start+i], &array[i]);
- }
- }
- template<class T> inline U32 Vector<T>::memSize() const
- {
- return capacity() * sizeof(T);
- }
- template<class T> inline T* Vector<T>::address() const
- {
- return mArray;
- }
- template<class T> inline U32 Vector<T>::setSize(U32 size)
- {
- if (size > mArraySize)
- resize(size);
- else
- mElementCount = size;
- return mElementCount;
- }
- template<class T> inline void Vector<T>::increment( U32 delta)
- {
- U32 count = mElementCount;
- if ((mElementCount += delta) > mArraySize)
- resize(mElementCount);
- construct(count, mElementCount);
- }
- template<class T> inline void Vector<T>::increment(const T* array, U32 delta)
- {
- U32 count = mElementCount;
- if ((mElementCount += delta) > mArraySize)
- resize(mElementCount);
- construct(count, mElementCount, array);
- }
- template<class T> inline void Vector<T>::decrement(U32 delta)
- {
- AssertFatal(mElementCount != 0, "Vector<T>::decrement - cannot decrement zero-length vector.");
- const U32 count = mElementCount;
- // Determine new count after decrement...
- U32 newCount = mElementCount;
- if (mElementCount > delta)
- newCount -= delta;
- else
- newCount = 0;
- // Destruct removed items...
- destroy(newCount, count);
- // Note new element count.
- mElementCount = newCount;
- }
- template<class T> inline void Vector<T>::insert(U32 index)
- {
- // Assert: index >= 0 && index < mElementCount
- increment();
- dMemmove(&mArray[index + 1],
- &mArray[index],
- (mElementCount - index - 1) * sizeof(value_type));
- }
- template<class T> inline void Vector<T>::erase(U32 index)
- {
- AssertFatal(index < mElementCount, "Vector<T>::erase - out of bounds index!");
- if (index < (mElementCount - 1))
- {
- dMemmove(&mArray[index],
- &mArray[index + 1],
- (mElementCount - index - 1) * sizeof(value_type));
- }
- mElementCount--;
- }
- template<class T> inline void Vector<T>::erase_fast(U32 index)
- {
- AssertFatal(index < mElementCount, "Vector<T>::erase_fast - out of bounds index.");
- // CAUTION: this operator does NOT maintain list order
- // Copy the last element into the deleted 'hole' and decrement the
- // size of the vector.
- // Assert: index >= 0 && index < mElementCount
- if (index < (mElementCount - 1))
- dMemmove(&mArray[index], &mArray[mElementCount - 1], sizeof(value_type));
- decrement();
- }
- template<class T> inline T& Vector<T>::first()
- {
- AssertFatal(mElementCount != 0, "Vector<T>::first - Error, no first element of a zero sized array!");
- return mArray[0];
- }
- template<class T> inline const T& Vector<T>::first() const
- {
- AssertFatal(mElementCount != 0, "Vector<T>::first - Error, no first element of a zero sized array! (const)");
- return mArray[0];
- }
- template<class T> inline T& Vector<T>::last()
- {
- AssertFatal(mElementCount != 0, "Vector<T>::last - Error, no last element of a zero sized array!");
- return mArray[mElementCount - 1];
- }
- template<class T> inline const T& Vector<T>::last() const
- {
- AssertFatal(mElementCount != 0, "Vector<T>::last - Error, no last element of a zero sized array! (const)");
- return mArray[mElementCount - 1];
- }
- template<class T> inline void Vector<T>::clear()
- {
- mElementCount = 0;
- }
- template<class T> inline void Vector<T>::compact()
- {
- resize(mElementCount);
- }
- typedef int (QSORT_CALLBACK *qsort_compare_func)(const void *, const void *);
- template<class T> inline void Vector<T>::sort(compare_func f)
- {
- qsort(address(), size(), sizeof(T), (qsort_compare_func) f);
- }
- //-----------------------------------------------------------------------------
- template<class T> inline Vector<T>& Vector<T>::operator=(const Vector<T>& p)
- {
- resize(p.mElementCount);
- if (p.mElementCount)
- dMemcpy(mArray,p.mArray,mElementCount * sizeof(value_type));
- return *this;
- }
- template<class T> inline typename Vector<T>::iterator Vector<T>::begin()
- {
- return mArray;
- }
- template<class T> inline typename Vector<T>::const_iterator Vector<T>::begin() const
- {
- return mArray;
- }
- template<class T> inline typename Vector<T>::iterator Vector<T>::end()
- {
- return mArray + mElementCount;
- }
- template<class T> inline typename Vector<T>::const_iterator Vector<T>::end() const
- {
- return mArray + mElementCount;
- }
- template<class T> inline S32 Vector<T>::size() const
- {
- return (S32)mElementCount;
- }
- template<class T> inline bool Vector<T>::empty() const
- {
- return (mElementCount == 0);
- }
- template<class T> inline bool Vector<T>::contains(const T& t) const
- {
- return find_next(t) != -1;
- }
- template<class T> inline void Vector<T>::insert(iterator p,const T& x)
- {
- U32 index = (U32) (p - mArray);
- insert(index);
- mArray[index] = x;
- }
- template<class T> inline void Vector<T>::erase(iterator q)
- {
- erase(U32(q - mArray));
- }
- template<class T> inline void Vector<T>::erase_fast(iterator q)
- {
- erase_fast(U32(q - mArray));
- }
- template<class T> inline T& Vector<T>::front()
- {
- return *begin();
- }
- template<class T> inline const T& Vector<T>::front() const
- {
- return *begin();
- }
- template<class T> inline T& Vector<T>::back()
- {
- AssertFatal(mElementCount != 0, "Vector<T>::end - Error, no end element of a zero sized array!");
- return *(end()-1);
- }
- template<class T> inline const T& Vector<T>::back() const
- {
- AssertFatal(mElementCount != 0, "Vector<T>::end - Error, no end element of a zero sized array! (const)");
- return *(end()-1);
- }
- template<class T> inline void Vector<T>::push_front(const T& x)
- {
- insert(0);
- mArray[0] = x;
- }
- template<class T> inline void Vector<T>::push_back(const T& x)
- {
- increment(&x);
- // mArray[mElementCount - 1] = x;
- }
- template<class T> inline U32 Vector<T>::push_front_unique(const T& x)
- {
- S32 index = find_next(x);
- if (index == -1)
- {
- index = 0;
- insert(index);
- mArray[index] = x;
- }
- return index;
- }
- template<class T> inline U32 Vector<T>::push_back_unique(const T& x)
- {
- S32 index = find_next(x);
- if (index == -1)
- {
- increment(&x);
- index = mElementCount - 1;
- }
- return index;
- }
- template<class T> inline S32 Vector<T>::find_next( const T& x, U32 start ) const
- {
- S32 index = -1;
- if (start < mElementCount)
- {
- for (U32 i = start; i < mElementCount; i++)
- {
- if (mArray[i] == x)
- {
- index = i;
- break;
- }
- }
- }
- return index;
- }
- template<class T> inline void Vector<T>::pop_front()
- {
- AssertFatal(mElementCount != 0, "Vector<T>::pop_front - cannot pop the front of a zero-length vector.");
- erase(U32(0));
- }
- template<class T> inline void Vector<T>::pop_back()
- {
- AssertFatal(mElementCount != 0, "Vector<T>::pop_back - cannot pop the back of a zero-length vector.");
- decrement();
- }
- template<class T> inline T& Vector<T>::operator[](U32 index)
- {
- AssertFatal(index < mElementCount, "Vector<T>::operator[] - out of bounds array access!");
- return mArray[index];
- }
- template<class T> inline const T& Vector<T>::operator[](U32 index) const
- {
- AssertFatal(index < mElementCount, "Vector<T>::operator[] - out of bounds array access!");
- return mArray[index];
- }
- template<class T> inline T& Vector<T>::at(U32 index)
- {
- AssertFatal(index < mElementCount, "Vector<T>::at - out of bounds array access!");
- return mArray[index];
- }
- template<class T> inline const T& Vector<T>::at(U32 index) const
- {
- AssertFatal(index < mElementCount, "Vector<T>::at - out of bounds array access!");
- return mArray[index];
- }
- template<class T> inline void Vector<T>::reserve(U32 size)
- {
- if (size <= mArraySize)
- return;
- const U32 ec = mElementCount;
- if (resize(size))
- mElementCount = ec;
- }
- template<class T> inline U32 Vector<T>::capacity() const
- {
- return mArraySize;
- }
- template<class T> inline void Vector<T>::set(void * addr, U32 sz)
- {
- setSize(sz);
- if (addr)
- dMemcpy(address(),addr,sz*sizeof(T));
- }
- //-----------------------------------------------------------------------------
- template<class T> inline bool Vector<T>::resize(U32 ecount)
- {
- #ifdef TORQUE_DEBUG
- return VectorResize(&mArraySize, &mElementCount, (void**) &mArray, ecount, sizeof(T),
- mFileAssociation, mLineAssociation);
- #else
- return VectorResize(&mArraySize, &mElementCount, (void**) &mArray, ecount, sizeof(T));
- #endif
- }
- template<class T> inline void Vector<T>::merge(const Vector& p)
- {
- if (!p.size())
- return;
- const S32 oldsize = size();
- resize(oldsize + p.size());
- dMemcpy( &mArray[oldsize], p.address(), p.size() * sizeof(T) );
- }
- //-----------------------------------------------------------------------------
- /// Template for vectors of pointers.
- template <class T>
- class VectorPtr : public Vector<void *>
- {
- /// @deprecated Disallowed.
- VectorPtr(const VectorPtr&); // Disallowed
- public:
- VectorPtr();
- VectorPtr(const char* fileName, const U32 lineNum);
- /// @name STL interface
- /// @{
- typedef T value_type;
- typedef T& reference;
- typedef const T& const_reference;
- typedef T* iterator;
- typedef const T* const_iterator;
- typedef U32 difference_type;
- typedef U32 size_type;
- iterator begin();
- const_iterator begin() const;
- iterator end();
- const_iterator end() const;
- void insert(iterator,const T&);
- void insert(int idx) { Parent::insert(idx); }
- void erase(iterator);
- T& front();
- const T& front() const;
- T& back();
- const T& back() const;
- void push_front(const T&);
- void push_back(const T&);
- T& operator[](U32);
- const T& operator[](U32) const;
- /// @}
- /// @name Extended interface
- /// @{
- typedef Vector<void*> Parent;
- T& first();
- T& last();
- const T& first() const;
- const T& last() const;
- void erase_fast(U32);
- void erase_fast(iterator);
- /// @}
- };
- //-----------------------------------------------------------------------------
- template<class T> inline VectorPtr<T>::VectorPtr()
- {
- //
- }
- template<class T> inline VectorPtr<T>::VectorPtr(const char* fileName,
- const U32 lineNum)
- : Vector<void*>(fileName, lineNum)
- {
- //
- }
- template<class T> inline T& VectorPtr<T>::first()
- {
- return (T&)Parent::first();
- }
- template<class T> inline const T& VectorPtr<T>::first() const
- {
- return (const T)Parent::first();
- }
- template<class T> inline T& VectorPtr<T>::last()
- {
- return (T&)Parent::last();
- }
- template<class T> inline const T& VectorPtr<T>::last() const
- {
- return (const T&)Parent::last();
- }
- template<class T> inline typename VectorPtr<T>::iterator VectorPtr<T>::begin()
- {
- return (iterator)Parent::begin();
- }
- template<class T> inline typename VectorPtr<T>::const_iterator VectorPtr<T>::begin() const
- {
- return (const_iterator)Parent::begin();
- }
- template<class T> inline typename VectorPtr<T>::iterator VectorPtr<T>::end()
- {
- return (iterator)Parent::end();
- }
- template<class T> inline typename VectorPtr<T>::const_iterator VectorPtr<T>::end() const
- {
- return (const_iterator)Parent::end();
- }
- template<class T> inline void VectorPtr<T>::insert(iterator i,const T& x)
- {
- Parent::insert( (Parent::iterator)i, (Parent::reference)x );
- }
- template<class T> inline void VectorPtr<T>::erase(iterator i)
- {
- Parent::erase( (Parent::iterator)i );
- }
- template<class T> inline void VectorPtr<T>::erase_fast(U32 index)
- {
- AssertFatal(index < mElementCount, "VectorPtr<T>::erase_fast - out of bounds index." );
- // CAUTION: this operator does not maintain list order
- // Copy the last element into the deleted 'hole' and decrement the
- // size of the vector.
- // Assert: index >= 0 && index < mElementCount
- if (index < (mElementCount - 1))
- mArray[index] = mArray[mElementCount - 1];
- decrement();
- }
- template<class T> inline void VectorPtr<T>::erase_fast(iterator i)
- {
- erase_fast(U32(i - iterator(mArray)));
- }
- template<class T> inline T& VectorPtr<T>::front()
- {
- return *begin();
- }
- template<class T> inline const T& VectorPtr<T>::front() const
- {
- return *begin();
- }
- template<class T> inline T& VectorPtr<T>::back()
- {
- return *end();
- }
- template<class T> inline const T& VectorPtr<T>::back() const
- {
- return *end();
- }
- template<class T> inline void VectorPtr<T>::push_front(const T& x)
- {
- Parent::push_front((Parent::const_reference)x);
- }
- template<class T> inline void VectorPtr<T>::push_back(const T& x)
- {
- Parent::push_back((Parent::const_reference)x);
- }
- template<class T> inline T& VectorPtr<T>::operator[](U32 index)
- {
- return (T&)Parent::operator[](index);
- }
- template<class T> inline const T& VectorPtr<T>::operator[](U32 index) const
- {
- return (const T&)Parent::operator[](index);
- }
- #endif //_VECTOR_H_
|